diff options
author | nsz <nsz@port70.net> | 2012-05-06 13:08:59 +0200 |
---|---|---|
committer | nsz <nsz@port70.net> | 2012-05-06 13:08:59 +0200 |
commit | 6cf865dba69bab6346dc268d9173609af36b984e (patch) | |
tree | d30e0262f1114a707bb1bc9fa03fb381e6dba324 /src/math/nextafterl.c | |
parent | 98c9af500125df41fdb46d7e384b00982d72493a (diff) | |
download | musl-6cf865dba69bab6346dc268d9173609af36b984e.tar.gz musl-6cf865dba69bab6346dc268d9173609af36b984e.tar.xz musl-6cf865dba69bab6346dc268d9173609af36b984e.zip |
math: nextafter and nexttoward cleanup
make nexttoward, nexttowardf independent of long double representation. fix nextafterl: it did not raise underflow flag when the result was 0.
Diffstat (limited to 'src/math/nextafterl.c')
-rw-r--r-- | src/math/nextafterl.c | 123 |
1 files changed, 65 insertions, 58 deletions
diff --git a/src/math/nextafterl.c b/src/math/nextafterl.c index aec8ab40..611ea53d 100644 --- a/src/math/nextafterl.c +++ b/src/math/nextafterl.c @@ -1,21 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_nextafterl.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* IEEE functions - * nextafter(x,y) - * return the next machine floating-point number of x in the - * direction toward y. - * Special cases: - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -23,55 +5,80 @@ long double nextafterl(long double x, long double y) { return nextafter(x, y); } -#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 +#define MSB ((uint64_t)1<<63) long double nextafterl(long double x, long double y) { - volatile long double t; - union IEEEl2bits ux, uy; - - ux.e = x; - uy.e = y; + union ldshape ux, uy; - if ((ux.bits.exp == 0x7fff && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) || - (uy.bits.exp == 0x7fff && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) - return x+y; /* x or y is nan */ + if (isnan(x) || isnan(y)) + return x + y; if (x == y) - return y; /* x=y, return y */ - if (x == 0.0) { - /* return +-minsubnormal */ - ux.bits.manh = 0; - ux.bits.manl = 1; + return y; + ux.value = x; + if (x == 0) { + uy.value = y; + ux.bits.m = 1; ux.bits.sign = uy.bits.sign; - /* raise underflow flag */ - t = ux.e*ux.e; - if (t == ux.e) - return t; - return ux.e; - } - if(x > 0.0 ^ x < y) { /* x -= ulp */ - if (ux.bits.manl == 0) { - if ((ux.bits.manh&~LDBL_NBIT) == 0) - ux.bits.exp--; - ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT); + } else if (x < y ^ ux.bits.sign) { + ux.bits.m++; + if ((ux.bits.m & ~MSB) == 0) { + ux.bits.m = MSB; + ux.bits.exp++; } - ux.bits.manl--; - } else { /* x += ulp */ - ux.bits.manl++; - if (ux.bits.manl == 0) { - ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT); - if ((ux.bits.manh&~LDBL_NBIT)==0) + } else { + if ((ux.bits.m & ~MSB) == 0) { + ux.bits.exp--; + if (ux.bits.exp) + ux.bits.m = 0; + } + ux.bits.m--; + } + /* raise overflow if ux.value is infinite and x is finite */ + if (ux.bits.exp == 0x7fff) + return x + x; + /* raise underflow if ux.value is subnormal or zero */ + if (ux.bits.exp == 0) { + volatile float z = x*x + ux.value*ux.value; + } + return ux.value; +} +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 +long double nextafterl(long double x, long double y) +{ + union ldshape ux, uy; + + if (isnan(x) || isnan(y)) + return x + y; + if (x == y) + return y; + ux.value = x; + if (x == 0) { + uy.value = y; + ux.bits.mlo = 1; + ux.bits.sign = uy.bits.sign; + } else if (x < y ^ ux.bits.sign) { + ux.bits.mlo++; + if (ux.bits.mlo == 0) { + ux.bits.mhi++; + if (ux.bits.mhi == 0) ux.bits.exp++; } + } else { + if (ux.bits.mlo == 0) { + if (ux.bits.mhi == 0) + ux.bits.exp--; + ux.bits.mhi--; + } + ux.bits.mlo--; } - if (ux.bits.exp == 0x7fff) /* overflow */ - return x+x; - if (ux.bits.exp == 0) { /* underflow */ - mask_nbit_l(ux); - /* raise underflow flag */ - t = ux.e * ux.e; - if (t != ux.e) - return ux.e; + /* raise overflow if ux.value is infinite and x is finite */ + if (ux.bits.exp == 0x7fff) + return x + x; + /* raise underflow if ux.value is subnormal or zero */ + if (ux.bits.exp == 0) { + volatile float z = x*x + ux.value*ux.value; } - return ux.e; + return ux.value; } #endif |