frexp.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. double
  12. frexp(double d, int *ep)
  13. {
  14. FPdbleword x;
  15. if(d == 0) {
  16. *ep = 0;
  17. return 0;
  18. }
  19. x.x = d;
  20. *ep = ((x.hi >> SHIFT) & MASK) - BIAS;
  21. x.hi &= ~(MASK << SHIFT);
  22. x.hi |= BIAS << SHIFT;
  23. return x.x;
  24. }
  25. double
  26. ldexp(double d, int deltae)
  27. {
  28. int e, bits;
  29. FPdbleword x;
  30. ulong z;
  31. if(d == 0)
  32. return 0;
  33. x.x = d;
  34. e = (x.hi >> SHIFT) & MASK;
  35. if(deltae >= 0 || e+deltae >= 1){ /* no underflow */
  36. e += deltae;
  37. if(e >= MASK){ /* overflow */
  38. if(d < 0)
  39. return Inf(-1);
  40. return Inf(1);
  41. }
  42. }else{ /* underflow gracefully */
  43. deltae = -deltae;
  44. /* need to shift d right deltae */
  45. if(e > 1){ /* shift e-1 by exponent manipulation */
  46. deltae -= e-1;
  47. e = 1;
  48. }
  49. if(deltae > 0 && e==1){ /* shift 1 by switch from 1.fff to 0.1ff */
  50. deltae--;
  51. e = 0;
  52. x.lo >>= 1;
  53. x.lo |= (x.hi&1)<<31;
  54. z = x.hi & ((1<<SHIFT)-1);
  55. x.hi &= ~((1<<SHIFT)-1);
  56. x.hi |= (1<<(SHIFT-1)) | (z>>1);
  57. }
  58. while(deltae > 0){ /* shift bits down */
  59. bits = deltae;
  60. if(bits > SHIFT)
  61. bits = SHIFT;
  62. x.lo >>= bits;
  63. x.lo |= (x.hi&((1<<bits)-1)) << (32-bits);
  64. z = x.hi & ((1<<SHIFT)-1);
  65. x.hi &= ~((1<<SHIFT)-1);
  66. x.hi |= z>>bits;
  67. deltae -= bits;
  68. }
  69. }
  70. x.hi &= ~(MASK << SHIFT);
  71. x.hi |= (long)e << SHIFT;
  72. return x.x;
  73. }
  74. double
  75. modf(double d, double *ip)
  76. {
  77. FPdbleword x;
  78. int e;
  79. if(d < 1) {
  80. if(d < 0) {
  81. x.x = modf(-d, ip);
  82. *ip = -*ip;
  83. return -x.x;
  84. }
  85. *ip = 0;
  86. return d;
  87. }
  88. x.x = d;
  89. e = ((x.hi >> SHIFT) & MASK) - BIAS;
  90. if(e <= SHIFT+1) {
  91. x.hi &= ~(0x1fffffL >> e);
  92. x.lo = 0;
  93. } else
  94. if(e <= SHIFT+33)
  95. x.lo &= ~(0x7fffffffL >> (e-SHIFT-2));
  96. *ip = x.x;
  97. return d - x.x;
  98. }