diff options
Diffstat (limited to 'sysdeps/ieee754/ldbl-128ibm')
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c | 75 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/printf_fphex.c | 35 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c | 37 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c | 107 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c | 23 | ||||
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c | 26 |
6 files changed, 111 insertions, 192 deletions
diff --git a/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c b/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c index 21d1e62dab..8a2d45e2d8 100644 --- a/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c +++ b/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2004, 2006, 2007 +/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -31,20 +31,19 @@ long double __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign) { union ibm_extended_long_double u; - unsigned long lzcount; + unsigned long hidden2, lzcount; unsigned long long hi, lo; - int exponent2; u.ieee.negative = sign; u.ieee.negative2 = sign; u.ieee.exponent = expt + IBM_EXTENDED_LONG_DOUBLE_BIAS; - u.ieee.exponent2 = 0; - exponent2 = expt - 53 + IBM_EXTENDED_LONG_DOUBLE_BIAS; + u.ieee.exponent2 = expt - 53 + IBM_EXTENDED_LONG_DOUBLE_BIAS; #if BITS_PER_MP_LIMB == 32 /* The low order 53 bits (52 + hidden) go into the lower double */ lo = frac_ptr[0]; lo |= (frac_ptr[1] & ((1LL << (53 - 32)) - 1)) << 32; + hidden2 = (frac_ptr[1] >> (52 - 32)) & ((mp_limb_t) 1); /* The high order 53 bits (52 + hidden) go into the upper double */ hi = (frac_ptr[1] >> (53 - 32)) & ((1 << 11) - 1); hi |= ((unsigned long long) frac_ptr[2]) << 11; @@ -52,6 +51,7 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign) #elif BITS_PER_MP_LIMB == 64 /* The low order 53 bits (52 + hidden) go into the lower double */ lo = frac_ptr[0] & (((mp_limb_t) 1 << 53) - 1); + hidden2 = (frac_ptr[0] >> 52) & ((mp_limb_t) 1); /* The high order 53 bits (52 + hidden) go into the upper double */ hi = (frac_ptr[0] >> 53) & (((mp_limb_t) 1 << 11) - 1); hi |= (frac_ptr[1] << 11); @@ -59,62 +59,14 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign) #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for" #endif - if ((hi & (1LL << 52)) == 0 && (hi | lo) != 0) - { - /* denormal number */ - unsigned long long val = hi ? hi : lo; - - if (sizeof (val) == sizeof (long)) - lzcount = __builtin_clzl (val); - else if ((val >> 32) != 0) - lzcount = __builtin_clzl ((long) (val >> 32)); - else - lzcount = __builtin_clzl ((long) val) + 32; - if (hi) - lzcount = lzcount - 11; - else - lzcount = lzcount + 42; - - if (lzcount > u.ieee.exponent) - { - lzcount = u.ieee.exponent; - u.ieee.exponent = 0; - exponent2 -= lzcount; - } - else - { - u.ieee.exponent -= (lzcount - 1); - exponent2 -= (lzcount - 1); - } - - if (lzcount <= 53) - { - hi = (hi << lzcount) | (lo >> (53 - lzcount)); - lo = (lo << lzcount) & ((1LL << 53) - 1); - } - else - { - hi = lo << (lzcount - 53); - lo = 0; - } - } - if (lo != 0L) { /* hidden2 bit of low double controls rounding of the high double. - If hidden2 is '1' and either the explicit mantissa is non-zero - or hi is odd, then round up hi and adjust lo (2nd mantissa) + If hidden2 is '1' then round up hi and adjust lo (2nd mantissa) plus change the sign of the low double to compensate. */ - if ((lo & (1LL << 52)) != 0 - && ((hi & 1) != 0 || (lo & ((1LL << 52) - 1)))) + if (hidden2) { hi++; - if ((hi & ((1LL << 52) - 1)) == 0) - { - if ((hi & (1LL << 53)) != 0) - hi -= 1LL << 52; - u.ieee.exponent++; - } u.ieee.negative2 = !sign; lo = (1LL << 53) - lo; } @@ -133,18 +85,17 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign) if (lzcount > 0) { lo = lo << lzcount; - exponent2 = exponent2 - lzcount; + u.ieee.exponent2 = u.ieee.exponent2 - lzcount; } - if (exponent2 > 0) - u.ieee.exponent2 = exponent2; - else - lo >>= 1 - exponent2; } else - u.ieee.negative2 = 0; + { + u.ieee.negative2 = 0; + u.ieee.exponent2 = 0; + } u.ieee.mantissa3 = lo & 0xffffffffLL; - u.ieee.mantissa2 = (lo >> 32) & 0xfffff; + u.ieee.mantissa2 = (lo >> 32) & 0xffffff; u.ieee.mantissa1 = hi & 0xffffffffLL; u.ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1); diff --git a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c index b2ad25e31f..2a7b70fabf 100644 --- a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c +++ b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c @@ -1,5 +1,5 @@ /* Print floating point number in hexadecimal notation according to ISO C99. - Copyright (C) 1997,1998,1999,2000,2001,2002,2004,2006,2007 + Copyright (C) 1997,1998,1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -35,24 +35,21 @@ do { \ \ lo = ((long long)eldbl.ieee.mantissa2 << 32) | eldbl.ieee.mantissa3; \ hi = ((long long)eldbl.ieee.mantissa0 << 32) | eldbl.ieee.mantissa1; \ - lo <<= 7; /* pre-shift lo to match ieee854. */ \ - /* If the lower double is not a denomal or zero then set the hidden \ - 53rd bit. */ \ - if (eldbl.ieee.exponent2 != 0) \ - lo |= (1ULL << (52 + 7)); \ - else \ - lo <<= 1; \ - /* The lower double is normalized separately from the upper. We \ - may need to adjust the lower manitissa to reflect this. */ \ - ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2; \ - if (ediff > 53 + 63) \ - lo = 0; \ - else if (ediff > 53) \ - lo = lo >> (ediff - 53); \ - else if (eldbl.ieee.exponent2 == 0 && ediff < 53) \ - lo = lo << (53 - ediff); \ - if (eldbl.ieee.negative != eldbl.ieee.negative2 \ - && (eldbl.ieee.exponent2 != 0 || lo != 0L)) \ + /* If the lower double is not a denomal or zero then set the hidden \ + 53rd bit. */ \ + if (eldbl.ieee.exponent2 > 0x001) \ + { \ + lo |= (1ULL << 52); \ + lo = lo << 7; /* pre-shift lo to match ieee854. */ \ + /* The lower double is normalized separately from the upper. We \ + may need to adjust the lower manitissa to reflect this. */ \ + ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2; \ + if (ediff > 53) \ + lo = lo >> (ediff-53); \ + } \ + \ + if ((eldbl.ieee.negative != eldbl.ieee.negative2) \ + && ((eldbl.ieee.exponent2 != 0) && (lo != 0L))) \ { \ lo = (1ULL << 60) - lo; \ if (hi == 0L) \ diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c b/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c index 6999abc250..3ca178a3c5 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c @@ -1,5 +1,5 @@ /* Return classification value corresponding to argument. - Copyright (C) 1997,1999,2002,2004,2006,2007 Free Software Foundation, Inc. + Copyright (C) 1997,1999,2002,2004,2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and Jakub Jelinek <jj@ultra.linux.cz>, 1999. @@ -30,16 +30,14 @@ * -NaN fffn nnnn nnnn nnnn xxxx xxxx xxxx xxxx * +Inf 7ff0 0000 0000 0000 xxxx xxxx xxxx xxxx * -Inf fff0 0000 0000 0000 xxxx xxxx xxxx xxxx - * +0 0000 0000 0000 0000 xxxx xxxx xxxx xxxx - * -0 8000 0000 0000 0000 xxxx xxxx xxxx xxxx - * +normal 0360 0000 0000 0000 0000 0000 0000 0000 (smallest) - * -normal 8360 0000 0000 0000 0000 0000 0000 0000 (smallest) - * +normal 7fef ffff ffff ffff 7c8f ffff ffff fffe (largest) - * +normal ffef ffff ffff ffff fc8f ffff ffff fffe (largest) - * +denorm 0360 0000 0000 0000 8000 0000 0000 0001 (largest) - * -denorm 8360 0000 0000 0000 0000 0000 0000 0001 (largest) - * +denorm 000n nnnn nnnn nnnn xxxx xxxx xxxx xxxx - * -denorm 800n nnnn nnnn nnnn xxxx xxxx xxxx xxxx + * +0 0000 0000 0000 0000 + * -0 8000 0000 0000 0000 + * +normal 001n nnnn nnnn nnnn (smallest) + * -normal 801n nnnn nnnn nnnn (smallest) + * +normal 7fen nnnn nnnn nnnn (largest) + * -normal ffen nnnn nnnn nnnn (largest) + * +denorm 000n nnnn nnnn nnnn + * -denorm 800n nnnn nnnn nnnn */ int @@ -61,23 +59,12 @@ ___fpclassifyl (long double x) /* +/-zero or +/- normal or +/- denormal */ if (hx & 0x7fffffffffffffffULL) { /* +/- normal or +/- denormal */ - if ((hx & 0x7ff0000000000000ULL) > 0x0360000000000000ULL) { + if ((hx & 0x7ff0000000000000ULL) >= 0x0360000000000000ULL) { /* +/- normal */ retval = FP_NORMAL; } else { - if ((hx & 0x7ff0000000000000ULL) == 0x0360000000000000ULL) { - if ((lx & 0x7fffffffffffffff) /* lower is non-zero */ - && ((lx^hx) & 0x8000000000000000ULL)) { /* and sign differs */ - /* +/- denormal */ - retval = FP_SUBNORMAL; - } else { - /* +/- normal */ - retval = FP_NORMAL; - } - } else { - /* +/- denormal */ - retval = FP_SUBNORMAL; - } + /* +/- denormal */ + retval = FP_SUBNORMAL; } } else { /* +/- zero */ diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c b/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c index 39d0e6a5e3..e35ce50829 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c @@ -24,8 +24,8 @@ static char rcsid[] = "$NetBSD: $"; * Special cases: */ -#include <math.h> -#include <math_private.h> +#include "math.h" +#include "math_private.h" #include <math_ldbl_opt.h> #ifdef __STDC__ @@ -35,7 +35,7 @@ static char rcsid[] = "$NetBSD: $"; long double x,y; #endif { - int64_t hx,hy,ihx,ihy,ilx; + int64_t hx,hy,ihx,ihy,ilx,ily; u_int64_t lx,ly; GET_LDOUBLE_WORDS64(hx,lx,x); @@ -43,6 +43,7 @@ static char rcsid[] = "$NetBSD: $"; ihx = hx&0x7fffffffffffffffLL; /* |hx| */ ilx = lx&0x7fffffffffffffffLL; /* |lx| */ ihy = hy&0x7fffffffffffffffLL; /* |hy| */ + ily = ly&0x7fffffffffffffffLL; /* |ly| */ if((((ihx&0x7ff0000000000000LL)==0x7ff0000000000000LL)&& ((ihx&0x000fffffffffffffLL)!=0)) || /* x is nan */ @@ -52,67 +53,55 @@ static char rcsid[] = "$NetBSD: $"; if(x==y) return y; /* x=y, return y */ if(ihx == 0 && ilx == 0) { /* x == 0 */ - long double u; - hy = (hy & 0x8000000000000000ULL) | 1; - SET_LDOUBLE_WORDS64(x,hy,0ULL);/* return +-minsubnormal */ - u = math_opt_barrier (x); - u = u * u; - math_force_eval (u); /* raise underflow flag */ - return x; + SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */ + y = x*x; + if(y==x) return y; else return x; /* raise underflow flag */ } - - long double u; - if(x > y) { /* x > y, x -= ulp */ - if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL)) - return x+x; /* overflow, return -inf */ - if (hx >= 0x7ff0000000000000LL) { - SET_LDOUBLE_WORDS64(u,0x7fefffffffffffffLL,0x7c8ffffffffffffeLL); - return u; - } - if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */ - u = math_opt_barrier (x); - x -= __LDBL_DENORM_MIN__; - if (ihx < 0x0360000000000000LL - || (hx > 0 && (int64_t) lx <= 0) - || (hx < 0 && (int64_t) lx > 1)) { - u = u * u; - math_force_eval (u); /* raise underflow flag */ - } - return x; + if(ihx>=0) { /* x > 0 */ + if(ihx>ihy||((ihx==ihy)&&(ilx>ily))) { /* x > y, x -= ulp */ + + if(ilx==0) + hx--; + else + lx--; + } else { /* x < y, x += ulp */ + if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL)) + { + SET_LDOUBLE_WORDS64(x,0x7ff0000000000000,0x8000000000000000); + return x; + } + else if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL)) + { + SET_LDOUBLE_WORDS64(x,0xfff0000000000000,0x8000000000000000); + return x; + } + else if((lx&0x7fffffffffffffff)==0) hx++; + else + lx++; } - if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ - SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL); - u *= 0x1.0000000000000p-105L; - } else - SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL); - return x - u; - } else { /* x < y, x += ulp */ - if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL)) - return x+x; /* overflow, return +inf */ - if ((u_int64_t) hx >= 0xfff0000000000000ULL) { - SET_LDOUBLE_WORDS64(u,0xffefffffffffffffLL,0xfc8ffffffffffffeLL); - return u; + } else { /* x < 0 */ + if(ihy>=0||ihx>ihy||((ihx==ihy)&&(ilx>ily))){/* x < y, x -= ulp */ + if((lx&0x7fffffffffffffff)==0) + hx--; + else + lx--; + } else { /* x > y, x += ulp */ + if((lx&0x7fffffffffffffff)==0) hx++; + else + lx++; } - if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */ - u = math_opt_barrier (x); - x += __LDBL_DENORM_MIN__; - if (ihx < 0x0360000000000000LL - || (hx > 0 && (int64_t) lx < 0 && lx != 0x8000000000000001LL) - || (hx < 0 && (int64_t) lx >= 0)) { - u = u * u; - math_force_eval (u); /* raise underflow flag */ - } - if (x == 0.0L) /* handle negative __LDBL_DENORM_MIN__ case */ - x = -0.0L; - return x; + } + hy = hx&0x7ff0000000000000LL; + if(hy==0x7ff0000000000000LL) return x+x;/* overflow */ + if(hy==0) { /* underflow */ + y = x*x; + if(y!=x) { /* raise underflow flag */ + SET_LDOUBLE_WORDS64(y,hx,lx); + return y; } - if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */ - SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL); - u *= 0x1.0000000000000p-105L; - } else - SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL); - return x + u; } + SET_LDOUBLE_WORDS64(x,hx,lx); + return x; } strong_alias (__nextafterl, __nexttowardl) long_double_symbol (libm, __nextafterl, nextafterl); diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c b/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c index e2f6521f57..3335100592 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c @@ -26,7 +26,7 @@ static char rcsid[] = "$NetBSD: $"; */ #include "math.h" -#include <math_private.h> +#include "math_private.h" #include <math_ldbl_opt.h> #include <float.h> @@ -55,12 +55,10 @@ static char rcsid[] = "$NetBSD: $"; return x+y; if((long double) x==y) return y; /* x=y, return y */ if((ix|lx)==0) { /* x == 0 */ - double u; + double x2; INSERT_WORDS(x,(u_int32_t)((hy>>32)&0x80000000),1);/* return +-minsub */ - u = math_opt_barrier (x); - u = u * u; - math_force_eval (u); /* raise underflow flag */ - return x; + x2 = x*x; + if(x2==x) return x2; else return x; /* raise underflow flag */ } if(hx>=0) { /* x > 0 */ if (hy<0||(ix>>20)>(iy>>52) @@ -91,13 +89,16 @@ static char rcsid[] = "$NetBSD: $"; if(hy>=0x7ff00000) { x = x+x; /* overflow */ if (FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1) - /* Force conversion to double. */ - asm ("" : "+m"(x)); + /* Force conversion to float. */ + asm ("" : "=m"(x) : "m"(x)); return x; } - if(hy<0x00100000) { - double u = x*x; /* underflow */ - math_force_eval (u); /* raise underflow flag */ + if(hy<0x00100000) { /* underflow */ + double x2 = x*x; + if(x2!=x) { /* raise underflow flag */ + INSERT_WORDS(x2,hx,lx); + return x2; + } } INSERT_WORDS(x,hx,lx); return x; diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c b/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c index cf655fad16..a9373ff822 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c @@ -19,9 +19,8 @@ static char rcsid[] = "$NetBSD: $"; #endif #include "math.h" -#include <math_private.h> +#include "math_private.h" #include <math_ldbl_opt.h> -#include <float.h> #ifdef __STDC__ float __nexttowardf(float x, long double y) @@ -47,12 +46,10 @@ static char rcsid[] = "$NetBSD: $"; return x+y; if((long double) x==y) return y; /* x=y, return y */ if(ix==0) { /* x == 0 */ - float u; + float x2; SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/ - u = math_opt_barrier (x); - u = u * u; - math_force_eval (u); /* raise underflow flag */ - return x; + x2 = x*x; + if(x2==x) return x2; else return x; /* raise underflow flag */ } if(hx>=0) { /* x > 0 */ if(hy<0||(ix>>23)>(iy>>52)-0x380 @@ -72,16 +69,13 @@ static char rcsid[] = "$NetBSD: $"; } } hy = hx&0x7f800000; - if(hy>=0x7f800000) { - x = x+x; /* overflow */ - if (FLT_EVAL_METHOD != 0) - /* Force conversion to float. */ - asm ("" : "+m"(x)); - return x; - } + if(hy>=0x7f800000) return x+x; /* overflow */ if(hy<0x00800000) { /* underflow */ - float u = x*x; - math_force_eval (u); /* raise underflow flag */ + float x2 = x*x; + if(x2!=x) { /* raise underflow flag */ + SET_FLOAT_WORD(x2,hx); + return x2; + } } SET_FLOAT_WORD(x,hx); return x; |