nextafterf.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /* origin: FreeBSD /usr/src/lib/msun/src/s_nextafterf.c */
  2. /*
  3. * Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
  4. */
  5. /*
  6. * ====================================================
  7. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  8. *
  9. * Developed at SunPro, a Sun Microsystems, Inc. business.
  10. * Permission to use, copy, modify, and distribute this
  11. * software is freely granted, provided that this notice
  12. * is preserved.
  13. * ====================================================
  14. */
  15. #include "libm.h"
  16. float nextafterf(float x, float y)
  17. {
  18. volatile float t;
  19. int32_t hx,hy,ix,iy;
  20. GET_FLOAT_WORD(hx, x);
  21. GET_FLOAT_WORD(hy, y);
  22. ix = hx & 0x7fffffff; /* |x| */
  23. iy = hy & 0x7fffffff; /* |y| */
  24. if (ix > 0x7f800000 || /* x is nan */
  25. iy > 0x7f800000) /* y is nan */
  26. return x+y;
  27. if (x == y) /* x == y */
  28. return y;
  29. if (ix == 0) { /* x == 0 */
  30. SET_FLOAT_WORD(x, (hy&0x80000000)|1); /* return +-minsubnormal */
  31. /* raise underflow flag */
  32. t = x*x;
  33. if (t == x)
  34. return t;
  35. return x;
  36. }
  37. if (hx >= 0) { /* x > 0 */
  38. if (hx > hy) { /* x > y, x -= ulp */
  39. hx--;
  40. } else { /* x < y, x += ulp */
  41. hx++;
  42. }
  43. } else { /* x < 0 */
  44. if (hy >= 0 || hx > hy) { /* x < y, x -= ulp */
  45. hx--;
  46. } else { /* x > y, x += ulp */
  47. hx++;
  48. }
  49. }
  50. hy = hx & 0x7f800000;
  51. if (hy >= 0x7f800000) /* overflow */
  52. return x+x;
  53. if (hy < 0x00800000) { /* underflow */
  54. /* raise underflow flag */
  55. t = x*x;
  56. if (t != x) {
  57. SET_FLOAT_WORD(y, hx);
  58. return y;
  59. }
  60. }
  61. SET_FLOAT_WORD(x, hx);
  62. return x;
  63. }