s_remquol.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /* @(#)e_fmod.c 1.3 95/01/18 */
  2. /*-
  3. * ====================================================
  4. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  5. *
  6. * Developed at SunSoft, a Sun Microsystems, Inc. business.
  7. * Permission to use, copy, modify, and distribute this
  8. * software is freely granted, provided that this notice
  9. * is preserved.
  10. * ====================================================
  11. */
  12. #include <sys/types.h>
  13. #include <machine/ieee.h>
  14. #include <float.h>
  15. #include <openlibm_math.h>
  16. #include <stdint.h>
  17. #include "math_private.h"
  18. #define BIAS (LDBL_MAX_EXP - 1)
  19. /*
  20. * These macros add and remove an explicit integer bit in front of the
  21. * fractional mantissa, if the architecture doesn't have such a bit by
  22. * default already.
  23. */
  24. #ifdef LDBL_IMPLICIT_NBIT
  25. #define LDBL_NBIT 0
  26. #define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE))
  27. #define HFRAC_BITS (EXT_FRACHBITS + EXT_FRACHMBITS)
  28. #else
  29. #define LDBL_NBIT 0x80000000
  30. #define SET_NBIT(hx) (hx)
  31. #define HFRAC_BITS (EXT_FRACHBITS + EXT_FRACHMBITS - 1)
  32. #endif
  33. #define MANL_SHIFT (EXT_FRACLMBITS + EXT_FRACLBITS - 1)
  34. static const long double Zero[] = {0.0L, -0.0L};
  35. /*
  36. * Return the IEEE remainder and set *quo to the last n bits of the
  37. * quotient, rounded to the nearest integer. We choose n=31 because
  38. * we wind up computing all the integer bits of the quotient anyway as
  39. * a side-effect of computing the remainder by the shift and subtract
  40. * method. In practice, this is far more bits than are needed to use
  41. * remquo in reduction algorithms.
  42. *
  43. * Assumptions:
  44. * - The low part of the mantissa fits in a manl_t exactly.
  45. * - The high part of the mantissa fits in an int64_t with enough room
  46. * for an explicit integer bit in front of the fractional bits.
  47. */
  48. long double
  49. remquol(long double x, long double y, int *quo)
  50. {
  51. int64_t hx,hz,hy,_hx;
  52. uint64_t lx,ly,lz;
  53. uint64_t sx,sxy;
  54. int ix,iy,n,q;
  55. GET_LDOUBLE_WORDS64(hx,lx,x);
  56. GET_LDOUBLE_WORDS64(hy,ly,y);
  57. sx = (hx>>48)&0x8000;
  58. sxy = sx ^ ((hy>>48)&0x8000);
  59. hx &= 0x7fffffffffffffffLL; /* |x| */
  60. hy &= 0x7fffffffffffffffLL; /* |y| */
  61. SET_LDOUBLE_WORDS64(x,hx,lx);
  62. SET_LDOUBLE_WORDS64(y,hy,ly);
  63. /* purge off exception values */
  64. if((hy|ly)==0 || /* y=0 */
  65. ((hx>>48) == BIAS + LDBL_MAX_EXP) || /* or x not finite */
  66. ((hy>>48) == BIAS + LDBL_MAX_EXP &&
  67. (((hy&0x0000ffffffffffffLL)&~LDBL_NBIT)|ly)!=0)) /* or y is NaN */
  68. return (x*y)/(x*y);
  69. if((hx>>48)<=(hy>>48)) {
  70. if(((hx>>48)<(hy>>48)) ||
  71. ((hx&0x0000ffffffffffffLL)<=(hy&0x0000ffffffffffffLL) &&
  72. ((hx&0x0000ffffffffffffLL)<(hy&0x0000ffffffffffffLL) ||
  73. lx<ly))) {
  74. q = 0;
  75. goto fixup; /* |x|<|y| return x or x-y */
  76. }
  77. if((hx&0x0000ffffffffffffLL)==(hy&0x0000ffffffffffffLL) &&
  78. lx==ly) {
  79. *quo = 1;
  80. return Zero[sx!=0]; /* |x|=|y| return x*0*/
  81. }
  82. }
  83. /* determine ix = ilogb(x) */
  84. if((hx>>48) == 0) { /* subnormal x */
  85. x *= 0x1.0p512;
  86. GET_LDOUBLE_WORDS64(hx,lx,x);
  87. ix = (hx>>48) - (BIAS + 512);
  88. } else {
  89. ix = (hx>>48) - BIAS;
  90. }
  91. /* determine iy = ilogb(y) */
  92. if((hy>>48) == 0) { /* subnormal y */
  93. y *= 0x1.0p512;
  94. GET_LDOUBLE_WORDS64(hy,ly,y);
  95. iy = (hy>>48) - (BIAS + 512);
  96. } else {
  97. iy = (hy>>48) - BIAS;
  98. }
  99. /* set up {hx,lx}, {hy,ly} and align y to x */
  100. _hx = SET_NBIT(hx) & 0x0000ffffffffffffLL;
  101. hy = SET_NBIT(hy);
  102. /* fix point fmod */
  103. n = ix - iy;
  104. q = 0;
  105. while(n--) {
  106. hz=_hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
  107. if(hz<0){_hx = _hx+_hx+(lx>>MANL_SHIFT); lx = lx+lx;}
  108. else {_hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
  109. q <<= 1;
  110. }
  111. hz=_hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
  112. if(hz>=0) {_hx=hz;lx=lz;q++;}
  113. /* convert back to floating value and restore the sign */
  114. if((_hx|lx)==0) { /* return sign(x)*0 */
  115. *quo = (sxy ? -q : q);
  116. return Zero[sx!=0];
  117. }
  118. while(_hx<(1ULL<<HFRAC_BITS)) { /* normalize x */
  119. _hx = _hx+_hx+(lx>>MANL_SHIFT); lx = lx+lx;
  120. iy -= 1;
  121. }
  122. hx = (hx&0xffff000000000000LL) | (_hx&0x0000ffffffffffffLL);
  123. if (iy < LDBL_MIN_EXP) {
  124. hx = (hx&0x0000ffffffffffffLL) | (uint64_t)(iy + BIAS + 512)<<48;
  125. SET_LDOUBLE_WORDS64(x,hx,lx);
  126. x *= 0x1p-512;
  127. GET_LDOUBLE_WORDS64(hx,lx,x);
  128. } else {
  129. hx = (hx&0x0000ffffffffffffLL) | (uint64_t)(iy + BIAS)<<48;
  130. }
  131. hx &= 0x7fffffffffffffffLL;
  132. SET_LDOUBLE_WORDS64(x,hx,lx);
  133. fixup:
  134. y = fabsl(y);
  135. if (y < LDBL_MIN * 2) {
  136. if (x+x>y || (x+x==y && (q & 1))) {
  137. q++;
  138. x-=y;
  139. }
  140. } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
  141. q++;
  142. x-=y;
  143. }
  144. GET_LDOUBLE_MSW64(hx,x);
  145. hx ^= sx;
  146. SET_LDOUBLE_MSW64(x,hx);
  147. q &= 0x7fffffff;
  148. *quo = (sxy ? -q : q);
  149. return x;
  150. }