polmisc.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /* Square root, sine, cosine, and arctangent of polynomial.
  2. * See polyn.c for data structures and discussion.
  3. */
  4. #include <stdio.h>
  5. #include <math.h>
  6. #ifdef ANSIPROT
  7. extern double atan2 ( double, double );
  8. extern double sqrt ( double );
  9. extern double fabs ( double );
  10. extern double sin ( double );
  11. extern double cos ( double );
  12. extern void polclr ( double *a, int n );
  13. extern void polmov ( double *a, int na, double *b );
  14. extern void polmul ( double a[], int na, double b[], int nb, double c[] );
  15. extern void poladd ( double a[], int na, double b[], int nb, double c[] );
  16. extern void polsub ( double a[], int na, double b[], int nb, double c[] );
  17. extern int poldiv ( double a[], int na, double b[], int nb, double c[] );
  18. extern void polsbt ( double a[], int na, double b[], int nb, double c[] );
  19. extern void * malloc ( long );
  20. extern void free ( void * );
  21. #else
  22. double atan2(), sqrt(), fabs(), sin(), cos();
  23. void polclr(), polmov(), polsbt(), poladd(), polsub(), polmul();
  24. int poldiv();
  25. void * malloc();
  26. void free ();
  27. #endif
  28. /* Highest degree of polynomial to be handled
  29. by the polyn.c subroutine package. */
  30. #define N 16
  31. /* Highest degree actually initialized at runtime. */
  32. extern int MAXPOL;
  33. /* Taylor series coefficients for various functions
  34. */
  35. double patan[N+1] = {
  36. 0.0, 1.0, 0.0, -1.0/3.0, 0.0,
  37. 1.0/5.0, 0.0, -1.0/7.0, 0.0, 1.0/9.0, 0.0, -1.0/11.0,
  38. 0.0, 1.0/13.0, 0.0, -1.0/15.0, 0.0 };
  39. double psin[N+1] = {
  40. 0.0, 1.0, 0.0, -1.0/6.0, 0.0, 1.0/120.0, 0.0,
  41. -1.0/5040.0, 0.0, 1.0/362880.0, 0.0, -1.0/39916800.0,
  42. 0.0, 1.0/6227020800.0, 0.0, -1.0/1.307674368e12, 0.0};
  43. double pcos[N+1] = {
  44. 1.0, 0.0, -1.0/2.0, 0.0, 1.0/24.0, 0.0,
  45. -1.0/720.0, 0.0, 1.0/40320.0, 0.0, -1.0/3628800.0, 0.0,
  46. 1.0/479001600.0, 0.0, -1.0/8.7179291e10, 0.0, 1.0/2.0922789888e13};
  47. double pasin[N+1] = {
  48. 0.0, 1.0, 0.0, 1.0/6.0, 0.0,
  49. 3.0/40.0, 0.0, 15.0/336.0, 0.0, 105.0/3456.0, 0.0, 945.0/42240.0,
  50. 0.0, 10395.0/599040.0 , 0.0, 135135.0/9676800.0 , 0.0
  51. };
  52. /* Square root of 1 + x. */
  53. double psqrt[N+1] = {
  54. 1.0, 1./2., -1./8., 1./16., -5./128., 7./256., -21./1024., 33./2048.,
  55. -429./32768., 715./65536., -2431./262144., 4199./524288., -29393./4194304.,
  56. 52003./8388608., -185725./33554432., 334305./67108864.,
  57. -9694845./2147483648.};
  58. /* Arctangent of the ratio num/den of two polynomials.
  59. */
  60. void
  61. polatn( num, den, ans, nn )
  62. double num[], den[], ans[];
  63. int nn;
  64. {
  65. double a, t;
  66. double *polq, *polu, *polt;
  67. int i;
  68. if (nn > N)
  69. {
  70. mtherr ("polatn", OVERFLOW);
  71. return;
  72. }
  73. /* arctan( a + b ) = arctan(a) + arctan( b/(1 + ab + a**2) ) */
  74. t = num[0];
  75. a = den[0];
  76. if( (t == 0.0) && (a == 0.0 ) )
  77. {
  78. t = num[1];
  79. a = den[1];
  80. }
  81. t = atan2( t, a ); /* arctan(num/den), the ANSI argument order */
  82. polq = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  83. polu = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  84. polt = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  85. polclr( polq, MAXPOL );
  86. i = poldiv( den, nn, num, nn, polq );
  87. a = polq[0]; /* a */
  88. polq[0] = 0.0; /* b */
  89. polmov( polq, nn, polu ); /* b */
  90. /* Form the polynomial
  91. 1 + ab + a**2
  92. where a is a scalar. */
  93. for( i=0; i<=nn; i++ )
  94. polu[i] *= a;
  95. polu[0] += 1.0 + a * a;
  96. poldiv( polu, nn, polq, nn, polt ); /* divide into b */
  97. polsbt( polt, nn, patan, nn, polu ); /* arctan(b) */
  98. polu[0] += t; /* plus arctan(a) */
  99. polmov( polu, nn, ans );
  100. free( polt );
  101. free( polu );
  102. free( polq );
  103. }
  104. /* Square root of a polynomial.
  105. * Assumes the lowest degree nonzero term is dominant
  106. * and of even degree. An error message is given
  107. * if the Newton iteration does not converge.
  108. */
  109. void
  110. polsqt( pol, ans, nn )
  111. double pol[], ans[];
  112. int nn;
  113. {
  114. double t;
  115. double *x, *y;
  116. int i, n;
  117. #if 0
  118. double z[N+1];
  119. double u;
  120. #endif
  121. if (nn > N)
  122. {
  123. mtherr ("polatn", OVERFLOW);
  124. return;
  125. }
  126. x = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  127. y = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  128. polmov( pol, nn, x );
  129. polclr( y, MAXPOL );
  130. /* Find lowest degree nonzero term. */
  131. t = 0.0;
  132. for( n=0; n<nn; n++ )
  133. {
  134. if( x[n] != 0.0 )
  135. goto nzero;
  136. }
  137. polmov( y, nn, ans );
  138. return;
  139. nzero:
  140. if( n > 0 )
  141. {
  142. if (n & 1)
  143. {
  144. printf("error, sqrt of odd polynomial\n");
  145. return;
  146. }
  147. /* Divide by x^n. */
  148. y[n] = x[n];
  149. poldiv (y, nn, pol, N, x);
  150. }
  151. t = x[0];
  152. for( i=1; i<=nn; i++ )
  153. x[i] /= t;
  154. x[0] = 0.0;
  155. /* series development sqrt(1+x) = 1 + x / 2 - x**2 / 8 + x**3 / 16
  156. hopes that first (constant) term is greater than what follows */
  157. polsbt( x, nn, psqrt, nn, y);
  158. t = sqrt( t );
  159. for( i=0; i<=nn; i++ )
  160. y[i] *= t;
  161. /* If first nonzero coefficient was at degree n > 0, multiply by
  162. x^(n/2). */
  163. if (n > 0)
  164. {
  165. polclr (x, MAXPOL);
  166. x[n/2] = 1.0;
  167. polmul (x, nn, y, nn, y);
  168. }
  169. #if 0
  170. /* Newton iterations */
  171. for( n=0; n<10; n++ )
  172. {
  173. poldiv( y, nn, pol, nn, z );
  174. poladd( y, nn, z, nn, y );
  175. for( i=0; i<=nn; i++ )
  176. y[i] *= 0.5;
  177. for( i=0; i<=nn; i++ )
  178. {
  179. u = fabs( y[i] - z[i] );
  180. if( u > 1.0e-15 )
  181. goto more;
  182. }
  183. goto done;
  184. more: ;
  185. }
  186. printf( "square root did not converge\n" );
  187. done:
  188. #endif /* 0 */
  189. polmov( y, nn, ans );
  190. free( y );
  191. free( x );
  192. }
  193. /* Sine of a polynomial.
  194. * The computation uses
  195. * sin(a+b) = sin(a) cos(b) + cos(a) sin(b)
  196. * where a is the constant term of the polynomial and
  197. * b is the sum of the rest of the terms.
  198. * Since sin(b) and cos(b) are computed by series expansions,
  199. * the value of b should be small.
  200. */
  201. void
  202. polsin( x, y, nn )
  203. double x[], y[];
  204. int nn;
  205. {
  206. double a, sc;
  207. double *w, *c;
  208. int i;
  209. if (nn > N)
  210. {
  211. mtherr ("polatn", OVERFLOW);
  212. return;
  213. }
  214. w = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  215. c = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  216. polmov( x, nn, w );
  217. polclr( c, MAXPOL );
  218. polclr( y, nn );
  219. /* a, in the description, is x[0]. b is the polynomial x - x[0]. */
  220. a = w[0];
  221. /* c = cos (b) */
  222. w[0] = 0.0;
  223. polsbt( w, nn, pcos, nn, c );
  224. sc = sin(a);
  225. /* sin(a) cos (b) */
  226. for( i=0; i<=nn; i++ )
  227. c[i] *= sc;
  228. /* y = sin (b) */
  229. polsbt( w, nn, psin, nn, y );
  230. sc = cos(a);
  231. /* cos(a) sin(b) */
  232. for( i=0; i<=nn; i++ )
  233. y[i] *= sc;
  234. poladd( c, nn, y, nn, y );
  235. free( c );
  236. free( w );
  237. }
  238. /* Cosine of a polynomial.
  239. * The computation uses
  240. * cos(a+b) = cos(a) cos(b) - sin(a) sin(b)
  241. * where a is the constant term of the polynomial and
  242. * b is the sum of the rest of the terms.
  243. * Since sin(b) and cos(b) are computed by series expansions,
  244. * the value of b should be small.
  245. */
  246. void
  247. polcos( x, y, nn )
  248. double x[], y[];
  249. int nn;
  250. {
  251. double a, sc;
  252. double *w, *c;
  253. int i;
  254. double sin(), cos();
  255. if (nn > N)
  256. {
  257. mtherr ("polatn", OVERFLOW);
  258. return;
  259. }
  260. w = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  261. c = (double * )malloc( (MAXPOL+1) * sizeof (double) );
  262. polmov( x, nn, w );
  263. polclr( c, MAXPOL );
  264. polclr( y, nn );
  265. a = w[0];
  266. w[0] = 0.0;
  267. /* c = cos(b) */
  268. polsbt( w, nn, pcos, nn, c );
  269. sc = cos(a);
  270. /* cos(a) cos(b) */
  271. for( i=0; i<=nn; i++ )
  272. c[i] *= sc;
  273. /* y = sin(b) */
  274. polsbt( w, nn, psin, nn, y );
  275. sc = sin(a);
  276. /* sin(a) sin(b) */
  277. for( i=0; i<=nn; i++ )
  278. y[i] *= sc;
  279. polsub( y, nn, c, nn, y );
  280. free( c );
  281. free( w );
  282. }