Source code of Windows XP (NT5)
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.

665 lines
19 KiB

  1. //-----------------------------------------------------------------------------
  2. // Package Title ratpak
  3. // File num.c
  4. // Author Timothy David Corrie Jr. ([email protected])
  5. // Copyright (C) 1995-97 Microsoft
  6. // Date 01-16-95
  7. //
  8. //
  9. // Description
  10. //
  11. // Contains number routines for add, mul, div, rem and other support
  12. // and longs.
  13. //
  14. // Special Information
  15. //
  16. //
  17. //-----------------------------------------------------------------------------
  18. #if defined( DOS )
  19. #include <dosstub.h>
  20. #else
  21. #include <windows.h>
  22. #endif
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <malloc.h>
  26. #include <stdlib.h>
  27. #include <ratpak.h>
  28. //----------------------------------------------------------------------------
  29. //
  30. // FUNCTION: addnum
  31. //
  32. // ARGUMENTS: pointer to a number a second number, and the
  33. // nRadix.
  34. //
  35. // RETURN: None, changes first pointer.
  36. //
  37. // DESCRIPTION: Does the number equivalent of *pa += b.
  38. // Assumes nRadix is the base of both numbers.
  39. //
  40. // ALGORITHM: Adds each digit from least significant to most
  41. // significant.
  42. //
  43. //
  44. //----------------------------------------------------------------------------
  45. void _addnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix );
  46. void __inline addnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix )
  47. {
  48. if ( b->cdigit > 1 || b->mant[0] != 0 )
  49. { // If b is zero we are done.
  50. if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 0 )
  51. { // pa and b are both nonzero.
  52. _addnum( pa, b, nRadix );
  53. }
  54. else
  55. { // if pa is zero and b isn't just copy b.
  56. DUPNUM(*pa,b);
  57. }
  58. }
  59. }
  60. void _addnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix )
  61. {
  62. PNUMBER c=NULL; // c will contain the result.
  63. PNUMBER a=NULL; // a is the dereferenced number pointer from *pa
  64. MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
  65. MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
  66. MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
  67. long cdigits; // cdigits is the max count of the digits results
  68. // used as a counter.
  69. long mexp; // mexp is the exponent of the result.
  70. MANTTYPE da; // da is a single 'digit' after possible padding.
  71. MANTTYPE db; // db is a single 'digit' after possible padding.
  72. MANTTYPE cy=0; // cy is the value of a carry after adding two 'digits'
  73. long fcompla = 0; // fcompla is a flag to signal a is negative.
  74. long fcomplb = 0; // fcomplb is a flag to signal b is negative.
  75. a=*pa;
  76. // Calculate the overlap of the numbers after alignment, this includes
  77. // necessary padding 0's
  78. cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
  79. min( a->exp, b->exp );
  80. createnum( c, cdigits + 1 );
  81. c->exp = min( a->exp, b->exp );
  82. mexp = c->exp;
  83. c->cdigit = cdigits;
  84. pcha = MANT(a);
  85. pchb = MANT(b);
  86. pchc = MANT(c);
  87. // Figure out the sign of the numbers
  88. if ( a->sign != b->sign )
  89. {
  90. cy = 1;
  91. fcompla = ( a->sign == -1 );
  92. fcomplb = ( b->sign == -1 );
  93. }
  94. // Loop over all the digits, real and 0 padded. Here we know a and b are
  95. // aligned
  96. for ( ;cdigits > 0; cdigits--, mexp++ )
  97. {
  98. // Get digit from a, taking padding into account.
  99. da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
  100. (c->cdigit - a->cdigit) ) ) ?
  101. *pcha++ : 0 );
  102. // Get digit from b, taking padding into account.
  103. db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
  104. (c->cdigit - b->cdigit) ) ) ?
  105. *pchb++ : 0 );
  106. // Handle complementing for a and b digit. Might be a better way, but
  107. // haven't found it yet.
  108. if ( fcompla )
  109. {
  110. da = (MANTTYPE)(nRadix) - 1 - da;
  111. }
  112. if ( fcomplb )
  113. {
  114. db = (MANTTYPE)(nRadix) - 1 - db;
  115. }
  116. // Update carry as necessary
  117. cy = da + db + cy;
  118. *pchc++ = (MANTTYPE)(cy % (MANTTYPE)nRadix);
  119. cy /= (MANTTYPE)nRadix;
  120. }
  121. // Handle carry from last sum as extra digit
  122. if ( cy && !(fcompla || fcomplb) )
  123. {
  124. *pchc++ = cy;
  125. c->cdigit++;
  126. }
  127. // Compute sign of result
  128. if ( !(fcompla || fcomplb) )
  129. {
  130. c->sign = a->sign;
  131. }
  132. else
  133. {
  134. if ( cy )
  135. {
  136. c->sign = 1;
  137. }
  138. else
  139. {
  140. // In this particular case an overflow or underflow has occoured
  141. // and all the digits need to be complemented, at one time an
  142. // attempt to handle this above was made, it turned out to be much
  143. // slower on average.
  144. c->sign = -1;
  145. cy = 1;
  146. for ( ( cdigits = c->cdigit ), (pchc = MANT(c) );
  147. cdigits > 0;
  148. cdigits-- )
  149. {
  150. cy = (MANTTYPE)nRadix - (MANTTYPE)1 - *pchc + cy;
  151. *pchc++ = (MANTTYPE)( cy % (MANTTYPE)nRadix );
  152. cy /= (MANTTYPE)nRadix;
  153. }
  154. }
  155. }
  156. // Remove leading zeroes, remember digits are in order of
  157. // increasing significance. i.e. 100 would be 0,0,1
  158. while ( c->cdigit > 1 && *(--pchc) == 0 )
  159. {
  160. c->cdigit--;
  161. }
  162. destroynum( *pa );
  163. *pa=c;
  164. }
  165. //----------------------------------------------------------------------------
  166. //
  167. // FUNCTION: mulnum
  168. //
  169. // ARGUMENTS: pointer to a number a second number, and the
  170. // nRadix.
  171. //
  172. // RETURN: None, changes first pointer.
  173. //
  174. // DESCRIPTION: Does the number equivalent of *pa *= b.
  175. // Assumes nRadix is the nRadix of both numbers. This algorithm is the
  176. // same one you learned in gradeschool.
  177. //
  178. //----------------------------------------------------------------------------
  179. void _mulnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix );
  180. void __inline mulnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix )
  181. {
  182. if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
  183. { // If b is one we don't multiply exactly.
  184. if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
  185. { // pa and b are both nonone.
  186. _mulnum( pa, b, nRadix );
  187. }
  188. else
  189. { // if pa is one and b isn't just copy b, and adjust the sign.
  190. long sign = (*pa)->sign;
  191. DUPNUM(*pa,b);
  192. (*pa)->sign *= sign;
  193. }
  194. }
  195. else
  196. { // But we do have to set the sign.
  197. (*pa)->sign *= b->sign;
  198. }
  199. }
  200. void _mulnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix )
  201. {
  202. PNUMBER c=NULL; // c will contain the result.
  203. PNUMBER a=NULL; // a is the dereferenced number pointer from *pa
  204. MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
  205. MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
  206. MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
  207. MANTTYPE *pchcoffset; // pchcoffset, is the anchor location of the next
  208. // single digit multiply partial result.
  209. long iadigit = 0; // Index of digit being used in the first number.
  210. long ibdigit = 0; // Index of digit being used in the second number.
  211. MANTTYPE da = 0; // da is the digit from the fist number.
  212. TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
  213. // a multiplied row into the result.
  214. TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
  215. // multiply, AND the carry of that multiply.
  216. long icdigit = 0; // Index of digit being calculated in final result.
  217. a=*pa;
  218. ibdigit = a->cdigit + b->cdigit - 1;
  219. createnum( c, ibdigit + 1 );
  220. c->cdigit = ibdigit;
  221. c->sign = a->sign * b->sign;
  222. c->exp = a->exp + b->exp;
  223. pcha = MANT(a);
  224. pchcoffset = MANT(c);
  225. for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
  226. {
  227. da = *pcha++;
  228. pchb = MANT(b);
  229. // Shift pchc, and pchcoffset, one for each digit
  230. pchc = pchcoffset++;
  231. for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
  232. {
  233. cy = 0;
  234. mcy = (TWO_MANTTYPE)da * *pchb;
  235. if ( mcy )
  236. {
  237. icdigit = 0;
  238. if ( ibdigit == 1 && iadigit == 1 )
  239. {
  240. c->cdigit++;
  241. }
  242. }
  243. // If result is nonzero, or while result of carry is nonzero...
  244. while ( mcy || cy )
  245. {
  246. // update carry from addition(s) and multiply.
  247. cy += (TWO_MANTTYPE)pchc[icdigit]+(mcy%(TWO_MANTTYPE)nRadix);
  248. // update result digit from
  249. pchc[icdigit++]=(MANTTYPE)(cy%(TWO_MANTTYPE)nRadix);
  250. // update carries from
  251. mcy /= (TWO_MANTTYPE)nRadix;
  252. cy /= (TWO_MANTTYPE)nRadix;
  253. }
  254. *pchb++;
  255. *pchc++;
  256. }
  257. }
  258. // prevent different kinds of zeros, by stripping leading duplicate zeroes.
  259. // digits are in order of increasing significance.
  260. while ( c->cdigit > 1 && MANT(c)[c->cdigit-1] == 0 )
  261. {
  262. c->cdigit--;
  263. }
  264. destroynum( *pa );
  265. *pa=c;
  266. }
  267. //----------------------------------------------------------------------------
  268. //
  269. // FUNCTION: remnum
  270. //
  271. // ARGUMENTS: pointer to a number a second number, and the
  272. // nRadix.
  273. //
  274. // RETURN: None, changes first pointer.
  275. //
  276. // DESCRIPTION: Does the number equivalent of *pa %= b.
  277. // Repeatedly subtracts off powers of 2 of b until *pa < b.
  278. //
  279. //
  280. //----------------------------------------------------------------------------
  281. void remnum( PNUMBER *pa, PNUMBER b, long nRadix )
  282. {
  283. PNUMBER tmp = NULL; // tmp is the working remainder.
  284. PNUMBER lasttmp = NULL; // lasttmp is the last remainder which worked.
  285. // Once *pa is less than b, *pa is the remainder.
  286. while ( !lessnum( *pa, b ) && !fhalt )
  287. {
  288. DUPNUM( tmp, b );
  289. if ( lessnum( tmp, *pa ) )
  290. {
  291. // Start off close to the right answer for subtraction.
  292. tmp->exp = (*pa)->cdigit+(*pa)->exp - tmp->cdigit;
  293. if ( MSD(*pa) <= MSD(tmp) )
  294. {
  295. // Don't take the chance that the numbers are equal.
  296. tmp->exp--;
  297. }
  298. }
  299. destroynum( lasttmp );
  300. lasttmp=longtonum( 0, nRadix );
  301. while ( lessnum( tmp, *pa ) )
  302. {
  303. DUPNUM( lasttmp, tmp );
  304. addnum( &tmp, tmp, nRadix );
  305. }
  306. if ( lessnum( *pa, tmp ) )
  307. {
  308. // too far, back up...
  309. destroynum( tmp );
  310. tmp=lasttmp;
  311. lasttmp=NULL;
  312. }
  313. // Subtract the working remainder from the remainder holder.
  314. tmp->sign = -1*(*pa)->sign;
  315. addnum( pa, tmp, nRadix );
  316. destroynum( tmp );
  317. destroynum( lasttmp );
  318. }
  319. }
  320. //---------------------------------------------------------------------------
  321. //
  322. // FUNCTION: divnum
  323. //
  324. // ARGUMENTS: pointer to a number a second number, and the
  325. // nRadix.
  326. //
  327. // RETURN: None, changes first pointer.
  328. //
  329. // DESCRIPTION: Does the number equivalent of *pa /= b.
  330. // Assumes nRadix is the nRadix of both numbers.
  331. //
  332. //---------------------------------------------------------------------------
  333. void _divnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix );
  334. void __inline divnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix )
  335. {
  336. if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
  337. {
  338. // b is not one
  339. _divnum( pa, b, nRadix );
  340. }
  341. else
  342. { // But we do have to set the sign.
  343. (*pa)->sign *= b->sign;
  344. }
  345. }
  346. void _divnum( PNUMBER *pa, PNUMBER b, unsigned long nRadix )
  347. {
  348. PNUMBER a = NULL;
  349. PNUMBER c = NULL;
  350. PNUMBER tmp = NULL;
  351. PNUMBER rem = NULL;
  352. PLINKEDLIST pll = NULL;
  353. PLINKEDLIST pllrover = NULL;
  354. long digit;
  355. long cdigits;
  356. BOOL bret;
  357. MANTTYPE *ptrc;
  358. long thismax = maxout+2;
  359. a=*pa;
  360. if ( thismax < a->cdigit )
  361. {
  362. thismax = a->cdigit;
  363. }
  364. if ( thismax < b->cdigit )
  365. {
  366. thismax = b->cdigit;
  367. }
  368. createnum( c, thismax + 1 );
  369. c->exp = (a->cdigit+a->exp) - (b->cdigit+b->exp) + 1;
  370. c->sign = a->sign * b->sign;
  371. ptrc = MANT(c) + thismax;
  372. cdigits = 0;
  373. DUPNUM( rem, a );
  374. DUPNUM( tmp, b );
  375. tmp->sign = a->sign;
  376. rem->exp = b->cdigit + b->exp - rem->cdigit;
  377. // Build a table of multiplications of the divisor, this is quicker for
  378. // more than nRadix 'digits'
  379. pll = (PLINKEDLIST)zmalloc( sizeof( LINKEDLIST ) );
  380. pll->pnum = longtonum( 0L, nRadix );
  381. pll->llprev = NULL;
  382. for ( cdigits = 1; cdigits < (long)nRadix; cdigits++ )
  383. {
  384. pllrover = (PLINKEDLIST)zmalloc( sizeof( LINKEDLIST ) );
  385. pllrover->pnum=NULL;
  386. DUPNUM( pllrover->pnum, pll->pnum );
  387. addnum( &(pllrover->pnum), tmp, nRadix );
  388. pllrover->llprev = pll;
  389. pll = pllrover;
  390. }
  391. destroynum( tmp );
  392. cdigits = 0;
  393. while ( cdigits++ < thismax && !zernum(rem) )
  394. {
  395. pllrover = pll;
  396. digit = nRadix - 1;
  397. do {
  398. bret = lessnum( rem, pllrover->pnum );
  399. } while ( bret && --digit && ( pllrover = pllrover->llprev ) );
  400. if ( digit )
  401. {
  402. pllrover->pnum->sign *= -1;
  403. addnum( &rem, pllrover->pnum, nRadix );
  404. pllrover->pnum->sign *= -1;
  405. }
  406. rem->exp++;
  407. *ptrc-- = (MANTTYPE)digit;
  408. }
  409. cdigits--;
  410. if ( MANT(c) != ++ptrc )
  411. {
  412. memcpy( MANT(c), ptrc, (int)(cdigits*sizeof(MANTTYPE)) );
  413. }
  414. // Cleanup table structure
  415. pllrover = pll;
  416. do {
  417. pll = pllrover->llprev;
  418. destroynum( pllrover->pnum );
  419. zfree( pllrover );
  420. } while ( pllrover = pll );
  421. if ( !cdigits )
  422. {
  423. c->cdigit = 1;
  424. c->exp = 0;
  425. }
  426. else
  427. {
  428. c->cdigit = cdigits;
  429. c->exp -= cdigits;
  430. while ( c->cdigit > 1 && MANT(c)[c->cdigit-1] == 0 )
  431. {
  432. c->cdigit--;
  433. }
  434. }
  435. destroynum( rem );
  436. destroynum( *pa );
  437. *pa=c;
  438. }
  439. //---------------------------------------------------------------------------
  440. //
  441. // FUNCTION: equnum
  442. //
  443. // ARGUMENTS: two numbers.
  444. //
  445. // RETURN: Boolean
  446. //
  447. // DESCRIPTION: Does the number equivalent of ( a == b )
  448. // Only assumes that a and b are the same nRadix.
  449. //
  450. //---------------------------------------------------------------------------
  451. BOOL equnum( PNUMBER a, PNUMBER b )
  452. {
  453. long diff;
  454. MANTTYPE *pa;
  455. MANTTYPE *pb;
  456. long cdigits;
  457. long ccdigits;
  458. MANTTYPE da;
  459. MANTTYPE db;
  460. diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
  461. if ( diff < 0 )
  462. {
  463. // If the exponents are different, these are different numbers.
  464. return( FALSE );
  465. }
  466. else
  467. {
  468. if ( diff > 0 )
  469. {
  470. // If the exponents are different, these are different numbers.
  471. return( FALSE );
  472. }
  473. else
  474. {
  475. // OK the exponents match.
  476. pa = MANT(a);
  477. pb = MANT(b);
  478. pa += a->cdigit - 1;
  479. pb += b->cdigit - 1;
  480. cdigits = max( a->cdigit, b->cdigit );
  481. ccdigits = cdigits;
  482. // Loop over all digits until we run out of digits or there is a
  483. // difference in the digits.
  484. for ( ;cdigits > 0; cdigits-- )
  485. {
  486. da = ( (cdigits > (ccdigits - a->cdigit) ) ?
  487. *pa-- : 0 );
  488. db = ( (cdigits > (ccdigits - b->cdigit) ) ?
  489. *pb-- : 0 );
  490. if ( da != db )
  491. {
  492. return( FALSE );
  493. }
  494. }
  495. // In this case, they are equal.
  496. return( TRUE );
  497. }
  498. }
  499. }
  500. //---------------------------------------------------------------------------
  501. //
  502. // FUNCTION: lessnum
  503. //
  504. // ARGUMENTS: two numbers.
  505. //
  506. // RETURN: Boolean
  507. //
  508. // DESCRIPTION: Does the number equivalent of ( abs(a) < abs(b) )
  509. // Only assumes that a and b are the same nRadix, WARNING THIS IS AN.
  510. // UNSIGNED COMPARE!
  511. //
  512. //---------------------------------------------------------------------------
  513. BOOL lessnum( PNUMBER a, PNUMBER b )
  514. {
  515. long diff;
  516. MANTTYPE *pa;
  517. MANTTYPE *pb;
  518. long cdigits;
  519. long ccdigits;
  520. MANTTYPE da;
  521. MANTTYPE db;
  522. diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
  523. if ( diff < 0 )
  524. {
  525. // The exponent of a is less than b
  526. return( TRUE );
  527. }
  528. else
  529. {
  530. if ( diff > 0 )
  531. {
  532. return( FALSE );
  533. }
  534. else
  535. {
  536. pa = MANT(a);
  537. pb = MANT(b);
  538. pa += a->cdigit - 1;
  539. pb += b->cdigit - 1;
  540. cdigits = max( a->cdigit, b->cdigit );
  541. ccdigits = cdigits;
  542. for ( ;cdigits > 0; cdigits-- )
  543. {
  544. da = ( (cdigits > (ccdigits - a->cdigit) ) ?
  545. *pa-- : 0 );
  546. db = ( (cdigits > (ccdigits - b->cdigit) ) ?
  547. *pb-- : 0 );
  548. diff = da-db;
  549. if ( diff )
  550. {
  551. return( diff < 0 );
  552. }
  553. }
  554. // In this case, they are equal.
  555. return( FALSE );
  556. }
  557. }
  558. }
  559. //----------------------------------------------------------------------------
  560. //
  561. // FUNCTION: zernum
  562. //
  563. // ARGUMENTS: number
  564. //
  565. // RETURN: Boolean
  566. //
  567. // DESCRIPTION: Does the number equivalent of ( !a )
  568. //
  569. //----------------------------------------------------------------------------
  570. BOOL zernum( PNUMBER a )
  571. {
  572. long length;
  573. MANTTYPE *pcha;
  574. length = a->cdigit;
  575. pcha = MANT( a );
  576. // loop over all the digits until you find a nonzero or until you run
  577. // out of digits
  578. while ( length-- > 0 )
  579. {
  580. if ( *pcha++ )
  581. {
  582. // One of the digits isn't zero, therefore the number isn't zero
  583. return( FALSE );
  584. }
  585. }
  586. // All of the digits are zero, therefore the number is zero
  587. return( TRUE );
  588. }