sqrt.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* sqrt.c
  2. *
  3. * Square root
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double x, y, sqrt();
  10. *
  11. * y = sqrt( x );
  12. *
  13. *
  14. *
  15. * DESCRIPTION:
  16. *
  17. * Returns the square root of x.
  18. *
  19. * Range reduction involves isolating the power of two of the
  20. * argument and using a polynomial approximation to obtain
  21. * a rough value for the square root. Then Heron's iteration
  22. * is used three times to converge to an accurate value.
  23. *
  24. *
  25. *
  26. * ACCURACY:
  27. *
  28. *
  29. * Relative error:
  30. * arithmetic domain # trials peak rms
  31. * DEC 0, 10 60000 2.1e-17 7.9e-18
  32. * IEEE 0,1.7e308 30000 1.7e-16 6.3e-17
  33. *
  34. *
  35. * ERROR MESSAGES:
  36. *
  37. * message condition value returned
  38. * sqrt domain x < 0 0.0
  39. *
  40. */
  41. /*
  42. Cephes Math Library Release 2.8: June, 2000
  43. Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
  44. */
  45. #include <math.h>
  46. #ifdef ANSIPROT
  47. extern double frexp ( double, int * );
  48. extern double ldexp ( double, int );
  49. #else
  50. double frexp(), ldexp();
  51. #endif
  52. extern double SQRT2; /* SQRT2 = 1.41421356237309504880 */
  53. double sqrt(x)
  54. double x;
  55. {
  56. int e;
  57. #ifndef UNK
  58. short *q;
  59. #endif
  60. double z, w;
  61. if( x <= 0.0 )
  62. {
  63. if( x < 0.0 )
  64. mtherr( "sqrt", DOMAIN );
  65. return( 0.0 );
  66. }
  67. w = x;
  68. /* separate exponent and significand */
  69. #ifdef UNK
  70. z = frexp( x, &e );
  71. #endif
  72. #ifdef DEC
  73. q = (short *)&x;
  74. e = ((*q >> 7) & 0377) - 0200;
  75. *q &= 0177;
  76. *q |= 040000;
  77. z = x;
  78. #endif
  79. /* Note, frexp and ldexp are used in order to
  80. * handle denormal numbers properly.
  81. */
  82. #ifdef IBMPC
  83. z = frexp( x, &e );
  84. q = (short *)&x;
  85. q += 3;
  86. /*
  87. e = ((*q >> 4) & 0x0fff) - 0x3fe;
  88. *q &= 0x000f;
  89. *q |= 0x3fe0;
  90. z = x;
  91. */
  92. #endif
  93. #ifdef MIEEE
  94. z = frexp( x, &e );
  95. q = (short *)&x;
  96. /*
  97. e = ((*q >> 4) & 0x0fff) - 0x3fe;
  98. *q &= 0x000f;
  99. *q |= 0x3fe0;
  100. z = x;
  101. */
  102. #endif
  103. /* approximate square root of number between 0.5 and 1
  104. * relative error of approximation = 7.47e-3
  105. */
  106. x = 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
  107. /* adjust for odd powers of 2 */
  108. if( (e & 1) != 0 )
  109. x *= SQRT2;
  110. /* re-insert exponent */
  111. #ifdef UNK
  112. x = ldexp( x, (e >> 1) );
  113. #endif
  114. #ifdef DEC
  115. *q += ((e >> 1) & 0377) << 7;
  116. *q &= 077777;
  117. #endif
  118. #ifdef IBMPC
  119. x = ldexp( x, (e >> 1) );
  120. /*
  121. *q += ((e >>1) & 0x7ff) << 4;
  122. *q &= 077777;
  123. */
  124. #endif
  125. #ifdef MIEEE
  126. x = ldexp( x, (e >> 1) );
  127. /*
  128. *q += ((e >>1) & 0x7ff) << 4;
  129. *q &= 077777;
  130. */
  131. #endif
  132. /* Newton iterations: */
  133. #ifdef UNK
  134. x = 0.5*(x + w/x);
  135. x = 0.5*(x + w/x);
  136. x = 0.5*(x + w/x);
  137. #endif
  138. /* Note, assume the square root cannot be denormal,
  139. * so it is safe to use integer exponent operations here.
  140. */
  141. #ifdef DEC
  142. x += w/x;
  143. *q -= 0200;
  144. x += w/x;
  145. *q -= 0200;
  146. x += w/x;
  147. *q -= 0200;
  148. #endif
  149. #ifdef IBMPC
  150. x += w/x;
  151. *q -= 0x10;
  152. x += w/x;
  153. *q -= 0x10;
  154. x += w/x;
  155. *q -= 0x10;
  156. #endif
  157. #ifdef MIEEE
  158. x += w/x;
  159. *q -= 0x10;
  160. x += w/x;
  161. *q -= 0x10;
  162. x += w/x;
  163. *q -= 0x10;
  164. #endif
  165. return(x);
  166. }