123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /* cheby.c
- *
- * Program to calculate coefficients of the Chebyshev polynomial
- * expansion of a given input function. The algorithm computes
- * the discrete Fourier cosine transform of the function evaluated
- * at unevenly spaced points. Library routine chbevl.c uses the
- * coefficients to calculate an approximate value of the original
- * function.
- * -- S. L. Moshier
- */
- extern double PI; /* 3.14159... */
- extern double PIO2;
- double cosi[33] = {0.0,}; /* cosine array for Fourier transform */
- double func[65] = {0.0,}; /* values of the function */
- double cos(), log(), exp(), sqrt();
- main()
- {
- double c, r, s, t, x, y, z, temp;
- double low, high, dtemp;
- long n;
- int i, ii, j, n2, k, rr, invflg;
- short *p;
- char st[40];
- low = 0.0; /* low end of approximation interval */
- high = 1.0; /* high end */
- invflg = 0; /* set to 1 if inverted interval, else zero */
- /* Note: inverted interval goes from 1/high to 1/low */
- z = 0.0;
- n = 64; /* will find 64 coefficients */
- /* but use only those greater than roundoff error */
- n2 = n/2;
- t = n;
- t = PI/t;
- /* calculate array of cosines */
- puts("calculating cosines");
- s = 1.0;
- cosi[0] = 1.0;
- i = 1;
- while( i < 32 )
- {
- y = cos( s * t );
- cosi[i] = y;
- s += 1.0;
- ++i;
- }
- cosi[32] = 0.0;
- /* cheby.c 2 */
- /* calculate function at special values of the argument */
- puts("calculating function values");
- x = low;
- y = high;
- if( invflg && (low != 0.0) )
- { /* inverted interval */
- temp = 1.0/x;
- x = 1.0/y;
- y = temp;
- }
- r = (x + y)/2.0;
- printf( "center %.15E ", r);
- s = (y - x)/2.0;
- printf( "width %.15E\n", s);
- i = 0;
- while( i < 65 )
- {
- if( i < n2 )
- c = cosi[i];
- else
- c = -cosi[64-i];
- temp = r + s * c;
- /* if inverted interval, compute function(1/x) */
- if( invflg && (temp != 0.0) )
- temp = 1.0/temp;
- printf( "%.15E ", temp );
- /* insert call to function routine here: */
- /**********************************/
- if( temp == 0.0 )
- y = 1.0;
- else
- y = exp( temp * log(2.0) );
- /**********************************/
- func[i] = y;
- printf( "%.15E\n", y );
- ++i;
- }
- /* cheby.c 3 */
- puts( "calculating Chebyshev coefficients");
- rr = 0;
- while( rr < 65 )
- {
- z = func[0]/2.0;
- j = 1;
- while( j < 65 )
- {
- k = (rr * j)/n2;
- i = rr * j - n2 * k;
- k &= 3;
- if( k == 0 )
- c = cosi[i];
- if( k == 1 )
- {
- i = 32-i;
- c = -cosi[i];
- if( i == 32 )
- c = -c;
- }
- if( k == 2 )
- {
- c = -cosi[i];
- }
- if( k == 3 )
- {
- i = 32-i;
- c = cosi[i];
- }
- if( i != 32)
- {
- temp = func[j];
- temp = c * temp;
- z += temp;
- }
- ++j;
- }
- if( i != 32 )
- {
- temp /= 2.0;
- z = z - temp;
- }
- z *= 2.0;
- temp = n;
- z /= temp;
- dtemp = z;
- ++rr;
- sprintf( st, "/* %.16E */", dtemp );
- puts( st );
- }
- }
|