blob: d3486f394d3a5b7c15d22fe144c41e433385c47d [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
// The [m/m] Pade approximant p(x)/q(x) of exp(x), q(0) = 1, from its Taylor
// coefficients. Matching the series through degree 2m gives the denominator
// from a Hankel system in the coefficients c_k,
// sum_{j=1}^{m} c_{m+i-j} q_j = -c_{m+i}, i = 1..m,
// written with H(i,j) = c_{i+j+1} (j reversed), and the numerator by a
// truncated convolution p_i = sum_{j<=i} c_{i-j} q_j.
//
// The raw coefficients 1/k! fall from 1 to 1/(2m)! across H, which leaves it
// badly scaled: kappa(H) ~ 7e15 at m = 8. Approximating exp(t y) instead, with
// coefficients c_k = t^k / k!, scales H to t D H D, D = diag(t^i) -- still
// Hankel -- and t = m equilibrates it: kappa(H) ~ 5e7 at m = 8. The
// approximant of exp(x) is then p(x/t) / q(x/t), since the substitution
// preserves both the degrees and the order of contact.
#include <contrib/Eigen/StructuredMatrices>
#include <cmath>
#include <iomanip>
#include <iostream>
using namespace Eigen;
int main() {
std::cout << " m |r(1) - e| |r(-2) - e^-2|\n";
for (int m : {2, 4, 6, 8, 10}) {
const double t = m;
VectorXd c(2 * m + 1);
c[0] = 1;
for (int k = 1; k <= 2 * m; ++k) c[k] = c[k - 1] * t / k;
// H(i, j) = c_{i+j+1} for i, j = 0..m-1: first column c_1..c_m, last row c_m..c_{2m-1}.
const auto H = makeHankel(c.segment(1, m), c.segment(m, m));
// The unknowns are q_m, ..., q_1 (reversed): row i reads c_{i+1} q_m + ... + c_{m+i} q_1.
const VectorXd reversed = H.solve(-c.segment(m + 1, m));
VectorXd q(m + 1), p(m + 1);
q[0] = 1;
q.tail(m) = reversed.reverse();
for (int i = 0; i <= m; ++i) p[i] = c.head(i + 1).reverse().dot(q.head(i + 1));
const auto r = [&](double x) {
const double y = x / t;
double num = 0, den = 0;
for (int i = m; i >= 0; --i) {
num = num * y + p[i];
den = den * y + q[i];
}
return num / den;
};
std::cout << std::setw(2) << m << " " << std::setw(15) << std::abs(r(1) - std::exp(1.0)) << " "
<< std::abs(r(-2) - std::exp(-2.0)) << "\n";
}
}