From patchwork Fri Oct 21 16:31:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 16724 Received: (qmail 104628 invoked by alias); 21 Oct 2016 16:31:47 -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 104613 invoked by uid 89); 21 Oct 2016 16:31:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Subject: Re: [PATCH] Define iszero as a function template for C++ [BZ #20715] To: Joseph Myers References: <2b2fa3c4-5bd6-4025-717f-fe2e2ee19555@redhat.com> Cc: GNU C Library From: Florian Weimer Message-ID: Date: Fri, 21 Oct 2016 18:31:33 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: On 10/21/2016 06:23 PM, Joseph Myers wrote: > On Fri, 21 Oct 2016, Florian Weimer wrote: > >> On 10/21/2016 06:12 PM, Joseph Myers wrote: >>> On Fri, 21 Oct 2016, Florian Weimer wrote: >>> >>>> Tested on x86_64, ppc64, ppc64le, s390x, aarch64. >>>> >>>> I'm not sure if the new test is particularly meaningful, but at least it >>>> catches syntax errors in . >>> >>> This seems fine to me (with negative zero included in the testcase), >> >> Oh. How do I get a negative zero? Would T{-0.0} be sufficient? Or should I > > Yes, T{-0.0} or -T{0} should suffice. Thanks. Here is what I've committed. Everything is optimized away anyway (but I deliberately introduced a bug to make sure the test still tests something). Florian math: Define iszero as a function template for C++ [BZ #20715] This increases compatibility with C++ code which is forced to compile with _GNU_SOURCE. 2016-10-21 Florian Weimer [BZ #20715] * math/math.h [__cplusplus] (iszero): Define as function template. * math/Makefile [CXX] (tests): Add test-math-iszero. (CFLAGS-test-math-iszero.cc): Set. * math/test-math-iszero.cc: New file. diff --git a/math/Makefile b/math/Makefile index 2aa6a34..7cecba5 100644 --- a/math/Makefile +++ b/math/Makefile @@ -165,7 +165,7 @@ tests-static = test-fpucw-static test-fpucw-ieee-static \ test-signgam-ullong-static test-signgam-ullong-init-static ifneq (,$(CXX)) -tests += test-math-isinff +tests += test-math-isinff test-math-iszero endif ifneq (no,$(PERL)) @@ -267,6 +267,7 @@ CFLAGS-test-signgam-ullong-static.c = -std=c99 CFLAGS-test-signgam-ullong-init-static.c = -std=c99 CFLAGS-test-math-isinff.cc = -std=gnu++11 +CFLAGS-test-math-iszero.cc = -std=gnu++11 CFLAGS-test-iszero-excess-precision.c = -fexcess-precision=standard CFLAGS-test-iseqsig-excess-precision.c = -fexcess-precision=standard diff --git a/math/math.h b/math/math.h index 880b4a0..0220d08 100644 --- a/math/math.h +++ b/math/math.h @@ -335,11 +335,25 @@ enum # define issubnormal(x) (fpclassify (x) == FP_SUBNORMAL) /* Return nonzero value if X is zero. */ -# ifdef __SUPPORT_SNAN__ -# define iszero(x) (fpclassify (x) == FP_ZERO) -# else -# define iszero(x) (((__typeof (x)) (x)) == 0) -# endif +# ifndef __cplusplus +# ifdef __SUPPORT_SNAN__ +# define iszero(x) (fpclassify (x) == FP_ZERO) +# else +# define iszero(x) (((__typeof (x)) (x)) == 0) +# endif +# else /* __cplusplus */ +__END_DECLS +template inline bool +iszero (__T __val) +{ +# ifdef __SUPPORT_SNAN__ + return fpclassify (__val) == FP_ZERO; +# else + return __val == 0; +# endif +} +__BEGIN_DECLS +# endif /* __cplusplus */ #endif /* Use IEC_60559_BFP_EXT. */ #ifdef __USE_MISC diff --git a/math/test-math-iszero.cc b/math/test-math-iszero.cc new file mode 100644 index 0000000..5de251a --- /dev/null +++ b/math/test-math-iszero.cc @@ -0,0 +1,87 @@ +/* Test for the C++ implementation of iszero. + Copyright (C) 2016 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 + . */ + +#define _GNU_SOURCE 1 +#include +#include + +#include + +static bool errors; + +static void +check (int actual, int expected, const char *actual_expr, int line) +{ + if (actual != expected) + { + errors = true; + printf ("%s:%d: error: %s\n", __FILE__, line, actual_expr); + printf ("%s:%d: expected: %d\n", __FILE__, line, expected); + printf ("%s:%d: actual: %d\n", __FILE__, line, actual); + } +} + +#define CHECK(actual, expected) \ + check ((actual), (expected), #actual, __LINE__) + +template +static void +check_type () +{ + typedef std::numeric_limits limits; + CHECK (iszero (T{}), 1); + CHECK (iszero (T{0}), 1); + CHECK (iszero (T{-0.0}), 1); + CHECK (iszero (T{1}), 0); + CHECK (iszero (T{-1}), 0); + CHECK (iszero (limits::min ()), 0); + CHECK (iszero (-limits::min ()), 0); + CHECK (iszero (limits::max ()), 0); + CHECK (iszero (-limits::max ()), 0); + if (limits::has_infinity) + { + CHECK (iszero (limits::infinity ()), 0); + CHECK (iszero (-limits::infinity ()), 0); + } + CHECK (iszero (limits::epsilon ()), 0); + CHECK (iszero (-limits::epsilon ()), 0); + if (limits::has_quiet_NaN) + CHECK (iszero (limits::quiet_NaN ()), 0); + if (limits::has_signaling_NaN) + CHECK (iszero (limits::signaling_NaN ()), 0); + if (limits::has_signaling_NaN) + CHECK (iszero (limits::signaling_NaN ()), 0); + CHECK (iszero (limits::denorm_min ()), + std::numeric_limits::has_denorm == std::denorm_absent); + CHECK (iszero (-limits::denorm_min ()), + std::numeric_limits::has_denorm == std::denorm_absent); +} + +static int +do_test (void) +{ + check_type (); + check_type (); +#ifndef NO_LONG_DOUBLE + check_type (); +#endif + return errors; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c"