s_nextafterl.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. * nextafterl(x,y)
  14. * return the next machine floating-point number of x in the
  15. * direction toward y.
  16. * Special cases:
  17. */
  18. #include <openlibm_math.h>
  19. #include "math_private.h"
  20. long double
  21. nextafterl(long double x, long double y)
  22. {
  23. int64_t hx,hy,ix,iy;
  24. u_int64_t lx,ly;
  25. GET_LDOUBLE_WORDS64(hx,lx,x);
  26. GET_LDOUBLE_WORDS64(hy,ly,y);
  27. ix = hx&0x7fffffffffffffffLL; /* |x| */
  28. iy = hy&0x7fffffffffffffffLL; /* |y| */
  29. if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) || /* x is nan */
  30. ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0)) /* y is nan */
  31. return x+y;
  32. if(x==y) return y; /* x=y, return y */
  33. if((ix|lx)==0) { /* x == 0 */
  34. volatile long double u;
  35. SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */
  36. u = x;
  37. u = u * u; /* raise underflow flag */
  38. return x;
  39. }
  40. if(hx>=0) { /* x > 0 */
  41. if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */
  42. if(lx==0) hx--;
  43. lx--;
  44. } else { /* x < y, x += ulp */
  45. lx++;
  46. if(lx==0) hx++;
  47. }
  48. } else { /* x < 0 */
  49. if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
  50. if(lx==0) hx--;
  51. lx--;
  52. } else { /* x > y, x += ulp */
  53. lx++;
  54. if(lx==0) hx++;
  55. }
  56. }
  57. hy = hx&0x7fff000000000000LL;
  58. if(hy==0x7fff000000000000LL) return x+x;/* overflow */
  59. if(hy==0) {
  60. volatile long double u = x*x; /* underflow */
  61. }
  62. SET_LDOUBLE_WORDS64(x,hx,lx);
  63. return x;
  64. }
  65. __strong_alias(nexttowardl, nextafterl);