diff options
Diffstat (limited to 'sysdeps/libm-ieee754/s_llround.c')
-rw-r--r-- | sysdeps/libm-ieee754/s_llround.c | 151 |
1 files changed, 25 insertions, 126 deletions
diff --git a/sysdeps/libm-ieee754/s_llround.c b/sysdeps/libm-ieee754/s_llround.c index aee0e31fc0..1deb630e96 100644 --- a/sysdeps/libm-ieee754/s_llround.c +++ b/sysdeps/libm-ieee754/s_llround.c @@ -1,4 +1,4 @@ -/* Round long double value to long long int. +/* Round double value to long long int. Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. @@ -23,157 +23,56 @@ #include "math_private.h" -#ifdef NO_LONG_DOUBLE -/* The `long double' is in fact the IEEE `double' type. */ - long long int -__llround (long double x) +__llround (double x) { int32_t j0; u_int32_t i1, i0; long long int result; + int sign; EXTRACT_WORDS (i0, i1, x); j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; + i0 |= 0x100000; + if (j0 < 20) { if (j0 < 0) - result = j0 < -1 ? 0 : ((i0 & 0x80000000) ? -1 : 1); + return j0 < -1 ? 0 : sign; else { - u_int32_t i = 0xfffff >> j0; - if (((i0 & i) | i1) == 0) - result = (long long int) ((i0 & 0xfffff) | 0x100000) >> j0; - else - { - /* X is not integral. */ - u_int32_t j = i0 + (0x80000 >> j0); - if (j < i0) - result = (long long int) 0x80000 >> (20 - j0); - else - result = (j | 0x100000) >> (20 - j0); - } + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); } } - else if (j0 >= 8 * sizeof (long long int) || j0 > 51) - { - /* The number is too large. It is left implementation defined - what happens. */ - result = (long long int) x; - } - else + else if (j0 < (int32_t) (8 * sizeof (long long int))) { - u_int32_t i = ((u_int32_t) (0xffffffff)) >> (j0 - 20); - if ((i1 & i) != 0) + if (j0 >= 52) + result = ((long long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else { - /* x is not integral. */ u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); if (j < i1) - { - j = i0 + 1; - if ((j & 0xfffff) == 0) - { - if (sizeof (long long int) <= 4) - /* Overflow. */ - result = (long long int) x; - else - result = 1ll << (j0 + 1); - } - else - result = ((long long int) ((i0 & 0xfffff) | 0x100000) - << (j0 - 31)); - } - else - { - result = ((long long int) ((i0 & 0xfffff) | 0x100000) - << (j0 - 31)); - if (sizeof (long long int) > 4 && j0 > 31) - result |= j >> (63 - j0); - } - } - else - { - result = (long long int) ((i0 & 0xfffff) | 0x100000) << (j0 - 31); - if (sizeof (long long int) > 4 && j0 > 31) - result |= i1 >> (63 - j0); - } - } + ++i0; - return i0 & 0x80000000 ? -result : result; -} -#else -long long int -__llround (long double x) -{ - int32_t j0; - u_int32_t se, i1, i0; - long long int result; - - GET_LDOUBLE_WORDS (se, i0, i1, x); - j0 = (se & 0x7fff) - 0x3fff; - if (j0 < 31) - { - if (j0 < 0) - result = j0 < -1 ? 0 : 1; - else - { - u_int32_t i = 0x7fffffff >> j0; - if (((i0 & i) | i1) == 0) - result = (long long int) i0 >> j0; - else - { - /* X is not integral. */ - u_int32_t j = i0 + (0x40000000 >> j0); - if (j < i0) - result = 0x80000000l >> (30 - j0); - else - result = j >> (31 - j0); - } + result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0)); } } - else if ((unsigned int) j0 >= 8 * sizeof (long long int) || j0 > 62) + else { /* The number is too large. It is left implementation defined what happens. */ - result = (long long int) x; - } - else - { - u_int32_t i = ((u_int32_t) (0xffffffff)) >> (j0 - 31); - if ((i1 & i) != 0) - { - /* x is not integral. */ - u_int32_t j = i1 + (0x80000000 >> (j0 - 31)); - if (j < i1) - { - j = i0 + 1; - if (j == 0) - { - if (sizeof (long long int) <= 4) - /* Overflow. */ - result = (long long int) x; - else - result = 1ll << (j0 + 1); - } - else - result = (long long int) i0 << (j0 - 31); - } - else - { - result = (long long int) i0 << (j0 - 31); - if (sizeof (long long int) > 4 && j0 > 31) - result |= j >> (63 - j0); - } - } - else - { - result = (long long int) i0 << (j0 - 31); - if (sizeof (long long int) > 4 && j0 > 31) - result |= i1 >> (63 - j0); - } + return (long long int) x; } - return se & 0x8000 ? -result : result; + return sign * result; } -#endif + weak_alias (__llround, llround) +#ifdef NO_LONG_DOUBLE +strong_alias (__llround, __llroundl) +weak_alias (__llround, llroundl) +#endif |