From patchwork Wed Oct 19 08:23:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 4479 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4ac7:0:0:0:0:0 with SMTP id y7csp197065wrs; Wed, 19 Oct 2022 01:24:38 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4zJLdC+eCb4siPqgWU3D0tEzpAix5tAR8YNN4akBvgjCoeBuKVWUgj5jxxQH27qCiImG3K X-Received: by 2002:a17:906:7304:b0:6ff:a76:5b09 with SMTP id di4-20020a170906730400b006ff0a765b09mr5619400ejc.193.1666167878406; Wed, 19 Oct 2022 01:24:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666167878; cv=none; d=google.com; s=arc-20160816; b=yWC5P4LQlkAAekV3yvGwEWRr7Z8s7sPCkPqvPCFp6mAQcyLqU7zIYQXv6Nsc3p5EL6 rAVi7CWWiUUUB83Xi0vWHa/3ScMkmcSEdvY4lr32ILfMhxPu7MeFSWBSHYKDyvGFi3rK yp1Nf4ioJYKE2tSt0HBdHx3Sh5wfN0HyDXZBPeov8TkCygdPc7OYo5aPM9kRpWxFXmR9 J8VcYTlpigHeZwYogEJZXEZxNuWIaHlLu6zPXa1rxYbib8vk7gGEJjowXTuXgY/ra/5f PBY8rkNYPFf3YlxB3xv5kkewTVNe3WRbad/k0sv2lzsV3gP1P3GEpmsxPT9PUfSd6ByF MLmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:reply-to:from:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :content-disposition:mime-version:message-id:subject:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=ZnE9CqUH999MAJ4ov/1PP/D/J6TIkytmiD5GumAfLbI=; b=APruovP0XlB2yFtcd1AsoNcYjSBPqPnt+iGb0NtCQUuIO56SUDQDg/9R18t4yHLRNV A69oBfUQeKVsXbqxnsNu6mWNIERddOrtl9f/YW1UAjGX046Mh8W+9/rBBuswt+wfSitO 5GZDUj4M/nXWbngo4fe7s5Tt5nAJ9vGbr44uSTfM5QevrUYA6MBQfstIB4eIAKUKnVnd 7HdpEaPLGELakcg2hJT94udK18C75vl3P64bhYjLdaJh0bHXWQz3xFP/fOtA2GOgjqav bIYfmwXffXAD/Pf3Nz/ql0j+rFBZeRitowSSlYQ7pyyDQB5oJSPntgJvLOfqpBCuF3wY drhQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="lnv/NSqk"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id cz7-20020a0564021ca700b0045196fd6a9dsi11472827edb.477.2022.10.19.01.24.38 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Oct 2022 01:24:38 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b="lnv/NSqk"; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8401C3857BB2 for ; Wed, 19 Oct 2022 08:24:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8401C3857BB2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1666167870; bh=ZnE9CqUH999MAJ4ov/1PP/D/J6TIkytmiD5GumAfLbI=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=lnv/NSqkXEv4hYvRMJk1lSB9W4WsXrnmhCG3azby/38qCCfhoyvUSXuDJNuSkB71n 4XZym3dXa2aQcx5czOXrYpsxS9RzqKogAsUsciSUrG+BtDESBh7y7kFfavbj8aVzHj oZw1wFNuEo6Z8rbeLJtdXIcBohGpVlbSQcYPFty0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 1B8523858D39 for ; Wed, 19 Oct 2022 08:23:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 1B8523858D39 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-63-CokpVP9TM92OXqkRZJj_5A-1; Wed, 19 Oct 2022 04:23:35 -0400 X-MC-Unique: CokpVP9TM92OXqkRZJj_5A-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 16EF72932481; Wed, 19 Oct 2022 08:23:25 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.193.252]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 10D8314C4865; Wed, 19 Oct 2022 08:23:18 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 29J8NGrY3797229 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 19 Oct 2022 10:23:17 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 29J8NGq73797228; Wed, 19 Oct 2022 10:23:16 +0200 Date: Wed, 19 Oct 2022 10:23:16 +0200 To: Jonathan Wakely Subject: [PATCH] libstdc++-v3: Implement {,b}float16_t nextafter and some fixes [PR106652] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747103649126146558?= X-GMAIL-MSGID: =?utf-8?q?1747103649126146558?= Hi! The following patch implements nextafter for std::{,b}float16_t, though right now only without constexpr support, and adds a testcase for it. The testcase unfortunately relevealed I've screwed up testing of my last patch. I've tested earlier version of the patch with --target_board=unix/-std=c++23 but didn't test the final version with that RUNTESTFLAGS, so missed an invalid call to std::sph_neumann (too many arguments) in the test. And, I've made a typo in the guard for numeric_limits (the reason for the guard is I wanted to avoid defining a large macro that nothing will then use because the std::{,b}float*_t types are C++23 only) and so numeric_limits wasn't specialized for the types at all but testsuite/18_support/headers/limits/synopsis_cxx23.cc test didn't detect that. In the nextafter implementation I'm calling __builtin_nextafterf to get various required side-effects for nextafter from 0/-0, or from max to inf or from min to largest subnormal to avoid needing to set errno inline, or use inline asm specific for each processor to force math evaluation barriers. Dunno if #ifdef __INT16_TYPE__ using __float16_int_type = __INT16_TYPE__; #else using __float16_int_type = short int; #endif isn't too ugly, perhaps we could just blindly use short int and hope or even assert it has the same size as _Float16 or __gnu_cxx::__bfloat16_t? Only aarch64, arm, csky, gcn, x86, nvptx and riscv support these types and all of them have 16-bit short (I think the only target with some other short size is avr with certain command line switches where both short and int are 8-bit, but such mode isn't compatible with C and C++ requirements). Bootstrapped/regtested on x86_64-linux and i686-linux, additionally tested with --target_board=unix/-std=c++23, ok for trunk? 2022-10-19 Jakub Jelinek PR c++/106652 * include/std/limits: Fix a typo, 202202L -> 202002L. (numeric_limits::<_Float16>::radix, numeric_limits::<_Float32>::radix, numeric_limits::<_Float64>::radix, numeric_limits::<_Float128>::radix, numeric_limits::<__gnu_cxx::__bfloat16_t>::radix: Use __FLT_RADIX__ macro instead of type specific macros. * include/c_global/cmath (nextafter(_Float16, _Float16)): New overload. (nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Likewise. * testsuite/26_numerics/headers/cmath/functions_std_c++23.cc (test_functions): Uncomment nextafter test. Fix up sph_neumann call. * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc: New test. Jakub --- libstdc++-v3/include/std/limits.jj 2022-10-18 11:35:55.065871590 +0200 +++ libstdc++-v3/include/std/limits 2022-10-18 18:32:20.701757131 +0200 @@ -1890,7 +1890,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #undef __glibcxx_long_double_traps #undef __glibcxx_long_double_tinyness_before -#if __cplusplus > 202202L +#if __cplusplus > 202002L #define __glibcxx_concat3_(P,M,S) P ## M ## S #define __glibcxx_concat3(P,M,S) __glibcxx_concat3_ (P,M,S) @@ -1924,8 +1924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr bool is_signed = true; \ static constexpr bool is_integer = false; \ static constexpr bool is_exact = false; \ - static constexpr int radix \ - = __glibcxx_concat3 (__FLT, BITSIZE, _RADIX__); \ + static constexpr int radix = __FLT_RADIX__; \ \ static constexpr _Float##BITSIZE \ epsilon() noexcept \ @@ -2023,7 +2022,7 @@ __glibcxx_float_n(128) static constexpr bool is_signed = true; static constexpr bool is_integer = false; static constexpr bool is_exact = false; - static constexpr int radix = __BFLT16_RADIX__; + static constexpr int radix = __FLT_RADIX__; static constexpr __gnu_cxx::__bfloat16_t epsilon() noexcept --- libstdc++-v3/include/c_global/cmath.jj 2022-10-18 11:35:55.222869455 +0200 +++ libstdc++-v3/include/c_global/cmath 2022-10-18 17:05:50.737347845 +0200 @@ -2755,7 +2755,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION nearbyint(_Float16 __x) { return _Float16(__builtin_nearbyintf(__x)); } - // nextafter not implemented so far. + inline _Float16 + nextafter(_Float16 __x, _Float16 __y) + { +#ifdef __INT16_TYPE__ + using __float16_int_type = __INT16_TYPE__; +#else + using __float16_int_type = short int; +#endif + __float16_int_type __hx, __hy, __ix, __iy; + __builtin_memcpy(&__hx, &__x, sizeof(__x)); + __builtin_memcpy(&__hy, &__y, sizeof(__x)); + __ix = __hx & 0x7fff; // |x| + __iy = __hy & 0x7fff; // |y| + if (__ix > 0x7c00 || __iy > 0x7c00) // x or y is NaN + return __x + __y; + if (__x == __y) + return __y; // x == y, return y + if (__ix == 0) // x == 0 + { + __hy = (__hy & 0x8000) | 1; // return +-__FLT16_DENORM_MIN__ + __builtin_memcpy(&__x, &__hy, sizeof(__x)); + __builtin_nextafterf(0.0f, 1.0f); // raise underflow + return __x; + } + if (__hx >= 0) // x > 0 + { + if (__hx > __hy) // x > y, x -= ulp + --__hx; + else // x < y, x += ulp + ++__hx; + } + else // x < 0 + { + if (__hy >= 0 || __hx > __hy) // x < y, x -= ulp + --__hx; + else // x > y, x += ulp + ++__hx; + } + __hy = __hx & 0x7c00; + if (__hy >= 0x7c00) + __builtin_nextafterf(__FLT_MAX__, __builtin_inff()); // overflow + else if (__hy < 0x0400) + __builtin_nextafterf(__FLT_MIN__, 0.0f); // underflow + __builtin_memcpy(&__x, &__hx, sizeof(__x)); + return __x; + } constexpr _Float16 remainder(_Float16 __x, _Float16 __y) @@ -3426,7 +3471,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION nearbyint(__gnu_cxx::__bfloat16_t __x) { return __gnu_cxx::__bfloat16_t(__builtin_nearbyintf(__x)); } - // nextafter not implemented so far. + inline __gnu_cxx::__bfloat16_t + nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y) + { +#ifdef __INT16_TYPE__ + using __bfloat16_int_type = __INT16_TYPE__; +#else + using __bfloat16_int_type = short int; +#endif + __bfloat16_int_type __hx, __hy, __ix, __iy; + __builtin_memcpy(&__hx, &__x, sizeof(__x)); + __builtin_memcpy(&__hy, &__y, sizeof(__x)); + __ix = __hx & 0x7fff; // |x| + __iy = __hy & 0x7fff; // |y| + if (__ix > 0x7f80 || __iy > 0x7f80) // x or y is NaN + return __x + __y; + if (__x == __y) + return __y; // x == y, return y + if (__ix == 0) // x == 0 + { + __hy = (__hy & 0x8000) | 1; // return +-__BFLT16_DENORM_MIN__ + __builtin_memcpy(&__x, &__hy, sizeof(__x)); + __builtin_nextafterf(0.0f, 1.0f); // raise underflow + return __x; + } + if (__hx >= 0) // x > 0 + { + if (__hx > __hy) // x > y, x -= ulp + --__hx; + else // x < y, x += ulp + ++__hx; + } + else // x < 0 + { + if (__hy >= 0 || __hx > __hy) // x < y, x -= ulp + --__hx; + else // x > y, x += ulp + ++__hx; + } + __hy = __hx & 0x7f80; + if (__hy >= 0x7f80) + __builtin_nextafterf(__FLT_MAX__, __builtin_inff()); // overflow + else if (__hy < 0x0080) + __builtin_nextafterf(__FLT_MIN__, 0.0f); // underflow + __builtin_memcpy(&__x, &__hx, sizeof(__x)); + return __x; + } constexpr __gnu_cxx::__bfloat16_t remainder(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y) --- libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc.jj 2022-10-18 11:35:55.000000000 +0200 +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc 2022-10-18 18:12:08.311247121 +0200 @@ -63,7 +63,7 @@ test_functions (T *p, int *q, long int * p[36] = std::fmod (p[36], p[103]); p[37] = std::remainder (p[37], p[104]); p[38] = std::copysign (p[38], p[105]); -// p[39] = std::nextafter (p[39], p[106]); + p[39] = std::nextafter (p[39], p[106]); p[40] = std::fdim (p[40], p[107]); p[41] = std::fmax (p[41], p[108]); p[42] = std::fmin (p[42], p[109]); @@ -102,13 +102,13 @@ test_functions (T *p, int *q, long int * p[75] = std::riemann_zeta (p[75]); p[76] = std::sph_bessel (q[12], p[76]); p[77] = std::sph_legendre (q[13], q[14], p[77]); - p[78] = std::sph_neumann (q[15], q[16], p[78]); + p[78] = std::sph_neumann (q[15], p[78]); } int main () { - int q[17] = {}; + int q[16] = {}; long int r[16] = {}; long long int s[16] = {}; #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) --- libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc.jj 2022-10-18 17:18:32.237061706 +0200 +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc 2022-10-18 18:51:21.465258133 +0200 @@ -0,0 +1,124 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++23 } } + +#include +#include +#include +#include + +template +void +test () +{ + using lim = std::numeric_limits; + T t0 = std::nextafter(T(-0.0), T(2.0)); + VERIFY(t0 == lim::denorm_min()); + T t1 = std::nextafter(T(), T(1.0)); + VERIFY(t1 == lim::denorm_min()); + T t2 = std::nextafter(T(), T()); + VERIFY(t2 == T() && !std::signbit(t2)); + T t3 = std::nextafter(lim::denorm_min(), T(-2.0)); + VERIFY(t3 == T() && !std::signbit(t3)); + T t4 = std::nextafter(lim::min(), T(-0.0)); + VERIFY(std::fpclassify(t4) == FP_SUBNORMAL && t4 > T()); + T t5 = std::nextafter(t4, T(1.0)); + VERIFY(t5 == lim::min()); + T t6 = std::nextafter(lim::min(), lim::infinity()); + VERIFY(std::fpclassify(t6) == FP_NORMAL && t6 > lim::min()); + T t7 = std::nextafter(t6, -lim::infinity()); + VERIFY(t7 == lim::min()); + T t8 = std::nextafter(T(16.0), T(16.5)); + VERIFY(t8 > t7); + T t9 = std::nextafter(t8, T(15.5)); + VERIFY(t9 == T(16.0)); + T t10 = std::nextafter(lim::max(), T(-0.5)); + VERIFY(std::fpclassify(t10) == FP_NORMAL && t10 < lim::max()); + T t11 = std::nextafter(t10, lim::infinity()); + VERIFY(t11 == lim::max()); + T t12 = std::nextafter(t11, lim::infinity()); + VERIFY(std::fpclassify(t12) == FP_INFINITE && !std::signbit(t12)); + T t13 = std::nextafter(lim::infinity(), t12); + VERIFY(t13 == t12); + T t14 = std::nextafter(t13, T(1.0)); + VERIFY(t14 == lim::max()); + T t15 = std::nextafter(lim::quiet_NaN(), T()); + VERIFY(std::fpclassify(t15) == FP_NAN); + T t16 = std::nextafter(T(17.0), lim::quiet_NaN()); + VERIFY(std::fpclassify(t16) == FP_NAN); + T t17 = std::nextafter(T(), T(-0.0)); + VERIFY(t17 == T() && std::signbit(t17)); + T t20 = std::nextafter(T(-0.0), T(-2.0)); + VERIFY(t20 == -lim::denorm_min()); + T t21 = std::nextafter(T(), T(-1.0)); + VERIFY(t21 == -lim::denorm_min()); + T t22 = std::nextafter(T(-0.0), T(-0.0)); + VERIFY(t22 == T() && std::signbit(t22)); + T t23 = std::nextafter(-lim::denorm_min(), T(2.0)); + VERIFY(t23 == T() && std::signbit(t23)); + T t24 = std::nextafter(-lim::min(), T()); + VERIFY(std::fpclassify(t24) == FP_SUBNORMAL && t24 < T()); + T t25 = std::nextafter(t24, T(-1.0)); + VERIFY(t25 == -lim::min()); + T t26 = std::nextafter(-lim::min(), -lim::infinity()); + VERIFY(std::fpclassify(t26) == FP_NORMAL && t26 < -lim::min()); + T t27 = std::nextafter(t26, lim::infinity()); + VERIFY(t27 == -lim::min()); + T t28 = std::nextafter(T(-16.0), T(-16.5)); + VERIFY(t28 < t27); + T t29 = std::nextafter(t28, T(-15.5)); + VERIFY(t29 == T(-16.0)); + T t30 = std::nextafter(-lim::max(), T(0.5)); + VERIFY(std::fpclassify(t30) == FP_NORMAL && t30 > -lim::max()); + T t31 = std::nextafter(t30, -lim::infinity()); + VERIFY(t31 == -lim::max()); + T t32 = std::nextafter(t31, -lim::infinity()); + VERIFY(std::fpclassify(t32) == FP_INFINITE && std::signbit(t32)); + T t33 = std::nextafter(-lim::infinity(), t32); + VERIFY(t33 == t32); + T t34 = std::nextafter(t33, T(-1.0)); + VERIFY(t34 == -lim::max()); + T t35 = std::nextafter(-lim::quiet_NaN(), T()); + VERIFY(std::fpclassify(t35) == FP_NAN); + T t36 = std::nextafter(T(-17.0), lim::quiet_NaN()); + VERIFY(std::fpclassify(t36) == FP_NAN); + T t37 = std::nextafter(T(-0.0), T()); + VERIFY(t37 == T() && !std::signbit(t37)); +} + +int +main () +{ +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test (); +#endif +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test (); +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test (); +#endif +#if defined(__STDCPP_FLOAT128_T__) \ + && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ + || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) + test (); +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test (); +#endif +}