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.

244 lines
6.4 KiB

  1. /***
  2. *tenpow.c - multiply a _LDBL12 by a power of 10
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 07-17-91 GDP Initial version (ported from assembly)
  10. * 11-15-93 GJF Merged in NT SDK verions. Replaced MIPS and _ALPHA_
  11. * by _M_MRX000 and _M_ALPHA (resp.).
  12. * 10-02-94 BWT PPC changes
  13. * 07-15-96 GJF Added parantheses to fix precedence problem in expr.
  14. * Also, detab-ed.
  15. * 05-05-99 RDL Added _M_IA64 to #if def's for alignment.
  16. * 07-15-01 PML Remove all ALPHA, MIPS, and PPC code
  17. *
  18. *******************************************************************************/
  19. #include <cv.h>
  20. extern _LDBL12 _pow10pos[];
  21. extern _LDBL12 _pow10neg[];
  22. /***
  23. *void _CALLTYPE5 __ld12mul(_LDBL12 *px, _LDBL12 *py) -
  24. * _LDBL12 multiplication
  25. *
  26. *Purpose: multiply two _LDBL12 numbers
  27. *
  28. *Entry: px,py: pointers to the _LDBL12 operands
  29. *
  30. *Exit: *px contains the product
  31. *
  32. *Exceptions:
  33. *
  34. *******************************************************************************/
  35. void _CALLTYPE5 __ld12mul(_LDBL12 *px, _LDBL12 *py)
  36. {
  37. u_short sign = 0;
  38. _LDBL12 tempman; /*this is actually a 12-byte mantissa,
  39. not a 12-byte long double */
  40. int i;
  41. u_short expx, expy, expsum;
  42. int roffs,poffs,qoffs;
  43. int sticky = 0;
  44. *UL_LO_12(&tempman) = 0;
  45. *UL_MED_12(&tempman) = 0;
  46. *UL_HI_12(&tempman) = 0;
  47. expx = *U_EXP_12(px);
  48. expy = *U_EXP_12(py);
  49. sign = (expx ^ expy) & (u_short)0x8000;
  50. expx &= 0x7fff;
  51. expy &= 0x7fff;
  52. expsum = expx+expy;
  53. if (expx >= LD_MAXEXP
  54. || expy >= LD_MAXEXP
  55. || expsum > LD_MAXEXP+ LD_BIASM1){
  56. /* overflow to infinity */
  57. PUT_INF_12(px,sign);
  58. return;
  59. }
  60. if (expsum <= LD_BIASM1-63) {
  61. /* underflow to zero */
  62. PUT_ZERO_12(px);
  63. return;
  64. }
  65. if (expx == 0) {
  66. /*
  67. * If this is a denormal temp real then the mantissa
  68. * was shifted right once to set bit 63 to zero.
  69. */
  70. expsum++; /* Correct for this */
  71. if (ISZERO_12(px)) {
  72. /* put positive sign */
  73. *U_EXP_12(px) = 0;
  74. return;
  75. }
  76. }
  77. if (expy == 0) {
  78. expsum++; /* because arg2 is denormal */
  79. if (ISZERO_12(py)) {
  80. PUT_ZERO_12(px);
  81. return;
  82. }
  83. }
  84. roffs = 0;
  85. for (i=0;i<5;i++) {
  86. int j;
  87. poffs = i<<1;
  88. qoffs = 8;
  89. for (j=5-i;j>0;j--) {
  90. u_long prod;
  91. #if defined(_M_IA64) || defined(_M_AMD64)
  92. /* a variable to hold temprary sums */
  93. u_long sum;
  94. #endif
  95. int carry;
  96. u_short *p, *q;
  97. u_long *r;
  98. p = USHORT_12(px,poffs);
  99. q = USHORT_12(py,qoffs);
  100. r = ULONG_12(&tempman,roffs);
  101. prod = (u_long)*p * (u_long)*q;
  102. #if defined(_M_IA64) || defined(_M_AMD64)
  103. /* handle misalignment problems */
  104. if (i&0x1){ /* i is odd */
  105. carry = __addl(*ALIGN(r), prod, &sum);
  106. *ALIGN(r) = sum;
  107. }
  108. else /* i is even */
  109. carry = __addl(*r, prod, r);
  110. #else
  111. carry = __addl(*r,prod,r);
  112. #endif
  113. if (carry) {
  114. /* roffs should be less than 8 in this case */
  115. (*USHORT_12(&tempman,roffs+4))++;
  116. }
  117. poffs+=2;
  118. qoffs-=2;
  119. }
  120. roffs+=2;
  121. }
  122. expsum -= LD_BIASM1;
  123. /* normalize */
  124. while ((s_short)expsum > 0 &&
  125. ((*UL_HI_12(&tempman) & MSB_ULONG) == 0)) {
  126. __shl_12(&tempman);
  127. expsum--;
  128. }
  129. if ((s_short)expsum <= 0) {
  130. expsum--;
  131. while ((s_short)expsum < 0) {
  132. if (*U_XT_12(&tempman) & 0x1)
  133. sticky++;
  134. __shr_12(&tempman);
  135. expsum++;
  136. }
  137. if (sticky)
  138. *U_XT_12(&tempman) |= 0x1;
  139. }
  140. if (*U_XT_12(&tempman) > 0x8000 ||
  141. ((*UL_LO_12(&tempman) & 0x1ffff) == 0x18000)) {
  142. /* round up */
  143. if (*UL_MANLO_12(&tempman) == MAX_ULONG) {
  144. *UL_MANLO_12(&tempman) = 0;
  145. if (*UL_MANHI_12(&tempman) == MAX_ULONG) {
  146. *UL_MANHI_12(&tempman) = 0;
  147. if (*U_EXP_12(&tempman) == MAX_USHORT) {
  148. /* 12-byte mantissa overflow */
  149. *U_EXP_12(&tempman) = MSB_USHORT;
  150. expsum++;
  151. }
  152. else
  153. (*U_EXP_12(&tempman))++;
  154. }
  155. else
  156. (*UL_MANHI_12(&tempman))++;
  157. }
  158. else
  159. (*UL_MANLO_12(&tempman))++;
  160. }
  161. /* check for exponent overflow */
  162. if (expsum >= 0x7fff){
  163. PUT_INF_12(px, sign);
  164. return;
  165. }
  166. /* put result in px */
  167. *U_XT_12(px) = *USHORT_12(&tempman,2);
  168. *UL_MANLO_12(px) = *UL_MED_12(&tempman);
  169. *UL_MANHI_12(px) = *UL_HI_12(&tempman);
  170. *U_EXP_12(px) = expsum | sign;
  171. }
  172. void _CALLTYPE5
  173. __multtenpow12(_LDBL12 *pld12, int pow, unsigned mult12)
  174. {
  175. _LDBL12 *pow_10p = _pow10pos-8;
  176. if (pow == 0)
  177. return;
  178. if (pow < 0) {
  179. pow = -pow;
  180. pow_10p = _pow10neg-8;
  181. }
  182. if (!mult12)
  183. *U_XT_12(pld12) = 0;
  184. while (pow) {
  185. int last3; /* the 3 LSBits of pow */
  186. _LDBL12 unround;
  187. _LDBL12 *py;
  188. pow_10p += 7;
  189. last3 = pow & 0x7;
  190. pow >>= 3;
  191. if (last3 == 0)
  192. continue;
  193. py = pow_10p + last3;
  194. #ifdef _LDSUPPORT
  195. if (mult12) {
  196. #endif
  197. /* do an exact 12byte multiplication */
  198. if (*U_XT_12(py) >= 0x8000) {
  199. /* copy number */
  200. unround = *py;
  201. /* unround adjacent byte */
  202. (*UL_MANLO_12(&unround))--;
  203. /* point to new operand */
  204. py = &unround;
  205. }
  206. __ld12mul(pld12,py);
  207. #ifdef _LDSUPPORT
  208. }
  209. else {
  210. /* do a 10byte multiplication */
  211. py = (_LDBL12 *)TEN_BYTE_PART(py);
  212. *(long double *)TEN_BYTE_PART(pld12) *=
  213. *(long double *)py;
  214. }
  215. #endif
  216. }
  217. }