diff options
-rw-r--r-- | libm/Makefile.in | 5 | ||||
-rw-r--r-- | libm/float_wrappers.c | 9 | ||||
-rw-r--r-- | libm/s_nextafterf.c | 103 |
3 files changed, 106 insertions, 11 deletions
diff --git a/libm/Makefile.in b/libm/Makefile.in index 58e420bf4..4b55b3a3a 100644 --- a/libm/Makefile.in +++ b/libm/Makefile.in @@ -61,7 +61,8 @@ libm_CSRC := \ s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c s_cos.c \ s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c s_frexp.c \ s_ilogb.c s_ldexp.c s_lib_version.c s_lrint.c s_lround.c s_llround.c \ - s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c s_round.c \ + s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c \ + s_nextafterf.c s_round.c \ s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c s_tan.c \ s_tanh.c s_trunc.c \ w_cabs.c \ @@ -76,7 +77,7 @@ FL_MOBJ := \ expm1f.o fabsf.o fdimf.o floorf.o fmaf.o fmaxf.o fminf.o fmodf.o \ frexpf.o hypotf.o ilogbf.o ldexpf.o lgammaf.o llroundf.o log10f.o \ log1pf.o log2f.o logbf.o logf.o lrintf.o lroundf.o modff.o nearbyintf.o \ - nextafterf.o powf.o remainderf.o remquof.o rintf.o roundf.o \ + powf.o remainderf.o remquof.o rintf.o roundf.o \ scalblnf.o scalbnf.o sinf.o sinhf.o sqrtf.o tanf.o tanhf.o \ tgammaf.o truncf.o cargf.o llrintf.o scalbf.o gammaf.o significandf.o diff --git a/libm/float_wrappers.c b/libm/float_wrappers.c index 6bdec8eeb..e6d660e13 100644 --- a/libm/float_wrappers.c +++ b/libm/float_wrappers.c @@ -64,7 +64,6 @@ float logbf(float); float logf(float); long lroundf(float); float modff(float, float *); -float nextafterf(float, float); float powf(float, float); float remainderf(float, float); float rintf(float); @@ -409,14 +408,6 @@ float nearbyintf (float x) #endif -#ifdef L_nextafterf -float nextafterf (float x, float y) -{ - return (float) nextafter( (double)x, (double)y ); -} -#endif - - #ifdef L_nexttowardf float nexttowardf (float x, long double y) { diff --git a/libm/s_nextafterf.c b/libm/s_nextafterf.c new file mode 100644 index 000000000..8dee00ff7 --- /dev/null +++ b/libm/s_nextafterf.c @@ -0,0 +1,103 @@ +/* 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" + +#ifndef math_opt_barrier +# define math_opt_barrier(x) ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; }) +# define math_force_eval(x) __asm __volatile ("" : : "m" (x)) +#endif + +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? */ + float u; + /* return +-minsubnormal */ + SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); + u = math_opt_barrier(x); + u = u * u; + math_force_eval(u); /* raise underflow flag */ + 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 */ +//?? if (FLT_EVAL_METHOD != 0) +// asm ("" : "+m"(x)); + 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 |