Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

838 lines
21 KiB

  1. //----------------------------------------------------------------------------
  2. // Package Title ratpak
  3. // File support.c
  4. // Author Timothy David Corrie Jr. ([email protected])
  5. // Copyright (C) 1995-96 Microsoft
  6. // Date 10-21-96
  7. //
  8. //
  9. // Description
  10. //
  11. // Contains support functions for rationals and numbers.
  12. //
  13. // Special Information
  14. //
  15. //
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #if defined( DOS )
  22. #include <dosstub.h>
  23. #else
  24. #include <windows.h>
  25. #endif
  26. #include <ratpak.h>
  27. BOOL fhalt;
  28. LINKEDLIST gllfact;
  29. void _readconstants( void );
  30. #if defined( GEN_CONST )
  31. void _dumprawrat( TCHAR *varname, PRAT rat );
  32. void _dumprawnum( PNUMBER num );
  33. static cbitsofprecision = 0;
  34. #define READRAWRAT(v)
  35. #define READRAWNUM(v)
  36. #define DUMPRAWRAT(v) _dumprawrat(#v,v)
  37. #define DUMPRAWNUM(v) fprintf( stderr, \
  38. "// Autogenerated by _dumprawrat in support.c\n" ); \
  39. fprintf( stderr, "NUMBER init_" #v "= {\n" ); \
  40. _dumprawnum(v); \
  41. fprintf( stderr, "};\n" )
  42. #else
  43. #define DUMPRAWRAT(v)
  44. #define DUMPRAWNUM(v)
  45. #define READRAWRAT(v) createrat(v); DUPNUM(v->pp,(&(init_p_##v))); \
  46. DUPNUM(v->pq,(&(init_q_##v)));
  47. #define READRAWNUM(v) DUPNUM(v,(&(init_##v)))
  48. #define RATIO_FOR_DECIMAL 9
  49. #define DECIMAL 10
  50. #define CALC_DECIMAL_DIGITS_DEFAULT 32
  51. static cbitsofprecision = RATIO_FOR_DECIMAL * DECIMAL *
  52. CALC_DECIMAL_DIGITS_DEFAULT;
  53. #include <ratconst.h>
  54. #endif
  55. unsigned char ftrueinfinite = FALSE; // Set to true if you don't want
  56. // chopping internally
  57. long maxout; // precision used internally
  58. PNUMBER num_one=NULL;
  59. PNUMBER num_two=NULL;
  60. PNUMBER num_five=NULL;
  61. PNUMBER num_six=NULL;
  62. PNUMBER num_ten=NULL;
  63. PNUMBER num_nRadix=NULL;
  64. PRAT ln_ten=NULL;
  65. PRAT ln_two=NULL;
  66. PRAT rat_zero=NULL;
  67. PRAT rat_one=NULL;
  68. PRAT rat_neg_one=NULL;
  69. PRAT rat_two=NULL;
  70. PRAT rat_six=NULL;
  71. PRAT rat_half=NULL;
  72. PRAT rat_ten=NULL;
  73. PRAT pt_eight_five=NULL;
  74. PRAT pi=NULL;
  75. PRAT pi_over_two=NULL;
  76. PRAT two_pi=NULL;
  77. PRAT one_pt_five_pi=NULL;
  78. PRAT e_to_one_half=NULL;
  79. PRAT rat_exp=NULL;
  80. PRAT rad_to_deg=NULL;
  81. PRAT rad_to_grad=NULL;
  82. PRAT rat_qword=NULL;
  83. PRAT rat_dword=NULL;
  84. PRAT rat_word=NULL;
  85. PRAT rat_byte=NULL;
  86. PRAT rat_360=NULL;
  87. PRAT rat_400=NULL;
  88. PRAT rat_180=NULL;
  89. PRAT rat_200=NULL;
  90. PRAT rat_nRadix=NULL;
  91. PRAT rat_smallest=NULL;
  92. PRAT rat_negsmallest=NULL;
  93. PRAT rat_max_exp=NULL;
  94. PRAT rat_min_exp=NULL;
  95. PRAT rat_min_long=NULL;
  96. //----------------------------------------------------------------------------
  97. //
  98. // FUNCTION: ChangeRadix
  99. //
  100. // ARGUMENTS: base changing to, and precision to use.
  101. //
  102. // RETURN: None
  103. //
  104. // SIDE EFFECTS: sets a mess of constants.
  105. //
  106. //
  107. //----------------------------------------------------------------------------
  108. void changeRadix( long nRadix )
  109. {
  110. ChangeConstants( nRadix, maxout );
  111. }
  112. //----------------------------------------------------------------------------
  113. //
  114. // FUNCTION: changePrecision
  115. //
  116. // ARGUMENTS: Precision to use
  117. //
  118. // RETURN: None
  119. //
  120. // SIDE EFFECTS: sets a mess of constants.
  121. //
  122. //
  123. //----------------------------------------------------------------------------
  124. void changePrecision( long nPrecision )
  125. {
  126. ChangeConstants( nRadix, nPrecision );
  127. }
  128. //----------------------------------------------------------------------------
  129. //
  130. // FUNCTION: ChangeConstants
  131. //
  132. // ARGUMENTS: base changing to, and precision to use.
  133. //
  134. // RETURN: None
  135. //
  136. // SIDE EFFECTS: sets a mess of constants.
  137. //
  138. //
  139. //----------------------------------------------------------------------------
  140. void ChangeConstants( long nRadix, long nPrecision )
  141. {
  142. long digit;
  143. DWORD dwLim;
  144. maxout = nPrecision;
  145. fhalt = FALSE;
  146. // ratio is set to the number of digits in the current nRadix, you can get
  147. // in the internal BASEX nRadix, this is important for length calculations
  148. // in translating from nRadix to BASEX and back.
  149. dwLim = (DWORD)BASEX / (DWORD)nRadix;
  150. for ( digit = 1, ratio = 0; (DWORD)digit < dwLim; digit *= nRadix )
  151. {
  152. ratio++;
  153. }
  154. ratio += !ratio;
  155. destroynum(num_nRadix);
  156. num_nRadix=longtonum( nRadix, BASEX );
  157. destroyrat(rat_nRadix);
  158. rat_nRadix=longtorat( nRadix );
  159. // Check to see what we have to recalculate and what we don't
  160. if ( cbitsofprecision < ( ratio * nRadix * nPrecision ) )
  161. {
  162. ftrueinfinite=FALSE;
  163. num_one=longtonum( 1L, BASEX );
  164. DUMPRAWNUM(num_one);
  165. num_two=longtonum( 2L, BASEX );
  166. DUMPRAWNUM(num_two);
  167. num_five=longtonum( 5L, BASEX );
  168. DUMPRAWNUM(num_five);
  169. num_six=longtonum( 6L, BASEX );
  170. DUMPRAWNUM(num_six);
  171. num_ten=longtonum( 10L, BASEX );
  172. DUMPRAWNUM(num_ten);
  173. DUPRAT(rat_smallest,rat_nRadix);
  174. ratpowlong(&rat_smallest,-nPrecision);
  175. DUPRAT(rat_negsmallest,rat_smallest);
  176. rat_negsmallest->pp->sign = -1;
  177. DUMPRAWRAT(rat_smallest);
  178. DUMPRAWRAT(rat_negsmallest);
  179. createrat( rat_half );
  180. createrat( pt_eight_five );
  181. pt_eight_five->pp=longtonum( 85L, BASEX );
  182. pt_eight_five->pq=longtonum( 100L, BASEX );
  183. DUMPRAWRAT(pt_eight_five);
  184. rat_six = longtorat( 6L );
  185. DUMPRAWRAT(rat_six);
  186. rat_two=longtorat( 2L );
  187. DUMPRAWRAT(rat_two);
  188. rat_zero=longtorat( 0L );
  189. DUMPRAWRAT(rat_zero);
  190. rat_one=longtorat( 1L );
  191. DUMPRAWRAT(rat_one);
  192. rat_neg_one=longtorat( -1L );
  193. DUMPRAWRAT(rat_neg_one);
  194. DUPNUM(rat_half->pp,num_one);
  195. DUPNUM(rat_half->pq,num_two);
  196. DUMPRAWRAT(rat_half);
  197. rat_ten=longtorat( 10L );
  198. DUMPRAWRAT(rat_ten);
  199. // Apparently when dividing 180 by pi, another (internal) digit of
  200. // precision is needed.
  201. maxout += ratio;
  202. DUPRAT(pi,rat_half);
  203. asinrat( &pi );
  204. mulrat( &pi, rat_six );
  205. DUMPRAWRAT(pi);
  206. DUPRAT(two_pi,pi);
  207. DUPRAT(pi_over_two,pi);
  208. DUPRAT(one_pt_five_pi,pi);
  209. addrat(&two_pi,pi);
  210. DUMPRAWRAT(two_pi);
  211. divrat(&pi_over_two,rat_two);
  212. DUMPRAWRAT(pi_over_two);
  213. addrat(&one_pt_five_pi,pi_over_two);
  214. DUMPRAWRAT(one_pt_five_pi);
  215. DUPRAT(e_to_one_half,rat_half);
  216. _exprat(&e_to_one_half);
  217. DUMPRAWRAT(e_to_one_half);
  218. DUPRAT(rat_exp,rat_one);
  219. _exprat(&rat_exp);
  220. DUMPRAWRAT(rat_exp);
  221. // WARNING: remember lograt uses exponent constants calculated above...
  222. DUPRAT(ln_ten,rat_ten);
  223. lograt( &ln_ten );
  224. DUMPRAWRAT(ln_ten);
  225. DUPRAT(ln_two,rat_two);
  226. lograt(&ln_two);
  227. DUMPRAWRAT(ln_two);
  228. destroyrat(rad_to_deg);
  229. rad_to_deg=longtorat(180L);
  230. divrat(&rad_to_deg,pi);
  231. DUMPRAWRAT(rad_to_deg);
  232. destroyrat(rad_to_grad);
  233. rad_to_grad=longtorat(200L);
  234. divrat(&rad_to_grad,pi);
  235. DUMPRAWRAT(rad_to_grad);
  236. maxout -= ratio;
  237. DUPRAT(rat_qword,rat_two);
  238. numpowlong( &(rat_qword->pp), 64, BASEX );
  239. subrat( &rat_qword, rat_one );
  240. DUMPRAWRAT(rat_qword);
  241. DUPRAT(rat_dword,rat_two);
  242. numpowlong( &(rat_dword->pp), 32, BASEX );
  243. subrat( &rat_dword, rat_one );
  244. DUMPRAWRAT(rat_dword);
  245. DUPRAT(rat_min_long,rat_dword);
  246. rat_min_long->pp->sign *= -1;
  247. DUMPRAWRAT(rat_min_long);
  248. rat_word = longtorat( 0xffff );
  249. DUMPRAWRAT(rat_word);
  250. rat_byte = longtorat( 0xff );
  251. DUMPRAWRAT(rat_byte);
  252. rat_400 = longtorat( 400 );
  253. DUMPRAWRAT(rat_400);
  254. rat_360 = longtorat( 360 );
  255. DUMPRAWRAT(rat_360);
  256. rat_200 = longtorat( 200 );
  257. DUMPRAWRAT(rat_200);
  258. rat_180 = longtorat( 180 );
  259. DUMPRAWRAT(rat_180);
  260. rat_max_exp = longtorat( 100000 );
  261. DUPRAT(rat_min_exp,rat_max_exp);
  262. rat_min_exp->pp->sign *= -1;
  263. DUMPRAWRAT(rat_max_exp);
  264. DUMPRAWRAT(rat_min_exp);
  265. cbitsofprecision = ratio * nRadix * nPrecision;
  266. }
  267. else
  268. {
  269. _readconstants();
  270. DUPRAT(rat_smallest,rat_nRadix);
  271. ratpowlong(&rat_smallest,-nPrecision);
  272. DUPRAT(rat_negsmallest,rat_smallest);
  273. rat_negsmallest->pp->sign = -1;
  274. }
  275. }
  276. //----------------------------------------------------------------------------
  277. //
  278. // FUNCTION: intrat
  279. //
  280. // ARGUMENTS: pointer to x PRAT representation of number
  281. //
  282. // RETURN: no return value x PRAT is smashed with integral number
  283. //
  284. //
  285. //----------------------------------------------------------------------------
  286. void intrat( PRAT *px)
  287. {
  288. PRAT pret=NULL;
  289. PNUMBER pnum=NULL;
  290. TCHAR *psz;
  291. // Only do the intrat operation if number is nonzero.
  292. // and only if the bottom part is not one.
  293. if ( !zernum( (*px)->pp ) && !equnum( (*px)->pq, num_one ) )
  294. {
  295. psz=putrat( NULL, px, nRadix, FMT_FLOAT );
  296. pnum = innum( psz );
  297. zfree( psz );
  298. destroyrat( *px );
  299. *px = numtorat( pnum, nRadix );
  300. destroynum( pnum );
  301. DUPRAT(pret,*px);
  302. modrat( &pret, rat_one );
  303. subrat( px, pret );
  304. destroyrat( pret );
  305. }
  306. }
  307. //---------------------------------------------------------------------------
  308. //
  309. // FUNCTION: rat_equ
  310. //
  311. // ARGUMENTS: PRAT a and PRAT b
  312. //
  313. // RETURN: TRUE if equal FALSE otherwise.
  314. //
  315. //
  316. //---------------------------------------------------------------------------
  317. BOOL rat_equ( PRAT a, PRAT b )
  318. {
  319. PRAT rattmp=NULL;
  320. BOOL bret;
  321. DUPRAT(rattmp,a);
  322. rattmp->pp->sign *= -1;
  323. addrat( &rattmp, b );
  324. bret = zernum( rattmp->pp );
  325. destroyrat( rattmp );
  326. return( bret );
  327. }
  328. //---------------------------------------------------------------------------
  329. //
  330. // FUNCTION: rat_ge
  331. //
  332. // ARGUMENTS: PRAT a and PRAT b
  333. //
  334. // RETURN: TRUE if a is greater than or equal to b
  335. //
  336. //
  337. //---------------------------------------------------------------------------
  338. BOOL rat_ge( PRAT a, PRAT b )
  339. {
  340. PRAT rattmp=NULL;
  341. BOOL bret;
  342. DUPRAT(rattmp,a);
  343. b->pp->sign *= -1;
  344. addrat( &rattmp, b );
  345. b->pp->sign *= -1;
  346. bret = ( zernum( rattmp->pp ) ||
  347. rattmp->pp->sign * rattmp->pq->sign == 1 );
  348. destroyrat( rattmp );
  349. return( bret );
  350. }
  351. //---------------------------------------------------------------------------
  352. //
  353. // FUNCTION: rat_gt
  354. //
  355. // ARGUMENTS: PRAT a and PRAT b
  356. //
  357. // RETURN: TRUE if a is greater than b
  358. //
  359. //
  360. //---------------------------------------------------------------------------
  361. BOOL rat_gt( PRAT a, PRAT b )
  362. {
  363. PRAT rattmp=NULL;
  364. BOOL bret;
  365. DUPRAT(rattmp,a);
  366. b->pp->sign *= -1;
  367. addrat( &rattmp, b );
  368. b->pp->sign *= -1;
  369. bret = ( !zernum( rattmp->pp ) &&
  370. rattmp->pp->sign * rattmp->pq->sign == 1 );
  371. destroyrat( rattmp );
  372. return( bret );
  373. }
  374. //---------------------------------------------------------------------------
  375. //
  376. // FUNCTION: rat_le
  377. //
  378. // ARGUMENTS: PRAT a and PRAT b
  379. //
  380. // RETURN: TRUE if a is less than or equal to b
  381. //
  382. //
  383. //---------------------------------------------------------------------------
  384. BOOL rat_le( PRAT a, PRAT b )
  385. {
  386. PRAT rattmp=NULL;
  387. BOOL bret;
  388. DUPRAT(rattmp,a);
  389. b->pp->sign *= -1;
  390. addrat( &rattmp, b );
  391. b->pp->sign *= -1;
  392. bret = ( zernum( rattmp->pp ) ||
  393. rattmp->pp->sign * rattmp->pq->sign == -1 );
  394. destroyrat( rattmp );
  395. return( bret );
  396. }
  397. //---------------------------------------------------------------------------
  398. //
  399. // FUNCTION: rat_lt
  400. //
  401. // ARGUMENTS: PRAT a and PRAT b
  402. //
  403. // RETURN: TRUE if a is less than b
  404. //
  405. //
  406. //---------------------------------------------------------------------------
  407. BOOL rat_lt( PRAT a, PRAT b )
  408. {
  409. PRAT rattmp=NULL;
  410. BOOL bret;
  411. DUPRAT(rattmp,a);
  412. b->pp->sign *= -1;
  413. addrat( &rattmp, b );
  414. b->pp->sign *= -1;
  415. bret = ( !zernum( rattmp->pp ) &&
  416. rattmp->pp->sign * rattmp->pq->sign == -1 );
  417. destroyrat( rattmp );
  418. return( bret );
  419. }
  420. //---------------------------------------------------------------------------
  421. //
  422. // FUNCTION: rat_neq
  423. //
  424. // ARGUMENTS: PRAT a and PRAT b
  425. //
  426. // RETURN: TRUE if a is not equal to b
  427. //
  428. //
  429. //---------------------------------------------------------------------------
  430. BOOL rat_neq( PRAT a, PRAT b )
  431. {
  432. PRAT rattmp=NULL;
  433. BOOL bret;
  434. DUPRAT(rattmp,a);
  435. rattmp->pp->sign *= -1;
  436. addrat( &rattmp, b );
  437. bret = !( zernum( rattmp->pp ) );
  438. destroyrat( rattmp );
  439. return( bret );
  440. }
  441. //---------------------------------------------------------------------------
  442. //
  443. // function: scale
  444. //
  445. // ARGUMENTS: pointer to x PRAT representation of number, and scaling factor
  446. //
  447. // RETURN: no return, value x PRAT is smashed with a scaled number in the
  448. // range of the scalefact.
  449. //
  450. //---------------------------------------------------------------------------
  451. void scale( PRAT *px, PRAT scalefact )
  452. {
  453. long logscale;
  454. PRAT pret=NULL;
  455. DUPRAT(pret,*px);
  456. // Logscale is a quick way to tell how much extra precision is needed for
  457. // scaleing by scalefact.
  458. logscale = ratio * ( (pret->pp->cdigit+pret->pp->exp) -
  459. (pret->pq->cdigit+pret->pq->exp) );
  460. if ( logscale > 0 )
  461. {
  462. maxout += logscale;
  463. }
  464. else
  465. {
  466. logscale = 0;
  467. }
  468. divrat( &pret, scalefact);
  469. intrat(&pret);
  470. mulrat( &pret, scalefact);
  471. pret->pp->sign *= -1;
  472. addrat( px, pret);
  473. maxout -= logscale;
  474. destroyrat( pret );
  475. }
  476. //---------------------------------------------------------------------------
  477. //
  478. // function: scale2pi
  479. //
  480. // ARGUMENTS: pointer to x PRAT representation of number
  481. //
  482. // RETURN: no return, value x PRAT is smashed with a scaled number in the
  483. // range of 0..2pi
  484. //
  485. //---------------------------------------------------------------------------
  486. void scale2pi( PRAT *px )
  487. {
  488. long logscale;
  489. PRAT pret=NULL;
  490. PRAT my_two_pi=NULL;
  491. DUPRAT(pret,*px);
  492. // Logscale is a quick way to tell how much extra precision is needed for
  493. // scaleing by 2 pi.
  494. logscale = ratio * ( (pret->pp->cdigit+pret->pp->exp) -
  495. (pret->pq->cdigit+pret->pq->exp) );
  496. if ( logscale > 0 )
  497. {
  498. maxout += logscale;
  499. DUPRAT(my_two_pi,rat_half);
  500. asinrat( &my_two_pi );
  501. mulrat( &my_two_pi, rat_six );
  502. mulrat( &my_two_pi, rat_two );
  503. }
  504. else
  505. {
  506. DUPRAT(my_two_pi,two_pi);
  507. logscale = 0;
  508. }
  509. divrat( &pret, my_two_pi);
  510. intrat(&pret);
  511. mulrat( &pret, my_two_pi);
  512. pret->pp->sign *= -1;
  513. addrat( px, pret);
  514. maxout -= logscale;
  515. destroyrat( my_two_pi );
  516. destroyrat( pret );
  517. }
  518. //---------------------------------------------------------------------------
  519. //
  520. // FUNCTION: inbetween
  521. //
  522. // ARGUMENTS: PRAT *px, and PRAT range.
  523. //
  524. // RETURN: none, changes *px to -/+range, if px is outside -range..+range
  525. //
  526. //---------------------------------------------------------------------------
  527. void inbetween( PRAT *px, PRAT range )
  528. {
  529. if ( rat_gt(*px,range) )
  530. {
  531. DUPRAT(*px,range);
  532. }
  533. else
  534. {
  535. range->pp->sign *= -1;
  536. if ( rat_lt(*px,range) )
  537. {
  538. DUPRAT(*px,range);
  539. }
  540. range->pp->sign *= -1;
  541. }
  542. }
  543. #if defined( GEN_CONST )
  544. //---------------------------------------------------------------------------
  545. //
  546. // FUNCTION: _dumprawrat
  547. //
  548. // ARGUMENTS: char *name of variable, PRAT x
  549. //
  550. // RETURN: none, prints the results of a dump of the internal structures
  551. // of a PRAT, suitable for READRAWRAT to stderr.
  552. //
  553. //---------------------------------------------------------------------------
  554. void _dumprawrat( TCHAR *varname, PRAT rat )
  555. {
  556. fprintf( stderr, "// Autogenerated by _dumprawrat in support.c\n" );
  557. fprintf( stderr, "NUMBER init_p_%s = {\n", varname );
  558. _dumprawnum( rat->pp );
  559. fprintf( stderr, "};\n" );
  560. fprintf( stderr, "NUMBER init_q_%s = {\n", varname );
  561. _dumprawnum( rat->pq );
  562. fprintf( stderr, "};\n" );
  563. }
  564. //---------------------------------------------------------------------------
  565. //
  566. // FUNCTION: _dumprawnum
  567. //
  568. // ARGUMENTS: PNUMBER num
  569. //
  570. // RETURN: none, prints the results of a dump of the internal structures
  571. // of a PNUMBER, suitable for READRAWNUM to stderr.
  572. //
  573. //---------------------------------------------------------------------------
  574. void _dumprawnum( PNUMBER num )
  575. {
  576. int i;
  577. fprintf( stderr, "\t%d,\n", num->sign );
  578. fprintf( stderr, "\t%d,\n", num->cdigit );
  579. fprintf( stderr, "\t%d,\n", num->exp );
  580. fprintf( stderr, "\t{ " );
  581. for ( i = 0; i < num->cdigit; i++ )
  582. {
  583. fprintf( stderr, " %d,", num->mant[i] );
  584. }
  585. fprintf( stderr, "}\n" );
  586. }
  587. #endif
  588. void _readconstants( void )
  589. {
  590. READRAWNUM(num_one);
  591. READRAWNUM(num_two);
  592. READRAWNUM(num_five);
  593. READRAWNUM(num_six);
  594. READRAWNUM(num_ten);
  595. READRAWRAT(pt_eight_five);
  596. READRAWRAT(rat_six);
  597. READRAWRAT(rat_two);
  598. READRAWRAT(rat_zero);
  599. READRAWRAT(rat_one);
  600. READRAWRAT(rat_neg_one);
  601. READRAWRAT(rat_half);
  602. READRAWRAT(rat_ten);
  603. READRAWRAT(pi);
  604. READRAWRAT(two_pi);
  605. READRAWRAT(pi_over_two);
  606. READRAWRAT(one_pt_five_pi);
  607. READRAWRAT(e_to_one_half);
  608. READRAWRAT(rat_exp);
  609. READRAWRAT(ln_ten);
  610. READRAWRAT(ln_two);
  611. READRAWRAT(rad_to_deg);
  612. READRAWRAT(rad_to_grad);
  613. READRAWRAT(rat_qword);
  614. READRAWRAT(rat_dword);
  615. READRAWRAT(rat_word);
  616. READRAWRAT(rat_byte);
  617. READRAWRAT(rat_360);
  618. READRAWRAT(rat_400);
  619. READRAWRAT(rat_180);
  620. READRAWRAT(rat_200);
  621. READRAWRAT(rat_smallest);
  622. READRAWRAT(rat_negsmallest);
  623. READRAWRAT(rat_max_exp);
  624. READRAWRAT(rat_min_exp);
  625. READRAWRAT(rat_min_long);
  626. DUPNUM(gllfact.pnum,num_one);
  627. gllfact.llprev = NULL;
  628. gllfact.llnext = NULL;
  629. }
  630. void factnum( IN OUT PLINKEDLIST *ppllfact, PNUMBER pnum )
  631. {
  632. PNUMBER thisnum=NULL;
  633. PLINKEDLIST pllfact = *ppllfact;
  634. if ( pllfact->llnext == NULL )
  635. {
  636. // This factorial hasn't happened yet, lets compute it.
  637. DUPNUM(thisnum,pllfact->pnum);
  638. mulnumx(&thisnum,pnum);
  639. pllfact->llnext = (PLINKEDLIST)zmalloc( sizeof( LINKEDLIST ) );
  640. if (pllfact->llnext)
  641. {
  642. pllfact->llnext->pnum = thisnum;
  643. pllfact->llnext->llprev = pllfact;
  644. pllfact->llnext->llnext = NULL;
  645. }
  646. }
  647. *ppllfact = pllfact->llnext;
  648. }
  649. //---------------------------------------------------------------------------
  650. //
  651. // FUNCTION: trimit
  652. //
  653. // ARGUMENTS: PRAT *px
  654. //
  655. //
  656. // DESCRIPTION: Chops off digits from rational numbers to avoid time
  657. // explosions in calculations of functions using series.
  658. // Gregory Stepanets proved it was enough to only keep the first n digits
  659. // of the largest of p or q in the rational p over q form, and of course
  660. // scale the smaller by the same number of digits. This will give you
  661. // n-1 digits of accuracy. This dramatically speeds up calculations
  662. // involving hundreds of digits or more.
  663. // The last part of this trim dealing with exponents never affects accuracy
  664. //
  665. // RETURN: none, modifies the pointed to PRAT
  666. //
  667. //---------------------------------------------------------------------------
  668. void trimit( PRAT *px )
  669. {
  670. if ( !ftrueinfinite )
  671. {
  672. long trim;
  673. PNUMBER pp=(*px)->pp;
  674. PNUMBER pq=(*px)->pq;
  675. trim = ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - maxout;
  676. if ( trim > ratio )
  677. {
  678. trim /= ratio;
  679. if ( trim <= pp->exp )
  680. {
  681. pp->exp -= trim;
  682. }
  683. else
  684. {
  685. memmove( MANT(pp), &(MANT(pp)[trim-pp->exp]), sizeof(MANTTYPE)*(pp->cdigit-trim+pp->exp) );
  686. pp->cdigit -= trim-pp->exp;
  687. pp->exp = 0;
  688. }
  689. if ( trim <= pq->exp )
  690. {
  691. pq->exp -= trim;
  692. }
  693. else
  694. {
  695. memmove( MANT(pq), &(MANT(pq)[trim-pq->exp]), sizeof(MANTTYPE)*(pq->cdigit-trim+pq->exp) );
  696. pq->cdigit -= trim-pq->exp;
  697. pq->exp = 0;
  698. }
  699. }
  700. trim = min(pp->exp,pq->exp);
  701. pp->exp -= trim;
  702. pq->exp -= trim;
  703. }
  704. }