1
0

__rem_pio2f.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */
  2. /*
  3. * Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
  4. * Debugged and optimized by Bruce D. Evans.
  5. */
  6. /*
  7. * ====================================================
  8. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  9. *
  10. * Developed at SunPro, a Sun Microsystems, Inc. business.
  11. * Permission to use, copy, modify, and distribute this
  12. * software is freely granted, provided that this notice
  13. * is preserved.
  14. * ====================================================
  15. */
  16. /* __rem_pio2f(x,y)
  17. *
  18. * return the remainder of x rem pi/2 in *y
  19. * use double precision for everything except passing x
  20. * use __rem_pio2_large() for large x
  21. */
  22. #include "libm.h"
  23. /*
  24. * invpio2: 53 bits of 2/pi
  25. * pio2_1: first 33 bit of pi/2
  26. * pio2_1t: pi/2 - pio2_1
  27. */
  28. static const double
  29. invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
  30. pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
  31. pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
  32. int __rem_pio2f(float x, double *y)
  33. {
  34. double w,r,fn;
  35. double tx[1],ty[1];
  36. float z;
  37. int32_t e0,n,ix,hx;
  38. GET_FLOAT_WORD(hx, x);
  39. ix = hx & 0x7fffffff;
  40. /* 33+53 bit pi is good enough for medium size */
  41. if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
  42. /* Use a specialized rint() to get fn. Assume round-to-nearest. */
  43. STRICT_ASSIGN(double, fn, x*invpio2 + 0x1.8p52);
  44. fn = fn - 0x1.8p52;
  45. // FIXME
  46. #ifdef HAVE_EFFICIENT_IRINT
  47. n = irint(fn);
  48. #else
  49. n = (int32_t)fn;
  50. #endif
  51. r = x - fn*pio2_1;
  52. w = fn*pio2_1t;
  53. *y = r - w;
  54. return n;
  55. }
  56. /*
  57. * all other (large) arguments
  58. */
  59. if(ix>=0x7f800000) { /* x is inf or NaN */
  60. *y = x-x;
  61. return 0;
  62. }
  63. /* set z = scalbn(|x|,ilogb(|x|)-23) */
  64. e0 = (ix>>23) - 150; /* e0 = ilogb(|x|)-23; */
  65. SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
  66. tx[0] = z;
  67. n = __rem_pio2_large(tx,ty,e0,1,0);
  68. if (hx < 0) {
  69. *y = -ty[0];
  70. return -n;
  71. }
  72. *y = ty[0];
  73. return n;
  74. }