#include <2geom/chebyshev.h> #include <2geom/sbasis.h> #include <2geom/sbasis-poly.h> #include using std::vector; #include #include namespace Geom{ SBasis cheb(unsigned n) { static std::vector basis; if(basis.empty()) { basis.push_back(Linear(1,1)); basis.push_back(Linear(0,1)); } for(unsigned i = basis.size(); i <= n; i++) { basis.push_back(Linear(0,2)*basis[i-1] - basis[i-2]); } return basis[n]; } SBasis cheb_series(unsigned n, double* cheb_coeff) { SBasis r; for(unsigned i = 0; i < n; i++) { double cof = cheb_coeff[i]; //if(i == 0) //cof /= 2; r += cheb(i)*cof; } return r; } SBasis clenshaw_series(unsigned m, double* cheb_coeff) { /** b_n = a_n b_n-1 = 2*x*b_n + a_n-1 b_n-k = 2*x*b_{n-k+1} + a_{n-k} - b_{n - k + 2} b_0 = x*b_1 + a_0 - b_2 */ double a = -1, b = 1; SBasis d, dd; SBasis y = (Linear(0, 2) - (a+b)) / (b-a); SBasis y2 = 2*y; for(int j = m - 1; j >= 1; j--) { SBasis sv = d; d = y2*d - dd + cheb_coeff[j]; dd = sv; } return y*d - dd + 0.5*cheb_coeff[0]; } SBasis chebyshev_approximant (double (*f)(double,void*), int order, Interval in, void* p) { gsl_cheb_series *cs = gsl_cheb_alloc (order+2); gsl_function F; F.function = f; F.params = p; gsl_cheb_init (cs, &F, in[0], in[1]); SBasis r = compose(clenshaw_series(order, cs->c), Linear(-1,1)); gsl_cheb_free (cs); return r; } struct wrap { double (*f)(double,void*); void* pp; double fa, fb; Interval in; }; double f_interp(double x, void* p) { struct wrap *wr = (struct wrap *)p; double z = (x - wr->in[0]) / (wr->in[1] - wr->in[0]); return (wr->f)(x, wr->pp) - ((1 - z)*wr->fa + z*wr->fb); } SBasis chebyshev_approximant_interpolating (double (*f)(double,void*), int order, Interval in, void* p) { double fa = f(in[0], p); double fb = f(in[1], p); struct wrap wr; wr.fa = fa; wr.fb = fb; wr.in = in; printf("%f %f\n", fa, fb); wr.f = f; wr.pp = p; return compose(Linear(in[0], in[1]), Linear(fa, fb)) + chebyshev_approximant(f_interp, order, in, &wr) + Linear(fa, fb); } SBasis chebyshev(unsigned n) { static std::vector basis; if(basis.empty()) { basis.push_back(Linear(1,1)); basis.push_back(Linear(0,1)); } for(unsigned i = basis.size(); i <= n; i++) { basis.push_back(Linear(0,2)*basis[i-1] - basis[i-2]); } return basis[n]; } }; /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :