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/ieee754/k_standardl.c | |
parent | 9d1fc928a4c3ab15b46945b0abdf7054a75cc010 (diff) | |
download | glibc-f56f91245a0a5aa0facaa14b5608cfb761df7c38.zip glibc-f56f91245a0a5aa0facaa14b5608cfb761df7c38.tar.gz glibc-f56f91245a0a5aa0facaa14b5608cfb761df7c38.tar.bz2 |
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/ieee754/k_standardl.c')
-rw-r--r-- | sysdeps/ieee754/k_standardl.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/sysdeps/ieee754/k_standardl.c b/sysdeps/ieee754/k_standardl.c new file mode 100644 index 0000000..3c0a447 --- /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); + } +} |