s_nexttowardf.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  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. #include <openlibm_math.h>
  13. #include "math_private.h"
  14. float
  15. nexttowardf(float x, long double y)
  16. {
  17. int32_t hx,ix;
  18. int64_t hy,iy;
  19. u_int64_t ly;
  20. GET_FLOAT_WORD(hx,x);
  21. GET_LDOUBLE_WORDS64(hy,ly,y);
  22. ix = hx&0x7fffffff; /* |x| */
  23. iy = hy&0x7fffffffffffffffLL; /* |y| */
  24. if((ix>0x7f800000) || /* x is nan */
  25. ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))
  26. /* y is nan */
  27. return x+y;
  28. if((long double) x==y) return y; /* x=y, return y */
  29. if(ix==0) { /* x == 0 */
  30. volatile float u;
  31. SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/
  32. u = x;
  33. u = u * u; /* raise underflow flag */
  34. return x;
  35. }
  36. if(hx>=0) { /* x > 0 */
  37. if(hy<0||(ix>>23)>(iy>>48)-0x3f80
  38. || ((ix>>23)==(iy>>48)-0x3f80
  39. && (ix&0x7fffff)>((hy>>25)&0x7fffff))) {/* x > y, x -= ulp */
  40. hx -= 1;
  41. } else { /* x < y, x += ulp */
  42. hx += 1;
  43. }
  44. } else { /* x < 0 */
  45. if(hy>=0||(ix>>23)>(iy>>48)-0x3f80
  46. || ((ix>>23)==(iy>>48)-0x3f80
  47. && (ix&0x7fffff)>((hy>>25)&0x7fffff))) {/* x < y, x -= ulp */
  48. hx -= 1;
  49. } else { /* x > y, x += ulp */
  50. hx += 1;
  51. }
  52. }
  53. hy = hx&0x7f800000;
  54. if(hy>=0x7f800000) return x+x; /* overflow */
  55. if(hy<0x00800000) {
  56. volatile float u = x*x; /* underflow */
  57. }
  58. SET_FLOAT_WORD(x,hx);
  59. return x;
  60. }