/* 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