From ea8e9b58cc284de51f163abf762c0504880a4041 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 3 Nov 2005 23:57:25 +0000 Subject: add implementations from glibc for the round functions --- libm/Makefile.in | 21 +++++++------ libm/s_llround.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ libm/s_lround.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ libm/s_round.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 254 insertions(+), 9 deletions(-) create mode 100644 libm/s_llround.c create mode 100644 libm/s_lround.c create mode 100644 libm/s_round.c (limited to 'libm') diff --git a/libm/Makefile.in b/libm/Makefile.in index a97624a06..465a5db4e 100644 --- a/libm/Makefile.in +++ b/libm/Makefile.in @@ -35,32 +35,35 @@ endif FL_MSRC:=float_wrappers.c ifeq ($(DO_C99_MATH),y) -CSRC:= e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c \ +CSRC:= \ + e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c \ e_exp.c e_fmod.c e_gamma.c e_gamma_r.c e_hypot.c e_j0.c \ e_j1.c e_jn.c e_lgamma.c e_lgamma_r.c e_log.c e_log10.c \ e_pow.c e_remainder.c e_rem_pio2.c e_scalb.c e_sinh.c \ e_sqrt.c k_cos.c k_rem_pio2.c k_sin.c k_standard.c k_tan.c \ 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_log1p.c s_logb.c \ - s_matherr.c s_modf.c s_nextafter.c s_rint.c s_scalbn.c \ - s_signgam.c s_significand.c s_sin.c s_tan.c s_tanh.c \ - w_acos.c w_acosh.c w_asin.c w_atan2.c w_atanh.c w_cabs.c \ + s_ilogb.c s_ldexp.c s_lib_version.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_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c s_tan.c \ + s_tanh.c w_acos.c w_acosh.c w_asin.c w_atan2.c w_atanh.c w_cabs.c \ w_cosh.c w_drem.c w_exp.c w_fmod.c w_gamma.c w_gamma_r.c \ w_hypot.c w_j0.c w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c \ w_log.c w_log10.c w_pow.c w_remainder.c w_scalb.c w_sinh.c \ w_sqrt.c fpmacros.c nan.c -FL_MOBJ:=acosf.o acoshf.o asinf.o asinhf.o atan2f.o atanf.o atanhf.o cbrtf.o \ +FL_MOBJ:= \ + acosf.o acoshf.o asinf.o asinhf.o atan2f.o atanf.o atanhf.o cbrtf.o \ ceilf.o copysignf.o cosf.o coshf.o erfcf.o erff.o exp2f.o expf.o \ 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 log10f.o log1pf.o \ - log2f.o logbf.o logf.o lrintf.o lroundf.o modff.o nearbyintf.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 \ scalblnf.o scalbnf.o sinf.o sinhf.o sqrtf.o tanf.o tanhf.o \ tgammaf.o truncf.o else # This list of math functions was taken from POSIX/IEEE 1003.1b-1993 -CSRC:= w_acos.c w_asin.c s_atan.c w_atan2.c s_ceil.c s_cos.c \ +CSRC:= \ + w_acos.c w_asin.c s_atan.c w_atan2.c s_ceil.c s_cos.c \ w_cosh.c w_exp.c s_fabs.c s_floor.c w_fmod.c s_frexp.c \ s_ldexp.c w_log.c w_log10.c s_modf.c w_pow.c s_sin.c \ w_sinh.c w_sqrt.c s_tan.c s_tanh.c \ diff --git a/libm/s_llround.c b/libm/s_llround.c new file mode 100644 index 000000000..a07238896 --- /dev/null +++ b/libm/s_llround.c @@ -0,0 +1,75 @@ +/* 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 , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + + +long long int +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) + return j0 < -1 ? 0 : sign; + else + { + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1) + { + if (j0 >= 52) + result = (((long long int) i0 << 32) | i1) << (j0 - 52); + else + { + u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); + if (j < i1) + ++i0; + + if (j0 == 20) + result = (long long int) i0; + else + result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long long int) x; + } + + return sign * result; +} diff --git a/libm/s_lround.c b/libm/s_lround.c new file mode 100644 index 000000000..5b1d5467e --- /dev/null +++ b/libm/s_lround.c @@ -0,0 +1,75 @@ +/* Round double value to long int. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + + +long int +lround (double x) +{ + int32_t j0; + u_int32_t i1, i0; + 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) + return j0 < -1 ? 0 : sign; + else + { + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long int)) - 1) + { + if (j0 >= 52) + result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else + { + u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); + if (j < i1) + ++i0; + + if (j0 == 20) + result = (long int) i0; + else + result = ((long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long int) x; + } + + return sign * result; +} diff --git a/libm/s_round.c b/libm/s_round.c new file mode 100644 index 000000000..b2d009520 --- /dev/null +++ b/libm/s_round.c @@ -0,0 +1,92 @@ +/* Round double to integer away from zero. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + + +static const double huge = 1.0e300; + + +double +round (double x) +{ + int32_t i0, j0; + u_int32_t i1; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) + { + if (j0 < 0) + { + if (huge + x > 0.0) + { + i0 &= 0x80000000; + if (j0 == -1) + i0 |= 0x3ff00000; + i1 = 0; + } + } + else + { + u_int32_t i = 0x000fffff >> j0; + if (((i0 & i) | i1) == 0) + /* X is integral. */ + return x; + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + i0 += 0x00080000 >> j0; + i0 &= ~i; + i1 = 0; + } + } + } + else if (j0 > 51) + { + if (j0 == 0x400) + /* Inf or NaN. */ + return x + x; + else + return x; + } + else + { + u_int32_t i = 0xffffffff >> (j0 - 20); + if ((i1 & i) == 0) + /* X is integral. */ + return x; + + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + u_int32_t j = i1 + (1 << (51 - j0)); + if (j < i1) + i0 += 1; + i1 = j; + } + i1 &= ~i; + } + + INSERT_WORDS (x, i0, i1); + return x; +} -- cgit v1.2.3