frexp.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include <u.h>
  2. #include <libc.h>
  3. /*
  4. * this is big/little endian non-portable
  5. * it gets the endian from the FPdbleword
  6. * union in u.h.
  7. */
  8. #define MASK 0x7ffL
  9. #define SHIFT 20
  10. #define BIAS 1022L
  11. #define SIG 52
  12. double
  13. frexp(double d, int *ep)
  14. {
  15. FPdbleword x, a;
  16. *ep = 0;
  17. /* order matters: only isNaN can operate on NaN */
  18. if(isNaN(d) || isInf(d, 0) || d == 0)
  19. return d;
  20. x.x = d;
  21. a.x = fabs(d);
  22. if((a.hi >> SHIFT) == 0){ /* normalize subnormal numbers */
  23. x.x = (double)(1ULL<<SIG) * d;
  24. *ep = -SIG;
  25. }
  26. *ep += ((x.hi >> SHIFT) & MASK) - BIAS;
  27. x.hi &= ~(MASK << SHIFT);
  28. x.hi |= BIAS << SHIFT;
  29. return x.x;
  30. }
  31. double
  32. ldexp(double d, int deltae)
  33. {
  34. int e, bits;
  35. FPdbleword x;
  36. ulong z;
  37. if(d == 0)
  38. return 0;
  39. x.x = d;
  40. e = (x.hi >> SHIFT) & MASK;
  41. if(deltae >= 0 || e+deltae >= 1){ /* no underflow */
  42. e += deltae;
  43. if(e >= MASK){ /* overflow */
  44. if(d < 0)
  45. return Inf(-1);
  46. return Inf(1);
  47. }
  48. }else{ /* underflow gracefully */
  49. deltae = -deltae;
  50. /* need to shift d right deltae */
  51. if(e > 1){ /* shift e-1 by exponent manipulation */
  52. deltae -= e-1;
  53. e = 1;
  54. }
  55. if(deltae > 0 && e==1){ /* shift 1 by switch from 1.fff to 0.1ff */
  56. deltae--;
  57. e = 0;
  58. x.lo >>= 1;
  59. x.lo |= (x.hi&1)<<31;
  60. z = x.hi & ((1<<SHIFT)-1);
  61. x.hi &= ~((1<<SHIFT)-1);
  62. x.hi |= (1<<(SHIFT-1)) | (z>>1);
  63. }
  64. while(deltae > 0){ /* shift bits down */
  65. bits = deltae;
  66. if(bits > SHIFT)
  67. bits = SHIFT;
  68. x.lo >>= bits;
  69. x.lo |= (x.hi&((1<<bits)-1)) << (32-bits);
  70. z = x.hi & ((1<<SHIFT)-1);
  71. x.hi &= ~((1<<SHIFT)-1);
  72. x.hi |= z>>bits;
  73. deltae -= bits;
  74. }
  75. }
  76. x.hi &= ~(MASK << SHIFT);
  77. x.hi |= (long)e << SHIFT;
  78. return x.x;
  79. }
  80. double
  81. modf(double d, double *ip)
  82. {
  83. FPdbleword x;
  84. int e;
  85. if(d < 1) {
  86. if(d < 0) {
  87. x.x = modf(-d, ip);
  88. *ip = -*ip;
  89. return -x.x;
  90. }
  91. *ip = 0;
  92. return d;
  93. }
  94. x.x = d;
  95. e = ((x.hi >> SHIFT) & MASK) - BIAS;
  96. if(e <= SHIFT+1) {
  97. x.hi &= ~(0x1fffffL >> e);
  98. x.lo = 0;
  99. } else
  100. if(e <= SHIFT+33)
  101. x.lo &= ~(0x7fffffffL >> (e-SHIFT-2));
  102. *ip = x.x;
  103. return d - x.x;
  104. }