diff options
Diffstat (limited to 'sysdeps/libm-ieee754/s_lround.c')
-rw-r--r-- | sysdeps/libm-ieee754/s_lround.c | 143 |
1 files changed, 22 insertions, 121 deletions
diff --git a/sysdeps/libm-ieee754/s_lround.c b/sysdeps/libm-ieee754/s_lround.c index 974dbde050..a6468ba78a 100644 --- a/sysdeps/libm-ieee754/s_lround.c +++ b/sysdeps/libm-ieee754/s_lround.c @@ -1,4 +1,4 @@ -/* Round long double value to long int. +/* Round double value to 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,13 +23,8 @@ #include "math_private.h" -#ifdef NO_LONG_DOUBLE -/* The `long double' is in fact the IEEE `double' type. */ - -/* This code does not presently work. */ - long int -__lround (long double x) +__lround (double x) { int32_t j0; u_int32_t i1, i0; @@ -40,138 +35,44 @@ __lround (long double 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 : sign; + return j0 < -1 ? 0 : sign; else { - u_int32_t i = 0xfffff >> j0; - i0 |= 0x100000; - if (((i0 & i) | i1) == 0) - result = i0 >> j0; - else - /* X is not integral. */ - result = (i0 + (0x80000 >> j0)) >> (20 - j0); + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); } } - else if (j0 >= 8 * sizeof (long int) || j0 > 51) - { - /* The number is too large. It is left implementation defined - what happens. */ - return (long int) x; - } - else + else if (j0 < (int32_t) (8 * sizeof (long int))) { - u_int32_t i = ((u_int32_t) (0xffffffff)) >> (j0 - 20); - if ((i1 & i) != 0) + if (j0 >= 52) + result = ((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 int) <= 4) - /* Overflow. */ - result = (long int) x; - else - result = 1l << (j0 + 1); - } - else - result = (long int) ((i0 & 0xfffff) | 0x100000) << (j0 - 31); - } - else - { - result = (long int) ((i0 & 0xfffff) | 0x100000) << (j0 - 31); - if (sizeof (long int) > 4 && j0 > 31) - result |= j >> (63 - j0); - } - } - else - { - result = (long int) ((i0 & 0xfffff) | 0x100000) << (j0 - 31); - if (sizeof (long int) > 4 && j0 > 31) - result |= i1 >> (63 - j0); - } - } - - return sign * result; -} -#else -long int -__lround (long double x) -{ - int32_t j0; - u_int32_t se, i1, i0; - long int result; + ++i0; - 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 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 int) i0 << (j0 - 20)) | (j >> (52 - j0)); } } - else if ((unsigned int) j0 >= 8 * sizeof (long int) || j0 > 62) + else { /* The number is too large. It is left implementation defined what happens. */ - result = (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 int) <= 4) - /* Overflow. */ - result = (long int) x; - else - result = 1l << (j0 + 1); - } - else - result = (long int) i0 << (j0 - 31); - } - else - { - result = (long int) i0 << (j0 - 31); - if (sizeof (long int) > 4 && j0 > 31) - result |= j >> (63 - j0); - } - } - else - { - result = (long int) i0 << (j0 - 31); - if (sizeof (long int) > 4 && j0 > 31) - result |= i1 >> (63 - j0); - } + return (long int) x; } - return se & 0x8000 ? -result : result; + return sign * result; } -#endif + weak_alias (__lround, lround) +#ifdef NO_LONG_DOUBLE +strong_alias (__lround, __lroundl) +weak_alias (__lround, lroundl) +#endif |