Approximation Demo — Approximating Functions with Polynomials & Rationals

The sangi approximation module handles everything from regression on data to uniform approximation of functions and rational approximation in a unified manner. This page presents three demos covering representative use cases.

Demo 1: Recovering a Line from Data with Linear Regression

We run least-squares linear regression on 5 points lying on $y=2x+1$. When the data lies exactly on a line, the slope and intercept are recovered exactly, and the coefficient of determination is $R^2=1$.

=== Demo 1: Linear regression (data on y = 2x + 1) === slope = 2 intercept = 1 R^2 = 1
$R^2=1$ means the regression line explains the data perfectly. With real-world data you get $R^2<1$.

Demo 2: Uniformly Approximating exp with Chebyshev

We represent $e^x$ on the interval $[-1,1]$ with a degree-12 Chebyshev approximation. A Chebyshev series is extremely close to the best uniform (minimax) approximation, producing a nearly even error across the whole interval.

=== Demo 2: Chebyshev approximation of exp(x), degree 12 === cheb(-1) = 0.3678794412 exp(-1) = 0.3678794412 cheb(0) = 1 exp(0) = 1 cheb(1) = 2.718281828 exp(1) = 2.718281828
Even at degree 12 the error stays around $10^{-10}$, matching the true value to the digits shown. Unlike a Taylor expansion, accuracy does not drop off at the ends of the interval.

Demo 3: Approximating exp with a Rational via Pade

From the Taylor coefficients of $e^x$ we construct the $[3/3]$ Pade approximation $P_3(x)/Q_3(x)$. It is more accurate over a wider range than a polynomial of the same degree, and it does not break down even at points far from the expansion center, such as $x=2$.

=== Demo 3: Pade [3/3] approximation of exp(x) === pade(1) = 2.718309859 exp(1) = 2.718281828 pade(2) = 7.4 exp(2) = 7.389056099
The $[3/3]$ Pade has degree 3 in both numerator and denominator. It matches to 4 digits at $x=1$ and still 2 digits at $x=2$, giving a better wide-range approximation than the degree-6 Taylor polynomial.

Source Code and How to Run

example_approximation.cpp (full source code)
// example_approximation.cpp — Approximation demo
#include <math/approx/approximation.hpp>
#include <iostream>
#include <iomanip>
#include <vector>
#include <span>
#include <cmath>
using namespace sangi;

int main() {
    std::cout << std::setprecision(10);

    // --- Demo 1: Linear regression of points on a line ---
    std::cout << "=== Demo 1: Linear regression (data on y = 2x + 1) ===\n";
    std::vector<double> x = {0.0, 1.0, 2.0, 3.0, 4.0};
    std::vector<double> y = {1.0, 3.0, 5.0, 7.0, 9.0};
    auto lr = linearRegression(x, y);
    std::cout << "  slope     = " << lr.slope << "\n";
    std::cout << "  intercept = " << lr.intercept << "\n";
    std::cout << "  R^2       = " << lr.r_squared << "\n";

    // --- Demo 2: Chebyshev approximation of exp on [-1, 1] ---
    std::cout << "\n=== Demo 2: Chebyshev approximation of exp(x), degree 12 ===\n";
    ChebyshevApprox<double> cheb([](double t) { return std::exp(t); }, -1.0, 1.0, 12);
    for (double xi : {-1.0, 0.0, 1.0})
        std::cout << "  cheb(" << xi << ") = " << cheb(xi)
                  << "   exp(" << xi << ") = " << std::exp(xi) << "\n";

    // --- Demo 3: Pade [3/3] approximation of exp ---
    std::cout << "\n=== Demo 3: Pade [3/3] approximation of exp(x) ===\n";
    std::vector<double> taylor = {
        1.0, 1.0, 1.0 / 2.0, 1.0 / 6.0, 1.0 / 24.0, 1.0 / 120.0, 1.0 / 720.0
    };
    auto pade = padeApprox(std::span<const double>(taylor), 3, 3);
    for (double xi : {1.0, 2.0})
        std::cout << "  pade(" << xi << ") = " << evaluatePade(pade, xi)
                  << "   exp(" << xi << ") = " << std::exp(xi) << "\n";

    return 0;
}

For API details, see the Approximation API Reference.

Build and Run

cd sangi
mkdir build && cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release --target example-approximation
examples\Release\example-approximation.exe