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.

715 lines
14 KiB

  1. /***
  2. * intrncvt.c - internal floating point conversions
  3. *
  4. * Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * All fp string conversion routines use the same core conversion code
  8. * that converts strings into an internal long double representation
  9. * with an 80-bit mantissa field. The mantissa is represented
  10. * as an array (man) of 32-bit unsigned longs, with man[0] holding
  11. * the high order 32 bits of the mantissa. The binary point is assumed
  12. * to be between the MSB and MSB-1 of man[0].
  13. *
  14. * Bits are counted as follows:
  15. *
  16. *
  17. * +-- binary point
  18. * |
  19. * v MSB LSB
  20. * ---------------- ------------------ --------------------
  21. * |0 1 .... 31| | 32 33 ... 63| | 64 65 ... 95|
  22. * ---------------- ------------------ --------------------
  23. *
  24. * man[0] man[1] man[2]
  25. *
  26. * This file provides the final conversion routines from this internal
  27. * form to the single, double, or long double precision floating point
  28. * format.
  29. *
  30. * All these functions do not handle NaNs (it is not necessary)
  31. *
  32. *
  33. *Revision History:
  34. * 04-29-92 GDP written
  35. * 06-18-92 GDP now ld12told returns INTRNCVT_STATUS
  36. * 06-22-92 GDP use new __strgtold12 interface (FORTRAN support)
  37. * 10-25-92 GDP _atoldbl bug fix (cuda 1345): if the mantissa overflows
  38. * set its MSB to 1)
  39. * 06-08-98 JWM fixed long-standing off-by-1 error in _RoundMan().
  40. *
  41. *******************************************************************************/
  42. #include <cv.h>
  43. #define INTRNMAN_LEN 3 /* internal mantissa length in int's */
  44. //
  45. // internal mantissaa representation
  46. // for string conversion routines
  47. //
  48. typedef u_long *intrnman;
  49. typedef struct {
  50. int max_exp; // maximum base 2 exponent (reserved for special values)
  51. int min_exp; // minimum base 2 exponent (reserved for denormals)
  52. int precision; // bits of precision carried in the mantissa
  53. int exp_width; // number of bits for exponent
  54. int format_width; // format width in bits
  55. int bias; // exponent bias
  56. } FpFormatDescriptor;
  57. static FpFormatDescriptor
  58. DoubleFormat = {
  59. 0x7ff - 0x3ff, // 1024, maximum base 2 exponent (reserved for special values)
  60. 0x0 - 0x3ff, // -1023, minimum base 2 exponent (reserved for denormals)
  61. 53, // bits of precision carried in the mantissa
  62. 11, // number of bits for exponent
  63. 64, // format width in bits
  64. 0x3ff, // exponent bias
  65. };
  66. static FpFormatDescriptor
  67. FloatFormat = {
  68. 0xff - 0x7f, // 128, maximum base 2 exponent (reserved for special values)
  69. 0x0 - 0x7f, // -127, minimum base 2 exponent (reserved for denormals)
  70. 24, // bits of precision carried in the mantissa
  71. 8, // number of bits for exponent
  72. 32, // format width in bits
  73. 0x7f, // exponent bias
  74. };
  75. //
  76. // function prototypes
  77. //
  78. int _RoundMan (intrnman man, int nbit);
  79. int _ZeroTail (intrnman man, int nbit);
  80. int _IncMan (intrnman man, int nbit);
  81. void _CopyMan (intrnman dest, intrnman src);
  82. void _CopyMan (intrnman dest, intrnman src);
  83. void _FillZeroMan(intrnman man);
  84. void _Shrman (intrnman man, int n);
  85. INTRNCVT_STATUS _ld12cvt(_LDBL12 *pld12, void *d, FpFormatDescriptor *format);
  86. /***
  87. * _ZeroTail - check if a mantissa ends in 0's
  88. *
  89. *Purpose:
  90. * Return TRUE if all mantissa bits after nbit (including nbit) are 0,
  91. * otherwise return FALSE
  92. *
  93. *
  94. *Entry:
  95. * man: mantissa
  96. * nbit: order of bit where the tail begins
  97. *
  98. *Exit:
  99. *
  100. *Exceptions:
  101. *
  102. *******************************************************************************/
  103. int _ZeroTail (intrnman man, int nbit)
  104. {
  105. int nl = nbit / 32;
  106. int nb = 31 - nbit % 32;
  107. //
  108. // |<---- tail to be checked --->
  109. //
  110. // -- ------------------------ ----
  111. // |... | | ... |
  112. // -- ------------------------ ----
  113. // ^ ^ ^
  114. // | | |<----nb----->
  115. // man nl nbit
  116. //
  117. u_long bitmask = ~(MAX_ULONG << nb);
  118. if (man[nl] & bitmask)
  119. return 0;
  120. nl++;
  121. for (;nl < INTRNMAN_LEN; nl++)
  122. if (man[nl])
  123. return 0;
  124. return 1;
  125. }
  126. /***
  127. * _IncMan - increment mantissa
  128. *
  129. *Purpose:
  130. *
  131. *
  132. *Entry:
  133. * man: mantissa in internal long form
  134. * nbit: order of bit that specifies the end of the part to be incremented
  135. *
  136. *Exit:
  137. * returns 1 on overflow, 0 otherwise
  138. *
  139. *Exceptions:
  140. *
  141. *******************************************************************************/
  142. int _IncMan (intrnman man, int nbit)
  143. {
  144. int nl = nbit / 32;
  145. int nb = 31 - nbit % 32;
  146. //
  147. // |<--- part to be incremented -->|
  148. //
  149. // -- --------------------------- ----
  150. // |... | | ... |
  151. // -- --------------------------- ----
  152. // ^ ^ ^
  153. // | | |<--nb-->
  154. // man nl nbit
  155. //
  156. u_long one = (u_long) 1 << nb;
  157. int carry;
  158. carry = __addl(man[nl], one, &man[nl]);
  159. nl--;
  160. for (; nl >= 0 && carry; nl--) {
  161. carry = (u_long) __addl(man[nl], (u_long) 1, &man[nl]);
  162. }
  163. return carry;
  164. }
  165. /***
  166. * _RoundMan - round mantissa
  167. *
  168. *Purpose:
  169. * round mantissa to nbit precision
  170. *
  171. *
  172. *Entry:
  173. * man: mantissa in internal form
  174. * precision: number of bits to be kept after rounding
  175. *
  176. *Exit:
  177. * returns 1 on overflow, 0 otherwise
  178. *
  179. *Exceptions:
  180. *
  181. *******************************************************************************/
  182. int _RoundMan (intrnman man, int precision)
  183. {
  184. int i,rndbit,nl,nb;
  185. u_long rndmask;
  186. int nbit;
  187. int retval = 0;
  188. //
  189. // The order of the n'th bit is n-1, since the first bit is bit 0
  190. // therefore decrement precision to get the order of the last bit
  191. // to be kept
  192. //
  193. nbit = precision - 1;
  194. rndbit = nbit+1;
  195. nl = rndbit / 32;
  196. nb = 31 - rndbit % 32;
  197. //
  198. // Get value of round bit
  199. //
  200. rndmask = (u_long)1 << nb;
  201. if ((man[nl] & rndmask) &&
  202. !_ZeroTail(man, rndbit)) {
  203. //
  204. // round up
  205. //
  206. retval = _IncMan(man, nbit);
  207. }
  208. //
  209. // fill rest of mantissa with zeroes
  210. //
  211. man[nl] &= MAX_ULONG << nb;
  212. for(i=nl+1; i<INTRNMAN_LEN; i++) {
  213. man[i] = (u_long)0;
  214. }
  215. return retval;
  216. }
  217. /***
  218. * _CopyMan - copy mantissa
  219. *
  220. *Purpose:
  221. * copy src to dest
  222. *
  223. *Entry:
  224. *
  225. *Exit:
  226. *
  227. *Exceptions:
  228. *
  229. *******************************************************************************/
  230. void _CopyMan (intrnman dest, intrnman src)
  231. {
  232. u_long *p, *q;
  233. int i;
  234. p = src;
  235. q = dest;
  236. for (i=0; i < INTRNMAN_LEN; i++) {
  237. *q++ = *p++;
  238. }
  239. }
  240. /***
  241. * _FillZeroMan - fill mantissa with zeroes
  242. *
  243. *Purpose:
  244. *
  245. *
  246. *Entry:
  247. *
  248. *Exit:
  249. *
  250. *Exceptions:
  251. *
  252. *******************************************************************************/
  253. void _FillZeroMan(intrnman man)
  254. {
  255. int i;
  256. for (i=0; i < INTRNMAN_LEN; i++)
  257. man[i] = (u_long)0;
  258. }
  259. /***
  260. * _IsZeroMan - check if mantissa is zero
  261. *
  262. *Purpose:
  263. *
  264. *
  265. *Entry:
  266. *
  267. *Exit:
  268. *
  269. *Exceptions:
  270. *
  271. *******************************************************************************/
  272. int _IsZeroMan(intrnman man)
  273. {
  274. int i;
  275. for (i=0; i < INTRNMAN_LEN; i++)
  276. if (man[i])
  277. return 0;
  278. return 1;
  279. }
  280. /***
  281. * _ShrMan - shift mantissa to the right
  282. *
  283. *Purpose:
  284. * shift man by n bits to the right
  285. *
  286. *Entry:
  287. *
  288. *Exit:
  289. *
  290. *Exceptions:
  291. *
  292. *******************************************************************************/
  293. void _ShrMan (intrnman man, int n)
  294. {
  295. int i, n1, n2, mask;
  296. int carry_from_left;
  297. //
  298. // declare this as volatile in order to work around a C8
  299. // optimization bug
  300. //
  301. volatile int carry_to_right;
  302. n1 = n / 32;
  303. n2 = n % 32;
  304. mask = ~(MAX_ULONG << n2);
  305. //
  306. // first deal with shifts by less than 32 bits
  307. //
  308. carry_from_left = 0;
  309. for (i=0; i<INTRNMAN_LEN; i++) {
  310. carry_to_right = man[i] & mask;
  311. man[i] >>= n2;
  312. man[i] |= carry_from_left;
  313. carry_from_left = carry_to_right << (32 - n2);
  314. }
  315. //
  316. // now shift whole 32-bit ints
  317. //
  318. for (i=INTRNMAN_LEN-1; i>=0; i--) {
  319. if (i >= n1) {
  320. man[i] = man[i-n1];
  321. }
  322. else {
  323. man[i] = 0;
  324. }
  325. }
  326. }
  327. /***
  328. * _ld12tocvt - _LDBL12 floating point conversion
  329. *
  330. *Purpose:
  331. * convert a internal _LBL12 structure into an IEEE floating point
  332. * representation
  333. *
  334. *
  335. *Entry:
  336. * pld12: pointer to the _LDBL12
  337. * format: pointer to the format descriptor structure
  338. *
  339. *Exit:
  340. * *d contains the IEEE representation
  341. * returns the INTRNCVT_STATUS
  342. *
  343. *Exceptions:
  344. *
  345. *******************************************************************************/
  346. INTRNCVT_STATUS _ld12cvt(_LDBL12 *pld12, void *d, FpFormatDescriptor *format)
  347. {
  348. u_long man[INTRNMAN_LEN];
  349. u_long saved_man[INTRNMAN_LEN];
  350. u_long msw;
  351. unsigned int bexp; // biased exponent
  352. int exp_shift;
  353. int exponent, sign;
  354. INTRNCVT_STATUS retval;
  355. exponent = (*U_EXP_12(pld12) & 0x7fff) - 0x3fff; // unbias exponent
  356. sign = *U_EXP_12(pld12) & 0x8000;
  357. man[0] = *UL_MANHI_12(pld12);
  358. man[1] = *UL_MANLO_12(pld12);
  359. man[2] = *U_XT_12(pld12) << 16;
  360. //
  361. // bexp is the final biased value of the exponent to be used
  362. // Each of the following blocks should provide appropriate
  363. // values for man, bexp and retval. The mantissa is also
  364. // shifted to the right, leaving space for the exponent
  365. // and sign to be inserted
  366. //
  367. if (exponent == 0 - 0x3fff) {
  368. // either a denormal or zero
  369. bexp = 0;
  370. if (_IsZeroMan(man)) {
  371. retval = INTRNCVT_OK;
  372. }
  373. else {
  374. _FillZeroMan(man);
  375. // denormal has been flushed to zero
  376. retval = INTRNCVT_UNDERFLOW;
  377. }
  378. }
  379. else {
  380. // save mantissa in case it needs to be rounded again
  381. // at a different point (e.g., if the result is a denormal)
  382. _CopyMan(saved_man, man);
  383. if (_RoundMan(man, format->precision)) {
  384. exponent ++;
  385. }
  386. if (exponent < format->min_exp - format->precision ) {
  387. //
  388. // underflow that produces a zero
  389. //
  390. _FillZeroMan(man);
  391. bexp = 0;
  392. retval = INTRNCVT_UNDERFLOW;
  393. }
  394. else if (exponent <= format->min_exp) {
  395. //
  396. // underflow that produces a denormal
  397. //
  398. //
  399. // The (unbiased) exponent will be MIN_EXP
  400. // Find out how much the mantissa should be shifted
  401. // One shift is done implicitly by moving the
  402. // binary point one bit to the left, i.e.,
  403. // we treat the mantissa as .ddddd instead of d.dddd
  404. // (where d is a binary digit)
  405. int shift = format->min_exp - exponent;
  406. // The mantissa should be rounded again, so it
  407. // has to be restored
  408. _CopyMan(man,saved_man);
  409. _ShrMan(man, shift);
  410. _RoundMan(man, format->precision); // need not check for carry
  411. // make room for the exponent + sign
  412. _ShrMan(man, format->exp_width + 1);
  413. bexp = 0;
  414. retval = INTRNCVT_UNDERFLOW;
  415. }
  416. else if (exponent >= format->max_exp) {
  417. //
  418. // overflow, return infinity
  419. //
  420. _FillZeroMan(man);
  421. man[0] |= (1 << 31); // set MSB
  422. // make room for the exponent + sign
  423. _ShrMan(man, (format->exp_width + 1) - 1);
  424. bexp = format->max_exp + format->bias;
  425. retval = INTRNCVT_OVERFLOW;
  426. }
  427. else {
  428. //
  429. // valid, normalized result
  430. //
  431. bexp = exponent + format->bias;
  432. // clear implied bit
  433. man[0] &= (~( 1 << 31));
  434. //
  435. // shift right to make room for exponent + sign
  436. //
  437. _ShrMan(man, (format->exp_width + 1) - 1);
  438. retval = INTRNCVT_OK;
  439. }
  440. }
  441. exp_shift = 32 - (format->exp_width + 1);
  442. msw = man[0] |
  443. (bexp << exp_shift) |
  444. (sign ? 1<<31 : 0);
  445. if (format->format_width == 64) {
  446. *UL_HI_D(d) = msw;
  447. *UL_LO_D(d) = man[1];
  448. }
  449. else if (format->format_width == 32) {
  450. *(u_long *)d = msw;
  451. }
  452. return retval;
  453. }
  454. /***
  455. * _ld12tod - convert _LDBL12 to double
  456. *
  457. *Purpose:
  458. *
  459. *
  460. *Entry:
  461. *
  462. *Exit:
  463. *
  464. *Exceptions:
  465. *
  466. *******************************************************************************/
  467. INTRNCVT_STATUS _ld12tod(_LDBL12 *pld12, DOUBLE *d)
  468. {
  469. return _ld12cvt(pld12, d, &DoubleFormat);
  470. }
  471. /***
  472. * _ld12tof - convert _LDBL12 to float
  473. *
  474. *Purpose:
  475. *
  476. *
  477. *Entry:
  478. *
  479. *Exit:
  480. *
  481. *Exceptions:
  482. *
  483. *******************************************************************************/
  484. INTRNCVT_STATUS _ld12tof(_LDBL12 *pld12, FLOAT *f)
  485. {
  486. return _ld12cvt(pld12, f, &FloatFormat);
  487. }
  488. /***
  489. * _ld12told - convert _LDBL12 to 80 bit long double
  490. *
  491. *Purpose:
  492. *
  493. *
  494. *Entry:
  495. *
  496. *Exit:
  497. *
  498. *Exceptions:
  499. *
  500. *******************************************************************************/
  501. INTRNCVT_STATUS _ld12told(_LDBL12 *pld12, _LDOUBLE *pld)
  502. {
  503. //
  504. // This implementation is based on the fact that the _LDBL12 format is
  505. // identical to the long double and has 2 extra bytes of mantissa
  506. //
  507. u_short exp, sign;
  508. u_long man[INTRNMAN_LEN];
  509. INTRNCVT_STATUS retval = 0;
  510. exp = *U_EXP_12(pld12) & (u_short)0x7fff;
  511. sign = *U_EXP_12(pld12) & (u_short)0x8000;
  512. man[0] = *UL_MANHI_12(pld12);
  513. man[1] = *UL_MANLO_12(pld12);
  514. man[2] = *U_XT_12(pld12) << 16;
  515. if (_RoundMan(man, 64)) {
  516. // The MSB of the mantissa is explicit and should be 1
  517. // since we had a carry, the mantissa is now 0.
  518. man[0] = MSB_ULONG;
  519. exp ++;
  520. }
  521. if (exp == 0x7fff)
  522. retval = INTRNCVT_OVERFLOW;
  523. *UL_MANHI_LD(pld) = man[0];
  524. *UL_MANLO_LD(pld) = man[1];
  525. *U_EXP_LD(pld) = sign | exp;
  526. return retval;
  527. }
  528. void _atodbl(DOUBLE *d, char *str)
  529. {
  530. const char *EndPtr;
  531. _LDBL12 ld12;
  532. __strgtold12(&ld12, &EndPtr, str, 0, 0, 0, 0 );
  533. _ld12tod(&ld12, d);
  534. }
  535. void _atoldbl(_LDOUBLE *ld, char *str)
  536. {
  537. const char *EndPtr;
  538. _LDBL12 ld12;
  539. __strgtold12(&ld12, &EndPtr, str, 1, 0, 0, 0 );
  540. _ld12told(&ld12, ld);
  541. }
  542. void _atoflt(FLOAT *f, char *str)
  543. {
  544. const char *EndPtr;
  545. _LDBL12 ld12;
  546. __strgtold12(&ld12, &EndPtr, str, 0, 0, 0, 0 );
  547. _ld12tof(&ld12, f);
  548. }