# Chebyshev Approximation¶

O2scl

## Chebyshev approximation introduction¶

A class implementing the Chebyshev approximations based on GSL is given in cheb_approx_tl. This class has its own copy constructor, so that Chebyshev approximations can be copied and passed as arguments to functions. Derivatives and integrals of cheb_approx_tl objects are created as new ref o2scl::cheb_approx_tl objects which can be easily manipulated.

## Chebyshev approximation example¶

This example performs an approximation of the function $$y=\sin\left[ 1/\left(x+0.08 \right) \right]$$ over $$[0,2 \pi]$$. This function oscillates strongly over this interval and requires a high order approximation to be accurate.

The image below shows the approximation for $$n=50$$ $$n=25$$. The $$n=100$$ would be nearly indistinguishable from the exact result on this scale.

/* Example: ex_chebapp.cpp
-------------------------------------------------------------------
*/

#include <iostream>
#include <o2scl/constants.h>
#include <o2scl/test_mgr.h>
#include <o2scl/cheb_approx.h>
#include <o2scl/deriv_cern.h>
#include <o2scl/inte_qag_gsl.h>

using namespace std;
using namespace o2scl;

double func(double x) {
return sin(1.0/(x+0.08));
}

double dfunc(double x) {
return -cos(1.0/(x+0.08))/pow(x+0.08,2.0);
}

// Simple function to output information to file for plotting
void write_file(cheb_approx &gc);

int main(void) {
test_mgr t;
t.set_output_level(1);

cout.setf(ios::scientific);

funct tf=func;

cheb_approx gc;
deriv_cern<> cd;
inte_qag_gsl<> gi;

double res, err;
double x0=0.55;

// Initialize the Chebyshev approximation
gc.init(func,100,0.0,2.0*o2scl_const::pi);

// Evaluate the approximation and compare with the exact result
cout << "f(0.55)" << endl;
cout << "Exact         : " << func(x0) << endl;
gc.eval_err(x0,res,err);
cout << "Approx (n=100): " << res << endl;
cout << " Est. Error   : " << err << endl;
cout << " Act. Error   : " << fabs(res-func(x0)) << endl;

// Evaluate the approximation at lower order
gc.eval_n_err(50,x0,res,err);
cout << "Approx (n=50) : " << res << endl;
cout << " Est. Error   : " << err << endl;
cout << " Act. Error   : " << fabs(res-func(x0)) << endl;
gc.eval_n_err(25,x0,res,err);
cout << "Approx (n=25) : " << res << endl;
cout << " Est. Error   : " << err << endl;
cout << " Act. Error   : " << fabs(res-func(x0)) << endl;
cout << endl;

t.test_rel(gc.eval(x0),func(x0),1.0e-4,"eval");

// Show how to use operator=() to create a new approximation
cheb_approx gc2=gc;
cout << "Using operator=(): " << gc2.eval(x0) << " " << func(x0) << endl;
cout << endl;

t.test_rel(gc2.eval(x0),gc.eval(x0),1.0e-10,"op=");

// Show how to compute the derivative
cheb_approx gc_deriv;
gc.deriv(gc_deriv);

cout << "f'(0.55)" << endl;
cout << "Exact         : " << dfunc(x0) << endl;
gc_deriv.eval_err(x0,res,err);
cout << "Approx (n=100): " << res << endl;
cout << " Est. Error   : " << err << endl;
cout << " Act. Error   : " << fabs(res-dfunc(x0)) << endl;
cd.deriv_err(x0,tf,res,err);
cout << "Direct deriv  : " << res << endl;
cout << " Est. Error   : " << err << endl;
cout << " Act. Error   : " << fabs(res-dfunc(x0)) << endl;
cout << endl;

t.test_abs(res,dfunc(x0),1.0e-12,"deriv with deriv_cern");
t.test_abs(gc_deriv.eval(x0),dfunc(x0),5.0e-3,"deriv with cheb");

// Show how to compute the integral
cheb_approx gc_integ;
gc.integ(gc_integ);

cout << "int(f,0,0.55)" << endl;
gc_integ.eval_err(x0,res,err);
cout << "Approx (n=100): " << res << endl;
cout << " Est. Error   : " << err << endl;
gi.integ_err(tf,0.0,x0,res,err);
cout << "Direct integ  : " << res << endl;
cout << " Est. Error   : " << err << endl;
cout << "Rel. Error    : " << fabs(res-gc_integ.eval(x0)) << endl;
cout << endl;

t.test_abs(gc_integ.eval(x0),gi.integ(tf,0.0,x0),1.0e-6,"integral");

write_file(gc);

t.report();
return 0;
}
// End of example

// Simple function to output information to file for plotting
void write_file(cheb_approx &gc) {

ofstream fout;
fout.open("ex_chebapp.out");
fout.setf(ios::scientific);

for(double x=0.0;x<1.0001;x+=0.01) {
fout << x << " " << func(x) << " " << gc.eval(x) << " "
<< gc.eval_n(50,x) << " " << gc.eval_n(25,x) << endl;
}

fout.close();

return;
}