s_nexttowardf.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* Single precision version of nexttoward.c.
  2. Conversion to IEEE single float by Jakub Jelinek, jj@ultra.linux.cz. */
  3. /*
  4. * ====================================================
  5. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  6. *
  7. * Developed at SunPro, a Sun Microsystems, Inc. business.
  8. * Permission to use, copy, modify, and distribute this
  9. * software is freely granted, provided that this notice
  10. * is preserved.
  11. * ====================================================
  12. */
  13. /* IEEE functions
  14. * nexttowardf(x,y)
  15. * return the next machine floating-point number of x in the
  16. * direction toward y.
  17. * This is for machines which use the same binary type for double and
  18. * long double.
  19. * Special cases:
  20. */
  21. #include <errno.h>
  22. #include <math.h>
  23. #include <math-barriers.h>
  24. #include <math_private.h>
  25. #include <float.h>
  26. float __nexttowardf(float x, long double y)
  27. {
  28. int32_t hx,hy,ix,iy;
  29. uint32_t ly;
  30. GET_FLOAT_WORD(hx,x);
  31. EXTRACT_WORDS(hy,ly,y);
  32. ix = hx&0x7fffffff; /* |x| */
  33. iy = hy&0x7fffffff; /* |y| */
  34. if((ix>0x7f800000) || /* x is nan */
  35. ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */
  36. return x+y;
  37. if((long double) x==y) return y; /* x=y, return y */
  38. if(ix==0) { /* x == 0 */
  39. float u;
  40. SET_FLOAT_WORD(x,(uint32_t)(hy&0x80000000)|1);/* return +-minsub*/
  41. u = math_opt_barrier (x);
  42. u = u * u;
  43. math_force_eval (u); /* raise underflow flag */
  44. return x;
  45. }
  46. if(hx>=0) { /* x > 0 */
  47. if(x > y) /* x -= ulp */
  48. hx -= 1;
  49. else /* x < y, x += ulp */
  50. hx += 1;
  51. } else { /* x < 0 */
  52. if(x < y) /* x -= ulp */
  53. hx -= 1;
  54. else /* x > y, x += ulp */
  55. hx += 1;
  56. }
  57. hy = hx&0x7f800000;
  58. if(hy>=0x7f800000) {
  59. float u = x+x; /* overflow */
  60. math_force_eval (u);
  61. __set_errno (ERANGE);
  62. }
  63. if(hy<0x00800000) {
  64. float u = x*x; /* underflow */
  65. math_force_eval (u); /* raise underflow flag */
  66. __set_errno (ERANGE);
  67. }
  68. SET_FLOAT_WORD(x,hx);
  69. return x;
  70. }
  71. weak_alias (__nexttowardf, nexttowardf)