s_nextafterf.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* s_nextafterf.c -- float version of s_nextafter.c.
  2. * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
  3. */
  4. /*
  5. * ====================================================
  6. * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  7. *
  8. * Developed at SunPro, a Sun Microsystems, Inc. business.
  9. * Permission to use, copy, modify, and distribute this
  10. * software is freely granted, provided that this notice
  11. * is preserved.
  12. * ====================================================
  13. */
  14. #include "math.h"
  15. #include "math_private.h"
  16. #ifndef math_opt_barrier
  17. # define math_opt_barrier(x) ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
  18. # define math_force_eval(x) __asm __volatile ("" : : "m" (x))
  19. #endif
  20. float nextafterf(float x, float y)
  21. {
  22. int32_t hx, hy, ix, iy;
  23. GET_FLOAT_WORD(hx, x);
  24. GET_FLOAT_WORD(hy, y);
  25. ix = hx & 0x7fffffff; /* |x| */
  26. iy = hy & 0x7fffffff; /* |y| */
  27. /* x is nan or y is nan? */
  28. if ((ix > 0x7f800000) || (iy > 0x7f800000))
  29. return x + y;
  30. if (x == y)
  31. return y;
  32. if (ix == 0) { /* x == 0? */
  33. float u;
  34. /* return +-minsubnormal */
  35. SET_FLOAT_WORD(x, (hy & 0x80000000) | 1);
  36. u = math_opt_barrier(x);
  37. u = u * u;
  38. math_force_eval(u); /* raise underflow flag */
  39. return x;
  40. }
  41. if (hx >= 0) { /* x > 0 */
  42. if (hx > hy) { /* x > y: x -= ulp */
  43. hx -= 1;
  44. } else { /* x < y: x += ulp */
  45. hx += 1;
  46. }
  47. } else { /* x < 0 */
  48. if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */
  49. hx -= 1;
  50. } else { /* x > y: x += ulp */
  51. hx += 1;
  52. }
  53. }
  54. hy = hx & 0x7f800000;
  55. if (hy >= 0x7f800000) {
  56. x = x + x; /* overflow */
  57. //?? if (FLT_EVAL_METHOD != 0)
  58. // asm ("" : "+m"(x));
  59. return x; /* overflow */
  60. }
  61. if (hy < 0x00800000) {
  62. float u = x * x; /* underflow */
  63. math_force_eval(u); /* raise underflow flag */
  64. }
  65. SET_FLOAT_WORD(x, hx);
  66. return x;
  67. }
  68. #if 0
  69. /* "testprog N a b"
  70. * calculates a = nextafterf(a, b) and prints a as float
  71. * and as raw bytes; repeats it N times.
  72. */
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <math.h>
  76. int main(int argc, char **argv)
  77. {
  78. int cnt, i;
  79. float a, b;
  80. cnt = atoi(argv[1]);
  81. a = strtod(argv[2], NULL);
  82. b = strtod(argv[3], NULL);
  83. while (cnt-- > 0) {
  84. for (i = 0; i < sizeof(a); i++) {
  85. unsigned char c = ((char*)(&a))[i];
  86. printf("%x%x", (c >> 4), (c & 0xf));
  87. }
  88. printf(" %f\n", a);
  89. a = nextafterf(a, b);
  90. }
  91. return 0;
  92. }
  93. #endif