frexp.c 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include <math.h>
  2. #include <errno.h>
  3. #define _RESEARCH_SOURCE
  4. #include <float.h>
  5. #define MASK 0x7ffL
  6. #define SHIFT 20
  7. #define BIAS 1022L
  8. #define SIG 52
  9. typedef union
  10. {
  11. double d;
  12. struct
  13. {
  14. #ifdef IEEE_8087
  15. long ls;
  16. long ms;
  17. #else
  18. long ms;
  19. long ls;
  20. #endif
  21. };
  22. } Cheat;
  23. double
  24. frexp(double d, int *ep)
  25. {
  26. Cheat x, a;
  27. *ep = 0;
  28. /* order matters: only isNaN can operate on NaN */
  29. if(isNaN(d) || isInf(d, 0) || d == 0)
  30. return d;
  31. x.d = d;
  32. a.d = fabs(d);
  33. if((a.ms >> SHIFT) == 0){ /* normalize subnormal numbers */
  34. x.d = (double)(1ULL<<SIG) * d;
  35. *ep = -SIG;
  36. }
  37. *ep = ((x.ms >> SHIFT) & MASK) - BIAS;
  38. x.ms &= ~(MASK << SHIFT);
  39. x.ms |= BIAS << SHIFT;
  40. return x.d;
  41. }
  42. double
  43. ldexp(double d, int e)
  44. {
  45. Cheat x;
  46. if(d == 0)
  47. return 0;
  48. x.d = d;
  49. e += (x.ms >> SHIFT) & MASK;
  50. if(e <= 0)
  51. return 0;
  52. if(e >= MASK){
  53. errno = ERANGE;
  54. if(d < 0)
  55. return -HUGE_VAL;
  56. return HUGE_VAL;
  57. }
  58. x.ms &= ~(MASK << SHIFT);
  59. x.ms |= (long)e << SHIFT;
  60. return x.d;
  61. }
  62. double
  63. modf(double d, double *ip)
  64. {
  65. double f;
  66. Cheat x;
  67. int e;
  68. if(d < 1) {
  69. if(d < 0) {
  70. f = modf(-d, ip);
  71. *ip = -*ip;
  72. return -f;
  73. }
  74. *ip = 0;
  75. return d;
  76. }
  77. x.d = d;
  78. e = ((x.ms >> SHIFT) & MASK) - BIAS;
  79. if(e <= SHIFT+1) {
  80. x.ms &= ~(0x1fffffL >> e);
  81. x.ls = 0;
  82. } else
  83. if(e <= SHIFT+33)
  84. x.ls &= ~(0x7fffffffL >> (e-SHIFT-2));
  85. *ip = x.d;
  86. return d - x.d;
  87. }