| /* s_nextafterf.c -- float version of s_nextafter.c. |
| * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. |
| */ |
| |
| /* |
| * ==================================================== |
| * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
| * |
| * Developed at SunPro, a Sun Microsystems, Inc. business. |
| * Permission to use, copy, modify, and distribute this |
| * software is freely granted, provided that this notice |
| * is preserved. |
| * ==================================================== |
| */ |
| |
| #include "math.h" |
| #include "math_private.h" |
| |
| float nextafterf(float x, float y) |
| { |
| int32_t hx, hy, ix, iy; |
| |
| GET_FLOAT_WORD(hx, x); |
| GET_FLOAT_WORD(hy, y); |
| ix = hx & 0x7fffffff; /* |x| */ |
| iy = hy & 0x7fffffff; /* |y| */ |
| |
| /* x is nan or y is nan? */ |
| if ((ix > 0x7f800000) || (iy > 0x7f800000)) |
| return x + y; |
| |
| if (x == y) |
| return y; |
| |
| if (ix == 0) { /* x == 0? */ |
| /* glibc 2.4 does not seem to set underflow? */ |
| /* float u; */ |
| /* return +-minsubnormal */ |
| SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); |
| /* u = x * x; raise underflow flag */ |
| /* math_force_eval(u); */ |
| return x; |
| } |
| |
| if (hx >= 0) { /* x > 0 */ |
| if (hx > hy) { /* x > y: x -= ulp */ |
| hx -= 1; |
| } else { /* x < y: x += ulp */ |
| hx += 1; |
| } |
| } else { /* x < 0 */ |
| if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */ |
| hx -= 1; |
| } else { /* x > y: x += ulp */ |
| hx += 1; |
| } |
| } |
| hy = hx & 0x7f800000; |
| if (hy >= 0x7f800000) { |
| x = x + x; /* overflow */ |
| return x; /* overflow */ |
| } |
| if (hy < 0x00800000) { |
| float u = x * x; /* underflow */ |
| math_force_eval(u); /* raise underflow flag */ |
| } |
| SET_FLOAT_WORD(x, hx); |
| return x; |
| } |
| |
| #if 0 |
| /* "testprog N a b" |
| * calculates a = nextafterf(a, b) and prints a as float |
| * and as raw bytes; repeats it N times. |
| */ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <math.h> |
| int main(int argc, char **argv) |
| { |
| int cnt, i; |
| float a, b; |
| cnt = atoi(argv[1]); |
| a = strtod(argv[2], NULL); |
| b = strtod(argv[3], NULL); |
| while (cnt-- > 0) { |
| for (i = 0; i < sizeof(a); i++) { |
| unsigned char c = ((char*)(&a))[i]; |
| printf("%x%x", (c >> 4), (c & 0xf)); |
| } |
| printf(" %f\n", a); |
| a = nextafterf(a, b); |
| } |
| return 0; |
| } |
| #endif |