polyn.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /* polyn.c
  2. * polyr.c
  3. * Arithmetic operations on polynomials
  4. *
  5. * In the following descriptions a, b, c are polynomials of degree
  6. * na, nb, nc respectively. The degree of a polynomial cannot
  7. * exceed a run-time value MAXPOL. An operation that attempts
  8. * to use or generate a polynomial of higher degree may produce a
  9. * result that suffers truncation at degree MAXPOL. The value of
  10. * MAXPOL is set by calling the function
  11. *
  12. * polini( maxpol );
  13. *
  14. * where maxpol is the desired maximum degree. This must be
  15. * done prior to calling any of the other functions in this module.
  16. * Memory for internal temporary polynomial storage is allocated
  17. * by polini().
  18. *
  19. * Each polynomial is represented by an array containing its
  20. * coefficients, together with a separately declared integer equal
  21. * to the degree of the polynomial. The coefficients appear in
  22. * ascending order; that is,
  23. *
  24. * 2 na
  25. * a(x) = a[0] + a[1] * x + a[2] * x + ... + a[na] * x .
  26. *
  27. *
  28. *
  29. * sum = poleva( a, na, x ); Evaluate polynomial a(t) at t = x.
  30. * polprt( a, na, D ); Print the coefficients of a to D digits.
  31. * polclr( a, na ); Set a identically equal to zero, up to a[na].
  32. * polmov( a, na, b ); Set b = a.
  33. * poladd( a, na, b, nb, c ); c = b + a, nc = max(na,nb)
  34. * polsub( a, na, b, nb, c ); c = b - a, nc = max(na,nb)
  35. * polmul( a, na, b, nb, c ); c = b * a, nc = na+nb
  36. *
  37. *
  38. * Division:
  39. *
  40. * i = poldiv( a, na, b, nb, c ); c = b / a, nc = MAXPOL
  41. *
  42. * returns i = the degree of the first nonzero coefficient of a.
  43. * The computed quotient c must be divided by x^i. An error message
  44. * is printed if a is identically zero.
  45. *
  46. *
  47. * Change of variables:
  48. * If a and b are polynomials, and t = a(x), then
  49. * c(t) = b(a(x))
  50. * is a polynomial found by substituting a(x) for t. The
  51. * subroutine call for this is
  52. *
  53. * polsbt( a, na, b, nb, c );
  54. *
  55. *
  56. * Notes:
  57. * poldiv() is an integer routine; poleva() is double.
  58. * Any of the arguments a, b, c may refer to the same array.
  59. *
  60. */
  61. #include <stdio.h>
  62. #include <math.h>
  63. #if ANSIPROT
  64. void exit (int);
  65. extern void * malloc ( long );
  66. extern void free ( void * );
  67. void polclr ( double *, int );
  68. void polmov ( double *, int, double * );
  69. void polmul ( double *, int, double *, int, double * );
  70. int poldiv ( double *, int, double *, int, double * );
  71. #else
  72. void exit();
  73. void * malloc();
  74. void free ();
  75. void polclr(), polmov(), poldiv(), polmul();
  76. #endif
  77. #ifndef NULL
  78. #define NULL 0
  79. #endif
  80. /* near pointer version of malloc() */
  81. /*
  82. #define malloc _nmalloc
  83. #define free _nfree
  84. */
  85. /* Pointers to internal arrays. Note poldiv() allocates
  86. * and deallocates some temporary arrays every time it is called.
  87. */
  88. static double *pt1 = 0;
  89. static double *pt2 = 0;
  90. static double *pt3 = 0;
  91. /* Maximum degree of polynomial. */
  92. int MAXPOL = 0;
  93. extern int MAXPOL;
  94. /* Number of bytes (chars) in maximum size polynomial. */
  95. static int psize = 0;
  96. /* Initialize max degree of polynomials
  97. * and allocate temporary storage.
  98. */
  99. void polini( maxdeg )
  100. int maxdeg;
  101. {
  102. MAXPOL = maxdeg;
  103. psize = (maxdeg + 1) * sizeof(double);
  104. /* Release previously allocated memory, if any. */
  105. if( pt3 )
  106. free(pt3);
  107. if( pt2 )
  108. free(pt2);
  109. if( pt1 )
  110. free(pt1);
  111. /* Allocate new arrays */
  112. pt1 = (double * )malloc(psize); /* used by polsbt */
  113. pt2 = (double * )malloc(psize); /* used by polsbt */
  114. pt3 = (double * )malloc(psize); /* used by polmul */
  115. /* Report if failure */
  116. if( (pt1 == NULL) || (pt2 == NULL) || (pt3 == NULL) )
  117. {
  118. mtherr( "polini", ERANGE );
  119. exit(1);
  120. }
  121. }
  122. /* Print the coefficients of a, with d decimal precision.
  123. */
  124. static char *form = "abcdefghijk";
  125. void polprt( a, na, d )
  126. double a[];
  127. int na, d;
  128. {
  129. int i, j, d1;
  130. char *p;
  131. /* Create format descriptor string for the printout.
  132. * Do this partly by hand, since sprintf() may be too
  133. * bug-ridden to accomplish this feat by itself.
  134. */
  135. p = form;
  136. *p++ = '%';
  137. d1 = d + 8;
  138. sprintf( p, "%d ", d1 );
  139. p += 1;
  140. if( d1 >= 10 )
  141. p += 1;
  142. *p++ = '.';
  143. sprintf( p, "%d ", d );
  144. p += 1;
  145. if( d >= 10 )
  146. p += 1;
  147. *p++ = 'e';
  148. *p++ = ' ';
  149. *p++ = '\0';
  150. /* Now do the printing.
  151. */
  152. d1 += 1;
  153. j = 0;
  154. for( i=0; i<=na; i++ )
  155. {
  156. /* Detect end of available line */
  157. j += d1;
  158. if( j >= 78 )
  159. {
  160. printf( "\n" );
  161. j = d1;
  162. }
  163. printf( form, a[i] );
  164. }
  165. printf( "\n" );
  166. }
  167. /* Set a = 0.
  168. */
  169. void polclr( a, n )
  170. register double *a;
  171. int n;
  172. {
  173. int i;
  174. if( n > MAXPOL )
  175. n = MAXPOL;
  176. for( i=0; i<=n; i++ )
  177. *a++ = 0.0;
  178. }
  179. /* Set b = a.
  180. */
  181. void polmov( a, na, b )
  182. register double *a, *b;
  183. int na;
  184. {
  185. int i;
  186. if( na > MAXPOL )
  187. na = MAXPOL;
  188. for( i=0; i<= na; i++ )
  189. {
  190. *b++ = *a++;
  191. }
  192. }
  193. /* c = b * a.
  194. */
  195. void polmul( a, na, b, nb, c )
  196. double a[], b[], c[];
  197. int na, nb;
  198. {
  199. int i, j, k, nc;
  200. double x;
  201. nc = na + nb;
  202. polclr( pt3, MAXPOL );
  203. for( i=0; i<=na; i++ )
  204. {
  205. x = a[i];
  206. for( j=0; j<=nb; j++ )
  207. {
  208. k = i + j;
  209. if( k > MAXPOL )
  210. break;
  211. pt3[k] += x * b[j];
  212. }
  213. }
  214. if( nc > MAXPOL )
  215. nc = MAXPOL;
  216. for( i=0; i<=nc; i++ )
  217. c[i] = pt3[i];
  218. }
  219. /* c = b + a.
  220. */
  221. void poladd( a, na, b, nb, c )
  222. double a[], b[], c[];
  223. int na, nb;
  224. {
  225. int i, n;
  226. if( na > nb )
  227. n = na;
  228. else
  229. n = nb;
  230. if( n > MAXPOL )
  231. n = MAXPOL;
  232. for( i=0; i<=n; i++ )
  233. {
  234. if( i > na )
  235. c[i] = b[i];
  236. else if( i > nb )
  237. c[i] = a[i];
  238. else
  239. c[i] = b[i] + a[i];
  240. }
  241. }
  242. /* c = b - a.
  243. */
  244. void polsub( a, na, b, nb, c )
  245. double a[], b[], c[];
  246. int na, nb;
  247. {
  248. int i, n;
  249. if( na > nb )
  250. n = na;
  251. else
  252. n = nb;
  253. if( n > MAXPOL )
  254. n = MAXPOL;
  255. for( i=0; i<=n; i++ )
  256. {
  257. if( i > na )
  258. c[i] = b[i];
  259. else if( i > nb )
  260. c[i] = -a[i];
  261. else
  262. c[i] = b[i] - a[i];
  263. }
  264. }
  265. /* c = b/a
  266. */
  267. int poldiv( a, na, b, nb, c )
  268. double a[], b[], c[];
  269. int na, nb;
  270. {
  271. double quot;
  272. double *ta, *tb, *tq;
  273. int i, j, k, sing;
  274. sing = 0;
  275. /* Allocate temporary arrays. This would be quicker
  276. * if done automatically on the stack, but stack space
  277. * may be hard to obtain on a small computer.
  278. */
  279. ta = (double * )malloc( psize );
  280. polclr( ta, MAXPOL );
  281. polmov( a, na, ta );
  282. tb = (double * )malloc( psize );
  283. polclr( tb, MAXPOL );
  284. polmov( b, nb, tb );
  285. tq = (double * )malloc( psize );
  286. polclr( tq, MAXPOL );
  287. /* What to do if leading (constant) coefficient
  288. * of denominator is zero.
  289. */
  290. if( a[0] == 0.0 )
  291. {
  292. for( i=0; i<=na; i++ )
  293. {
  294. if( ta[i] != 0.0 )
  295. goto nzero;
  296. }
  297. mtherr( "poldiv", SING );
  298. goto done;
  299. nzero:
  300. /* Reduce the degree of the denominator. */
  301. for( i=0; i<na; i++ )
  302. ta[i] = ta[i+1];
  303. ta[na] = 0.0;
  304. if( b[0] != 0.0 )
  305. {
  306. /* Optional message:
  307. printf( "poldiv singularity, divide quotient by x\n" );
  308. */
  309. sing += 1;
  310. }
  311. else
  312. {
  313. /* Reduce degree of numerator. */
  314. for( i=0; i<nb; i++ )
  315. tb[i] = tb[i+1];
  316. tb[nb] = 0.0;
  317. }
  318. /* Call self, using reduced polynomials. */
  319. sing += poldiv( ta, na, tb, nb, c );
  320. goto done;
  321. }
  322. /* Long division algorithm. ta[0] is nonzero.
  323. */
  324. for( i=0; i<=MAXPOL; i++ )
  325. {
  326. quot = tb[i]/ta[0];
  327. for( j=0; j<=MAXPOL; j++ )
  328. {
  329. k = j + i;
  330. if( k > MAXPOL )
  331. break;
  332. tb[k] -= quot * ta[j];
  333. }
  334. tq[i] = quot;
  335. }
  336. /* Send quotient to output array. */
  337. polmov( tq, MAXPOL, c );
  338. done:
  339. /* Restore allocated memory. */
  340. free(tq);
  341. free(tb);
  342. free(ta);
  343. return( sing );
  344. }
  345. /* Change of variables
  346. * Substitute a(y) for the variable x in b(x).
  347. * x = a(y)
  348. * c(x) = b(x) = b(a(y)).
  349. */
  350. void polsbt( a, na, b, nb, c )
  351. double a[], b[], c[];
  352. int na, nb;
  353. {
  354. int i, j, k, n2;
  355. double x;
  356. /* 0th degree term:
  357. */
  358. polclr( pt1, MAXPOL );
  359. pt1[0] = b[0];
  360. polclr( pt2, MAXPOL );
  361. pt2[0] = 1.0;
  362. n2 = 0;
  363. for( i=1; i<=nb; i++ )
  364. {
  365. /* Form ith power of a. */
  366. polmul( a, na, pt2, n2, pt2 );
  367. n2 += na;
  368. x = b[i];
  369. /* Add the ith coefficient of b times the ith power of a. */
  370. for( j=0; j<=n2; j++ )
  371. {
  372. if( j > MAXPOL )
  373. break;
  374. pt1[j] += x * pt2[j];
  375. }
  376. }
  377. k = n2 + nb;
  378. if( k > MAXPOL )
  379. k = MAXPOL;
  380. for( i=0; i<=k; i++ )
  381. c[i] = pt1[i];
  382. }
  383. /* Evaluate polynomial a(t) at t = x.
  384. */
  385. double poleva( a, na, x )
  386. double a[];
  387. int na;
  388. double x;
  389. {
  390. double s;
  391. int i;
  392. s = a[na];
  393. for( i=na-1; i>=0; i-- )
  394. {
  395. s = s * x + a[i];
  396. }
  397. return(s);
  398. }