sp_sqrt.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* IEEE754 floating point arithmetic
  2. * single precision square root
  3. */
  4. /*
  5. * MIPS floating point support
  6. * Copyright (C) 1994-2000 Algorithmics Ltd.
  7. *
  8. * ########################################################################
  9. *
  10. * This program is free software; you can distribute it and/or modify it
  11. * under the terms of the GNU General Public License (Version 2) as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  17. * for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  22. *
  23. * ########################################################################
  24. */
  25. #include "ieee754sp.h"
  26. ieee754sp ieee754sp_sqrt(ieee754sp x)
  27. {
  28. int ix, s, q, m, t, i;
  29. unsigned int r;
  30. COMPXSP;
  31. /* take care of Inf and NaN */
  32. EXPLODEXSP;
  33. CLEARCX;
  34. FLUSHXSP;
  35. /* x == INF or NAN? */
  36. switch (xc) {
  37. case IEEE754_CLASS_QNAN:
  38. /* sqrt(Nan) = Nan */
  39. return ieee754sp_nanxcpt(x, "sqrt");
  40. case IEEE754_CLASS_SNAN:
  41. SETCX(IEEE754_INVALID_OPERATION);
  42. return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
  43. case IEEE754_CLASS_ZERO:
  44. /* sqrt(0) = 0 */
  45. return x;
  46. case IEEE754_CLASS_INF:
  47. if (xs) {
  48. /* sqrt(-Inf) = Nan */
  49. SETCX(IEEE754_INVALID_OPERATION);
  50. return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
  51. }
  52. /* sqrt(+Inf) = Inf */
  53. return x;
  54. case IEEE754_CLASS_DNORM:
  55. case IEEE754_CLASS_NORM:
  56. if (xs) {
  57. /* sqrt(-x) = Nan */
  58. SETCX(IEEE754_INVALID_OPERATION);
  59. return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
  60. }
  61. break;
  62. }
  63. ix = x.bits;
  64. /* normalize x */
  65. m = (ix >> 23);
  66. if (m == 0) { /* subnormal x */
  67. for (i = 0; (ix & 0x00800000) == 0; i++)
  68. ix <<= 1;
  69. m -= i - 1;
  70. }
  71. m -= 127; /* unbias exponent */
  72. ix = (ix & 0x007fffff) | 0x00800000;
  73. if (m & 1) /* odd m, double x to make it even */
  74. ix += ix;
  75. m >>= 1; /* m = [m/2] */
  76. /* generate sqrt(x) bit by bit */
  77. ix += ix;
  78. q = s = 0; /* q = sqrt(x) */
  79. r = 0x01000000; /* r = moving bit from right to left */
  80. while (r != 0) {
  81. t = s + r;
  82. if (t <= ix) {
  83. s = t + r;
  84. ix -= t;
  85. q += r;
  86. }
  87. ix += ix;
  88. r >>= 1;
  89. }
  90. if (ix != 0) {
  91. SETCX(IEEE754_INEXACT);
  92. switch (ieee754_csr.rm) {
  93. case IEEE754_RP:
  94. q += 2;
  95. break;
  96. case IEEE754_RN:
  97. q += (q & 1);
  98. break;
  99. }
  100. }
  101. ix = (q >> 1) + 0x3f000000;
  102. ix += (m << 23);
  103. x.bits = ix;
  104. return x;
  105. }