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.

181 lines
3.6 KiB

  1. /***
  2. *sqrt.c - square root
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 8-15-91 GDP written
  10. * 1-29-91 GDP Kahan's algorithm for final rounding
  11. * 3-11-92 GDP new interval and initial approximation
  12. * 10-07-97 RDL Added IA64.
  13. *
  14. *******************************************************************************/
  15. #ifndef R4000
  16. #include <math.h>
  17. #include <trans.h>
  18. #if defined(_M_IA64)
  19. #pragma function(sqrt)
  20. #endif
  21. //
  22. // Coefficients for initial approximation (Hart & al)
  23. //
  24. static double p00 = .2592768763e+0;
  25. static double p01 = .1052021187e+1;
  26. static double p02 = -.3163221431e+0;
  27. /***
  28. *double sqrt(double x) - square root
  29. *
  30. *Purpose:
  31. * Compute the square root of a number.
  32. * This function should be provided by the underlying
  33. * hardware (IEEE spec).
  34. *Entry:
  35. *
  36. *Exit:
  37. *
  38. *Exceptions:
  39. * I P
  40. *******************************************************************************/
  41. double sqrt(double x)
  42. {
  43. uintptr_t savedcw, sw;
  44. double result,t;
  45. uintptr_t stat,rc;
  46. savedcw = _ctrlfp(ICW, IMCW);
  47. if (IS_D_SPECIAL(x)){
  48. switch (_sptype(x)) {
  49. case T_PINF:
  50. RETURN(savedcw, x);
  51. case T_QNAN:
  52. return _handle_qnan1(OP_SQRT, x, savedcw);
  53. case T_SNAN:
  54. return _except1(FP_I,OP_SQRT,x,QNAN_SQRT,savedcw);
  55. }
  56. /* -INF will be handled in the x<0 case */
  57. }
  58. if (x < 0.0) {
  59. return _except1(FP_I, OP_SQRT, x, QNAN_SQRT,savedcw);
  60. }
  61. if (x == 0.0) {
  62. RETURN (savedcw, x);
  63. }
  64. result = _fsqrt(x);
  65. _ctrlfp(IRC_DOWN, IMCW_RC);
  66. //
  67. // Kahan's algorithm
  68. //
  69. sw = _clrfp();
  70. t = x / result;
  71. stat = _statfp();
  72. if (! (stat & ISW_INEXACT)) {
  73. // exact
  74. if (t == result) {
  75. _set_statfp(sw); // restore status word
  76. RETURN(savedcw, result);
  77. }
  78. else {
  79. // t = t-1
  80. if (*D_LO(t) == 0) {
  81. (*D_HI(t)) --;
  82. }
  83. (*D_LO(t)) --;
  84. }
  85. }
  86. rc = savedcw & IMCW_RC;
  87. if (rc == IRC_UP || rc == IRC_NEAR) {
  88. // t = t+1
  89. (*D_LO(t)) ++;
  90. if (*D_LO(t) == 0) {
  91. (*D_HI(t)) ++;
  92. }
  93. if (rc == IRC_UP) {
  94. // y = y+1
  95. (*D_LO(t)) ++;
  96. if (*D_LO(t) == 0) {
  97. (*D_HI(t)) ++;
  98. }
  99. }
  100. }
  101. result = 0.5 * (t + result);
  102. _set_statfp(sw | ISW_INEXACT); // update status word
  103. RETURN_INEXACT1(OP_SQRT, x, result, savedcw);
  104. }
  105. /***
  106. * _fsqrt - non IEEE conforming square root
  107. *
  108. *Purpose:
  109. * compute a square root of a normal number without performing
  110. * IEEE rounding. The argument is a finite number (no NaN or INF)
  111. *
  112. *Entry:
  113. *
  114. *Exit:
  115. *
  116. *Exceptions:
  117. *
  118. *******************************************************************************/
  119. double _fsqrt(double x)
  120. {
  121. double f,y,result;
  122. int n;
  123. f = _decomp(x,&n);
  124. if (n & 0x1) {
  125. // n is odd
  126. n++;
  127. f = _add_exp(f, -1);
  128. }
  129. //
  130. // approximation for sqrt in the interval [.25, 1]
  131. // (Computer Approximationsn, Hart & al.)
  132. // gives more than 7 bits of accuracy
  133. //
  134. y = p00 + f * (p01 + f * p02);
  135. y += f / y;
  136. y = _add_exp(y, -1);
  137. y += f / y;
  138. y = _add_exp(y, -1);
  139. y += f / y;
  140. y = _add_exp(y, -1);
  141. n >>= 1;
  142. result = _add_exp(y,n);
  143. return result;
  144. }
  145. #endif