Main Page   Class Hierarchy   Compound List   File List   Compound Members  

chebexp.cpp

00001 /*
00002 Chebyshev Series Expansion and Interpolation routine
00003 functions
00004     chebexp  : function f(x) -> Chebyshev series
00005     chebeval : Chebyshev series -> evaluation of the f(x)
00006 necessary package
00007     fft2f.c  : FFT package
00008 */
00009 
00010 /*
00011 chebexp, chebeval
00012     [description]
00013         evaluation of f(x) from Chebyshev series of f(x)
00014     [declaration]
00015         void chebexp(double (*f)(double), double a, double b, 
00016             double eps, int lenc, double *c, double *err);
00017         double chebeval(double x, double *c);
00018     [usage]
00019         chebexp(f, a, b, eps, lenc, c, &err);  // f(x) -> c[]
00020         ...
00021         y = chebeval(x, c);  // evaluation of the f(x) from c[]
00022     [parameters]
00023         f         : function f(x) (double (*f)(double))
00024         a         : lower limit of interpolation (double)
00025         b         : upper limit of interpolation (double)
00026         eps       : relative error of interpolation (double)
00027         lenc      : (length of c[]) - 1 (int)
00028         c         : data of Chebyshev expansion, 
00029                     c[0...lenc] (double *)
00030         err       : estimate of the maximum absolute error 
00031                     of the interpolation over [a,b] (double *)
00032     [remarks]
00033         initial parameters
00034             lenc >= 12
00035             example :
00036                 lenc = 1024 + 4;
00037         function
00038             f(x) needs to be analytic over [a,b].
00039         relative error
00040             eps is relative error requested excluding 
00041             cancellation of significant digits.
00042             i.e. eps means : (maximum absolute error) / 
00043                              (integral_a^b |f(x)| dx).
00044             eps does not mean : (maximum absolute error) / I.
00045         error message
00046             err >= 0 : normal termination.
00047             err < 0  : abnormal termination (n > lenc-4).
00048                        i.e. convergent error is detected :
00049                            1. f(x) or (d/dx)^n f(x) has 
00050                               discontinuous points or sharp 
00051                               peaks over [a,b].
00052                            2. relative error of f(x) is 
00053                               greater than eps.
00054                            3. f(x) has oscillatory factor 
00055                               and frequency of the oscillation 
00056                               is very high.
00057         array of c[]
00058             lenc           : (int) c[0]
00059             n              : (int) c[1]
00060             (b+a)/2        : c[2]
00061             2/(b-a)        : c[3]
00062             f(c[2]-t/c[3]) : c[lenc]*T_0(t) + c[lenc-1]*T_1(t) 
00063                              + ... + c[lenc-n]*T_n(t)
00064 */
00065 
00066 #ifndef chebexp_SOURCES
00067 #define chebexp_SOURCES
00068 
00069 #include "integrate.h"
00070 #include <math.h>
00071 
00074 namespace PLib {
00075 
00076 template <class T>
00077 void chebexp(double (*f)(T), T a, T b, T eps, 
00078     BasicArray<T> &c, T &err)
00079 {
00080     int lenc = c.n() ;
00081     int j, k, l, n;
00082     T esf, ba, cos2, sin2, wi, ss, x, y, t, h, eref, erefh, errh;
00083 
00084     
00085 
00086     esf = 10;
00087     ba = T(0.5) * (b - a);
00088     c[0] = T(0.5) * (*f)(a);
00089     c[2] = T(0.5) * (*f)(b);
00090     c[1] = (*f)(a + ba);
00091     c[lenc - 1] = c[0] - c[2];
00092     c[lenc] = c[0] + c[2] + c[1];
00093     c[lenc - 2] = c[0] + c[2] - c[1];
00094     cos2 = 0;
00095     sin2 = 1;
00096     wi = -1;
00097     h = 1;
00098     l = 1;
00099     n = 2;
00100     eref = erefh = T() ; 
00101     do {
00102         ss = 2 * sin2;
00103         cos2 = sqrt(2 + cos2);
00104         sin2 /= 2 + cos2;
00105         x = ba * sin2;
00106         y = 0;
00107         for (j = 0; j <= l - 1; j++) {
00108             x += y;
00109             y += ss * (ba - x);
00110             c[j] = (*f)(a + x);
00111             c[n - 1 - j] = (*f)(b - x);
00112         }
00113         wi /= cos2;
00114         ddct(n, T(0.5) * cos2, wi, c);
00115         l = n;
00116         n *= 2;
00117         for (j = l - 1; j >= 0; j--) {
00118             k = lenc - j;
00119             t = c[k] - c[j];
00120             c[k] += c[j];
00121             c[lenc - n + j] = t;
00122         }
00123         if (n == 4) {
00124             eref = T(0.25) * (fabs(c[lenc]) + fabs(c[lenc - 1]) + 
00125                 fabs(c[lenc - 2]) + fabs(c[lenc - 3]) + fabs(c[lenc - 4]));
00126             erefh = eref * sqrt(eps);
00127             eref *= eps;
00128             err = erefh;
00129         }
00130         h *= T(0.5);
00131         errh = esf * err;
00132         err = h * (T(0.5) * fabs(c[lenc - n]) + fabs(c[lenc - n + 1]));
00133     } while ((err > eref || errh > erefh) && 2 * n + 4 <= lenc);
00134     c[lenc - n] *= T(0.5);
00135     c[lenc] *= T(0.5);
00136     for (j = lenc - n; j <= lenc; j++) {
00137         c[j] *= h;
00138     }
00139     if (err > eref || errh > erefh) {
00140         err = -(err);
00141     } else {
00142         do {
00143             n -= 2;
00144             err += fabs(c[lenc - n]) + fabs(c[lenc - n + 1]);
00145         } while (err < eref && n > 2);
00146         n += 2;
00147         err = eref;
00148     }
00149     if (ba != 0) {
00150         c[3] = 1 / ba;
00151     } else {
00152         c[3] = 0;
00153     }
00154     c[2] = T(0.5) * (b + a);
00155     c[1] = n + T(0.5);
00156     c[0] = lenc + T(0.5);
00157 }
00158 
00159 
00160 template <class T>
00161 T chebeval(T x, const BasicArray<T> &c)
00162 {
00163     int lenc, n, j;
00164     T t, t2, v0, v1;
00165 
00166     lenc = (int) c[0];
00167     n = (int) c[1];
00168     t = (c[2] - x) * c[3];
00169     t2 = 2 * t;
00170     v0 = c[lenc - n];
00171     v1 = c[lenc - n + 1] + t2 * v0;
00172     for (j = lenc - n + 2; j <= lenc - 2; j += 2) {
00173         v0 = c[j] + t2 * v1 - v0;
00174         v1 = c[j + 1] + t2 * v0 - v1;
00175     }
00176     return c[lenc] + t * v1 - v0;
00177 }
00178 
00179 template <class T>
00180 void chebexp(double (*f)(T,void*), void* userData, T a, T b, T eps, 
00181     BasicArray<T> &c, T &err)
00182 {
00183     int lenc = c.n() ;
00184     int j, k, l, n;
00185     T esf, ba, cos2, sin2, wi, ss, x, y, t, h, eref, erefh, errh;
00186 
00187     
00188 
00189     esf = 10;
00190     ba = T(0.5) * (b - a);
00191     c[0] = T(0.5) * (*f)(a,userData);
00192     c[2] = T(0.5) * (*f)(b,userData);
00193     c[1] = (*f)(a + ba,userData);
00194     c[lenc - 1] = c[0] - c[2];
00195     c[lenc] = c[0] + c[2] + c[1];
00196     c[lenc - 2] = c[0] + c[2] - c[1];
00197     cos2 = 0;
00198     sin2 = 1;
00199     wi = -1;
00200     h = 1;
00201     l = 1;
00202     n = 2;
00203     eref = erefh = T() ; 
00204     do {
00205         ss = 2 * sin2;
00206         cos2 = sqrt(2 + cos2);
00207         sin2 /= 2 + cos2;
00208         x = ba * sin2;
00209         y = 0;
00210         for (j = 0; j <= l - 1; j++) {
00211             x += y;
00212             y += ss * (ba - x);
00213             c[j] = (*f)(a + x,userData);
00214             c[n - 1 - j] = (*f)(b - x,userData);
00215         }
00216         wi /= cos2;
00217         ddct(n, T(0.5) * cos2, wi, c);
00218         l = n;
00219         n *= 2;
00220         for (j = l - 1; j >= 0; j--) {
00221             k = lenc - j;
00222             t = c[k] - c[j];
00223             c[k] += c[j];
00224             c[lenc - n + j] = t;
00225         }
00226         if (n == 4) {
00227             eref = T(0.25) * (fabs(c[lenc]) + fabs(c[lenc - 1]) + 
00228                 fabs(c[lenc - 2]) + fabs(c[lenc - 3]) + fabs(c[lenc - 4]));
00229             erefh = eref * sqrt(eps);
00230             eref *= eps;
00231             err = erefh;
00232         }
00233         h *= T(0.5);
00234         errh = esf * err;
00235         err = h * (T(0.5) * fabs(c[lenc - n]) + fabs(c[lenc - n + 1]));
00236     } while ((err > eref || errh > erefh) && 2 * n + 4 <= lenc);
00237     c[lenc - n] *= T(0.5);
00238     c[lenc] *= T(0.5);
00239     for (j = lenc - n; j <= lenc; j++) {
00240         c[j] *= h;
00241     }
00242     if (err > eref || errh > erefh) {
00243         err = -(err);
00244     } else {
00245         do {
00246             n -= 2;
00247             err += fabs(c[lenc - n]) + fabs(c[lenc - n + 1]);
00248         } while (err < eref && n > 2);
00249         n += 2;
00250         err = eref;
00251     }
00252     if (ba != 0) {
00253         c[3] = 1 / ba;
00254     } else {
00255         c[3] = 0;
00256     }
00257     c[2] = T(0.5) * (b + a);
00258     c[1] = n + T(0.5);
00259     c[0] = lenc + T(0.5);
00260 }
00261 
00262 
00263 }
00264 
00265 #endif

Generated on Tue Jun 24 13:26:54 2003 for NURBS++ by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002