s_nexttoward.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /* @(#)s_nextafter.c 5.1 93/09/24 */
  2. /*
  3. * ====================================================
  4. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  5. *
  6. * Developed at SunPro, 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. /* IEEE functions
  13. * nexttoward(x,y)
  14. * return the next machine floating-point number of x in the
  15. * direction toward y.
  16. * Special cases:
  17. */
  18. #include <float.h>
  19. #include <openlibm_math.h>
  20. #include "math_private.h"
  21. double
  22. nexttoward(double x, long double y)
  23. {
  24. int32_t hx,ix,iy;
  25. u_int32_t lx,hy,ly,esy;
  26. EXTRACT_WORDS(hx,lx,x);
  27. GET_LDOUBLE_WORDS(esy,hy,ly,y);
  28. ix = hx&0x7fffffff; /* |x| */
  29. iy = esy&0x7fff; /* |y| */
  30. if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */
  31. ((iy>=0x7fff)&&(hy|ly)!=0)) /* y is nan */
  32. return x+y;
  33. if((long double) x==y) return y; /* x=y, return y */
  34. if((ix|lx)==0) { /* x == 0 */
  35. volatile double u;
  36. INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */
  37. u = x;
  38. u = u * u; /* raise underflow flag */
  39. return x;
  40. }
  41. if(hx>=0) { /* x > 0 */
  42. if (esy>=0x8000||((ix>>20)&0x7ff)>iy-0x3c00
  43. || (((ix>>20)&0x7ff)==iy-0x3c00
  44. && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
  45. || (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
  46. && (lx<<11)>ly)))) { /* x > y, x -= ulp */
  47. if(lx==0) hx -= 1;
  48. lx -= 1;
  49. } else { /* x < y, x += ulp */
  50. lx += 1;
  51. if(lx==0) hx += 1;
  52. }
  53. } else { /* x < 0 */
  54. if (esy<0x8000||((ix>>20)&0x7ff)>iy-0x3c00
  55. || (((ix>>20)&0x7ff)==iy-0x3c00
  56. && (((hx<<11)|(lx>>21))>(hy&0x7fffffff)
  57. || (((hx<<11)|(lx>>21))==(hy&0x7fffffff)
  58. && (lx<<11)>ly)))) {/* x < y, x -= ulp */
  59. if(lx==0) hx -= 1;
  60. lx -= 1;
  61. } else { /* x > y, x += ulp */
  62. lx += 1;
  63. if(lx==0) hx += 1;
  64. }
  65. }
  66. hy = hx&0x7ff00000;
  67. if(hy>=0x7ff00000) {
  68. x = x+x; /* overflow */
  69. return x;
  70. }
  71. if(hy<0x00100000) {
  72. volatile double u = x*x; /* underflow */
  73. if(u==x) {
  74. INSERT_WORDS(x,hx,lx);
  75. return x;
  76. }
  77. }
  78. INSERT_WORDS(x,hx,lx);
  79. return x;
  80. }