C++代码实现MATLAB中的pade函数功能

cpp 复制代码
// pade.cpp
// 用 C++ 实现 MATLAB 的 pade 函数(幂级数版本 + 纯延时版本)
// 编译: g++ -std=c++17 -O2 pade.cpp -o pade
#include <vector>
#include <complex>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <stdexcept>
#include <algorithm>
#include <string>

namespace mpad {

using Complex = std::complex<double>;
using VecC    = std::vector<Complex>;
using MatC    = std::vector<VecC>;

// ------------------------------------------------------------------
// 列主元高斯消元求解 A*x = b
// ------------------------------------------------------------------
VecC solveLinearSystem(const MatC& A_in, const VecC& b_in)
{
    const int n = static_cast<int>(A_in.size());
    if (n == 0) return {};

    MatC A = A_in;
    VecC b = b_in;
    for (int i = 0; i < n; ++i) A[i].push_back(b[i]);   // 增广矩阵

    for (int c = 0; c < n; ++c) {
        int piv = c;
        double best = std::abs(A[c][c]);
        for (int r = c + 1; r < n; ++r) {
            if (std::abs(A[r][c]) > best) { best = std::abs(A[r][c]); piv = r; }
        }
        if (best < 1e-14)
            throw std::runtime_error("pade: 线性方程组奇异,无法求得 Pade 系数");

        if (piv != c) std::swap(A[c], A[piv]);

        for (int r = c + 1; r < n; ++r) {
            Complex f = A[r][c] / A[c][c];
            for (int k = c; k <= n; ++k) A[r][k] -= f * A[c][k];
        }
    }

    VecC x(n);
    for (int r = n - 1; r >= 0; --r) {
        Complex s = A[r][n];
        for (int c = r + 1; c < n; ++c) s -= A[r][c] * x[c];
        x[r] = s / A[r][r];
    }
    return x;
}

// ------------------------------------------------------------------
// 核心:由幂级数系数(升幂)c[0..L+M] 求 [L/M] 阶 Pade 逼近
//   输出 P(分子系数,升幂,长度 L+1)
//        Q(分母系数,升幂,长度 M+1,Q[0] == 1)
// ------------------------------------------------------------------
void padeLM(const VecC& c, int L, int M, VecC& P, VecC& Q)
{
    const int N = L + M;
    if (static_cast<int>(c.size()) < N + 1)
        throw std::runtime_error("pade: 幂级数系数个数不足 (需要 >= L+M+1)");

    // 解 Q(x) = 1 + q1 x + ... + qM x^M
    // 匹配方程 (k = L+1 .. L+M): q1*c[k-1] + ... + qM*c[k-M] = -c[k]
    MatC A(M, VecC(M, Complex(0.0, 0.0)));
    VecC rhs(M, Complex(0.0, 0.0));
    for (int r = 0; r < M; ++r) {
        const int k = L + 1 + r;
        for (int j = 0; j < M; ++j) {
            const int idx = k - (j + 1);
            A[r][j] = (idx >= 0) ? c[idx] : Complex(0.0, 0.0);
        }
        rhs[r] = -c[k];
    }

    Q.assign(M + 1, Complex(0.0, 0.0));
    Q[0] = Complex(1.0, 0.0);
    if (M > 0) {
        VecC q = solveLinearSystem(A, rhs);
        for (int j = 0; j < M; ++j) Q[j + 1] = q[j];
    }

    // 回代 P(x) = p0 + p1 x + ... + pL x^L
    //   p_k = sum_{i=0..min(k,M)} q_i * c_{k-i}
    P.assign(L + 1, Complex(0.0, 0.0));
    for (int k = 0; k <= L; ++k) {
        Complex s(0.0, 0.0);
        const int imax = std::min(k, M);
        for (int i = 0; i <= imax; ++i) s += Q[i] * c[k - i];
        P[k] = s;
    }
}

// 升幂 -> 降幂(MATLAB 传递函数约定)
std::vector<double> toDescending(const VecC& a)
{
    const int n = static_cast<int>(a.size());
    std::vector<double> out(n);
    for (int i = 0; i < n; ++i) out[i] = a[n - 1 - i].real();
    return out;
}

// ------------------------------------------------------------------
// [num,den] = pade(coeffs, N)
//   coeffs : f(x) 幂级数系数(升幂)
//   N      : 总阶数,L = floor(N/2),M = N - L
// ------------------------------------------------------------------
void pade(const std::vector<double>& coeffsAscending, int N,
          std::vector<double>& num, std::vector<double>& den)
{
    if (N < 0) throw std::runtime_error("pade: N 必须为非负整数");
    const int L = N / 2;
    const int M = N - L;

    VecC c(coeffsAscending.begin(), coeffsAscending.end());
    VecC P, Q;
    padeLM(c, L, M, P, Q);

    num = toDescending(P);
    den = toDescending(Q);
}

// ------------------------------------------------------------------
// [num,den] = pade(T, N)  ------ exp(-T*s) 的 N 阶 Pade 逼近
// ------------------------------------------------------------------
void padeDelay(double T, int N,
               std::vector<double>& num, std::vector<double>& den)
{
    if (N < 0) throw std::runtime_error("pade: N 必须为非负整数");
    const int L = N / 2;
    const int M = N - L;

    // exp(-T*s) 在 s=0 的泰勒系数 c_k = (-T)^k / k!
    std::vector<double> c(L + M + 1);
    c[0] = 1.0;
    for (int k = 1; k <= L + M; ++k)
        c[k] = c[k - 1] * (-T) / static_cast<double>(k);

    pade(c, N, num, den);
}

void printVector(const std::string& name, const std::vector<double>& v)
{
    std::cout << name << " = [";
    for (size_t i = 0; i < v.size(); ++i) {
        std::cout << v[i];
        if (i + 1 < v.size()) std::cout << ", ";
    }
    std::cout << "]\n";
}

} // namespace mpad

// ==================================================================
int main()
{
    using namespace mpad;
    std::cout << std::setprecision(10);

    // 例 1:exp(x) 的 [2/3] Pade
    //   coeffs = 1./factorial(0:5)
    std::vector<double> coeffs = {1.0, 1.0, 0.5, 1.0/6.0, 1.0/24.0, 1.0/120.0};
    std::vector<double> num, den;
    pade(coeffs, 5, num, den);
    std::cout << "--- [2/3] Pade of exp(x) ---\n";
    printVector("num", num);
    printVector("den", den);

    // 例 2:exp(-s) 的 [2/2] Pade(等价 pade(1,4))
    padeDelay(1.0, 4, num, den);
    std::cout << "\n--- [2/2] Pade of exp(-s) ---\n";
    printVector("num", num);
    printVector("den", den);

    // 例 3:exp(-0.1s) 的 [1/2] Pade(等价 pade(0.1,3))
    padeDelay(0.1, 3, num, den);
    std::cout << "\n--- [1/2] Pade of exp(-0.1s) ---\n";
    printVector("num", num);
    printVector("den", den);

    return 0;
}
相关推荐
smj2302_796826521 小时前
解决leetcode第4064题至多一次取反能被k整除的最长子数组II
python·算法·leetcode
AIGC小尼1 小时前
ACE-Step-1.5 本地 AI 音乐模型实战|text2music 歌词转人声,部署脚本、参数调优与排坑全记录
人工智能·算法·comfyui·ai漫剧
ProcessOn官方账号1 小时前
java IO操作 你快速认识IO的相关基本知识
java·开发语言
YOLO数据集集合1 小时前
树木检测数据集 | 树木检测 树种分类 航拍林业 森林监测9131期
人工智能·算法·机器学习·分类·数据挖掘·林业·树种分类
青山木1 小时前
Hot 100 --- 下一个排列
java·数据结构·算法·leetcode
垆边人似月.1 小时前
字符串重排后最大字典序
算法·leetcode·职场和发展
码流子1 小时前
AI稽核精灵-Agent落地
大数据·人工智能·物联网·算法·系统架构
神仙别闹1 小时前
基于C++实现的(控制台)学校开课查询系统
开发语言·c++
微三云生态系统架构师-彭丹1 小时前
排队免单资金池专户存管与返本算法:队列模型与熔断保护
算法·熔断机制·排队免单·消费增值·资金池·队列系统·返本算法