From patchwork Wed Aug 26 13:37:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 8449 Received: (qmail 129452 invoked by alias); 26 Aug 2015 13:37:51 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 129417 invoked by uid 89); 26 Aug 2015 13:37:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=AWL, BAYES_20, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f51.google.com X-Received: by 10.66.139.234 with SMTP id rb10mr69638110pab.118.1440596266696; Wed, 26 Aug 2015 06:37:46 -0700 (PDT) Date: Wed, 26 Aug 2015 06:37:45 -0700 From: "H.J. Lu" To: Carlos O'Donell Cc: GNU C Library , "Joseph S. Myers" Subject: [PATCH] [BZ #18875] Avoid excess precision in check against float zero Message-ID: <20150826133745.GA17104@gmail.com> References: <559C2EA4.8030409@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <559C2EA4.8030409@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) On Tue, Jul 07, 2015 at 03:55:16PM -0400, Carlos O'Donell wrote: > Joseph, > > I'm seeing these failures on i686 in test-float, have you seen these? > If not, I'll investigate the failures to see if they are related to > my compiler or linker. > > glibc-i686/math/test-float.out: > > testing float (without inline functions) > Failure: exp10 (-0x1.31p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp10 (-0x1.343792p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10 (-0x1.343794p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10 (-0x1.344p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10_downward (-0x1.31p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp10_downward (-0x1.343792p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10_downward (-0x1.343794p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10_downward (-0x1.344p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10_towardzero (-0x1.31p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp10_towardzero (-0x1.343792p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10_towardzero (-0x1.343794p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp10_towardzero (-0x1.344p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp2 (-0x1.3045fep+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2 (-0x3.fb8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2 (-0x3.fc8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2 (-0x3.fd8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2 (-0x4.01p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp2 (-0x4.32p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_downward (-0x1.3045fep+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_downward (-0x3.fb8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_downward (-0x3.fc8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_downward (-0x3.fd8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_downward (-0x4.01p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp2_downward (-0x4.32p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_towardzero (-0x1.3045fep+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_towardzero (-0x3.fb8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_towardzero (-0x3.fc8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_towardzero (-0x3.fd8p+8): errno set to 0, expected 34 (ERANGE) > Failure: exp2_towardzero (-0x4.01p+12): errno set to 0, expected 34 (ERANGE) > Failure: exp2_towardzero (-0x4.32p+8): errno set to 0, expected 34 (ERANGE) > Failure: pow10 (-0x1.31p+8): errno set to 0, expected 34 (ERANGE) > Failure: pow10 (-0x1.343792p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10 (-0x1.343794p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10 (-0x1.344p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10_downward (-0x1.31p+8): errno set to 0, expected 34 (ERANGE) > Failure: pow10_downward (-0x1.343792p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10_downward (-0x1.343794p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10_downward (-0x1.344p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10_towardzero (-0x1.31p+8): errno set to 0, expected 34 (ERANGE) > Failure: pow10_towardzero (-0x1.343792p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10_towardzero (-0x1.343794p+12): errno set to 0, expected 34 (ERANGE) > Failure: pow10_towardzero (-0x1.344p+12): errno set to 0, expected 34 (ERANGE) > > Test suite completed: > 38654 test cases plus 36610 tests for exception flags and > 36610 tests for errno executed. > 42 errors occurred. > For check against float zero: float z; z = ... if (z == 0) on x86 with excess precision, we may get (gdb) info float =>R7: Valid 0x3d30e0d9b4d78a806800 +6.369668676344082156e-217 R6: Empty 0x40029000000000000000 and z (+6.369668676344082156e-217) == 0 is false. We can avoid excess precision by checking binary representations of float zero directly. OK for master? Thanks. H.J. --- [BZ #18875] * sysdeps/i386/fpu/w_exp10f.c: New file. * sysdeps/i386/fpu/w_exp2f.c: Likwise. * sysdeps/i386/fpu/w_expf.c: Likwise. --- sysdeps/i386/fpu/w_exp10f.c | 41 +++++++++++++++++++++++++++++++++++++++++ sysdeps/i386/fpu/w_exp2f.c | 38 ++++++++++++++++++++++++++++++++++++++ sysdeps/i386/fpu/w_expf.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 sysdeps/i386/fpu/w_exp10f.c create mode 100644 sysdeps/i386/fpu/w_exp2f.c create mode 100644 sysdeps/i386/fpu/w_expf.c diff --git a/sysdeps/i386/fpu/w_exp10f.c b/sysdeps/i386/fpu/w_exp10f.c new file mode 100644 index 0000000..bee27b0 --- /dev/null +++ b/sysdeps/i386/fpu/w_exp10f.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2015 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 + . */ + + +/* + * wrapper exp10f(x) + */ + +#include +#include + +float +__exp10f (float x) +{ + float z = __ieee754_exp10f (x); + int32_t iz; + GET_FLOAT_WORD (iz, z); + if (__builtin_expect (!isfinite (z) || (iz & 0x7fffffff) == 0, 0) + && isfinite (x) && _LIB_VERSION != _IEEE_) + /* exp10f overflow (146) if x > 0, underflow (147) if x < 0. */ + return __kernel_standard_f (x, x, 146 + !!signbit (x)); + + return z; +} +weak_alias (__exp10f, exp10f) +strong_alias (__exp10f, __pow10f) +weak_alias (__pow10f, pow10f) diff --git a/sysdeps/i386/fpu/w_exp2f.c b/sysdeps/i386/fpu/w_exp2f.c new file mode 100644 index 0000000..bf86212 --- /dev/null +++ b/sysdeps/i386/fpu/w_exp2f.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2015 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 + . */ + +/* + * wrapper exp2f(x) + */ + +#include +#include + +float +__exp2f (float x) +{ + float z = __ieee754_exp2f (x); + int32_t iz; + GET_FLOAT_WORD (iz, z); + if (__builtin_expect (!isfinite (z) || (iz & 0x7fffffff) == 0, 0) + && isfinite (x) && _LIB_VERSION != _IEEE_) + /* exp2 overflow: 144, exp2 underflow: 145 */ + return __kernel_standard_f (x, x, 144 + !!signbit (x)); + + return z; +} +weak_alias (__exp2f, exp2f) diff --git a/sysdeps/i386/fpu/w_expf.c b/sysdeps/i386/fpu/w_expf.c new file mode 100644 index 0000000..5eb7f56 --- /dev/null +++ b/sysdeps/i386/fpu/w_expf.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2015 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 + . */ + +#include +#include + +/* wrapper expf */ +float +__expf (float x) +{ + float z = __ieee754_expf (x); + int32_t iz; + + GET_FLOAT_WORD (iz, z); + + if (__builtin_expect (!isfinite (z) || (iz & 0x7fffffff) == 0, 0) + && isfinite (x) && _LIB_VERSION != _IEEE_) + return __kernel_standard_f (x, x, 106 + !!signbit (x)); + + return z; +} +hidden_def (__expf) +weak_alias (__expf, expf)