public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Implement "P0631R4 Math Constants" for C++20
@ 2019-07-31 16:41 Jonathan Wakely
  2019-07-31 17:34 ` Marc Glisse
  0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2019-07-31 16:41 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 796 bytes --]

The values of the constants are taken from Glibc where the equivalent
constant exists, or by rounding the actual constant to the same number
of digits as the Glibc constants have.

	P0631R4 Math Constants
	* include/Makefile.am: Add new header.
	* include/Makefile.in: Regenerate.
	* include/precompiled/stdc++.h: Include new header.
	* include/std/numbers: New header.
	* include/std/version (__cpp_lib_math_constants): Define.
	* testsuite/26_numerics/numbers/1.cc: New test.
	* testsuite/26_numerics/numbers/2.cc: New test.
	* testsuite/26_numerics/numbers/3.cc: New test.
	* testsuite/26_numerics/numbers/nonfloat_neg.cc: New test.

Tested x86_64-linux, committed to trunk.

The C++20 status table in the docs is getting out of date, we need to
add the new proposals (like this one) to it.



[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 15671 bytes --]

commit 2612c312d60f09ab1e4124c30856e2bb2b5bd76a
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Jul 31 16:43:45 2019 +0100

    Implement "P0631R4 Math Constants" for C++20
    
    The values of the constants are taken from Glibc where the equivalent
    constant exists, or by rounding the actual constant to the same number
    of digits as the Glibc constants have.
    
            P0631R4 Math Constants
            * include/Makefile.am: Add new header.
            * include/Makefile.in: Regenerate.
            * include/precompiled/stdc++.h: Include new header.
            * include/std/numbers: New header.
            * include/std/version (__cpp_lib_math_constants): Define.
            * testsuite/26_numerics/numbers/1.cc: New test.
            * testsuite/26_numerics/numbers/2.cc: New test.
            * testsuite/26_numerics/numbers/3.cc: New test.
            * testsuite/26_numerics/numbers/nonfloat_neg.cc: New test.

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 742f2c38ad5..3fe80f32cc4 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -57,6 +57,7 @@ std_headers = \
 	${std_srcdir}/memory \
 	${std_srcdir}/memory_resource \
 	${std_srcdir}/mutex \
+	${std_srcdir}/numbers \
 	${std_srcdir}/numeric \
 	${std_srcdir}/optional \
 	${std_srcdir}/ostream \
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index 477c5c88b36..d62f64b9f6e 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -136,6 +136,9 @@
 #if __cplusplus > 201703L
 #include <bit>
 // #include <compare>
+// #include <concepts>
+#include <numbers>
+// #include <ranges>
 // #include <span>
 // #include <syncstream>
 #include <version>
diff --git a/libstdc++-v3/include/std/numbers b/libstdc++-v3/include/std/numbers
new file mode 100644
index 00000000000..b8e38dd8080
--- /dev/null
+++ b/libstdc++-v3/include/std/numbers
@@ -0,0 +1,142 @@
+// <numbers> -*- C++ -*-
+
+// Copyright (C) 2019 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/numbers
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_NUMBERS
+#define _GLIBCXX_NUMBERS 1
+
+#pragma GCC system_header
+
+#if __cplusplus > 201703L
+
+#include <type_traits>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+/** @defgroup math_constants Mathematical constants
+ *  @ingroup numerics
+ *  @{
+ */
+
+/// Namespace for mathematical constants
+namespace numbers
+{
+#define __cpp_lib_math_constants 201907L
+
+  /// @cond undoc
+  template<typename _Tp>
+    using _Enable_if_floating = enable_if_t<is_floating_point_v<_Tp>, _Tp>;
+  /// @endcond
+
+  /// e
+  template<typename _Tp>
+    inline constexpr _Tp e_v
+      = _Enable_if_floating<_Tp>(2.718281828459045235360287471352662498L);
+
+  /// log_2 e
+  template<typename _Tp>
+    inline constexpr _Tp log2e_v
+      = _Enable_if_floating<_Tp>(1.442695040888963407359924681001892137L);
+
+  /// log_10 e
+  template<typename _Tp>
+    inline constexpr _Tp log10e_v
+      = _Enable_if_floating<_Tp>(0.434294481903251827651128918916605082L);
+
+  /// pi
+  template<typename _Tp>
+    inline constexpr _Tp pi_v
+      = _Enable_if_floating<_Tp>(3.141592653589793238462643383279502884L);
+
+  /// 1/pi
+  template<typename _Tp>
+    inline constexpr _Tp inv_pi_v
+      = _Enable_if_floating<_Tp>(0.318309886183790671537767526745028724L);
+
+  /// 1/sqrt(pi)
+  template<typename _Tp>
+    inline constexpr _Tp inv_sqrtpi_v
+      = _Enable_if_floating<_Tp>(0.564189583547756286948079451560772586L);
+
+  /// log_e 2
+  template<typename _Tp>
+    inline constexpr _Tp ln2_v
+      = _Enable_if_floating<_Tp>(0.693147180559945309417232121458176568L);
+
+  /// log_e 10
+  template<typename _Tp>
+    inline constexpr _Tp ln10_v
+      = _Enable_if_floating<_Tp>(2.302585092994045684017991454684364208L);
+
+  /// sqrt(2)
+  template<typename _Tp>
+    inline constexpr _Tp sqrt2_v
+      = _Enable_if_floating<_Tp>(1.414213562373095048801688724209698079L);
+
+  /// sqrt(3)
+  template<typename _Tp>
+    inline constexpr _Tp sqrt3_v
+      = _Enable_if_floating<_Tp>(1.732050807568877293527446341505872367L);
+
+  /// 1/sqrt(3)
+  template<typename _Tp>
+    inline constexpr _Tp inv_sqrt3_v
+      = _Enable_if_floating<_Tp>(0.577350269189625764509148780501957456L);
+
+  /// The Euler-Mascheroni constant
+  template<typename _Tp>
+    inline constexpr _Tp egamma_v
+      = _Enable_if_floating<_Tp>(0.577215664901532860606512090082402431L);
+
+  /// The golden ratio, (1+sqrt(5))/2
+  template<typename _Tp>
+    inline constexpr _Tp phi_v
+      = _Enable_if_floating<_Tp>(1.618033988749894848204586834365638118L);
+
+  inline constexpr double e = e_v<double>;
+  inline constexpr double log2e = log2e_v<double>;
+  inline constexpr double log10e = log10e_v<double>;
+  inline constexpr double pi = pi_v<double>;
+  inline constexpr double inv_pi = inv_pi_v<double>;
+  inline constexpr double inv_sqrtpi = inv_sqrtpi_v<double>;
+  inline constexpr double ln2 = ln2_v<double>;
+  inline constexpr double ln10 = ln10_v<double>;
+  inline constexpr double sqrt2 = sqrt2_v<double>;
+  inline constexpr double sqrt3 = sqrt3_v<double>;
+  inline constexpr double inv_sqrt3 = inv_sqrt3_v<double>;
+  inline constexpr double egamma = egamma_v<double>;
+  inline constexpr double phi = phi_v<double>;
+
+} // namespace numbers
+/// @}
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // C++20
+#endif // _GLIBCXX_NUMBERS
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index 6940b4499e6..8ebd6ba1682 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -163,6 +163,7 @@
 # define __cpp_lib_is_constant_evaluated 201811L
 #endif
 #define __cpp_lib_list_remove_return_type 201806L
+#define __cpp_lib_math_constants 201907L
 #endif // C++2a
 #endif // C++17
 #endif // C++14
diff --git a/libstdc++-v3/testsuite/26_numerics/numbers/1.cc b/libstdc++-v3/testsuite/26_numerics/numbers/1.cc
new file mode 100644
index 00000000000..78d0a5fb269
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/numbers/1.cc
@@ -0,0 +1,99 @@
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <numbers>
+
+#ifndef __cpp_lib_math_constants
+# error "Feature-test macro for math constants missing in <numbers>"
+#elif __cpp_lib_math_constants != 201907L
+# error "Feature-test macro for math constants has wrong value in <numbers>"
+#endif
+
+void
+test01()
+{
+  const double* d1  = &std::numbers::e_v<double>;
+  const double* d2  = &std::numbers::log2e_v<double>;
+  const double* d3  = &std::numbers::log10e_v<double>;
+  const double* d4  = &std::numbers::pi_v<double>;
+  const double* d5  = &std::numbers::inv_pi_v<double>;
+  const double* d6  = &std::numbers::inv_sqrtpi_v<double>;
+  const double* d7  = &std::numbers::ln2_v<double>;
+  const double* d8  = &std::numbers::ln10_v<double>;
+  const double* d9  = &std::numbers::sqrt2_v<double>;
+  const double* d10 = &std::numbers::sqrt3_v<double>;
+  const double* d11 = &std::numbers::inv_sqrt3_v<double>;
+  const double* d12 = &std::numbers::egamma_v<double>;
+  const double* d13 = &std::numbers::phi_v<double>;
+}
+
+void
+test02()
+{
+  const float* d1  = &std::numbers::e_v<float>;
+  const float* d2  = &std::numbers::log2e_v<float>;
+  const float* d3  = &std::numbers::log10e_v<float>;
+  const float* d4  = &std::numbers::pi_v<float>;
+  const float* d5  = &std::numbers::inv_pi_v<float>;
+  const float* d6  = &std::numbers::inv_sqrtpi_v<float>;
+  const float* d7  = &std::numbers::ln2_v<float>;
+  const float* d8  = &std::numbers::ln10_v<float>;
+  const float* d9  = &std::numbers::sqrt2_v<float>;
+  const float* d10 = &std::numbers::sqrt3_v<float>;
+  const float* d11 = &std::numbers::inv_sqrt3_v<float>;
+  const float* d12 = &std::numbers::egamma_v<float>;
+  const float* d13 = &std::numbers::phi_v<float>;
+}
+
+void
+test03()
+{
+  const long double* d1  = &std::numbers::e_v<long double>;
+  const long double* d2  = &std::numbers::log2e_v<long double>;
+  const long double* d3  = &std::numbers::log10e_v<long double>;
+  const long double* d4  = &std::numbers::pi_v<long double>;
+  const long double* d5  = &std::numbers::inv_pi_v<long double>;
+  const long double* d6  = &std::numbers::inv_sqrtpi_v<long double>;
+  const long double* d7  = &std::numbers::ln2_v<long double>;
+  const long double* d8  = &std::numbers::ln10_v<long double>;
+  const long double* d9  = &std::numbers::sqrt2_v<long double>;
+  const long double* d10 = &std::numbers::sqrt3_v<long double>;
+  const long double* d11 = &std::numbers::inv_sqrt3_v<long double>;
+  const long double* d12 = &std::numbers::egamma_v<long double>;
+  const long double* d13 = &std::numbers::phi_v<long double>;
+}
+
+void
+test04()
+{
+  static_assert(std::numbers::e == std::numbers::e_v<double>);
+  static_assert(std::numbers::log2e == std::numbers::log2e_v<double>);
+  static_assert(std::numbers::log10e == std::numbers::log10e_v<double>);
+  static_assert(std::numbers::pi == std::numbers::pi_v<double>);
+  static_assert(std::numbers::inv_pi == std::numbers::inv_pi_v<double>);
+  static_assert(std::numbers::inv_sqrtpi == std::numbers::inv_sqrtpi_v<double>);
+  static_assert(std::numbers::ln2 == std::numbers::ln2_v<double>);
+  static_assert(std::numbers::ln10 == std::numbers::ln10_v<double>);
+  static_assert(std::numbers::sqrt2 == std::numbers::sqrt2_v<double>);
+  static_assert(std::numbers::sqrt3 == std::numbers::sqrt3_v<double>);
+  static_assert(std::numbers::inv_sqrt3 == std::numbers::inv_sqrt3_v<double>);
+  static_assert(std::numbers::egamma == std::numbers::egamma_v<double>);
+  static_assert(std::numbers::phi == std::numbers::phi_v<double>);
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/numbers/2.cc b/libstdc++-v3/testsuite/26_numerics/numbers/2.cc
new file mode 100644
index 00000000000..a363bce9dab
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/numbers/2.cc
@@ -0,0 +1,27 @@
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <version>
+
+#ifndef __cpp_lib_math_constants
+# error "Feature-test macro for math constants missing in <version>"
+#elif __cpp_lib_math_constants != 201907L
+# error "Feature-test macro for math constants has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/26_numerics/numbers/3.cc b/libstdc++-v3/testsuite/26_numerics/numbers/3.cc
new file mode 100644
index 00000000000..56f4c953a85
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/numbers/3.cc
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <numbers>
+
+struct D { double val; };
+template<> inline constexpr D std::numbers::pi_v<D> = D{std::numbers::pi};
+static_assert( std::numbers::pi_v<D>.val == std::numbers::pi );
diff --git a/libstdc++-v3/testsuite/26_numerics/numbers/nonfloat_neg.cc b/libstdc++-v3/testsuite/26_numerics/numbers/nonfloat_neg.cc
new file mode 100644
index 00000000000..a83f55efc89
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/numbers/nonfloat_neg.cc
@@ -0,0 +1,36 @@
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <numbers>
+
+int
+test01()
+{
+  return std::numbers::pi_v<int>; // { dg-error "here" }
+}
+
+void
+test02()
+{
+  struct S { };
+  auto s = std::numbers::egamma_v<S>; // { dg-error "here" }
+}
+
+// { dg-prune-output "no type named 'type' in" }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 16:41 [PATCH] Implement "P0631R4 Math Constants" for C++20 Jonathan Wakely
@ 2019-07-31 17:34 ` Marc Glisse
  2019-07-31 18:44   ` Jonathan Wakely
  0 siblings, 1 reply; 10+ messages in thread
From: Marc Glisse @ 2019-07-31 17:34 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Wed, 31 Jul 2019, Jonathan Wakely wrote:

> The values of the constants are taken from Glibc where the equivalent
> constant exists, or by rounding the actual constant to the same number
> of digits as the Glibc constants have.

How does it behave with __float128? I think that with -std=gnu++2a, it 
counts as a floating point type, but the constant first becomes a long 
double and thus loses precision.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 17:34 ` Marc Glisse
@ 2019-07-31 18:44   ` Jonathan Wakely
  2019-07-31 18:49     ` Marc Glisse
  2019-07-31 18:53     ` Jakub Jelinek
  0 siblings, 2 replies; 10+ messages in thread
From: Jonathan Wakely @ 2019-07-31 18:44 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1329 bytes --]

On 31/07/19 19:07 +0200, Marc Glisse wrote:
>On Wed, 31 Jul 2019, Jonathan Wakely wrote:
>
>>The values of the constants are taken from Glibc where the equivalent
>>constant exists, or by rounding the actual constant to the same number
>>of digits as the Glibc constants have.
>
>How does it behave with __float128? I think that with -std=gnu++2a, it 
>counts as a floating point type, but the constant first becomes a long 
>double and thus loses precision.

Indeed it does:

#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
  template<>
    struct __is_floating_point_helper<__float128>
    : public true_type { };
#endif

We could add explicit specializations for __float128 and use the Q
suffix. That's not valid when __STRICT_ANSI__ is defined (unless 
-fext-numeric-literals is also used) but as the snippet above shows,
__float128 isn't a floating-point type when __STRICT_ANSI__ is
defined.

So something like the attached patch.  The glibc <math.h> says the
values I used have enough digits for IEEE quad-precision:

/* The above constants are not adequate for computation using `long double's.
   Therefore we provide as an extension constants with similar names as a
   GNU extension.  Provide enough digits for the 128-bit IEEE quad.  */

I don't know if we need more accuracy for IBM double double.



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 2265 bytes --]

diff --git a/libstdc++-v3/include/std/numbers b/libstdc++-v3/include/std/numbers
index b8e38dd8080..314b130fbd5 100644
--- a/libstdc++-v3/include/std/numbers
+++ b/libstdc++-v3/include/std/numbers
@@ -133,6 +133,72 @@ namespace numbers
   inline constexpr double egamma = egamma_v<double>;
   inline constexpr double phi = phi_v<double>;
 
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+  template<>
+    inline constexpr __float128 e_v<__float128>
+      = 2.718281828459045235360287471352662498Q;
+
+  /// log_2 e
+  template<>
+    inline constexpr __float128 log2e_v<__float128>
+      = 1.442695040888963407359924681001892137Q;
+
+  /// log_10 e
+  template<>
+    inline constexpr __float128 log10e_v<__float128>
+      = 0.434294481903251827651128918916605082Q;
+
+  /// pi
+  template<>
+    inline constexpr __float128 pi_v<__float128>
+      = 3.141592653589793238462643383279502884Q;
+
+  /// 1/pi
+  template<>
+    inline constexpr __float128 inv_pi_v<__float128>
+      = 0.318309886183790671537767526745028724Q;
+
+  /// 1/sqrt(pi)
+  template<>
+    inline constexpr __float128 inv_sqrtpi_v<__float128>
+      = 0.564189583547756286948079451560772586Q;
+
+  /// log_e 2
+  template<>
+    inline constexpr __float128 ln2_v<__float128>
+      = 0.693147180559945309417232121458176568Q;
+
+  /// log_e 10
+  template<>
+    inline constexpr __float128 ln10_v<__float128>
+      = 2.302585092994045684017991454684364208Q;
+
+  /// sqrt(2)
+  template<>
+    inline constexpr __float128 sqrt2_v<__float128>
+      = 1.414213562373095048801688724209698079Q;
+
+  /// sqrt(3)
+  template<>
+    inline constexpr __float128 sqrt3_v<__float128>
+      = 1.732050807568877293527446341505872367Q;
+
+  /// 1/sqrt(3)
+  template<>
+    inline constexpr __float128 inv_sqrt3_v<__float128>
+      = 0.577350269189625764509148780501957456Q;
+
+  /// The Euler-Mascheroni constant
+  template<>
+    inline constexpr __float128 egamma_v<__float128>
+      = 0.577215664901532860606512090082402431Q;
+
+  /// The golden ratio, (1+sqrt(5))/2
+  template<>
+    inline constexpr __float128 phi_v<__float128>
+      = 1.618033988749894848204586834365638118Q;
+#endif // USE_FLOAT128
+
 } // namespace numbers
 /// @}
 _GLIBCXX_END_NAMESPACE_VERSION

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 18:44   ` Jonathan Wakely
@ 2019-07-31 18:49     ` Marc Glisse
  2019-07-31 23:05       ` Segher Boessenkool
  2019-07-31 18:53     ` Jakub Jelinek
  1 sibling, 1 reply; 10+ messages in thread
From: Marc Glisse @ 2019-07-31 18:49 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Wed, 31 Jul 2019, Jonathan Wakely wrote:

> So something like the attached patch.  The glibc <math.h> says the
> values I used have enough digits for IEEE quad-precision:
>
> /* The above constants are not adequate for computation using `long double's.
>  Therefore we provide as an extension constants with similar names as a
>  GNU extension.  Provide enough digits for the 128-bit IEEE quad.  */
>
> I don't know if we need more accuracy for IBM double double.

double double has less precision than quad so it should be fine.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 18:44   ` Jonathan Wakely
  2019-07-31 18:49     ` Marc Glisse
@ 2019-07-31 18:53     ` Jakub Jelinek
  2019-07-31 19:09       ` Jonathan Wakely
  1 sibling, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2019-07-31 18:53 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Wed, Jul 31, 2019 at 07:37:03PM +0100, Jonathan Wakely wrote:
> On 31/07/19 19:07 +0200, Marc Glisse wrote:
> > On Wed, 31 Jul 2019, Jonathan Wakely wrote:
> > 
> > > The values of the constants are taken from Glibc where the equivalent
> > > constant exists, or by rounding the actual constant to the same number
> > > of digits as the Glibc constants have.
> > 
> > How does it behave with __float128? I think that with -std=gnu++2a, it
> > counts as a floating point type, but the constant first becomes a long
> > double and thus loses precision.
> 
> Indeed it does:
> 
> #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
>  template<>
>    struct __is_floating_point_helper<__float128>
>    : public true_type { };
> #endif
> 
> We could add explicit specializations for __float128 and use the Q
> suffix. That's not valid when __STRICT_ANSI__ is defined (unless
> -fext-numeric-literals is also used) but as the snippet above shows,
> __float128 isn't a floating-point type when __STRICT_ANSI__ is
> defined.

Perhaps add __extension__ before the literals too?

> I don't know if we need more accuracy for IBM double double.

I'd think the *L constants should be good enough.

	Jakub

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 18:53     ` Jakub Jelinek
@ 2019-07-31 19:09       ` Jonathan Wakely
  2019-07-31 19:27         ` Jakub Jelinek
  0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2019-07-31 19:09 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: libstdc++, gcc-patches

On 31/07/19 20:50 +0200, Jakub Jelinek wrote:
>On Wed, Jul 31, 2019 at 07:37:03PM +0100, Jonathan Wakely wrote:
>> On 31/07/19 19:07 +0200, Marc Glisse wrote:
>> > On Wed, 31 Jul 2019, Jonathan Wakely wrote:
>> >
>> > > The values of the constants are taken from Glibc where the equivalent
>> > > constant exists, or by rounding the actual constant to the same number
>> > > of digits as the Glibc constants have.
>> >
>> > How does it behave with __float128? I think that with -std=gnu++2a, it
>> > counts as a floating point type, but the constant first becomes a long
>> > double and thus loses precision.
>>
>> Indeed it does:
>>
>> #if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
>>  template<>
>>    struct __is_floating_point_helper<__float128>
>>    : public true_type { };
>> #endif
>>
>> We could add explicit specializations for __float128 and use the Q
>> suffix. That's not valid when __STRICT_ANSI__ is defined (unless
>> -fext-numeric-literals is also used) but as the snippet above shows,
>> __float128 isn't a floating-point type when __STRICT_ANSI__ is
>> defined.
>
>Perhaps add __extension__ before the literals too?

Does that do anything for Q literals? I thought I'd tried it
previously and decided it didn't. I'm happy to add it though.

>> I don't know if we need more accuracy for IBM double double.
>
>I'd think the *L constants should be good enough.

OK, great.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 19:09       ` Jonathan Wakely
@ 2019-07-31 19:27         ` Jakub Jelinek
  2019-07-31 21:38           ` Jonathan Wakely
  0 siblings, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2019-07-31 19:27 UTC (permalink / raw)
  To: Jonathan Wakely, Jason Merrill; +Cc: libstdc++, gcc-patches

On Wed, Jul 31, 2019 at 07:58:55PM +0100, Jonathan Wakely wrote:
> > Perhaps add __extension__ before the literals too?
> 
> Does that do anything for Q literals? I thought I'd tried it
> previously and decided it didn't. I'm happy to add it though.

You're right, it works well that way only in C, not in C++, on say:
long double x = 1.234Q;
long double y = __extension__ 1.234Q;
This is pedwarned not when actually parsing the number, but
when tokenizing it, which for C++ we do before parsing for all tokens.

We could add a hack for it, say don't emit the pedwarn if the previous token
is RID_EXTENSION, but it wouldn't be anything close to how we handle
__extension__ during parsing (where pedantic is disabled while parsing the
whole cast expression after it).

	Jakub

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 19:27         ` Jakub Jelinek
@ 2019-07-31 21:38           ` Jonathan Wakely
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2019-07-31 21:38 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jason Merrill, libstdc++, gcc-patches

On 31/07/19 21:16 +0200, Jakub Jelinek wrote:
>On Wed, Jul 31, 2019 at 07:58:55PM +0100, Jonathan Wakely wrote:
>> > Perhaps add __extension__ before the literals too?
>>
>> Does that do anything for Q literals? I thought I'd tried it
>> previously and decided it didn't. I'm happy to add it though.
>
>You're right, it works well that way only in C, not in C++, on say:
>long double x = 1.234Q;
>long double y = __extension__ 1.234Q;
>This is pedwarned not when actually parsing the number, but
>when tokenizing it, which for C++ we do before parsing for all tokens.
>
>We could add a hack for it, say don't emit the pedwarn if the previous token
>is RID_EXTENSION, but it wouldn't be anything close to how we handle
>__extension__ during parsing (where pedantic is disabled while parsing the
>whole cast expression after it).

Ah yes, I definitely looked into this before.

If I use the Q suffix like so ...

#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
  template<>
    inline constexpr __float128 e_v<__float128>
      = 2.718281828459045235360287471352662498Q;

...
#endif

Then it produces 13 pedwarns with -pedantic -Wsystem-headers:

In file included from num.cc:1:
/home/jwakely/gcc/10/include/c++/10.0.0/numbers:139:7: warning: non-standard suffix on floating constant [-Wpedantic]
  139 |       = 2.718281828459045235360287471352662498Q;
      |       ^

Users would get those warnings even if not using the __float128
constants. Admittedly, if they use -pedantic combined with
-std=gnu++2a, and combine that with -Wsystem-headers, they deserve
what they get.

I think it's better to have accurate __float128 constants even if they
warn with certain combinations of warning flags.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 18:49     ` Marc Glisse
@ 2019-07-31 23:05       ` Segher Boessenkool
  2019-08-06 16:03         ` Jonathan Wakely
  0 siblings, 1 reply; 10+ messages in thread
From: Segher Boessenkool @ 2019-07-31 23:05 UTC (permalink / raw)
  To: libstdc++; +Cc: Jonathan Wakely, gcc-patches

On Wed, Jul 31, 2019 at 08:43:50PM +0200, Marc Glisse wrote:
> On Wed, 31 Jul 2019, Jonathan Wakely wrote:
> 
> >So something like the attached patch.  The glibc <math.h> says the
> >values I used have enough digits for IEEE quad-precision:
> >
> >/* The above constants are not adequate for computation using `long 
> >double's.
> > Therefore we provide as an extension constants with similar names as a
> > GNU extension.  Provide enough digits for the 128-bit IEEE quad.  */
> >
> >I don't know if we need more accuracy for IBM double double.
> 
> double double has less precision than quad so it should be fine.

The *precision* (as defined in IEEE 754) of double double is much higher
than that of IEEE quad precision float: "the maximum number of
significant digits that can be represented in a format" -- it's just
that most of those bits have to be zero!

Neither double-double is a subset of QP, nor the other way around.  This
is *the* problem we have in rs6000 with these two float formats: GCC
cannot handle if two FP formats are like that.

(The math constants here are fine for double double, of course).


Segher

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Implement "P0631R4 Math Constants" for C++20
  2019-07-31 23:05       ` Segher Boessenkool
@ 2019-08-06 16:03         ` Jonathan Wakely
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2019-08-06 16:03 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1296 bytes --]

On 31/07/19 17:57 -0500, Segher Boessenkool wrote:
>On Wed, Jul 31, 2019 at 08:43:50PM +0200, Marc Glisse wrote:
>> On Wed, 31 Jul 2019, Jonathan Wakely wrote:
>>
>> >So something like the attached patch.  The glibc <math.h> says the
>> >values I used have enough digits for IEEE quad-precision:
>> >
>> >/* The above constants are not adequate for computation using `long
>> >double's.
>> > Therefore we provide as an extension constants with similar names as a
>> > GNU extension.  Provide enough digits for the 128-bit IEEE quad.  */
>> >
>> >I don't know if we need more accuracy for IBM double double.
>>
>> double double has less precision than quad so it should be fine.
>
>The *precision* (as defined in IEEE 754) of double double is much higher
>than that of IEEE quad precision float: "the maximum number of
>significant digits that can be represented in a format" -- it's just
>that most of those bits have to be zero!
>
>Neither double-double is a subset of QP, nor the other way around.  This
>is *the* problem we have in rs6000 with these two float formats: GCC
>cannot handle if two FP formats are like that.
>
>(The math constants here are fine for double double, of course).

Thanks. I've committed the attached patch then, after testing on
x86_64-linux and powerpc64le-linux.



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 4940 bytes --]

commit 8c16cb54739973f84f27055c32c7e0cc557a784e
Author: redi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Aug 6 15:57:51 2019 +0000

    Specialize std::numbers constants for __float128
    
            * include/std/numbers [!__STRICT_ANSI__ && _GLIBCXX_USE_FLOAT128]
            (e_v, log2e_v, log10e_v, pi_v, inv_pi_v, inv_sqrtpi_v, ln2_v, ln10_v)
            (sqrt2_v, sqrt3_v, inv_sqrt3, egamma_v, phi_v): Add explicit
            specializations for __float128.
            * testsuite/26_numerics/numbers/float128.cc: New test.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@274145 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/libstdc++-v3/include/std/numbers b/libstdc++-v3/include/std/numbers
index b8e38dd8080..314b130fbd5 100644
--- a/libstdc++-v3/include/std/numbers
+++ b/libstdc++-v3/include/std/numbers
@@ -133,6 +133,72 @@ namespace numbers
   inline constexpr double egamma = egamma_v<double>;
   inline constexpr double phi = phi_v<double>;
 
+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
+  template<>
+    inline constexpr __float128 e_v<__float128>
+      = 2.718281828459045235360287471352662498Q;
+
+  /// log_2 e
+  template<>
+    inline constexpr __float128 log2e_v<__float128>
+      = 1.442695040888963407359924681001892137Q;
+
+  /// log_10 e
+  template<>
+    inline constexpr __float128 log10e_v<__float128>
+      = 0.434294481903251827651128918916605082Q;
+
+  /// pi
+  template<>
+    inline constexpr __float128 pi_v<__float128>
+      = 3.141592653589793238462643383279502884Q;
+
+  /// 1/pi
+  template<>
+    inline constexpr __float128 inv_pi_v<__float128>
+      = 0.318309886183790671537767526745028724Q;
+
+  /// 1/sqrt(pi)
+  template<>
+    inline constexpr __float128 inv_sqrtpi_v<__float128>
+      = 0.564189583547756286948079451560772586Q;
+
+  /// log_e 2
+  template<>
+    inline constexpr __float128 ln2_v<__float128>
+      = 0.693147180559945309417232121458176568Q;
+
+  /// log_e 10
+  template<>
+    inline constexpr __float128 ln10_v<__float128>
+      = 2.302585092994045684017991454684364208Q;
+
+  /// sqrt(2)
+  template<>
+    inline constexpr __float128 sqrt2_v<__float128>
+      = 1.414213562373095048801688724209698079Q;
+
+  /// sqrt(3)
+  template<>
+    inline constexpr __float128 sqrt3_v<__float128>
+      = 1.732050807568877293527446341505872367Q;
+
+  /// 1/sqrt(3)
+  template<>
+    inline constexpr __float128 inv_sqrt3_v<__float128>
+      = 0.577350269189625764509148780501957456Q;
+
+  /// The Euler-Mascheroni constant
+  template<>
+    inline constexpr __float128 egamma_v<__float128>
+      = 0.577215664901532860606512090082402431Q;
+
+  /// The golden ratio, (1+sqrt(5))/2
+  template<>
+    inline constexpr __float128 phi_v<__float128>
+      = 1.618033988749894848204586834365638118Q;
+#endif // USE_FLOAT128
+
 } // namespace numbers
 /// @}
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/26_numerics/numbers/float128.cc b/libstdc++-v3/testsuite/26_numerics/numbers/float128.cc
new file mode 100644
index 00000000000..2d9dafcd482
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/numbers/float128.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2019 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <numbers>
+
+#if defined(_GLIBCXX_USE_FLOAT128)
+void
+test01()
+{
+  const __float128* d1  = &std::numbers::e_v<__float128>;
+  const __float128* d2  = &std::numbers::log2e_v<__float128>;
+  const __float128* d3  = &std::numbers::log10e_v<__float128>;
+  const __float128* d4  = &std::numbers::pi_v<__float128>;
+  const __float128* d5  = &std::numbers::inv_pi_v<__float128>;
+  const __float128* d6  = &std::numbers::inv_sqrtpi_v<__float128>;
+  const __float128* d7  = &std::numbers::ln2_v<__float128>;
+  const __float128* d8  = &std::numbers::ln10_v<__float128>;
+  const __float128* d9  = &std::numbers::sqrt2_v<__float128>;
+  const __float128* d10 = &std::numbers::sqrt3_v<__float128>;
+  const __float128* d11 = &std::numbers::inv_sqrt3_v<__float128>;
+  const __float128* d12 = &std::numbers::egamma_v<__float128>;
+  const __float128* d13 = &std::numbers::phi_v<__float128>;
+}
+#endif

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-08-06 15:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-31 16:41 [PATCH] Implement "P0631R4 Math Constants" for C++20 Jonathan Wakely
2019-07-31 17:34 ` Marc Glisse
2019-07-31 18:44   ` Jonathan Wakely
2019-07-31 18:49     ` Marc Glisse
2019-07-31 23:05       ` Segher Boessenkool
2019-08-06 16:03         ` Jonathan Wakely
2019-07-31 18:53     ` Jakub Jelinek
2019-07-31 19:09       ` Jonathan Wakely
2019-07-31 19:27         ` Jakub Jelinek
2019-07-31 21:38           ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).