polyr.c 8.9 KB

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