s_remquol.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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
  28. #else
  29. #define LDBL_NBIT 0x80000000
  30. #define SET_NBIT(hx) (hx)
  31. #define HFRAC_BITS (EXT_FRACHBITS - 1)
  32. #endif
  33. #define MANL_SHIFT (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; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */
  52. uint32_t hy;
  53. uint32_t lx,ly,lz;
  54. uint32_t esx, esy;
  55. int ix,iy,n,q,sx,sxy;
  56. GET_LDOUBLE_WORDS(esx,hx,lx,x);
  57. GET_LDOUBLE_WORDS(esy,hy,ly,y);
  58. sx = esx & 0x8000;
  59. sxy = sx ^ (esy & 0x8000);
  60. esx &= 0x7fff; /* |x| */
  61. esy &= 0x7fff; /* |y| */
  62. SET_LDOUBLE_EXP(x,esx);
  63. SET_LDOUBLE_EXP(y,esy);
  64. /* purge off exception values */
  65. if((esy|hy|ly)==0 || /* y=0 */
  66. (esx == BIAS + LDBL_MAX_EXP) || /* or x not finite */
  67. (esy == BIAS + LDBL_MAX_EXP &&
  68. ((hy&~LDBL_NBIT)|ly)!=0)) /* or y is NaN */
  69. return (x*y)/(x*y);
  70. if(esx<=esy) {
  71. if((esx<esy) ||
  72. (hx<=hy &&
  73. (hx<hy ||
  74. lx<ly))) {
  75. q = 0;
  76. goto fixup; /* |x|<|y| return x or x-y */
  77. }
  78. if(hx==hy && lx==ly) {
  79. *quo = 1;
  80. return Zero[sx!=0]; /* |x|=|y| return x*0*/
  81. }
  82. }
  83. /* determine ix = ilogb(x) */
  84. if(esx == 0) { /* subnormal x */
  85. x *= 0x1.0p512;
  86. GET_LDOUBLE_WORDS(esx,hx,lx,x);
  87. ix = esx - (BIAS + 512);
  88. } else {
  89. ix = esx - BIAS;
  90. }
  91. /* determine iy = ilogb(y) */
  92. if(esy == 0) { /* subnormal y */
  93. y *= 0x1.0p512;
  94. GET_LDOUBLE_WORDS(esy,hy,ly,y);
  95. iy = esy - (BIAS + 512);
  96. } else {
  97. iy = esy - BIAS;
  98. }
  99. /* set up {hx,lx}, {hy,ly} and align y to x */
  100. hx = SET_NBIT(hx);
  101. lx = SET_NBIT(lx);
  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. if (iy < LDBL_MIN_EXP) {
  123. esx = (iy + BIAS + 512) & 0x7fff;
  124. SET_LDOUBLE_WORDS(x,esx,hx,lx);
  125. x *= 0x1p-512;
  126. GET_LDOUBLE_WORDS(esx,hx,lx,x);
  127. } else {
  128. esx = (iy + BIAS) & 0x7fff;
  129. }
  130. SET_LDOUBLE_WORDS(x,esx,hx,lx);
  131. fixup:
  132. y = fabsl(y);
  133. if (y < LDBL_MIN * 2) {
  134. if (x+x>y || (x+x==y && (q & 1))) {
  135. q++;
  136. x-=y;
  137. }
  138. } else if (x>0.5*y || (x==0.5*y && (q & 1))) {
  139. q++;
  140. x-=y;
  141. }
  142. GET_LDOUBLE_EXP(esx,x);
  143. esx ^= sx;
  144. SET_LDOUBLE_EXP(x,esx);
  145. q &= 0x7fffffff;
  146. *quo = (sxy ? -q : q);
  147. return x;
  148. }