cheby.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* cheby.c
  2. *
  3. * Program to calculate coefficients of the Chebyshev polynomial
  4. * expansion of a given input function. The algorithm computes
  5. * the discrete Fourier cosine transform of the function evaluated
  6. * at unevenly spaced points. Library routine chbevl.c uses the
  7. * coefficients to calculate an approximate value of the original
  8. * function.
  9. * -- S. L. Moshier
  10. */
  11. extern double PI; /* 3.14159... */
  12. extern double PIO2;
  13. double cosi[33] = {0.0,}; /* cosine array for Fourier transform */
  14. double func[65] = {0.0,}; /* values of the function */
  15. double cos(), log(), exp(), sqrt();
  16. main()
  17. {
  18. double c, r, s, t, x, y, z, temp;
  19. double low, high, dtemp;
  20. long n;
  21. int i, ii, j, n2, k, rr, invflg;
  22. short *p;
  23. char st[40];
  24. low = 0.0; /* low end of approximation interval */
  25. high = 1.0; /* high end */
  26. invflg = 0; /* set to 1 if inverted interval, else zero */
  27. /* Note: inverted interval goes from 1/high to 1/low */
  28. z = 0.0;
  29. n = 64; /* will find 64 coefficients */
  30. /* but use only those greater than roundoff error */
  31. n2 = n/2;
  32. t = n;
  33. t = PI/t;
  34. /* calculate array of cosines */
  35. puts("calculating cosines");
  36. s = 1.0;
  37. cosi[0] = 1.0;
  38. i = 1;
  39. while( i < 32 )
  40. {
  41. y = cos( s * t );
  42. cosi[i] = y;
  43. s += 1.0;
  44. ++i;
  45. }
  46. cosi[32] = 0.0;
  47. /* cheby.c 2 */
  48. /* calculate function at special values of the argument */
  49. puts("calculating function values");
  50. x = low;
  51. y = high;
  52. if( invflg && (low != 0.0) )
  53. { /* inverted interval */
  54. temp = 1.0/x;
  55. x = 1.0/y;
  56. y = temp;
  57. }
  58. r = (x + y)/2.0;
  59. printf( "center %.15E ", r);
  60. s = (y - x)/2.0;
  61. printf( "width %.15E\n", s);
  62. i = 0;
  63. while( i < 65 )
  64. {
  65. if( i < n2 )
  66. c = cosi[i];
  67. else
  68. c = -cosi[64-i];
  69. temp = r + s * c;
  70. /* if inverted interval, compute function(1/x) */
  71. if( invflg && (temp != 0.0) )
  72. temp = 1.0/temp;
  73. printf( "%.15E ", temp );
  74. /* insert call to function routine here: */
  75. /**********************************/
  76. if( temp == 0.0 )
  77. y = 1.0;
  78. else
  79. y = exp( temp * log(2.0) );
  80. /**********************************/
  81. func[i] = y;
  82. printf( "%.15E\n", y );
  83. ++i;
  84. }
  85. /* cheby.c 3 */
  86. puts( "calculating Chebyshev coefficients");
  87. rr = 0;
  88. while( rr < 65 )
  89. {
  90. z = func[0]/2.0;
  91. j = 1;
  92. while( j < 65 )
  93. {
  94. k = (rr * j)/n2;
  95. i = rr * j - n2 * k;
  96. k &= 3;
  97. if( k == 0 )
  98. c = cosi[i];
  99. if( k == 1 )
  100. {
  101. i = 32-i;
  102. c = -cosi[i];
  103. if( i == 32 )
  104. c = -c;
  105. }
  106. if( k == 2 )
  107. {
  108. c = -cosi[i];
  109. }
  110. if( k == 3 )
  111. {
  112. i = 32-i;
  113. c = cosi[i];
  114. }
  115. if( i != 32)
  116. {
  117. temp = func[j];
  118. temp = c * temp;
  119. z += temp;
  120. }
  121. ++j;
  122. }
  123. if( i != 32 )
  124. {
  125. temp /= 2.0;
  126. z = z - temp;
  127. }
  128. z *= 2.0;
  129. temp = n;
  130. z /= temp;
  131. dtemp = z;
  132. ++rr;
  133. sprintf( st, "/* %.16E */", dtemp );
  134. puts( st );
  135. }
  136. }