diff options
author | Joseph Myers <joseph@codesourcery.com> | 2014-12-22 18:45:50 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2014-12-22 18:45:50 +0000 |
commit | f56f91245a0a5aa0facaa14b5608cfb761df7c38 (patch) | |
tree | 22f4e47bc078aa8e74c5943bcb75422fed2518a4 /sysdeps | |
parent | 9d1fc928a4c3ab15b46945b0abdf7054a75cc010 (diff) | |
download | glibc-f56f91245a0a5aa0facaa14b5608cfb761df7c38.tar.gz glibc-f56f91245a0a5aa0facaa14b5608cfb761df7c38.tar.xz glibc-f56f91245a0a5aa0facaa14b5608cfb761df7c38.zip |
Split __kernel_standard* functions (fixes bug 17724).
Bug 17724 reports references to fesetround being brought in by ldbl-128ibm rintl via references to __rintl from __kernel_standard_l. Because all three __kernel_standard* functions are in the same file, this gets brought in even though only the long double version __kernel_standard_l needs __rintl, and the C90 functions use only __kernel_standard. This patch fixes this by splitting the three versions into separate files; it's fine for long double functions to refer to fe* functions directly, unless they get called by C90 double functions. Tested for x86_64 (testsuite; the reordering of code means disassembly of shared libraries can't usefully be compared). Tested for powerpc that the relevant issue disappears from the linknamespace test output. [BZ #17724] * sysdeps/ieee754/k_standard.c: Don't include <float.h>. (__kernel_standard_f): Remove. Moved to k_standardf.c. (__kernel_standard_l): Remove. Moved to k_standardl.c with (char *) casts added. * sysdeps/ieee754/k_standardf.c: New file. * sysdeps/ieee754/k_standardl.c: Likewise. * math/Makefile (libm-support): Remove k_standard. (libm-calls): Add k_standard.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/ieee754/k_standard.c | 90 | ||||
-rw-r--r-- | sysdeps/ieee754/k_standardf.c | 31 | ||||
-rw-r--r-- | sysdeps/ieee754/k_standardl.c | 123 |
3 files changed, 154 insertions, 90 deletions
diff --git a/sysdeps/ieee754/k_standard.c b/sysdeps/ieee754/k_standard.c index 5399c6682d..7b82cd1130 100644 --- a/sysdeps/ieee754/k_standard.c +++ b/sysdeps/ieee754/k_standard.c @@ -16,7 +16,6 @@ static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $ #include <math.h> #include <math_private.h> -#include <float.h> #include <errno.h> #include <assert.h> @@ -997,92 +996,3 @@ __kernel_standard(double x, double y, int type) } return exc.retval; } - - -float -__kernel_standard_f(float x, float y, int type) -{ - return __kernel_standard(x, y, type); -} - -#ifndef __NO_LONG_DOUBLE_MATH -long double -__kernel_standard_l (long double x, long double y, int type) -{ - double dx, dy; - struct exception exc; - - if (isfinite (x)) - { - long double ax = fabsl (x); - if (ax > DBL_MAX) - dx = __copysignl (DBL_MAX, x); - else if (ax > 0 && ax < DBL_MIN) - dx = __copysignl (DBL_MIN, x); - else - dx = x; - } - else - dx = x; - if (isfinite (y)) - { - long double ay = fabsl (y); - if (ay > DBL_MAX) - dy = __copysignl (DBL_MAX, y); - else if (ay > 0 && ay < DBL_MIN) - dy = __copysignl (DBL_MIN, y); - else - dy = y; - } - else - dy = y; - - switch (type) - { - case 221: - /* powl (x, y) overflow. */ - exc.arg1 = dx; - exc.arg2 = dy; - exc.type = OVERFLOW; - exc.name = "powl"; - if (_LIB_VERSION == _SVID_) - { - exc.retval = HUGE; - y *= 0.5; - if (x < zero && __rintl (y) != y) - exc.retval = -HUGE; - } - else - { - exc.retval = HUGE_VAL; - y *= 0.5; - if (x < zero && __rintl (y) != y) - exc.retval = -HUGE_VAL; - } - if (_LIB_VERSION == _POSIX_) - __set_errno (ERANGE); - else if (!matherr (&exc)) - __set_errno (ERANGE); - return exc.retval; - - case 222: - /* powl (x, y) underflow. */ - exc.arg1 = dx; - exc.arg2 = dy; - exc.type = UNDERFLOW; - exc.name = "powl"; - exc.retval = zero; - y *= 0.5; - if (x < zero && __rintl (y) != y) - exc.retval = -zero; - if (_LIB_VERSION == _POSIX_) - __set_errno (ERANGE); - else if (!matherr (&exc)) - __set_errno (ERANGE); - return exc.retval; - - default: - return __kernel_standard (dx, dy, type); - } -} -#endif diff --git a/sysdeps/ieee754/k_standardf.c b/sysdeps/ieee754/k_standardf.c new file mode 100644 index 0000000000..b4aeadf72e --- /dev/null +++ b/sysdeps/ieee754/k_standardf.c @@ -0,0 +1,31 @@ +/* Implement __kernel_standard_f. + Copyright (C) 2011-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <math.h> +#include <math_private.h> + + +/* Handle errors for a libm function as specified by TYPE (see + comments in k_standard.c for details), with arguments X and Y, + returning the appropriate return value for that function. */ + +float +__kernel_standard_f (float x, float y, int type) +{ + return __kernel_standard (x, y, type); +} diff --git a/sysdeps/ieee754/k_standardl.c b/sysdeps/ieee754/k_standardl.c new file mode 100644 index 0000000000..3c0a447f5b --- /dev/null +++ b/sysdeps/ieee754/k_standardl.c @@ -0,0 +1,123 @@ +/* Implement __kernel_standard_l. + Copyright (C) 2012-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + 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, see + <http://www.gnu.org/licenses/>. + + Parts based on k_standard.c from fdlibm: */ + +/* @(#)k_standard.c 5.1 93/09/24 */ +/* + * ==================================================== + * 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. + * ==================================================== + */ + +#include <math.h> +#include <math_private.h> +#include <float.h> +#include <errno.h> + + +static double zero = 0.0; + +/* Handle errors for a libm function as specified by TYPE (see + comments in k_standard.c for details), with arguments X and Y, + returning the appropriate return value for that function. */ + +long double +__kernel_standard_l (long double x, long double y, int type) +{ + double dx, dy; + struct exception exc; + + if (isfinite (x)) + { + long double ax = fabsl (x); + if (ax > DBL_MAX) + dx = __copysignl (DBL_MAX, x); + else if (ax > 0 && ax < DBL_MIN) + dx = __copysignl (DBL_MIN, x); + else + dx = x; + } + else + dx = x; + if (isfinite (y)) + { + long double ay = fabsl (y); + if (ay > DBL_MAX) + dy = __copysignl (DBL_MAX, y); + else if (ay > 0 && ay < DBL_MIN) + dy = __copysignl (DBL_MIN, y); + else + dy = y; + } + else + dy = y; + + switch (type) + { + case 221: + /* powl (x, y) overflow. */ + exc.arg1 = dx; + exc.arg2 = dy; + exc.type = OVERFLOW; + exc.name = (char *) "powl"; + if (_LIB_VERSION == _SVID_) + { + exc.retval = HUGE; + y *= 0.5; + if (x < zero && __rintl (y) != y) + exc.retval = -HUGE; + } + else + { + exc.retval = HUGE_VAL; + y *= 0.5; + if (x < zero && __rintl (y) != y) + exc.retval = -HUGE_VAL; + } + if (_LIB_VERSION == _POSIX_) + __set_errno (ERANGE); + else if (!matherr (&exc)) + __set_errno (ERANGE); + return exc.retval; + + case 222: + /* powl (x, y) underflow. */ + exc.arg1 = dx; + exc.arg2 = dy; + exc.type = UNDERFLOW; + exc.name = (char *) "powl"; + exc.retval = zero; + y *= 0.5; + if (x < zero && __rintl (y) != y) + exc.retval = -zero; + if (_LIB_VERSION == _POSIX_) + __set_errno (ERANGE); + else if (!matherr (&exc)) + __set_errno (ERANGE); + return exc.retval; + + default: + return __kernel_standard (dx, dy, type); + } +} |