[libcxx-commits] [libcxx] [libc++][math] Mathematical Special Functions: Hermite Polynomial (PR #89982)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu May 16 13:19:22 PDT 2024
https://github.com/PaulXiCao updated https://github.com/llvm/llvm-project/pull/89982
>From 0f3397f9ceca9f61b12368c06aceb029c8ffacfe Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 20 Apr 2024 20:59:20 +0200
Subject: [PATCH 01/76] apply original diff from D58876
This commit was created by taking the abandoned merge request from
https://reviews.llvm.org/D58876 .
---
libcxx/include/experimental/__hermite | 50 +++
libcxx/include/experimental/__laguerre | 71 +++++
libcxx/include/experimental/__legendre | 123 ++++++++
libcxx/include/experimental/cmath | 103 +++++++
.../numerics/c.math/assoc_laguerre.pass.cpp | 134 ++++++++
.../numerics/c.math/assoc_legendre.pass.cpp | 203 ++++++++++++
.../numerics/c.math/hermite.pass.cpp | 290 ++++++++++++++++++
.../numerics/c.math/laguerre.pass.cpp | 119 +++++++
.../numerics/c.math/legendre.pass.cpp | 114 +++++++
9 files changed, 1207 insertions(+)
create mode 100644 libcxx/include/experimental/__hermite
create mode 100644 libcxx/include/experimental/__laguerre
create mode 100644 libcxx/include/experimental/__legendre
create mode 100644 libcxx/include/experimental/cmath
create mode 100644 libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp
create mode 100644 libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp
create mode 100644 libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp
create mode 100644 libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp
create mode 100644 libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp
diff --git a/libcxx/include/experimental/__hermite b/libcxx/include/experimental/__hermite
new file mode 100644
index 0000000000000..daa89129fc8de
--- /dev/null
+++ b/libcxx/include/experimental/__hermite
@@ -0,0 +1,50 @@
+//===------------------------ __hermite -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the internal implementations of std::hermite.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL___HERMITE
+#define _LIBCPP_EXPERIMENTAL___HERMITE
+
+#include <experimental/__config>
+#include <cmath>
+#include <limits>
+
+/// \return the hermite polynomial \f$ H_{n}(x) \f$
+/// \note The implementation is based on the recurrence formula
+/// \f[
+/// nH_{n+1}(x) = 2x H_{n}(x) - 2 n H_{n-1}
+/// \f]
+/// Press, William H., et al. Numerical recipes 3rd edition: The art of
+/// scientific computing. Cambridge university press, 2007, p. 182.
+template <class _Real>
+_Real __libcpp_hermite_recurrence(unsigned __n, _Real __x) {
+ if (__n == 0u)
+ return _Real(1);
+
+ _Real __t2(1);
+ _Real __t1 = _Real(2) * __x;
+ for (unsigned __i = 1; __i < __n; ++__i) {
+ const _Real __t0 = _Real(2) * (__x * __t1 - _Real(__i) * __t2);
+ __t2 = __t1;
+ __t1 = __t0;
+ }
+ return __t1;
+}
+
+template <class _Real> _Real __libcpp_hermite(unsigned __n, _Real __x) {
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ return __libcpp_hermite_recurrence(__n, __x);
+}
+
+#endif // _LIBCPP_EXPERIMENTAL___HERMITE
diff --git a/libcxx/include/experimental/__laguerre b/libcxx/include/experimental/__laguerre
new file mode 100644
index 0000000000000..a7fc6cfbde20e
--- /dev/null
+++ b/libcxx/include/experimental/__laguerre
@@ -0,0 +1,71 @@
+//===------------------------ __laguerre ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the internal implementations of std::laguerre
+/// and std::assoc_laguerre.
+///
+//===----------------------------------------------------------------------===//
+
+
+#ifndef _LIBCPP_EXPERIMENTAL___LAGUERRE
+#define _LIBCPP_EXPERIMENTAL___LAGUERRE
+
+#include <experimental/__config>
+#include <cmath>
+#include <limits>
+#include <stdexcept>
+
+/// \return the generalized laguerre polynomial \f$ L_{n}^{(\alpha)}(x) \f$
+/// \note The implementation is based on the recurrence formula
+/// \f[
+/// nL_{n}^{(\alpha)}(x) = (-x + 2n + \alpha - 1) L_{n-1}^{(\alpha)}(x) -
+/// (n + \alpha - 1) L_{n-2}^{(\alpha)}(x)
+/// \f]
+/// Press, William H., et al. Numerical recipes 3rd edition: The art of
+/// scientific computing. Cambridge university press, 2007, p. 182.
+template <class _Real>
+_Real __libcpp_generalized_laguerre_recurrence(unsigned __n, _Real __alpha,
+ _Real __x) {
+ if (__n == 0u)
+ return _Real(1);
+
+ _Real __delta = __alpha - __x;
+ _Real __li = _Real(1) + __delta;
+ const _Real __alpham1 = __alpha - _Real(1);
+ for (unsigned __i = 2; __i <= __n; ++__i) {
+ __delta = (__delta * (_Real(__i) + __alpham1) - __x * __li) / _Real(__i);
+ __li += __delta;
+ }
+ return __li;
+}
+
+template <class _Real>
+_Real __libcpp_assoc_laguerre(unsigned __n, unsigned __m, _Real __x) {
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ if (__x < _Real(0))
+ _VSTD::__throw_domain_error(
+ "Argument of assoc_laguerre function is out of range");
+
+ return __libcpp_generalized_laguerre_recurrence(__n, _Real(__m), __x);
+}
+
+template <class _Real> _Real __libcpp_laguerre(unsigned __n, _Real __x) {
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ if (__x < _Real(0))
+ _VSTD::__throw_domain_error(
+ "Argument of laguerre function is out of range");
+
+ return __libcpp_generalized_laguerre_recurrence(__n, _Real(0), __x);
+}
+
+#endif // _LIBCPP_EXPERIMENTAL___LAGUERRE
diff --git a/libcxx/include/experimental/__legendre b/libcxx/include/experimental/__legendre
new file mode 100644
index 0000000000000..d2be9b4842226
--- /dev/null
+++ b/libcxx/include/experimental/__legendre
@@ -0,0 +1,123 @@
+//===------------------------ __legendre ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the internal implementations of std::legendre
+/// and std::assoc_legendre.
+///
+//===----------------------------------------------------------------------===//
+
+
+#ifndef _LIBCPP_EXPERIMENTAL___LEGENDRE
+#define _LIBCPP_EXPERIMENTAL___LEGENDRE
+
+#include <experimental/__config>
+#include <cmath>
+#include <limits>
+#include <stdexcept>
+
+/// \return the Legendre polynomial \f$ P_{n}(x) \f$
+/// \note The implementation is based on the recurrence formula
+/// \f[
+/// (n+1)P_{n+1}(x) = (2n+1)xP_{n}(x) - nP_{n-1}(x)
+/// \f]
+/// Press, William H., et al. Numerical recipes 3rd edition: The art of
+/// scientific computing. Cambridge university press, 2007, p. 182.
+template <class _Real>
+_Real __libcpp_legendre_recurrence(unsigned __n, _Real __x) {
+ if (__n == 0u)
+ return _Real(1);
+
+ _Real __t2(1);
+ _Real __t1 = __x;
+ for (unsigned __i = 1; __i < __n; ++__i) {
+ const _Real __k = _Real(__i);
+ _Real __t0 = ((_Real(2) * __k + _Real(1)) * __x * __t1 - __k * __t2) /
+ (__k + _Real(1));
+ __t2 = __t1;
+ __t1 = __t0;
+ }
+ return __t1;
+}
+
+template <class _Real> _Real __libcpp_legendre(unsigned __n, _Real __x) {
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ if (std::abs(__x) > _Real(1))
+ _VSTD::__throw_domain_error(
+ "Argument of legendre function is out of range");
+
+ return __libcpp_legendre_recurrence(__n, __x);
+}
+
+/// \return \f$ s^{-m} P_{l}^{m}(x) \f$ with an additonal scaling factor to
+/// prevent overflow. \note The implementation is based on the recurrence
+/// formula \f[ (l-m+1)P_{l+1}^{m}(x) = (2l+1)xP_{l}^{m}(x) -
+/// (l+m)P_{l-1}^{m}(x) \f] with \f[ P_{m}^{m}(x) = \sqrt{1 -
+/// x^2}^{m}\frac{(2m)!}{2^m m!} \f] and \f[ P_{m-1}^{m}(x) = 0 \f] \attention
+/// The starting point of the recursion grows exponentially with __m! For large
+/// m, we have the following relation: \f[ P_{m}^{m}(x) \approx \sqrt{1 -
+/// x^2}^{m}\sqrt{2} 2^{n} \exp( n(\ln n - 1 )) \f] For example, for \f$ m = 40
+/// \f$, we already have \f$ P_{40}^{40}(0) \approx 8 \cdot 10^{58} \f$
+/// \attention The so-called Condon-Shortley phase term is omitted in the C++17
+/// standard's definition of std::assoc_laguerre.
+template <class _Real>
+_Real __libcpp_assoc_legendre_recurrence(unsigned __l, unsigned __m, _Real __x,
+ _Real __scale = _Real(1)) {
+ if (__m == 0u)
+ return __libcpp_legendre_recurrence(__l, __x);
+
+ if (__l < __m)
+ return _Real(0);
+
+ if (__l == 0u)
+ return _Real(1);
+
+ _Real __pmm = _Real(1);
+ // Note: (1-x)*(1+x) is more accurate than (1-x*x)
+ // "What Every Computer Scientist Should Know About Floating-Point
+ // Arithmetic", David Goldberg, p. 38
+ const _Real __t =
+ std::sqrt((_Real(1) - __x) * (_Real(1) + __x)) / (_Real(2) * __scale);
+ for (unsigned __i = 2u * __m; __i > __m; --__i)
+ __pmm *= __t * __i;
+
+ if (__l == __m)
+ return __pmm;
+
+ // Actually, we'd start with _pmm but it grows exponentially with __m.
+ // Luckily, the recursion scales. So we can start with 1 and multiply
+ // afterwards.
+ _Real __t2 = _Real(1);
+ _Real __t1 = _Real(2u * __m + 1u) * __x; // first iteration unfolded
+ for (unsigned __i = __m + 1u; __i < __l; ++__i) {
+ // As soon as one of the terms becomes inf, this will quickly lead to NaNs.
+ // float just doesn't do it for the whole range up to l==127.
+ const _Real __t0 =
+ (_Real(2u * __i + 1u) * __x * __t1 - _Real(__i + __m) * __t2) /
+ _Real(__i - __m + 1u);
+ __t2 = __t1;
+ __t1 = __t0;
+ }
+ return __t1 * __pmm;
+}
+
+template <class _Real>
+_Real __libcpp_assoc_legendre(unsigned __n, unsigned __m, _Real __x) {
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ if (std::abs(__x) > _Real(1))
+ _VSTD::__throw_domain_error(
+ "Argument of assoc_legendre function is out of range");
+
+ return __libcpp_assoc_legendre_recurrence(__n, __m, __x);
+}
+
+#endif // _LIBCPP_EXPERIMENTAL___LEGENDRE
diff --git a/libcxx/include/experimental/cmath b/libcxx/include/experimental/cmath
new file mode 100644
index 0000000000000..9fd5d4fcbe190
--- /dev/null
+++ b/libcxx/include/experimental/cmath
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+//===---------------------------- cmath ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_CMATH
+#define _LIBCPP_EXPERIMENTAL_CMATH
+
+// The following macro name shall be conditionally defined by the implementation
+// to indicate conformance to the International Standard ISO/IEC JTC 1/SC 22/WG 21 N3060
+//#define __STDCPP_MATH_SPEC_FUNCS__ 201003L
+
+#include <experimental/__config>
+#include <cmath>
+
+#if _LIBCPP_STD_VER > 14
+
+#include <experimental/__hermite>
+#include <experimental/__laguerre>
+#include <experimental/__legendre>
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+
+inline _LIBCPP_INLINE_VISIBILITY double assoc_laguerre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
+{
+ return __libcpp_assoc_laguerre<double>(__lcpp_n , __lcpp_m, __lcpp_x);
+}
+inline _LIBCPP_INLINE_VISIBILITY float assoc_laguerref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
+{
+ return static_cast<float>(__libcpp_assoc_laguerre<double>(__lcpp_n , __lcpp_m, static_cast<double>(__lcpp_x)));
+}
+inline _LIBCPP_INLINE_VISIBILITY long double assoc_laguerrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
+{
+ return __libcpp_assoc_laguerre<long double>(__lcpp_n , __lcpp_m, __lcpp_x);
+}
+
+
+inline _LIBCPP_INLINE_VISIBILITY double assoc_legendre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
+{
+ return __libcpp_assoc_legendre<double>(__lcpp_n , __lcpp_m, __lcpp_x);
+}
+inline _LIBCPP_INLINE_VISIBILITY float assoc_legendref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
+{
+ // use double internally -- float is too prone to overflow!
+ return static_cast<float>(__libcpp_assoc_legendre<double>(__lcpp_n , __lcpp_m, static_cast<double>(__lcpp_x)));
+}
+inline _LIBCPP_INLINE_VISIBILITY long double assoc_legendrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
+{
+ return __libcpp_assoc_legendre<long double>(__lcpp_n , __lcpp_m, __lcpp_x);
+}
+
+
+inline _LIBCPP_INLINE_VISIBILITY double laguerre(unsigned __lcpp_n, double __lcpp_x)
+{
+ return __libcpp_laguerre<double>(__lcpp_n ,__lcpp_x);
+}
+inline _LIBCPP_INLINE_VISIBILITY float laguerref(unsigned __lcpp_n, float __lcpp_x)
+{
+ return static_cast<float>(__libcpp_laguerre<double>(__lcpp_n, static_cast<double>(__lcpp_x)));
+}
+inline _LIBCPP_INLINE_VISIBILITY long double laguerrel(unsigned __lcpp_n, long double __lcpp_x)
+{
+ return __libcpp_laguerre<long double>(__lcpp_n ,__lcpp_x);
+}
+
+
+inline _LIBCPP_INLINE_VISIBILITY double legendre(unsigned __lcpp_n, double __lcpp_x)
+{
+ return __libcpp_legendre<double>(__lcpp_n ,__lcpp_x);
+}
+inline _LIBCPP_INLINE_VISIBILITY float legendref(unsigned __lcpp_n, float __lcpp_x)
+{
+ return static_cast<float>(__libcpp_legendre<double>(__lcpp_n, static_cast<double>(__lcpp_x)));
+}
+inline _LIBCPP_INLINE_VISIBILITY long double legendrel(unsigned __lcpp_n, long double __lcpp_x)
+{
+ return __libcpp_legendre<long double>(__lcpp_n ,__lcpp_x);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY double hermite(unsigned __lcpp_n, double __lcpp_x)
+{
+ return __libcpp_hermite<double>(__lcpp_n ,__lcpp_x);
+}
+inline _LIBCPP_INLINE_VISIBILITY float hermitef(unsigned __lcpp_n, float __lcpp_x)
+{
+ // use double internally -- float is too prone to overflow!
+ return static_cast<float>(__libcpp_hermite(__lcpp_n , static_cast<double>(__lcpp_x)));
+}
+inline _LIBCPP_INLINE_VISIBILITY long double hermitel(unsigned __lcpp_n, long double __lcpp_x)
+{
+ return __libcpp_hermite<long double>(__lcpp_n ,__lcpp_x);
+}
+
+
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL
+
+#endif // _LIBCPP_STD_VER > 14
+
+#endif // _LIBCPP_EXPERIMENTAL_CMATH
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp b/libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp
new file mode 100644
index 0000000000000..10261f017ad70
--- /dev/null
+++ b/libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp
@@ -0,0 +1,134 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/cmath>
+
+#include <cassert>
+#include <experimental/cmath>
+#include <limits>
+
+#if _LIBCPP_STD_VER > 14
+
+template <class T> void testAssocLaguerreNaNPropagation() {
+ const unsigned MaxN = 127;
+ const T x = std::numeric_limits<T>::quiet_NaN();
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ assert(std::isnan(std::experimental::assoc_laguerre(n, m, x)));
+ }
+ }
+}
+
+template <class T> void testAssocLaguerreNotNaN(const T x) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ assert(!std::isnan(std::experimental::assoc_laguerre(n, m, x)));
+ }
+ }
+}
+
+template <class T> void testAssocLaguerreThrows(const T x) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ bool Throws = false;
+ try {
+ std::experimental::assoc_laguerre(n, m, x);
+ } catch (const std::domain_error &) {
+ Throws = true;
+ }
+ assert(Throws);
+ }
+ }
+#endif // _LIBCPP_NO_EXCEPTIONS
+}
+
+template <class T>
+void testAssocLaguerreVsLaguerre(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ const T Result = std::experimental::assoc_laguerre(n, 0, x);
+ const T ExpectedResult = std::experimental::laguerre(n, x);
+ const T Tolerance =
+ AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
+ const T Difference = std::abs(Result - ExpectedResult);
+ assert(Difference <= Tolerance);
+ }
+ }
+}
+
+template <class T>
+void testAssocLaguerreAnalytic(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const auto compareFloatingPoint =
+ [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
+ if (std::isinf(ExpectedResult) && std::isinf(Result))
+ return true;
+
+ if (std::isnan(ExpectedResult) || std::isnan(Result))
+ return false;
+
+ const T Tolerance =
+ AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
+ return std::abs(Result - ExpectedResult) < Tolerance;
+ };
+
+ const auto l0 = [](T, unsigned) { return T(1); };
+ const auto l1 = [](T x, unsigned m) { return -x + T(m + 1); };
+ const auto l2 = [](T x, unsigned m) {
+ return x * x / T(2) - T(m + 2) * x + T(m + 1) * T(m + 2) / T(2);
+ };
+ const auto l3 = [](T x, unsigned m) {
+ return -x * x * x / T(6) + T(m + 3) * x * x / T(2) -
+ T(m + 2) * T(m + 3) * x / T(2) +
+ T(m + 1) * T(m + 2) * T(m + 3) / T(6);
+ };
+
+ for (unsigned m = 0; m < 128; ++m) {
+ assert(compareFloatingPoint(std::experimental::assoc_laguerre(0, m, x),
+ l0(x, m)));
+ assert(compareFloatingPoint(std::experimental::assoc_laguerre(1, m, x),
+ l1(x, m)));
+ assert(compareFloatingPoint(std::experimental::assoc_laguerre(2, m, x),
+ l2(x, m)));
+ assert(compareFloatingPoint(std::experimental::assoc_laguerre(3, m, x),
+ l3(x, m)));
+ }
+}
+
+template <class T>
+void testAssocLaguerre(const T AbsTolerance, const T RelTolerance) {
+ testAssocLaguerreNaNPropagation<T>();
+ testAssocLaguerreThrows<T>(T(-5));
+
+ const T Samples[] = {T(0.0), T(0.1), T(0.5), T(1.0), T(10.0)};
+
+ for (T x : Samples) {
+ testAssocLaguerreNotNaN(x);
+ testAssocLaguerreAnalytic(x, AbsTolerance, RelTolerance);
+ testAssocLaguerreVsLaguerre(x, AbsTolerance, RelTolerance);
+ }
+}
+
+#endif
+
+int main(int, char **) {
+#if _LIBCPP_STD_VER > 14
+ testAssocLaguerre<float>(1e-5f, 1e-5f);
+ testAssocLaguerre<double>(1e-9, 1e-9);
+ testAssocLaguerre<long double>(1e-12, 1e-12);
+#endif
+ return 0;
+}
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp b/libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp
new file mode 100644
index 0000000000000..029f8cbf3d852
--- /dev/null
+++ b/libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp
@@ -0,0 +1,203 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/cmath>
+
+#include <cassert>
+#include <experimental/cmath>
+#include <limits>
+
+#if _LIBCPP_STD_VER > 14
+
+template <class T> void testAssocLegendreNaNPropagation() {
+ const unsigned MaxN = 127;
+ const T x = std::numeric_limits<T>::quiet_NaN();
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ assert(std::isnan(std::experimental::assoc_legendre(n, m, x)));
+ }
+ }
+}
+
+template <class T> void testAssocLegendreNotNaN(const T x) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ assert(!std::isnan(std::experimental::assoc_legendre(n, m, x)));
+ }
+ }
+}
+
+template <class T> void testAssocLegendreThrows(const T x) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ bool Throws = false;
+ try {
+ std::experimental::assoc_legendre(n, m, x);
+ } catch (const std::domain_error &) {
+ Throws = true;
+ }
+ assert(Throws);
+ }
+ }
+#endif // _LIBCPP_NO_EXCEPTIONS
+}
+
+template <class T>
+void testAssocLegendreVsLegendre(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = 0; m <= MaxN; ++m) {
+ const T Result = std::experimental::assoc_legendre(n, 0, x);
+ const T ExpectedResult = std::experimental::legendre(n, x);
+ const T Tolerance =
+ AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
+ const T Difference = std::abs(Result - ExpectedResult);
+ assert(Difference <= Tolerance);
+ }
+ }
+}
+
+template <class T>
+void testAssocLegendreAnalytic(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const auto compareFloatingPoint =
+ [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
+ if (std::isinf(ExpectedResult) && std::isinf(Result))
+ return true;
+
+ if (std::isnan(ExpectedResult) || std::isnan(Result))
+ return false;
+
+ const T Tolerance =
+ AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
+ return std::abs(Result - ExpectedResult) < Tolerance;
+ };
+
+ const auto l00 = [](T) { return T(1); };
+
+ const auto l10 = [](T x) { return x; };
+ const auto l11 = [](T x) { return std::sqrt((T(1) - x) * (T(1) + x)); };
+
+ const auto l20 = [](T x) { return (T(3) * x * x - T(1)) / T(2); };
+ const auto l21 = [](T x) {
+ return T(3) * x * std::sqrt((T(1) - x) * (T(1) + x));
+ };
+ const auto l22 = [](T x) { return T(3) * (T(1) - x) * (T(1) + x); };
+
+ const auto l30 = [](T x) { return (T(5) * x * x - T(3)) * x / T(2); };
+ const auto l31 = [](T x) {
+ return T(3) / T(2) * (T(5) * x * x - T(1)) *
+ std::sqrt((T(1) - x) * (T(1) + x));
+ };
+ const auto l32 = [](T x) { return T(15) * x * (T(1) - x) * (T(1) + x); };
+ const auto l33 = [](T x) {
+ const T temp = (T(1) - x) * (T(1) + x);
+ return T(15) * temp * std::sqrt(temp);
+ };
+
+ const auto l40 = [](T x) {
+ return (T(35) * x * x * x * x - T(30) * x * x + T(3)) / T(8);
+ };
+ const auto l41 = [](T x) {
+ return T(5) / T(2) * x * (T(7) * x * x - T(3)) *
+ std::sqrt((T(1) - x) * (T(1) + x));
+ };
+ const auto l42 = [](T x) {
+ return T(15) / T(2) * (T(7) * x * x - 1) * (T(1) - x) * (T(1) + x);
+ };
+ const auto l43 = [](T x) {
+ const T temp = (T(1) - x) * (T(1) + x);
+ return T(105) * x * temp * std::sqrt(temp);
+ };
+ const auto l44 = [](T x) {
+ const T temp = (T(1) - x) * (T(1) + x);
+ return T(105) * temp * temp;
+ };
+
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(0, 0, x), l00(x)));
+
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(1, 0, x), l10(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(1, 1, x), l11(x)));
+
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(2, 0, x), l20(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(2, 1, x), l21(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(2, 2, x), l22(x)));
+
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(3, 0, x), l30(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(3, 1, x), l31(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(3, 2, x), l32(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(3, 3, x), l33(x)));
+
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(4, 0, x), l40(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(4, 1, x), l41(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(4, 2, x), l42(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(4, 3, x), l43(x)));
+ assert(
+ compareFloatingPoint(std::experimental::assoc_legendre(4, 4, x), l44(x)));
+
+ try {
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned m = n + 1; m <= MaxN; ++m) {
+ assert(std::experimental::assoc_legendre(n, m, x) <= AbsTolerance);
+ }
+ }
+ } catch (const std::domain_error &) {
+ // Should not throw! The expression given in
+ // ISO/IEC JTC 1/SC 22/WG 21 N3060 is actually well-defined for m > n!
+ assert(false);
+ }
+}
+
+template <class T>
+void testAssocLegendre(const T AbsTolerance, const T RelTolerance) {
+ testAssocLegendreNaNPropagation<T>();
+ testAssocLegendreThrows<T>(T(-5));
+ testAssocLegendreThrows<T>(T(5));
+
+ const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
+ T(0.1), T(0.5), T(1.0)};
+
+ for (T x : Samples) {
+ testAssocLegendreNotNaN(x);
+ testAssocLegendreVsLegendre(x, AbsTolerance, RelTolerance);
+ testAssocLegendreAnalytic(x, AbsTolerance, RelTolerance);
+ }
+}
+
+#endif
+
+int main(int, char **) {
+#if _LIBCPP_STD_VER > 14
+ testAssocLegendre<float>(1e-6f, 1e-6f);
+ testAssocLegendre<double>(1e-9, 1e-9);
+ testAssocLegendre<long double>(1e-12, 1e-12);
+#endif
+ return 0;
+}
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp b/libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp
new file mode 100644
index 0000000000000..38cddf6025f61
--- /dev/null
+++ b/libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp
@@ -0,0 +1,290 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/cmath>
+
+#include <cassert>
+#include <experimental/cmath>
+#include <iostream>
+#include <limits>
+#include <vector>
+
+#if _LIBCPP_STD_VER > 14
+
+template <class T> void testHermiteNaNPropagation() {
+ const unsigned MaxN = 127;
+ const T x = std::numeric_limits<T>::quiet_NaN();
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ assert(std::isnan(std::experimental::hermite(n, x)));
+ }
+}
+
+template <class T> void testHermiteNotNaN(const T x) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ assert(!std::isnan(std::experimental::hermite(n, x)));
+ }
+}
+
+template <class T>
+void testHermiteAnalytic(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const auto compareFloatingPoint =
+ [AbsTolerance, RelTolerance](const T Result, const T Expected) {
+ if (std::isinf(Expected) && std::isinf(Result))
+ return true;
+
+ if (std::isnan(Expected) || std::isnan(Result))
+ return false;
+
+ const T Tolerance = AbsTolerance + std::abs(Expected) * RelTolerance;
+ return std::abs(Result - Expected) < Tolerance;
+ };
+
+ const auto h0 = [](T) { return T(1); };
+ const auto h1 = [](T x) { return T(2) * x; };
+ const auto h2 = [](T x) { return T(4) * x * x - T(2); };
+ const auto h3 = [](T x) { return x * (T(8) * x * x - T(12)); };
+ const auto h4 = [](T x) {
+ return (T(16) * x * x * x * x - T(48) * x * x + T(12));
+ };
+ const auto h5 = [](T x) {
+ return x * (T(32) * x * x * x * x - T(160) * x * x + T(120));
+ };
+
+ assert(compareFloatingPoint(std::experimental::hermite(0, x), h0(x)));
+ assert(compareFloatingPoint(std::experimental::hermite(1, x), h1(x)));
+ assert(compareFloatingPoint(std::experimental::hermite(2, x), h2(x)));
+ assert(compareFloatingPoint(std::experimental::hermite(3, x), h3(x)));
+ assert(compareFloatingPoint(std::experimental::hermite(4, x), h4(x)));
+ assert(compareFloatingPoint(std::experimental::hermite(5, x), h5(x)));
+}
+
+/// \details This method checks if the following recurrence relation holds:
+/// \f[
+/// H_{n+1}(x) = 2x H_{n}(x) - 2n H_{n-1}(x)
+/// \f]
+template <class T>
+void testRecurrenceRelation(T x, T RelTolerance, T AbsTolerance) {
+ const unsigned MaxN = 127;
+ for (unsigned n = 1; n < MaxN; ++n) {
+ const T HermiteNext = std::experimental::hermite(n + 1, x);
+ const T HermiteNextRecurrence =
+ T(2) * x * std::experimental::hermite(n, x) -
+ T(2) * T(n) * std::experimental::hermite(n - 1, x);
+ const T Tolerance = AbsTolerance + std::abs(HermiteNext) * RelTolerance;
+ const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
+
+ if (std::isinf(HermiteNext))
+ break;
+ assert(Error < Tolerance);
+ }
+}
+
+template <class T> void testRecurrenceRelation(T RelTolerance, T AbsTolerance) {
+ const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
+ T(0.1), T(0.5), T(1.0)};
+ for (T x : Samples)
+ testRecurrenceRelation(x, RelTolerance, AbsTolerance);
+}
+
+/// \note Roots are taken from
+/// Salzer, Herbert E., Ruth Zucker, and Ruth Capuano.
+/// Table of the zeros and weight factors of the first twenty Hermite
+/// polynomials. US Government Printing Office, 1952.
+template <class T> std::vector<T> getHermiteRoots(unsigned n) {
+ if (n == 0u)
+ return {};
+ if (n == 1u)
+ return {T(0)};
+ if (n == 2u)
+ return {T(0.707106781186548)};
+ if (n == 3u)
+ return {T(0),
+ T(1.224744871391589)};
+ if (n == 4u)
+ return {T(0.524647623275290),
+ T(1.650680123885785)};
+ if (n == 5u)
+ return {T(0), T(0.958572464613819),
+ T(2.020182870456086)};
+ if (n == 6u)
+ return {T(0.436077411927617),
+ T(1.335849074013697),
+ T(2.350604973674492)};
+ if (n == 7u)
+ return {T(0),
+ T(0.816287882858965),
+ T(1.673551628767471),
+ T(2.651961356835233)};
+ if (n == 8u)
+ return {T(0.381186990207322),
+ T(1.157193712446780),
+ T(1.981656756695843),
+ T(2.930637420257244)};
+ if (n == 9u)
+ return {T(0),
+ T(0.723551018752838),
+ T(1.468553289216668),
+ T(2.266580584531843),
+ T(3.190993201781528)};
+ if (n == 10u)
+ return {T(0.342901327223705),
+ T(1.036610829789514),
+ T(1.756683649299882),
+ T(2.532731674232790),
+ T(3.436159118837738)};
+ if (n == 11u)
+ return {T(0),
+ T(0.65680956682100),
+ T(1.326557084494933),
+ T(2.025948015825755),
+ T(2.783290099781652),
+ T(3.668470846559583)};
+
+ if (n == 12u)
+ return {T(0.314240376254359),
+ T(0.947788391240164),
+ T(1.597682635152605),
+ T(2.279507080501060),
+ T(3.020637025120890),
+ T(3.889724897869782)};
+
+ if (n == 13u)
+ return {T(0),
+ T(0.605763879171060),
+ T(1.220055036590748),
+ T(1.853107651601512),
+ T(2.519735685678238),
+ T(3.246608978372410),
+ T(4.101337596178640)};
+
+ if (n == 14u)
+ return {T(0.29174551067256),
+ T(0.87871378732940),
+ T(1.47668273114114),
+ T(2.09518325850772),
+ T(2.74847072498540),
+ T(3.46265693360227),
+ T(4.30444857047363)};
+
+ if (n == 15u)
+ return {T(0.00000000000000),
+ T(0.56506958325558),
+ T(1.13611558521092),
+ T(1.71999257518649),
+ T(2.32573248617386),
+ T(2.96716692790560),
+ T(3.66995037340445),
+ T(4.49999070730939)};
+
+ if (n == 16u)
+ return {T(0.27348104613815),
+ T(0.82295144914466),
+ T(1.38025853919888),
+ T(1.95178799091625),
+ T(2.54620215784748),
+ T(3.17699916197996),
+ T(3.86944790486012),
+ T(4.68873893930582)};
+
+ if (n == 17u)
+ return {T(0),
+ T(0.5316330013427),
+ T(1.0676487257435),
+ T(1.6129243142212),
+ T(2.1735028266666),
+ T(2.7577629157039),
+ T(3.3789320911415),
+ T(4.0619466758755),
+ T(4.8713451936744)};
+ if (n == 18u)
+ return {T(0.2582677505191),
+ T(0.7766829192674),
+ T(1.3009208583896),
+ T(1.8355316042616),
+ T(2.3862990891667),
+ T(2.9613775055316),
+ T(3.5737690684863),
+ T(4.2481178735681),
+ T(5.0483640088745)};
+ if (n == 19u)
+ return {T(0),
+ T(0.5035201634239),
+ T(1.0103683871343),
+ T(1.5241706193935),
+ T(2.0492317098506),
+ T(2.5911337897945),
+ T(3.1578488183476),
+ T(3.7621873519640),
+ T(4.4285328066038),
+ T(5.2202716905375)};
+ if (n == 20u)
+ return {T(0.2453407083009),
+ T(0.7374737285454),
+ T(1.2340762153953),
+ T(1.7385377121166),
+ T(2.2549740020893),
+ T(2.7888060584281),
+ T(3.347854567332),
+ T(3.9447640401156),
+ T(4.6036824495507),
+ T(5.3874808900112)};
+
+ return {};
+}
+
+/// \param [in] Tolerance of the root. This value must be smaller than
+/// the smallest difference between adjacent roots in the given range
+/// with n <= 20.
+template <class T> void testHermiteRoots(T Tolerance) {
+ for (unsigned n = 0; n <= 20u; ++n) {
+ const auto Roots = getHermiteRoots<T>(n);
+ for (T x : Roots) {
+ // the roots are symmetric: if x is a root, so is -x
+ if (x > T(0))
+ assert(std::signbit(std::experimental::hermite(n, -x + Tolerance)) !=
+ std::signbit(std::experimental::hermite(n, -x - Tolerance)));
+ assert(std::signbit(std::experimental::hermite(n, x + Tolerance)) !=
+ std::signbit(std::experimental::hermite(n, x - Tolerance)));
+ }
+ }
+}
+
+template <class T>
+void testHermite(const T AbsTolerance, const T RelTolerance) {
+ testHermiteNaNPropagation<T>();
+ const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
+ T(0.1), T(0.5), T(1.0)};
+
+ for (T x : Samples) {
+ testHermiteNotNaN(x);
+ testHermiteAnalytic(x, AbsTolerance, RelTolerance);
+ }
+}
+
+#endif
+
+int main(int, char **) {
+#if _LIBCPP_STD_VER > 14
+ testHermite<float>(1e-6f, 1e-6f);
+ testHermite<double>(1e-9, 1e-9);
+ testHermite<long double>(1e-12l, 1e-12l);
+
+ testRecurrenceRelation<float>(1e-6f, 1e-6f);
+ testRecurrenceRelation<double>(1e-9, 1e-9);
+ testRecurrenceRelation<long double>(1e-12l, 1e-12l);
+
+ testHermiteRoots<float>(1e-6f);
+ testHermiteRoots<double>(1e-9);
+ testHermiteRoots<long double>(1e-10l);
+#endif
+ return 0;
+}
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp b/libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp
new file mode 100644
index 0000000000000..9856ca4838160
--- /dev/null
+++ b/libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/cmath>
+
+#include <cassert>
+#include <experimental/cmath>
+#include <limits>
+
+#if _LIBCPP_STD_VER > 14
+
+template <class T> void testLaguerreNaNPropagation() {
+ const unsigned MaxN = 127;
+ const T x = std::numeric_limits<T>::quiet_NaN();
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ assert(std::isnan(std::experimental::laguerre(n, x)));
+ }
+}
+
+template <class T> void testLaguerreNotNaN(const T x) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ assert(!std::isnan(std::experimental::laguerre(n, x)));
+ }
+}
+
+template <class T> void testLaguerreThrows(const T x) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ bool Throws = false;
+ try {
+ std::experimental::laguerre(n, x);
+ } catch (const std::domain_error &) {
+ Throws = true;
+ }
+ assert(Throws);
+ }
+#endif // _LIBCPP_NO_EXCEPTIONS
+}
+
+template <class T>
+void testLaguerreAnalytic(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const auto compareFloatingPoint =
+ [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
+ if (std::isinf(ExpectedResult) && std::isinf(Result))
+ return true;
+
+ if (std::isnan(ExpectedResult) || std::isnan(Result))
+ return false;
+
+ const T Tolerance =
+ AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
+ return std::abs(Result - ExpectedResult) < Tolerance;
+ };
+
+ const auto l0 = [](T) { return T(1); };
+ const auto l1 = [](T x) { return -x + 1; };
+ const auto l2 = [](T x) { return (x * x - T(4) * x + T(2)) / T(2); };
+ const auto l3 = [](T x) {
+ return (-x * x * x + T(9) * x * x - T(18) * x + T(6)) / T(6);
+ };
+ const auto l4 = [](T x) {
+ return (x * x * x * x - T(16) * x * x * x + T(72) * x * x - T(96) * x +
+ T(24)) /
+ T(24);
+ };
+ const auto l5 = [](T x) {
+ return (-x * x * x * x * x + T(25) * x * x * x * x - T(200) * x * x * x +
+ T(600) * x * x - T(600) * x + T(120)) /
+ T(120);
+ };
+ const auto l6 = [](T x) {
+ return (x * x * x * x * x * x - T(36) * x * x * x * x * x +
+ T(450) * x * x * x * x - T(2400) * x * x * x + T(5400) * x * x -
+ T(4320) * x + T(720)) /
+ T(720);
+ };
+
+ assert(compareFloatingPoint(std::experimental::laguerre(0, x), l0(x)));
+ assert(compareFloatingPoint(std::experimental::laguerre(1, x), l1(x)));
+ assert(compareFloatingPoint(std::experimental::laguerre(2, x), l2(x)));
+ assert(compareFloatingPoint(std::experimental::laguerre(3, x), l3(x)));
+ assert(compareFloatingPoint(std::experimental::laguerre(4, x), l4(x)));
+ assert(compareFloatingPoint(std::experimental::laguerre(5, x), l5(x)));
+ assert(compareFloatingPoint(std::experimental::laguerre(6, x), l6(x)));
+}
+
+template <class T>
+void testLaguerre(const T AbsTolerance, const T RelTolerance) {
+ testLaguerreNaNPropagation<T>();
+ testLaguerreThrows<T>(T(-5));
+
+ const T Samples[] = {T(0.0), T(0.1), T(0.5), T(1.0), T(10.0)};
+
+ for (T x : Samples) {
+ testLaguerreNotNaN(x);
+ testLaguerreAnalytic(x, AbsTolerance, RelTolerance);
+ }
+}
+
+#endif
+
+int main(int, char **) {
+#if _LIBCPP_STD_VER > 14
+ testLaguerre<float>(1e-6f, 1e-6f);
+ testLaguerre<double>(1e-9, 1e-9);
+ testLaguerre<long double>(1e-12, 1e-12);
+#endif
+ return 0;
+}
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp b/libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp
new file mode 100644
index 0000000000000..79a555c5bb78e
--- /dev/null
+++ b/libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp
@@ -0,0 +1,114 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <experimental/cmath>
+
+#include <cassert>
+#include <experimental/cmath>
+#include <limits>
+
+#if _LIBCPP_STD_VER > 14
+
+template <class T> void testLegendreNaNPropagation() {
+ const unsigned MaxN = 127;
+ const T x = std::numeric_limits<T>::quiet_NaN();
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ assert(std::isnan(std::experimental::legendre(n, x)));
+ }
+}
+
+template <class T> void testLegendreNotNaN(const T x) {
+ assert(!std::isnan(x));
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ assert(!std::isnan(std::experimental::legendre(n, x)));
+ }
+}
+
+template <class T> void testLegendreThrows(const T x) {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ const unsigned MaxN = 127;
+ for (unsigned n = 0; n <= MaxN; ++n) {
+ bool Throws = false;
+ try {
+ std::experimental::legendre(n, x);
+ } catch (const std::domain_error &) {
+ Throws = true;
+ }
+ assert(Throws);
+ }
+#endif // _LIBCPP_NO_EXCEPTIONS
+}
+
+template <class T>
+void testLegendreAnalytic(const T x, const T AbsTolerance,
+ const T RelTolerance) {
+ assert(!std::isnan(x));
+ const auto compareFloatingPoint =
+ [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
+ if (std::isinf(ExpectedResult) && std::isinf(Result))
+ return true;
+
+ if (std::isnan(ExpectedResult) || std::isnan(Result))
+ return false;
+
+ const T Tolerance =
+ AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
+ return std::abs(Result - ExpectedResult) < Tolerance;
+ };
+
+ const auto l0 = [](T) { return T(1); };
+ const auto l1 = [](T x) { return x; };
+ const auto l2 = [](T x) { return (T(3) * x * x - T(1)) / T(2); };
+ const auto l3 = [](T x) { return (T(5) * x * x - T(3)) * x / T(2); };
+ const auto l4 = [](T x) {
+ return (T(35) * x * x * x * x - T(30) * x * x + T(3)) / T(8);
+ };
+ const auto l5 = [](T x) {
+ return (T(63) * x * x * x * x - T(70) * x * x + T(15)) * x / T(8);
+ };
+ const auto l6 = [](T x) {
+ const T x2 = x * x;
+ return (T(231) * x2 * x2 * x2 - T(315) * x2 * x2 + T(105) * x2 - T(5)) /
+ T(16);
+ };
+
+ assert(compareFloatingPoint(std::experimental::legendre(0, x), l0(x)));
+ assert(compareFloatingPoint(std::experimental::legendre(1, x), l1(x)));
+ assert(compareFloatingPoint(std::experimental::legendre(2, x), l2(x)));
+ assert(compareFloatingPoint(std::experimental::legendre(3, x), l3(x)));
+ assert(compareFloatingPoint(std::experimental::legendre(4, x), l4(x)));
+ assert(compareFloatingPoint(std::experimental::legendre(5, x), l5(x)));
+ assert(compareFloatingPoint(std::experimental::legendre(6, x), l6(x)));
+}
+
+template <class T>
+void testLegendre(const T AbsTolerance, const T RelTolerance) {
+ testLegendreNaNPropagation<T>();
+ testLegendreThrows<T>(T(-5));
+ testLegendreThrows<T>(T(5));
+
+ const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
+ T(0.1), T(0.5), T(1.0)};
+
+ for (T x : Samples) {
+ testLegendreNotNaN(x);
+ testLegendreAnalytic(x, AbsTolerance, RelTolerance);
+ }
+}
+
+#endif
+
+int main(int, char **) {
+#if _LIBCPP_STD_VER > 14
+ testLegendre<float>(1e-6f, 1e-6f);
+ testLegendre<double>(1e-9, 1e-9);
+ testLegendre<long double>(1e-12, 1e-12);
+#endif
+ return 0;
+}
>From 8c40b62faabcdc9f5a0473f439d178d61a4d344c Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 20 Apr 2024 23:08:49 +0200
Subject: [PATCH 02/76] moved new files into math/
---
.../experimental/{__hermite => __math/hermite.h} | 9 +++++----
.../experimental/{__laguerre => __math/laguerre.h} | 9 +++++----
.../experimental/{__legendre => __math/legendre.h} | 9 +++++----
libcxx/include/experimental/{cmath => math} | 14 +++++++-------
.../c.math => math}/assoc_laguerre.pass.cpp | 2 +-
.../c.math => math}/assoc_legendre.pass.cpp | 2 +-
.../{numerics/c.math => math}/hermite.pass.cpp | 2 +-
.../{numerics/c.math => math}/laguerre.pass.cpp | 2 +-
.../{numerics/c.math => math}/legendre.pass.cpp | 2 +-
9 files changed, 27 insertions(+), 24 deletions(-)
rename libcxx/include/experimental/{__hermite => __math/hermite.h} (85%)
rename libcxx/include/experimental/{__laguerre => __math/laguerre.h} (90%)
rename libcxx/include/experimental/{__legendre => __math/legendre.h} (94%)
rename libcxx/include/experimental/{cmath => math} (92%)
rename libcxx/test/libcxx/experimental/{numerics/c.math => math}/assoc_laguerre.pass.cpp (99%)
rename libcxx/test/libcxx/experimental/{numerics/c.math => math}/assoc_legendre.pass.cpp (99%)
rename libcxx/test/libcxx/experimental/{numerics/c.math => math}/hermite.pass.cpp (99%)
rename libcxx/test/libcxx/experimental/{numerics/c.math => math}/laguerre.pass.cpp (99%)
rename libcxx/test/libcxx/experimental/{numerics/c.math => math}/legendre.pass.cpp (99%)
diff --git a/libcxx/include/experimental/__hermite b/libcxx/include/experimental/__math/hermite.h
similarity index 85%
rename from libcxx/include/experimental/__hermite
rename to libcxx/include/experimental/__math/hermite.h
index daa89129fc8de..c93e05ae11303 100644
--- a/libcxx/include/experimental/__hermite
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -1,4 +1,5 @@
-//===------------------------ __hermite -------------------------*- C++ -*-===//
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -11,8 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef _LIBCPP_EXPERIMENTAL___HERMITE
-#define _LIBCPP_EXPERIMENTAL___HERMITE
+#ifndef _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
+#define _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
#include <experimental/__config>
#include <cmath>
@@ -47,4 +48,4 @@ template <class _Real> _Real __libcpp_hermite(unsigned __n, _Real __x) {
return __libcpp_hermite_recurrence(__n, __x);
}
-#endif // _LIBCPP_EXPERIMENTAL___HERMITE
+#endif // _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
diff --git a/libcxx/include/experimental/__laguerre b/libcxx/include/experimental/__math/laguerre.h
similarity index 90%
rename from libcxx/include/experimental/__laguerre
rename to libcxx/include/experimental/__math/laguerre.h
index a7fc6cfbde20e..bf1140eb75aa0 100644
--- a/libcxx/include/experimental/__laguerre
+++ b/libcxx/include/experimental/__math/laguerre.h
@@ -1,4 +1,5 @@
-//===------------------------ __laguerre ------------------------*- C++ -*-===//
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -13,8 +14,8 @@
//===----------------------------------------------------------------------===//
-#ifndef _LIBCPP_EXPERIMENTAL___LAGUERRE
-#define _LIBCPP_EXPERIMENTAL___LAGUERRE
+#ifndef _LIBCPP_EXPERIMENTAL___MATH_LAGUERRE_H
+#define _LIBCPP_EXPERIMENTAL___MATH_LAGUERRE_H
#include <experimental/__config>
#include <cmath>
@@ -68,4 +69,4 @@ template <class _Real> _Real __libcpp_laguerre(unsigned __n, _Real __x) {
return __libcpp_generalized_laguerre_recurrence(__n, _Real(0), __x);
}
-#endif // _LIBCPP_EXPERIMENTAL___LAGUERRE
+#endif // _LIBCPP_EXPERIMENTAL___MATH_LAGUERRE_H
diff --git a/libcxx/include/experimental/__legendre b/libcxx/include/experimental/__math/legendre.h
similarity index 94%
rename from libcxx/include/experimental/__legendre
rename to libcxx/include/experimental/__math/legendre.h
index d2be9b4842226..aa4e168853179 100644
--- a/libcxx/include/experimental/__legendre
+++ b/libcxx/include/experimental/__math/legendre.h
@@ -1,4 +1,5 @@
-//===------------------------ __legendre ------------------------*- C++ -*-===//
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -13,8 +14,8 @@
//===----------------------------------------------------------------------===//
-#ifndef _LIBCPP_EXPERIMENTAL___LEGENDRE
-#define _LIBCPP_EXPERIMENTAL___LEGENDRE
+#ifndef _LIBCPP_EXPERIMENTAL___MATH_LEGENDRE_H
+#define _LIBCPP_EXPERIMENTAL___MATH_LEGENDRE_H
#include <experimental/__config>
#include <cmath>
@@ -120,4 +121,4 @@ _Real __libcpp_assoc_legendre(unsigned __n, unsigned __m, _Real __x) {
return __libcpp_assoc_legendre_recurrence(__n, __m, __x);
}
-#endif // _LIBCPP_EXPERIMENTAL___LEGENDRE
+#endif // _LIBCPP_EXPERIMENTAL___MATH_LEGENDRE_H
diff --git a/libcxx/include/experimental/cmath b/libcxx/include/experimental/math
similarity index 92%
rename from libcxx/include/experimental/cmath
rename to libcxx/include/experimental/math
index 9fd5d4fcbe190..18289a97ae5a3 100644
--- a/libcxx/include/experimental/cmath
+++ b/libcxx/include/experimental/math
@@ -1,5 +1,5 @@
// -*- C++ -*-
-//===---------------------------- cmath ----------------------------------===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef _LIBCPP_EXPERIMENTAL_CMATH
-#define _LIBCPP_EXPERIMENTAL_CMATH
+#ifndef _LIBCPP_EXPERIMENTAL_MATH
+#define _LIBCPP_EXPERIMENTAL_MATH
// The following macro name shall be conditionally defined by the implementation
// to indicate conformance to the International Standard ISO/IEC JTC 1/SC 22/WG 21 N3060
@@ -19,9 +19,9 @@
#if _LIBCPP_STD_VER > 14
-#include <experimental/__hermite>
-#include <experimental/__laguerre>
-#include <experimental/__legendre>
+#include <experimental/__math/hermite.h>
+#include <experimental/__math/laguerre.h>
+#include <experimental/__math/legendre.h>
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
@@ -100,4 +100,4 @@ _LIBCPP_END_NAMESPACE_EXPERIMENTAL
#endif // _LIBCPP_STD_VER > 14
-#endif // _LIBCPP_EXPERIMENTAL_CMATH
+#endif // _LIBCPP_EXPERIMENTAL_MATH
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp b/libcxx/test/libcxx/experimental/math/assoc_laguerre.pass.cpp
similarity index 99%
rename from libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp
rename to libcxx/test/libcxx/experimental/math/assoc_laguerre.pass.cpp
index 10261f017ad70..945b4d531c924 100644
--- a/libcxx/test/libcxx/experimental/numerics/c.math/assoc_laguerre.pass.cpp
+++ b/libcxx/test/libcxx/experimental/math/assoc_laguerre.pass.cpp
@@ -9,7 +9,7 @@
// <experimental/cmath>
#include <cassert>
-#include <experimental/cmath>
+#include <experimental/math>
#include <limits>
#if _LIBCPP_STD_VER > 14
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp b/libcxx/test/libcxx/experimental/math/assoc_legendre.pass.cpp
similarity index 99%
rename from libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp
rename to libcxx/test/libcxx/experimental/math/assoc_legendre.pass.cpp
index 029f8cbf3d852..3de555cac6f36 100644
--- a/libcxx/test/libcxx/experimental/numerics/c.math/assoc_legendre.pass.cpp
+++ b/libcxx/test/libcxx/experimental/math/assoc_legendre.pass.cpp
@@ -9,7 +9,7 @@
// <experimental/cmath>
#include <cassert>
-#include <experimental/cmath>
+#include <experimental/math>
#include <limits>
#if _LIBCPP_STD_VER > 14
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp b/libcxx/test/libcxx/experimental/math/hermite.pass.cpp
similarity index 99%
rename from libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp
rename to libcxx/test/libcxx/experimental/math/hermite.pass.cpp
index 38cddf6025f61..e8b89b5e746e0 100644
--- a/libcxx/test/libcxx/experimental/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/libcxx/experimental/math/hermite.pass.cpp
@@ -9,7 +9,7 @@
// <experimental/cmath>
#include <cassert>
-#include <experimental/cmath>
+#include <experimental/math>
#include <iostream>
#include <limits>
#include <vector>
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp b/libcxx/test/libcxx/experimental/math/laguerre.pass.cpp
similarity index 99%
rename from libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp
rename to libcxx/test/libcxx/experimental/math/laguerre.pass.cpp
index 9856ca4838160..6c25cb83788fc 100644
--- a/libcxx/test/libcxx/experimental/numerics/c.math/laguerre.pass.cpp
+++ b/libcxx/test/libcxx/experimental/math/laguerre.pass.cpp
@@ -9,7 +9,7 @@
// <experimental/cmath>
#include <cassert>
-#include <experimental/cmath>
+#include <experimental/math>
#include <limits>
#if _LIBCPP_STD_VER > 14
diff --git a/libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp b/libcxx/test/libcxx/experimental/math/legendre.pass.cpp
similarity index 99%
rename from libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp
rename to libcxx/test/libcxx/experimental/math/legendre.pass.cpp
index 79a555c5bb78e..35cad4bff9561 100644
--- a/libcxx/test/libcxx/experimental/numerics/c.math/legendre.pass.cpp
+++ b/libcxx/test/libcxx/experimental/math/legendre.pass.cpp
@@ -9,7 +9,7 @@
// <experimental/cmath>
#include <cassert>
-#include <experimental/cmath>
+#include <experimental/math>
#include <limits>
#if _LIBCPP_STD_VER > 14
>From 34fb10a9951a64f3448831a9884b1c5f2a01205e Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 20 Apr 2024 23:36:26 +0200
Subject: [PATCH 03/76] cmake: fix include by adding new files to file listing
---
libcxx/include/CMakeLists.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 4ecd834c5382a..15e7e892f81a0 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -922,6 +922,9 @@ set(files
execution
expected
experimental/__config
+ experimental/__math/hermite.h
+ experimental/__math/laguerre.h
+ experimental/__math/legendre.h
experimental/__simd/aligned_tag.h
experimental/__simd/declaration.h
experimental/__simd/reference.h
@@ -932,6 +935,7 @@ set(files
experimental/__simd/utility.h
experimental/__simd/vec_ext.h
experimental/iterator
+ experimental/math
experimental/memory
experimental/propagate_const
experimental/simd
>From 4572f3ab675aff7a0d8abc2fcf1dc2ebdbd36c2e Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 14:53:49 +0200
Subject: [PATCH 04/76] move test files from internal libcxx/ into std/
---
.../{libcxx => std}/experimental/math/assoc_laguerre.pass.cpp | 0
.../{libcxx => std}/experimental/math/assoc_legendre.pass.cpp | 0
libcxx/test/{libcxx => std}/experimental/math/hermite.pass.cpp | 0
libcxx/test/{libcxx => std}/experimental/math/laguerre.pass.cpp | 0
libcxx/test/{libcxx => std}/experimental/math/legendre.pass.cpp | 0
5 files changed, 0 insertions(+), 0 deletions(-)
rename libcxx/test/{libcxx => std}/experimental/math/assoc_laguerre.pass.cpp (100%)
rename libcxx/test/{libcxx => std}/experimental/math/assoc_legendre.pass.cpp (100%)
rename libcxx/test/{libcxx => std}/experimental/math/hermite.pass.cpp (100%)
rename libcxx/test/{libcxx => std}/experimental/math/laguerre.pass.cpp (100%)
rename libcxx/test/{libcxx => std}/experimental/math/legendre.pass.cpp (100%)
diff --git a/libcxx/test/libcxx/experimental/math/assoc_laguerre.pass.cpp b/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/experimental/math/assoc_laguerre.pass.cpp
rename to libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
diff --git a/libcxx/test/libcxx/experimental/math/assoc_legendre.pass.cpp b/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/experimental/math/assoc_legendre.pass.cpp
rename to libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
diff --git a/libcxx/test/libcxx/experimental/math/hermite.pass.cpp b/libcxx/test/std/experimental/math/hermite.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/experimental/math/hermite.pass.cpp
rename to libcxx/test/std/experimental/math/hermite.pass.cpp
diff --git a/libcxx/test/libcxx/experimental/math/laguerre.pass.cpp b/libcxx/test/std/experimental/math/laguerre.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/experimental/math/laguerre.pass.cpp
rename to libcxx/test/std/experimental/math/laguerre.pass.cpp
diff --git a/libcxx/test/libcxx/experimental/math/legendre.pass.cpp b/libcxx/test/std/experimental/math/legendre.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/experimental/math/legendre.pass.cpp
rename to libcxx/test/std/experimental/math/legendre.pass.cpp
>From 9debdf0a97db69e3e93cd07b51630310bca5c6de Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 21:54:11 +0200
Subject: [PATCH 05/76] replace "_VSTD" by "std". similar to D117811
see https://reviews.llvm.org/D117811
---
libcxx/include/experimental/__math/laguerre.h | 4 ++--
libcxx/include/experimental/__math/legendre.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/experimental/__math/laguerre.h b/libcxx/include/experimental/__math/laguerre.h
index bf1140eb75aa0..58b92345beb81 100644
--- a/libcxx/include/experimental/__math/laguerre.h
+++ b/libcxx/include/experimental/__math/laguerre.h
@@ -52,7 +52,7 @@ _Real __libcpp_assoc_laguerre(unsigned __n, unsigned __m, _Real __x) {
return std::numeric_limits<_Real>::quiet_NaN();
if (__x < _Real(0))
- _VSTD::__throw_domain_error(
+ std::__throw_domain_error(
"Argument of assoc_laguerre function is out of range");
return __libcpp_generalized_laguerre_recurrence(__n, _Real(__m), __x);
@@ -63,7 +63,7 @@ template <class _Real> _Real __libcpp_laguerre(unsigned __n, _Real __x) {
return std::numeric_limits<_Real>::quiet_NaN();
if (__x < _Real(0))
- _VSTD::__throw_domain_error(
+ std::__throw_domain_error(
"Argument of laguerre function is out of range");
return __libcpp_generalized_laguerre_recurrence(__n, _Real(0), __x);
diff --git a/libcxx/include/experimental/__math/legendre.h b/libcxx/include/experimental/__math/legendre.h
index aa4e168853179..ae98e6153278b 100644
--- a/libcxx/include/experimental/__math/legendre.h
+++ b/libcxx/include/experimental/__math/legendre.h
@@ -51,7 +51,7 @@ template <class _Real> _Real __libcpp_legendre(unsigned __n, _Real __x) {
return std::numeric_limits<_Real>::quiet_NaN();
if (std::abs(__x) > _Real(1))
- _VSTD::__throw_domain_error(
+ std::__throw_domain_error(
"Argument of legendre function is out of range");
return __libcpp_legendre_recurrence(__n, __x);
@@ -115,7 +115,7 @@ _Real __libcpp_assoc_legendre(unsigned __n, unsigned __m, _Real __x) {
return std::numeric_limits<_Real>::quiet_NaN();
if (std::abs(__x) > _Real(1))
- _VSTD::__throw_domain_error(
+ std::__throw_domain_error(
"Argument of assoc_legendre function is out of range");
return __libcpp_assoc_legendre_recurrence(__n, __m, __x);
>From 3d0bc681bc27fb54e1e47a1a2d161a8b603f8d6d Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:04:17 +0200
Subject: [PATCH 06/76] replace deprecated _LIBCPP_INLINE_VISIBILITY by
_LIBCPP_HIDE_FROM_ABI
---
libcxx/include/experimental/math | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 18289a97ae5a3..b2b76e913c049 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -25,72 +25,72 @@
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
-inline _LIBCPP_INLINE_VISIBILITY double assoc_laguerre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI double assoc_laguerre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
{
return __libcpp_assoc_laguerre<double>(__lcpp_n , __lcpp_m, __lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY float assoc_laguerref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI float assoc_laguerref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
{
return static_cast<float>(__libcpp_assoc_laguerre<double>(__lcpp_n , __lcpp_m, static_cast<double>(__lcpp_x)));
}
-inline _LIBCPP_INLINE_VISIBILITY long double assoc_laguerrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI long double assoc_laguerrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
{
return __libcpp_assoc_laguerre<long double>(__lcpp_n , __lcpp_m, __lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY double assoc_legendre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI double assoc_legendre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
{
return __libcpp_assoc_legendre<double>(__lcpp_n , __lcpp_m, __lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY float assoc_legendref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI float assoc_legendref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
{
// use double internally -- float is too prone to overflow!
return static_cast<float>(__libcpp_assoc_legendre<double>(__lcpp_n , __lcpp_m, static_cast<double>(__lcpp_x)));
}
-inline _LIBCPP_INLINE_VISIBILITY long double assoc_legendrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI long double assoc_legendrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
{
return __libcpp_assoc_legendre<long double>(__lcpp_n , __lcpp_m, __lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY double laguerre(unsigned __lcpp_n, double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI double laguerre(unsigned __lcpp_n, double __lcpp_x)
{
return __libcpp_laguerre<double>(__lcpp_n ,__lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY float laguerref(unsigned __lcpp_n, float __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI float laguerref(unsigned __lcpp_n, float __lcpp_x)
{
return static_cast<float>(__libcpp_laguerre<double>(__lcpp_n, static_cast<double>(__lcpp_x)));
}
-inline _LIBCPP_INLINE_VISIBILITY long double laguerrel(unsigned __lcpp_n, long double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI long double laguerrel(unsigned __lcpp_n, long double __lcpp_x)
{
return __libcpp_laguerre<long double>(__lcpp_n ,__lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY double legendre(unsigned __lcpp_n, double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI double legendre(unsigned __lcpp_n, double __lcpp_x)
{
return __libcpp_legendre<double>(__lcpp_n ,__lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY float legendref(unsigned __lcpp_n, float __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI float legendref(unsigned __lcpp_n, float __lcpp_x)
{
return static_cast<float>(__libcpp_legendre<double>(__lcpp_n, static_cast<double>(__lcpp_x)));
}
-inline _LIBCPP_INLINE_VISIBILITY long double legendrel(unsigned __lcpp_n, long double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI long double legendrel(unsigned __lcpp_n, long double __lcpp_x)
{
return __libcpp_legendre<long double>(__lcpp_n ,__lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY double hermite(unsigned __lcpp_n, double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __lcpp_n, double __lcpp_x)
{
return __libcpp_hermite<double>(__lcpp_n ,__lcpp_x);
}
-inline _LIBCPP_INLINE_VISIBILITY float hermitef(unsigned __lcpp_n, float __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __lcpp_n, float __lcpp_x)
{
// use double internally -- float is too prone to overflow!
return static_cast<float>(__libcpp_hermite(__lcpp_n , static_cast<double>(__lcpp_x)));
}
-inline _LIBCPP_INLINE_VISIBILITY long double hermitel(unsigned __lcpp_n, long double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __lcpp_n, long double __lcpp_x)
{
return __libcpp_hermite<long double>(__lcpp_n ,__lcpp_x);
}
>From d5f0e4659c795d488d5664fb0c31e4a762f451ea Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:09:42 +0200
Subject: [PATCH 07/76] hermite tests succeed! (fixed compiler warning:
shadowing variable)
---
libcxx/test/std/experimental/math/hermite.pass.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/libcxx/test/std/experimental/math/hermite.pass.cpp b/libcxx/test/std/experimental/math/hermite.pass.cpp
index e8b89b5e746e0..06522cdcb5d32 100644
--- a/libcxx/test/std/experimental/math/hermite.pass.cpp
+++ b/libcxx/test/std/experimental/math/hermite.pass.cpp
@@ -49,14 +49,14 @@ void testHermiteAnalytic(const T x, const T AbsTolerance,
};
const auto h0 = [](T) { return T(1); };
- const auto h1 = [](T x) { return T(2) * x; };
- const auto h2 = [](T x) { return T(4) * x * x - T(2); };
- const auto h3 = [](T x) { return x * (T(8) * x * x - T(12)); };
- const auto h4 = [](T x) {
- return (T(16) * x * x * x * x - T(48) * x * x + T(12));
+ const auto h1 = [](T y) { return T(2) * y; };
+ const auto h2 = [](T y) { return T(4) * y * y - T(2); };
+ const auto h3 = [](T y) { return y * (T(8) * y * y - T(12)); };
+ const auto h4 = [](T y) {
+ return (T(16) * y * y * y * y - T(48) * y * y + T(12));
};
- const auto h5 = [](T x) {
- return x * (T(32) * x * x * x * x - T(160) * x * x + T(120));
+ const auto h5 = [](T y) {
+ return y * (T(32) * y * y * y * y - T(160) * y * y + T(120));
};
assert(compareFloatingPoint(std::experimental::hermite(0, x), h0(x)));
>From 1da97b4d62f53ec7674181d62a41c6d3689042b6 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:11:54 +0200
Subject: [PATCH 08/76] laguerre tests succeeds! (fixed compiler warning:
shadowing variable)
---
.../std/experimental/math/laguerre.pass.cpp | 26 +++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/libcxx/test/std/experimental/math/laguerre.pass.cpp b/libcxx/test/std/experimental/math/laguerre.pass.cpp
index 6c25cb83788fc..f6a11221e2500 100644
--- a/libcxx/test/std/experimental/math/laguerre.pass.cpp
+++ b/libcxx/test/std/experimental/math/laguerre.pass.cpp
@@ -63,25 +63,25 @@ void testLaguerreAnalytic(const T x, const T AbsTolerance,
};
const auto l0 = [](T) { return T(1); };
- const auto l1 = [](T x) { return -x + 1; };
- const auto l2 = [](T x) { return (x * x - T(4) * x + T(2)) / T(2); };
- const auto l3 = [](T x) {
- return (-x * x * x + T(9) * x * x - T(18) * x + T(6)) / T(6);
+ const auto l1 = [](T y) { return -y + 1; };
+ const auto l2 = [](T y) { return (y * y - T(4) * y + T(2)) / T(2); };
+ const auto l3 = [](T y) {
+ return (-y * y * y + T(9) * y * y - T(18) * y + T(6)) / T(6);
};
- const auto l4 = [](T x) {
- return (x * x * x * x - T(16) * x * x * x + T(72) * x * x - T(96) * x +
+ const auto l4 = [](T y) {
+ return (y * y * y * y - T(16) * y * y * y + T(72) * y * y - T(96) * y +
T(24)) /
T(24);
};
- const auto l5 = [](T x) {
- return (-x * x * x * x * x + T(25) * x * x * x * x - T(200) * x * x * x +
- T(600) * x * x - T(600) * x + T(120)) /
+ const auto l5 = [](T y) {
+ return (-y * y * y * y * y + T(25) * y * y * y * y - T(200) * y * y * y +
+ T(600) * y * y - T(600) * y + T(120)) /
T(120);
};
- const auto l6 = [](T x) {
- return (x * x * x * x * x * x - T(36) * x * x * x * x * x +
- T(450) * x * x * x * x - T(2400) * x * x * x + T(5400) * x * x -
- T(4320) * x + T(720)) /
+ const auto l6 = [](T y) {
+ return (y * y * y * y * y * y - T(36) * y * y * y * y * y +
+ T(450) * y * y * y * y - T(2400) * y * y * y + T(5400) * y * y -
+ T(4320) * y + T(720)) /
T(720);
};
>From 3721e893c074c0fe22521311ba0b55207d3d0cf1 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:13:24 +0200
Subject: [PATCH 09/76] legendre tests succeeds! (fixed compiler warning:
shadowing variable)
---
.../std/experimental/math/legendre.pass.cpp | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/libcxx/test/std/experimental/math/legendre.pass.cpp b/libcxx/test/std/experimental/math/legendre.pass.cpp
index 35cad4bff9561..493b1c10f345f 100644
--- a/libcxx/test/std/experimental/math/legendre.pass.cpp
+++ b/libcxx/test/std/experimental/math/legendre.pass.cpp
@@ -63,18 +63,18 @@ void testLegendreAnalytic(const T x, const T AbsTolerance,
};
const auto l0 = [](T) { return T(1); };
- const auto l1 = [](T x) { return x; };
- const auto l2 = [](T x) { return (T(3) * x * x - T(1)) / T(2); };
- const auto l3 = [](T x) { return (T(5) * x * x - T(3)) * x / T(2); };
- const auto l4 = [](T x) {
- return (T(35) * x * x * x * x - T(30) * x * x + T(3)) / T(8);
+ const auto l1 = [](T y) { return y; };
+ const auto l2 = [](T y) { return (T(3) * y * y - T(1)) / T(2); };
+ const auto l3 = [](T y) { return (T(5) * y * y - T(3)) * y / T(2); };
+ const auto l4 = [](T y) {
+ return (T(35) * y * y * y * y - T(30) * y * y + T(3)) / T(8);
};
- const auto l5 = [](T x) {
- return (T(63) * x * x * x * x - T(70) * x * x + T(15)) * x / T(8);
+ const auto l5 = [](T y) {
+ return (T(63) * y * y * y * y - T(70) * y * y + T(15)) * y / T(8);
};
- const auto l6 = [](T x) {
- const T x2 = x * x;
- return (T(231) * x2 * x2 * x2 - T(315) * x2 * x2 + T(105) * x2 - T(5)) /
+ const auto l6 = [](T y) {
+ const T y2 = y * y;
+ return (T(231) * y2 * y2 * y2 - T(315) * y2 * y2 + T(105) * y2 - T(5)) /
T(16);
};
>From c5cda4e5fa9f6a0bb6e491af7ae1a4cb52813bf5 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:14:26 +0200
Subject: [PATCH 10/76] assoc_laguerre tests succeeds! (fixed compiler warning:
shadowing variable)
---
.../std/experimental/math/assoc_laguerre.pass.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp b/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
index 945b4d531c924..793a723116d48 100644
--- a/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
+++ b/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
@@ -86,13 +86,13 @@ void testAssocLaguerreAnalytic(const T x, const T AbsTolerance,
};
const auto l0 = [](T, unsigned) { return T(1); };
- const auto l1 = [](T x, unsigned m) { return -x + T(m + 1); };
- const auto l2 = [](T x, unsigned m) {
- return x * x / T(2) - T(m + 2) * x + T(m + 1) * T(m + 2) / T(2);
+ const auto l1 = [](T y, unsigned m) { return -y + T(m + 1); };
+ const auto l2 = [](T y, unsigned m) {
+ return y * y / T(2) - T(m + 2) * y + T(m + 1) * T(m + 2) / T(2);
};
- const auto l3 = [](T x, unsigned m) {
- return -x * x * x / T(6) + T(m + 3) * x * x / T(2) -
- T(m + 2) * T(m + 3) * x / T(2) +
+ const auto l3 = [](T y, unsigned m) {
+ return -y * y * y / T(6) + T(m + 3) * y * y / T(2) -
+ T(m + 2) * T(m + 3) * y / T(2) +
T(m + 1) * T(m + 2) * T(m + 3) / T(6);
};
>From e8443b1e4f4929403b1e4e72d20b34afcb6bc6ed Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 22:15:12 +0200
Subject: [PATCH 11/76] assoc_legendre tests succeeds! (fixed compiler warning:
shadowing variable)
---
.../experimental/math/assoc_legendre.pass.cpp | 50 +++++++++----------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp b/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
index 3de555cac6f36..ed9b1e1f9178d 100644
--- a/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
+++ b/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
@@ -87,42 +87,42 @@ void testAssocLegendreAnalytic(const T x, const T AbsTolerance,
const auto l00 = [](T) { return T(1); };
- const auto l10 = [](T x) { return x; };
- const auto l11 = [](T x) { return std::sqrt((T(1) - x) * (T(1) + x)); };
+ const auto l10 = [](T y) { return y; };
+ const auto l11 = [](T y) { return std::sqrt((T(1) - y) * (T(1) + y)); };
- const auto l20 = [](T x) { return (T(3) * x * x - T(1)) / T(2); };
- const auto l21 = [](T x) {
- return T(3) * x * std::sqrt((T(1) - x) * (T(1) + x));
+ const auto l20 = [](T y) { return (T(3) * y * y - T(1)) / T(2); };
+ const auto l21 = [](T y) {
+ return T(3) * y * std::sqrt((T(1) - y) * (T(1) + y));
};
- const auto l22 = [](T x) { return T(3) * (T(1) - x) * (T(1) + x); };
+ const auto l22 = [](T y) { return T(3) * (T(1) - y) * (T(1) + y); };
- const auto l30 = [](T x) { return (T(5) * x * x - T(3)) * x / T(2); };
- const auto l31 = [](T x) {
- return T(3) / T(2) * (T(5) * x * x - T(1)) *
- std::sqrt((T(1) - x) * (T(1) + x));
+ const auto l30 = [](T y) { return (T(5) * y * y - T(3)) * y / T(2); };
+ const auto l31 = [](T y) {
+ return T(3) / T(2) * (T(5) * y * y - T(1)) *
+ std::sqrt((T(1) - y) * (T(1) + y));
};
- const auto l32 = [](T x) { return T(15) * x * (T(1) - x) * (T(1) + x); };
- const auto l33 = [](T x) {
- const T temp = (T(1) - x) * (T(1) + x);
+ const auto l32 = [](T y) { return T(15) * y * (T(1) - y) * (T(1) + y); };
+ const auto l33 = [](T y) {
+ const T temp = (T(1) - y) * (T(1) + y);
return T(15) * temp * std::sqrt(temp);
};
- const auto l40 = [](T x) {
- return (T(35) * x * x * x * x - T(30) * x * x + T(3)) / T(8);
+ const auto l40 = [](T y) {
+ return (T(35) * y * y * y * y - T(30) * y * y + T(3)) / T(8);
};
- const auto l41 = [](T x) {
- return T(5) / T(2) * x * (T(7) * x * x - T(3)) *
- std::sqrt((T(1) - x) * (T(1) + x));
+ const auto l41 = [](T y) {
+ return T(5) / T(2) * y * (T(7) * y * y - T(3)) *
+ std::sqrt((T(1) - y) * (T(1) + y));
};
- const auto l42 = [](T x) {
- return T(15) / T(2) * (T(7) * x * x - 1) * (T(1) - x) * (T(1) + x);
+ const auto l42 = [](T y) {
+ return T(15) / T(2) * (T(7) * y * y - 1) * (T(1) - y) * (T(1) + y);
};
- const auto l43 = [](T x) {
- const T temp = (T(1) - x) * (T(1) + x);
- return T(105) * x * temp * std::sqrt(temp);
+ const auto l43 = [](T y) {
+ const T temp = (T(1) - y) * (T(1) + y);
+ return T(105) * y * temp * std::sqrt(temp);
};
- const auto l44 = [](T x) {
- const T temp = (T(1) - x) * (T(1) + x);
+ const auto l44 = [](T y) {
+ const T temp = (T(1) - y) * (T(1) + y);
return T(105) * temp * temp;
};
>From 52de5c97fb9206fc623db556e1c174b5d75adb1e Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 23:10:05 +0200
Subject: [PATCH 12/76] hermite: fix documentation comment
---
libcxx/include/experimental/__math/hermite.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index c93e05ae11303..ebd4555b4a49e 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -22,10 +22,10 @@
/// \return the hermite polynomial \f$ H_{n}(x) \f$
/// \note The implementation is based on the recurrence formula
/// \f[
-/// nH_{n+1}(x) = 2x H_{n}(x) - 2 n H_{n-1}
+/// H_{n+1}(x) = 2x H_{n}(x) - 2 n H_{n-1}
/// \f]
/// Press, William H., et al. Numerical recipes 3rd edition: The art of
-/// scientific computing. Cambridge university press, 2007, p. 182.
+/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
_Real __libcpp_hermite_recurrence(unsigned __n, _Real __x) {
if (__n == 0u)
>From b500da25c7e14a0bf54e1678180a7f1c1a2d142d Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 23:39:03 +0200
Subject: [PATCH 13/76] hermite: minor code changes: rename variables, brace
initialization
---
libcxx/include/experimental/__math/hermite.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index ebd4555b4a49e..b89cb0b27b6d9 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -28,17 +28,17 @@
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
_Real __libcpp_hermite_recurrence(unsigned __n, _Real __x) {
- if (__n == 0u)
- return _Real(1);
+ if (0u == __n)
+ return _Real{1};
- _Real __t2(1);
- _Real __t1 = _Real(2) * __x;
+ _Real __H_nPrev{1};
+ _Real __H_n = _Real{2} * __x;
for (unsigned __i = 1; __i < __n; ++__i) {
- const _Real __t0 = _Real(2) * (__x * __t1 - _Real(__i) * __t2);
- __t2 = __t1;
- __t1 = __t0;
+ const _Real __H_nNext = _Real{2} * (__x * __H_n - _Real{__i} * __H_nPrev);
+ __H_nPrev = __H_n;
+ __H_n = __H_nNext;
}
- return __t1;
+ return __H_n;
}
template <class _Real> _Real __libcpp_hermite(unsigned __n, _Real __x) {
>From 6d5ef58aa041836b0352f26e2847ea9ab1f51f43 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 23:57:13 +0200
Subject: [PATCH 14/76] create experimental/math module
---
libcxx/include/module.modulemap | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 64652c8307c9e..eb0e4de920ab9 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -521,6 +521,10 @@ module std_experimental [system] {
header "experimental/iterator"
export *
}
+ module math {
+ header "experimental/math"
+ export *
+ }
module memory {
header "experimental/memory"
export *
>From 6feadb53ab55e131d6ea47e81c5ac2bb8e6de856 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 21 Apr 2024 23:58:10 +0200
Subject: [PATCH 15/76] set header info for lit
---
libcxx/utils/libcxx/header_information.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index bccae353b0c6b..690458887460a 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -56,6 +56,7 @@
"cwchar": "// UNSUPPORTED: no-wide-characters",
"cwctype": "// UNSUPPORTED: no-wide-characters",
"experimental/iterator": "// UNSUPPORTED: c++03",
+ "experimental/math": "// UNSUPPORTED: c++03, c++11, c++14",
"experimental/propagate_const": "// UNSUPPORTED: c++03",
"experimental/simd": "// UNSUPPORTED: c++03",
"experimental/type_traits": "// UNSUPPORTED: c++03",
>From d711e58716d8a662780ba10192924e501fd3f5a9 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 12:42:17 +0200
Subject: [PATCH 16/76] keeping only hermite, i.e. remove laguerre, legendre
---
libcxx/include/CMakeLists.txt | 2 -
libcxx/include/experimental/__math/laguerre.h | 72 -------
libcxx/include/experimental/__math/legendre.h | 124 -----------
libcxx/include/experimental/math | 57 -----
.../experimental/math/assoc_laguerre.pass.cpp | 134 ------------
.../experimental/math/assoc_legendre.pass.cpp | 203 ------------------
.../std/experimental/math/laguerre.pass.cpp | 119 ----------
.../std/experimental/math/legendre.pass.cpp | 114 ----------
8 files changed, 825 deletions(-)
delete mode 100644 libcxx/include/experimental/__math/laguerre.h
delete mode 100644 libcxx/include/experimental/__math/legendre.h
delete mode 100644 libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
delete mode 100644 libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
delete mode 100644 libcxx/test/std/experimental/math/laguerre.pass.cpp
delete mode 100644 libcxx/test/std/experimental/math/legendre.pass.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 15e7e892f81a0..30c00e033fe1b 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -923,8 +923,6 @@ set(files
expected
experimental/__config
experimental/__math/hermite.h
- experimental/__math/laguerre.h
- experimental/__math/legendre.h
experimental/__simd/aligned_tag.h
experimental/__simd/declaration.h
experimental/__simd/reference.h
diff --git a/libcxx/include/experimental/__math/laguerre.h b/libcxx/include/experimental/__math/laguerre.h
deleted file mode 100644
index 58b92345beb81..0000000000000
--- a/libcxx/include/experimental/__math/laguerre.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file contains the internal implementations of std::laguerre
-/// and std::assoc_laguerre.
-///
-//===----------------------------------------------------------------------===//
-
-
-#ifndef _LIBCPP_EXPERIMENTAL___MATH_LAGUERRE_H
-#define _LIBCPP_EXPERIMENTAL___MATH_LAGUERRE_H
-
-#include <experimental/__config>
-#include <cmath>
-#include <limits>
-#include <stdexcept>
-
-/// \return the generalized laguerre polynomial \f$ L_{n}^{(\alpha)}(x) \f$
-/// \note The implementation is based on the recurrence formula
-/// \f[
-/// nL_{n}^{(\alpha)}(x) = (-x + 2n + \alpha - 1) L_{n-1}^{(\alpha)}(x) -
-/// (n + \alpha - 1) L_{n-2}^{(\alpha)}(x)
-/// \f]
-/// Press, William H., et al. Numerical recipes 3rd edition: The art of
-/// scientific computing. Cambridge university press, 2007, p. 182.
-template <class _Real>
-_Real __libcpp_generalized_laguerre_recurrence(unsigned __n, _Real __alpha,
- _Real __x) {
- if (__n == 0u)
- return _Real(1);
-
- _Real __delta = __alpha - __x;
- _Real __li = _Real(1) + __delta;
- const _Real __alpham1 = __alpha - _Real(1);
- for (unsigned __i = 2; __i <= __n; ++__i) {
- __delta = (__delta * (_Real(__i) + __alpham1) - __x * __li) / _Real(__i);
- __li += __delta;
- }
- return __li;
-}
-
-template <class _Real>
-_Real __libcpp_assoc_laguerre(unsigned __n, unsigned __m, _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
-
- if (__x < _Real(0))
- std::__throw_domain_error(
- "Argument of assoc_laguerre function is out of range");
-
- return __libcpp_generalized_laguerre_recurrence(__n, _Real(__m), __x);
-}
-
-template <class _Real> _Real __libcpp_laguerre(unsigned __n, _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
-
- if (__x < _Real(0))
- std::__throw_domain_error(
- "Argument of laguerre function is out of range");
-
- return __libcpp_generalized_laguerre_recurrence(__n, _Real(0), __x);
-}
-
-#endif // _LIBCPP_EXPERIMENTAL___MATH_LAGUERRE_H
diff --git a/libcxx/include/experimental/__math/legendre.h b/libcxx/include/experimental/__math/legendre.h
deleted file mode 100644
index ae98e6153278b..0000000000000
--- a/libcxx/include/experimental/__math/legendre.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file contains the internal implementations of std::legendre
-/// and std::assoc_legendre.
-///
-//===----------------------------------------------------------------------===//
-
-
-#ifndef _LIBCPP_EXPERIMENTAL___MATH_LEGENDRE_H
-#define _LIBCPP_EXPERIMENTAL___MATH_LEGENDRE_H
-
-#include <experimental/__config>
-#include <cmath>
-#include <limits>
-#include <stdexcept>
-
-/// \return the Legendre polynomial \f$ P_{n}(x) \f$
-/// \note The implementation is based on the recurrence formula
-/// \f[
-/// (n+1)P_{n+1}(x) = (2n+1)xP_{n}(x) - nP_{n-1}(x)
-/// \f]
-/// Press, William H., et al. Numerical recipes 3rd edition: The art of
-/// scientific computing. Cambridge university press, 2007, p. 182.
-template <class _Real>
-_Real __libcpp_legendre_recurrence(unsigned __n, _Real __x) {
- if (__n == 0u)
- return _Real(1);
-
- _Real __t2(1);
- _Real __t1 = __x;
- for (unsigned __i = 1; __i < __n; ++__i) {
- const _Real __k = _Real(__i);
- _Real __t0 = ((_Real(2) * __k + _Real(1)) * __x * __t1 - __k * __t2) /
- (__k + _Real(1));
- __t2 = __t1;
- __t1 = __t0;
- }
- return __t1;
-}
-
-template <class _Real> _Real __libcpp_legendre(unsigned __n, _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
-
- if (std::abs(__x) > _Real(1))
- std::__throw_domain_error(
- "Argument of legendre function is out of range");
-
- return __libcpp_legendre_recurrence(__n, __x);
-}
-
-/// \return \f$ s^{-m} P_{l}^{m}(x) \f$ with an additonal scaling factor to
-/// prevent overflow. \note The implementation is based on the recurrence
-/// formula \f[ (l-m+1)P_{l+1}^{m}(x) = (2l+1)xP_{l}^{m}(x) -
-/// (l+m)P_{l-1}^{m}(x) \f] with \f[ P_{m}^{m}(x) = \sqrt{1 -
-/// x^2}^{m}\frac{(2m)!}{2^m m!} \f] and \f[ P_{m-1}^{m}(x) = 0 \f] \attention
-/// The starting point of the recursion grows exponentially with __m! For large
-/// m, we have the following relation: \f[ P_{m}^{m}(x) \approx \sqrt{1 -
-/// x^2}^{m}\sqrt{2} 2^{n} \exp( n(\ln n - 1 )) \f] For example, for \f$ m = 40
-/// \f$, we already have \f$ P_{40}^{40}(0) \approx 8 \cdot 10^{58} \f$
-/// \attention The so-called Condon-Shortley phase term is omitted in the C++17
-/// standard's definition of std::assoc_laguerre.
-template <class _Real>
-_Real __libcpp_assoc_legendre_recurrence(unsigned __l, unsigned __m, _Real __x,
- _Real __scale = _Real(1)) {
- if (__m == 0u)
- return __libcpp_legendre_recurrence(__l, __x);
-
- if (__l < __m)
- return _Real(0);
-
- if (__l == 0u)
- return _Real(1);
-
- _Real __pmm = _Real(1);
- // Note: (1-x)*(1+x) is more accurate than (1-x*x)
- // "What Every Computer Scientist Should Know About Floating-Point
- // Arithmetic", David Goldberg, p. 38
- const _Real __t =
- std::sqrt((_Real(1) - __x) * (_Real(1) + __x)) / (_Real(2) * __scale);
- for (unsigned __i = 2u * __m; __i > __m; --__i)
- __pmm *= __t * __i;
-
- if (__l == __m)
- return __pmm;
-
- // Actually, we'd start with _pmm but it grows exponentially with __m.
- // Luckily, the recursion scales. So we can start with 1 and multiply
- // afterwards.
- _Real __t2 = _Real(1);
- _Real __t1 = _Real(2u * __m + 1u) * __x; // first iteration unfolded
- for (unsigned __i = __m + 1u; __i < __l; ++__i) {
- // As soon as one of the terms becomes inf, this will quickly lead to NaNs.
- // float just doesn't do it for the whole range up to l==127.
- const _Real __t0 =
- (_Real(2u * __i + 1u) * __x * __t1 - _Real(__i + __m) * __t2) /
- _Real(__i - __m + 1u);
- __t2 = __t1;
- __t1 = __t0;
- }
- return __t1 * __pmm;
-}
-
-template <class _Real>
-_Real __libcpp_assoc_legendre(unsigned __n, unsigned __m, _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
-
- if (std::abs(__x) > _Real(1))
- std::__throw_domain_error(
- "Argument of assoc_legendre function is out of range");
-
- return __libcpp_assoc_legendre_recurrence(__n, __m, __x);
-}
-
-#endif // _LIBCPP_EXPERIMENTAL___MATH_LEGENDRE_H
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index b2b76e913c049..a0a4f70ad4237 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -20,66 +20,9 @@
#if _LIBCPP_STD_VER > 14
#include <experimental/__math/hermite.h>
-#include <experimental/__math/laguerre.h>
-#include <experimental/__math/legendre.h>
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
-inline _LIBCPP_HIDE_FROM_ABI double assoc_laguerre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
-{
- return __libcpp_assoc_laguerre<double>(__lcpp_n , __lcpp_m, __lcpp_x);
-}
-inline _LIBCPP_HIDE_FROM_ABI float assoc_laguerref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
-{
- return static_cast<float>(__libcpp_assoc_laguerre<double>(__lcpp_n , __lcpp_m, static_cast<double>(__lcpp_x)));
-}
-inline _LIBCPP_HIDE_FROM_ABI long double assoc_laguerrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
-{
- return __libcpp_assoc_laguerre<long double>(__lcpp_n , __lcpp_m, __lcpp_x);
-}
-
-
-inline _LIBCPP_HIDE_FROM_ABI double assoc_legendre(unsigned __lcpp_n, unsigned __lcpp_m, double __lcpp_x)
-{
- return __libcpp_assoc_legendre<double>(__lcpp_n , __lcpp_m, __lcpp_x);
-}
-inline _LIBCPP_HIDE_FROM_ABI float assoc_legendref(unsigned __lcpp_n, unsigned __lcpp_m, float __lcpp_x)
-{
- // use double internally -- float is too prone to overflow!
- return static_cast<float>(__libcpp_assoc_legendre<double>(__lcpp_n , __lcpp_m, static_cast<double>(__lcpp_x)));
-}
-inline _LIBCPP_HIDE_FROM_ABI long double assoc_legendrel(unsigned __lcpp_n, unsigned __lcpp_m, long double __lcpp_x)
-{
- return __libcpp_assoc_legendre<long double>(__lcpp_n , __lcpp_m, __lcpp_x);
-}
-
-
-inline _LIBCPP_HIDE_FROM_ABI double laguerre(unsigned __lcpp_n, double __lcpp_x)
-{
- return __libcpp_laguerre<double>(__lcpp_n ,__lcpp_x);
-}
-inline _LIBCPP_HIDE_FROM_ABI float laguerref(unsigned __lcpp_n, float __lcpp_x)
-{
- return static_cast<float>(__libcpp_laguerre<double>(__lcpp_n, static_cast<double>(__lcpp_x)));
-}
-inline _LIBCPP_HIDE_FROM_ABI long double laguerrel(unsigned __lcpp_n, long double __lcpp_x)
-{
- return __libcpp_laguerre<long double>(__lcpp_n ,__lcpp_x);
-}
-
-
-inline _LIBCPP_HIDE_FROM_ABI double legendre(unsigned __lcpp_n, double __lcpp_x)
-{
- return __libcpp_legendre<double>(__lcpp_n ,__lcpp_x);
-}
-inline _LIBCPP_HIDE_FROM_ABI float legendref(unsigned __lcpp_n, float __lcpp_x)
-{
- return static_cast<float>(__libcpp_legendre<double>(__lcpp_n, static_cast<double>(__lcpp_x)));
-}
-inline _LIBCPP_HIDE_FROM_ABI long double legendrel(unsigned __lcpp_n, long double __lcpp_x)
-{
- return __libcpp_legendre<long double>(__lcpp_n ,__lcpp_x);
-}
inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __lcpp_n, double __lcpp_x)
{
diff --git a/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp b/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
deleted file mode 100644
index 793a723116d48..0000000000000
--- a/libcxx/test/std/experimental/math/assoc_laguerre.pass.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <experimental/cmath>
-
-#include <cassert>
-#include <experimental/math>
-#include <limits>
-
-#if _LIBCPP_STD_VER > 14
-
-template <class T> void testAssocLaguerreNaNPropagation() {
- const unsigned MaxN = 127;
- const T x = std::numeric_limits<T>::quiet_NaN();
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- assert(std::isnan(std::experimental::assoc_laguerre(n, m, x)));
- }
- }
-}
-
-template <class T> void testAssocLaguerreNotNaN(const T x) {
- assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- assert(!std::isnan(std::experimental::assoc_laguerre(n, m, x)));
- }
- }
-}
-
-template <class T> void testAssocLaguerreThrows(const T x) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- bool Throws = false;
- try {
- std::experimental::assoc_laguerre(n, m, x);
- } catch (const std::domain_error &) {
- Throws = true;
- }
- assert(Throws);
- }
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
-}
-
-template <class T>
-void testAssocLaguerreVsLaguerre(const T x, const T AbsTolerance,
- const T RelTolerance) {
- assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- const T Result = std::experimental::assoc_laguerre(n, 0, x);
- const T ExpectedResult = std::experimental::laguerre(n, x);
- const T Tolerance =
- AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
- const T Difference = std::abs(Result - ExpectedResult);
- assert(Difference <= Tolerance);
- }
- }
-}
-
-template <class T>
-void testAssocLaguerreAnalytic(const T x, const T AbsTolerance,
- const T RelTolerance) {
- assert(!std::isnan(x));
- const auto compareFloatingPoint =
- [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
- if (std::isinf(ExpectedResult) && std::isinf(Result))
- return true;
-
- if (std::isnan(ExpectedResult) || std::isnan(Result))
- return false;
-
- const T Tolerance =
- AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
- return std::abs(Result - ExpectedResult) < Tolerance;
- };
-
- const auto l0 = [](T, unsigned) { return T(1); };
- const auto l1 = [](T y, unsigned m) { return -y + T(m + 1); };
- const auto l2 = [](T y, unsigned m) {
- return y * y / T(2) - T(m + 2) * y + T(m + 1) * T(m + 2) / T(2);
- };
- const auto l3 = [](T y, unsigned m) {
- return -y * y * y / T(6) + T(m + 3) * y * y / T(2) -
- T(m + 2) * T(m + 3) * y / T(2) +
- T(m + 1) * T(m + 2) * T(m + 3) / T(6);
- };
-
- for (unsigned m = 0; m < 128; ++m) {
- assert(compareFloatingPoint(std::experimental::assoc_laguerre(0, m, x),
- l0(x, m)));
- assert(compareFloatingPoint(std::experimental::assoc_laguerre(1, m, x),
- l1(x, m)));
- assert(compareFloatingPoint(std::experimental::assoc_laguerre(2, m, x),
- l2(x, m)));
- assert(compareFloatingPoint(std::experimental::assoc_laguerre(3, m, x),
- l3(x, m)));
- }
-}
-
-template <class T>
-void testAssocLaguerre(const T AbsTolerance, const T RelTolerance) {
- testAssocLaguerreNaNPropagation<T>();
- testAssocLaguerreThrows<T>(T(-5));
-
- const T Samples[] = {T(0.0), T(0.1), T(0.5), T(1.0), T(10.0)};
-
- for (T x : Samples) {
- testAssocLaguerreNotNaN(x);
- testAssocLaguerreAnalytic(x, AbsTolerance, RelTolerance);
- testAssocLaguerreVsLaguerre(x, AbsTolerance, RelTolerance);
- }
-}
-
-#endif
-
-int main(int, char **) {
-#if _LIBCPP_STD_VER > 14
- testAssocLaguerre<float>(1e-5f, 1e-5f);
- testAssocLaguerre<double>(1e-9, 1e-9);
- testAssocLaguerre<long double>(1e-12, 1e-12);
-#endif
- return 0;
-}
diff --git a/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp b/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
deleted file mode 100644
index ed9b1e1f9178d..0000000000000
--- a/libcxx/test/std/experimental/math/assoc_legendre.pass.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <experimental/cmath>
-
-#include <cassert>
-#include <experimental/math>
-#include <limits>
-
-#if _LIBCPP_STD_VER > 14
-
-template <class T> void testAssocLegendreNaNPropagation() {
- const unsigned MaxN = 127;
- const T x = std::numeric_limits<T>::quiet_NaN();
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- assert(std::isnan(std::experimental::assoc_legendre(n, m, x)));
- }
- }
-}
-
-template <class T> void testAssocLegendreNotNaN(const T x) {
- assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- assert(!std::isnan(std::experimental::assoc_legendre(n, m, x)));
- }
- }
-}
-
-template <class T> void testAssocLegendreThrows(const T x) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- bool Throws = false;
- try {
- std::experimental::assoc_legendre(n, m, x);
- } catch (const std::domain_error &) {
- Throws = true;
- }
- assert(Throws);
- }
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
-}
-
-template <class T>
-void testAssocLegendreVsLegendre(const T x, const T AbsTolerance,
- const T RelTolerance) {
- assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = 0; m <= MaxN; ++m) {
- const T Result = std::experimental::assoc_legendre(n, 0, x);
- const T ExpectedResult = std::experimental::legendre(n, x);
- const T Tolerance =
- AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
- const T Difference = std::abs(Result - ExpectedResult);
- assert(Difference <= Tolerance);
- }
- }
-}
-
-template <class T>
-void testAssocLegendreAnalytic(const T x, const T AbsTolerance,
- const T RelTolerance) {
- assert(!std::isnan(x));
- const auto compareFloatingPoint =
- [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
- if (std::isinf(ExpectedResult) && std::isinf(Result))
- return true;
-
- if (std::isnan(ExpectedResult) || std::isnan(Result))
- return false;
-
- const T Tolerance =
- AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
- return std::abs(Result - ExpectedResult) < Tolerance;
- };
-
- const auto l00 = [](T) { return T(1); };
-
- const auto l10 = [](T y) { return y; };
- const auto l11 = [](T y) { return std::sqrt((T(1) - y) * (T(1) + y)); };
-
- const auto l20 = [](T y) { return (T(3) * y * y - T(1)) / T(2); };
- const auto l21 = [](T y) {
- return T(3) * y * std::sqrt((T(1) - y) * (T(1) + y));
- };
- const auto l22 = [](T y) { return T(3) * (T(1) - y) * (T(1) + y); };
-
- const auto l30 = [](T y) { return (T(5) * y * y - T(3)) * y / T(2); };
- const auto l31 = [](T y) {
- return T(3) / T(2) * (T(5) * y * y - T(1)) *
- std::sqrt((T(1) - y) * (T(1) + y));
- };
- const auto l32 = [](T y) { return T(15) * y * (T(1) - y) * (T(1) + y); };
- const auto l33 = [](T y) {
- const T temp = (T(1) - y) * (T(1) + y);
- return T(15) * temp * std::sqrt(temp);
- };
-
- const auto l40 = [](T y) {
- return (T(35) * y * y * y * y - T(30) * y * y + T(3)) / T(8);
- };
- const auto l41 = [](T y) {
- return T(5) / T(2) * y * (T(7) * y * y - T(3)) *
- std::sqrt((T(1) - y) * (T(1) + y));
- };
- const auto l42 = [](T y) {
- return T(15) / T(2) * (T(7) * y * y - 1) * (T(1) - y) * (T(1) + y);
- };
- const auto l43 = [](T y) {
- const T temp = (T(1) - y) * (T(1) + y);
- return T(105) * y * temp * std::sqrt(temp);
- };
- const auto l44 = [](T y) {
- const T temp = (T(1) - y) * (T(1) + y);
- return T(105) * temp * temp;
- };
-
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(0, 0, x), l00(x)));
-
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(1, 0, x), l10(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(1, 1, x), l11(x)));
-
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(2, 0, x), l20(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(2, 1, x), l21(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(2, 2, x), l22(x)));
-
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(3, 0, x), l30(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(3, 1, x), l31(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(3, 2, x), l32(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(3, 3, x), l33(x)));
-
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(4, 0, x), l40(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(4, 1, x), l41(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(4, 2, x), l42(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(4, 3, x), l43(x)));
- assert(
- compareFloatingPoint(std::experimental::assoc_legendre(4, 4, x), l44(x)));
-
- try {
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- for (unsigned m = n + 1; m <= MaxN; ++m) {
- assert(std::experimental::assoc_legendre(n, m, x) <= AbsTolerance);
- }
- }
- } catch (const std::domain_error &) {
- // Should not throw! The expression given in
- // ISO/IEC JTC 1/SC 22/WG 21 N3060 is actually well-defined for m > n!
- assert(false);
- }
-}
-
-template <class T>
-void testAssocLegendre(const T AbsTolerance, const T RelTolerance) {
- testAssocLegendreNaNPropagation<T>();
- testAssocLegendreThrows<T>(T(-5));
- testAssocLegendreThrows<T>(T(5));
-
- const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
- T(0.1), T(0.5), T(1.0)};
-
- for (T x : Samples) {
- testAssocLegendreNotNaN(x);
- testAssocLegendreVsLegendre(x, AbsTolerance, RelTolerance);
- testAssocLegendreAnalytic(x, AbsTolerance, RelTolerance);
- }
-}
-
-#endif
-
-int main(int, char **) {
-#if _LIBCPP_STD_VER > 14
- testAssocLegendre<float>(1e-6f, 1e-6f);
- testAssocLegendre<double>(1e-9, 1e-9);
- testAssocLegendre<long double>(1e-12, 1e-12);
-#endif
- return 0;
-}
diff --git a/libcxx/test/std/experimental/math/laguerre.pass.cpp b/libcxx/test/std/experimental/math/laguerre.pass.cpp
deleted file mode 100644
index f6a11221e2500..0000000000000
--- a/libcxx/test/std/experimental/math/laguerre.pass.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <experimental/cmath>
-
-#include <cassert>
-#include <experimental/math>
-#include <limits>
-
-#if _LIBCPP_STD_VER > 14
-
-template <class T> void testLaguerreNaNPropagation() {
- const unsigned MaxN = 127;
- const T x = std::numeric_limits<T>::quiet_NaN();
- for (unsigned n = 0; n <= MaxN; ++n) {
- assert(std::isnan(std::experimental::laguerre(n, x)));
- }
-}
-
-template <class T> void testLaguerreNotNaN(const T x) {
- assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- assert(!std::isnan(std::experimental::laguerre(n, x)));
- }
-}
-
-template <class T> void testLaguerreThrows(const T x) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- bool Throws = false;
- try {
- std::experimental::laguerre(n, x);
- } catch (const std::domain_error &) {
- Throws = true;
- }
- assert(Throws);
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
-}
-
-template <class T>
-void testLaguerreAnalytic(const T x, const T AbsTolerance,
- const T RelTolerance) {
- assert(!std::isnan(x));
- const auto compareFloatingPoint =
- [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
- if (std::isinf(ExpectedResult) && std::isinf(Result))
- return true;
-
- if (std::isnan(ExpectedResult) || std::isnan(Result))
- return false;
-
- const T Tolerance =
- AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
- return std::abs(Result - ExpectedResult) < Tolerance;
- };
-
- const auto l0 = [](T) { return T(1); };
- const auto l1 = [](T y) { return -y + 1; };
- const auto l2 = [](T y) { return (y * y - T(4) * y + T(2)) / T(2); };
- const auto l3 = [](T y) {
- return (-y * y * y + T(9) * y * y - T(18) * y + T(6)) / T(6);
- };
- const auto l4 = [](T y) {
- return (y * y * y * y - T(16) * y * y * y + T(72) * y * y - T(96) * y +
- T(24)) /
- T(24);
- };
- const auto l5 = [](T y) {
- return (-y * y * y * y * y + T(25) * y * y * y * y - T(200) * y * y * y +
- T(600) * y * y - T(600) * y + T(120)) /
- T(120);
- };
- const auto l6 = [](T y) {
- return (y * y * y * y * y * y - T(36) * y * y * y * y * y +
- T(450) * y * y * y * y - T(2400) * y * y * y + T(5400) * y * y -
- T(4320) * y + T(720)) /
- T(720);
- };
-
- assert(compareFloatingPoint(std::experimental::laguerre(0, x), l0(x)));
- assert(compareFloatingPoint(std::experimental::laguerre(1, x), l1(x)));
- assert(compareFloatingPoint(std::experimental::laguerre(2, x), l2(x)));
- assert(compareFloatingPoint(std::experimental::laguerre(3, x), l3(x)));
- assert(compareFloatingPoint(std::experimental::laguerre(4, x), l4(x)));
- assert(compareFloatingPoint(std::experimental::laguerre(5, x), l5(x)));
- assert(compareFloatingPoint(std::experimental::laguerre(6, x), l6(x)));
-}
-
-template <class T>
-void testLaguerre(const T AbsTolerance, const T RelTolerance) {
- testLaguerreNaNPropagation<T>();
- testLaguerreThrows<T>(T(-5));
-
- const T Samples[] = {T(0.0), T(0.1), T(0.5), T(1.0), T(10.0)};
-
- for (T x : Samples) {
- testLaguerreNotNaN(x);
- testLaguerreAnalytic(x, AbsTolerance, RelTolerance);
- }
-}
-
-#endif
-
-int main(int, char **) {
-#if _LIBCPP_STD_VER > 14
- testLaguerre<float>(1e-6f, 1e-6f);
- testLaguerre<double>(1e-9, 1e-9);
- testLaguerre<long double>(1e-12, 1e-12);
-#endif
- return 0;
-}
diff --git a/libcxx/test/std/experimental/math/legendre.pass.cpp b/libcxx/test/std/experimental/math/legendre.pass.cpp
deleted file mode 100644
index 493b1c10f345f..0000000000000
--- a/libcxx/test/std/experimental/math/legendre.pass.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <experimental/cmath>
-
-#include <cassert>
-#include <experimental/math>
-#include <limits>
-
-#if _LIBCPP_STD_VER > 14
-
-template <class T> void testLegendreNaNPropagation() {
- const unsigned MaxN = 127;
- const T x = std::numeric_limits<T>::quiet_NaN();
- for (unsigned n = 0; n <= MaxN; ++n) {
- assert(std::isnan(std::experimental::legendre(n, x)));
- }
-}
-
-template <class T> void testLegendreNotNaN(const T x) {
- assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- assert(!std::isnan(std::experimental::legendre(n, x)));
- }
-}
-
-template <class T> void testLegendreThrows(const T x) {
-#ifndef _LIBCPP_NO_EXCEPTIONS
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
- bool Throws = false;
- try {
- std::experimental::legendre(n, x);
- } catch (const std::domain_error &) {
- Throws = true;
- }
- assert(Throws);
- }
-#endif // _LIBCPP_NO_EXCEPTIONS
-}
-
-template <class T>
-void testLegendreAnalytic(const T x, const T AbsTolerance,
- const T RelTolerance) {
- assert(!std::isnan(x));
- const auto compareFloatingPoint =
- [AbsTolerance, RelTolerance](const T Result, const T ExpectedResult) {
- if (std::isinf(ExpectedResult) && std::isinf(Result))
- return true;
-
- if (std::isnan(ExpectedResult) || std::isnan(Result))
- return false;
-
- const T Tolerance =
- AbsTolerance + std::abs(ExpectedResult) * RelTolerance;
- return std::abs(Result - ExpectedResult) < Tolerance;
- };
-
- const auto l0 = [](T) { return T(1); };
- const auto l1 = [](T y) { return y; };
- const auto l2 = [](T y) { return (T(3) * y * y - T(1)) / T(2); };
- const auto l3 = [](T y) { return (T(5) * y * y - T(3)) * y / T(2); };
- const auto l4 = [](T y) {
- return (T(35) * y * y * y * y - T(30) * y * y + T(3)) / T(8);
- };
- const auto l5 = [](T y) {
- return (T(63) * y * y * y * y - T(70) * y * y + T(15)) * y / T(8);
- };
- const auto l6 = [](T y) {
- const T y2 = y * y;
- return (T(231) * y2 * y2 * y2 - T(315) * y2 * y2 + T(105) * y2 - T(5)) /
- T(16);
- };
-
- assert(compareFloatingPoint(std::experimental::legendre(0, x), l0(x)));
- assert(compareFloatingPoint(std::experimental::legendre(1, x), l1(x)));
- assert(compareFloatingPoint(std::experimental::legendre(2, x), l2(x)));
- assert(compareFloatingPoint(std::experimental::legendre(3, x), l3(x)));
- assert(compareFloatingPoint(std::experimental::legendre(4, x), l4(x)));
- assert(compareFloatingPoint(std::experimental::legendre(5, x), l5(x)));
- assert(compareFloatingPoint(std::experimental::legendre(6, x), l6(x)));
-}
-
-template <class T>
-void testLegendre(const T AbsTolerance, const T RelTolerance) {
- testLegendreNaNPropagation<T>();
- testLegendreThrows<T>(T(-5));
- testLegendreThrows<T>(T(5));
-
- const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
- T(0.1), T(0.5), T(1.0)};
-
- for (T x : Samples) {
- testLegendreNotNaN(x);
- testLegendreAnalytic(x, AbsTolerance, RelTolerance);
- }
-}
-
-#endif
-
-int main(int, char **) {
-#if _LIBCPP_STD_VER > 14
- testLegendre<float>(1e-6f, 1e-6f);
- testLegendre<double>(1e-9, 1e-9);
- testLegendre<long double>(1e-12, 1e-12);
-#endif
- return 0;
-}
>From 8c284b98de68c680bee5f3d7bb17ecb1b9d9a91c Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 12:47:07 +0200
Subject: [PATCH 17/76] remove explicit type conversions
---
libcxx/include/experimental/__math/hermite.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index b89cb0b27b6d9..11eac3cfc691c 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -28,13 +28,13 @@
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
_Real __libcpp_hermite_recurrence(unsigned __n, _Real __x) {
- if (0u == __n)
- return _Real{1};
+ if (0 == __n)
+ return 1;
_Real __H_nPrev{1};
- _Real __H_n = _Real{2} * __x;
+ _Real __H_n = 2 * __x;
for (unsigned __i = 1; __i < __n; ++__i) {
- const _Real __H_nNext = _Real{2} * (__x * __H_n - _Real{__i} * __H_nPrev);
+ const _Real __H_nNext = 2 * (__x * __H_n - __i * __H_nPrev);
__H_nPrev = __H_n;
__H_n = __H_nNext;
}
>From a63f7664906b92f3940771e7db0c4fab1eacf6ee Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 13:07:25 +0200
Subject: [PATCH 18/76] use more readable variable names
---
libcxx/include/experimental/math | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index a0a4f70ad4237..c9e39cb961c65 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -24,18 +24,18 @@
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
-inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __lcpp_n, double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x)
{
- return __libcpp_hermite<double>(__lcpp_n ,__lcpp_x);
+ return __libcpp_hermite<double>(__n, __x);
}
-inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __lcpp_n, float __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x)
{
// use double internally -- float is too prone to overflow!
- return static_cast<float>(__libcpp_hermite(__lcpp_n , static_cast<double>(__lcpp_x)));
+ return static_cast<float>(__libcpp_hermite(__n, static_cast<double>(__x)));
}
-inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __lcpp_n, long double __lcpp_x)
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x)
{
- return __libcpp_hermite<long double>(__lcpp_n ,__lcpp_x);
+ return __libcpp_hermite<long double>(__n, __x);
}
>From 2c17683ec28e289cb28558ec2e63f16293cbd68c Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 13:13:22 +0200
Subject: [PATCH 19/76] make use of function template argument deduction
---
libcxx/include/experimental/math | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index c9e39cb961c65..3039a90815919 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -26,7 +26,7 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x)
{
- return __libcpp_hermite<double>(__n, __x);
+ return __libcpp_hermite(__n, __x);
}
inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x)
{
@@ -35,7 +35,7 @@ inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x)
}
inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x)
{
- return __libcpp_hermite<long double>(__n, __x);
+ return __libcpp_hermite(__n, __x);
}
>From 3105f4ec15046fc8c88df5083042043d2ae62310 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 13:14:42 +0200
Subject: [PATCH 20/76] constness of passed arguments
---
libcxx/include/experimental/__math/hermite.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index 11eac3cfc691c..09d12e4e17c29 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -27,7 +27,7 @@
/// Press, William H., et al. Numerical recipes 3rd edition: The art of
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
-_Real __libcpp_hermite_recurrence(unsigned __n, _Real __x) {
+_Real __libcpp_hermite_recurrence(const unsigned __n, const _Real __x) {
if (0 == __n)
return 1;
@@ -41,7 +41,7 @@ _Real __libcpp_hermite_recurrence(unsigned __n, _Real __x) {
return __H_n;
}
-template <class _Real> _Real __libcpp_hermite(unsigned __n, _Real __x) {
+template <class _Real> _Real __libcpp_hermite(const unsigned __n, const _Real __x) {
if (std::isnan(__x))
return std::numeric_limits<_Real>::quiet_NaN();
>From 38b3db96156b80cc05c71a5e697f494e81343fce Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 13:17:24 +0200
Subject: [PATCH 21/76] unify return path via ternary op
---
libcxx/include/experimental/__math/hermite.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index 09d12e4e17c29..a1ad77c32a4ec 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -42,10 +42,9 @@ _Real __libcpp_hermite_recurrence(const unsigned __n, const _Real __x) {
}
template <class _Real> _Real __libcpp_hermite(const unsigned __n, const _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
-
- return __libcpp_hermite_recurrence(__n, __x);
+ return std::isnan(__x)
+ ? std::numeric_limits<_Real>::quiet_NaN()
+ : __libcpp_hermite_recurrence(__n, __x);
}
#endif // _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
>From 5dd9791414ad87e781bd29b7f926c090f88d97f5 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 13:24:20 +0200
Subject: [PATCH 22/76] clang format
---
libcxx/include/experimental/__math/hermite.h | 13 ++-
libcxx/include/experimental/math | 23 ++---
.../std/experimental/math/hermite.pass.cpp | 94 +++++++------------
3 files changed, 50 insertions(+), 80 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index a1ad77c32a4ec..b95e7a084ff87 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -15,8 +15,8 @@
#ifndef _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
#define _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
-#include <experimental/__config>
#include <cmath>
+#include <experimental/__config>
#include <limits>
/// \return the hermite polynomial \f$ H_{n}(x) \f$
@@ -35,16 +35,15 @@ _Real __libcpp_hermite_recurrence(const unsigned __n, const _Real __x) {
_Real __H_n = 2 * __x;
for (unsigned __i = 1; __i < __n; ++__i) {
const _Real __H_nNext = 2 * (__x * __H_n - __i * __H_nPrev);
- __H_nPrev = __H_n;
- __H_n = __H_nNext;
+ __H_nPrev = __H_n;
+ __H_n = __H_nNext;
}
return __H_n;
}
-template <class _Real> _Real __libcpp_hermite(const unsigned __n, const _Real __x) {
- return std::isnan(__x)
- ? std::numeric_limits<_Real>::quiet_NaN()
- : __libcpp_hermite_recurrence(__n, __x);
+template <class _Real>
+_Real __libcpp_hermite(const unsigned __n, const _Real __x) {
+ return std::isnan(__x) ? std::numeric_limits<_Real>::quiet_NaN() : __libcpp_hermite_recurrence(__n, __x);
}
#endif // _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 3039a90815919..604a573281666 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -12,32 +12,25 @@
// The following macro name shall be conditionally defined by the implementation
// to indicate conformance to the International Standard ISO/IEC JTC 1/SC 22/WG 21 N3060
-//#define __STDCPP_MATH_SPEC_FUNCS__ 201003L
+// #define __STDCPP_MATH_SPEC_FUNCS__ 201003L
-#include <experimental/__config>
#include <cmath>
+#include <experimental/__config>
#if _LIBCPP_STD_VER > 14
-#include <experimental/__math/hermite.h>
+# include <experimental/__math/hermite.h>
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __libcpp_hermite(__n, __x); }
-inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x)
-{
- return __libcpp_hermite(__n, __x);
-}
-inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x)
-{
- // use double internally -- float is too prone to overflow!
- return static_cast<float>(__libcpp_hermite(__n, static_cast<double>(__x)));
-}
-inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x)
-{
- return __libcpp_hermite(__n, __x);
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) {
+ // use double internally -- float is too prone to overflow!
+ return static_cast<float>(__libcpp_hermite(__n, static_cast<double>(__x)));
}
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
diff --git a/libcxx/test/std/experimental/math/hermite.pass.cpp b/libcxx/test/std/experimental/math/hermite.pass.cpp
index 06522cdcb5d32..6347da68fe22d 100644
--- a/libcxx/test/std/experimental/math/hermite.pass.cpp
+++ b/libcxx/test/std/experimental/math/hermite.pass.cpp
@@ -16,15 +16,17 @@
#if _LIBCPP_STD_VER > 14
-template <class T> void testHermiteNaNPropagation() {
+template <class T>
+void testHermiteNaNPropagation() {
const unsigned MaxN = 127;
- const T x = std::numeric_limits<T>::quiet_NaN();
+ const T x = std::numeric_limits<T>::quiet_NaN();
for (unsigned n = 0; n <= MaxN; ++n) {
assert(std::isnan(std::experimental::hermite(n, x)));
}
}
-template <class T> void testHermiteNotNaN(const T x) {
+template <class T>
+void testHermiteNotNaN(const T x) {
assert(!std::isnan(x));
const unsigned MaxN = 127;
for (unsigned n = 0; n <= MaxN; ++n) {
@@ -33,31 +35,25 @@ template <class T> void testHermiteNotNaN(const T x) {
}
template <class T>
-void testHermiteAnalytic(const T x, const T AbsTolerance,
- const T RelTolerance) {
+void testHermiteAnalytic(const T x, const T AbsTolerance, const T RelTolerance) {
assert(!std::isnan(x));
- const auto compareFloatingPoint =
- [AbsTolerance, RelTolerance](const T Result, const T Expected) {
- if (std::isinf(Expected) && std::isinf(Result))
- return true;
+ const auto compareFloatingPoint = [AbsTolerance, RelTolerance](const T Result, const T Expected) {
+ if (std::isinf(Expected) && std::isinf(Result))
+ return true;
- if (std::isnan(Expected) || std::isnan(Result))
- return false;
+ if (std::isnan(Expected) || std::isnan(Result))
+ return false;
- const T Tolerance = AbsTolerance + std::abs(Expected) * RelTolerance;
- return std::abs(Result - Expected) < Tolerance;
- };
+ const T Tolerance = AbsTolerance + std::abs(Expected) * RelTolerance;
+ return std::abs(Result - Expected) < Tolerance;
+ };
const auto h0 = [](T) { return T(1); };
const auto h1 = [](T y) { return T(2) * y; };
const auto h2 = [](T y) { return T(4) * y * y - T(2); };
const auto h3 = [](T y) { return y * (T(8) * y * y - T(12)); };
- const auto h4 = [](T y) {
- return (T(16) * y * y * y * y - T(48) * y * y + T(12));
- };
- const auto h5 = [](T y) {
- return y * (T(32) * y * y * y * y - T(160) * y * y + T(120));
- };
+ const auto h4 = [](T y) { return (T(16) * y * y * y * y - T(48) * y * y + T(12)); };
+ const auto h5 = [](T y) { return y * (T(32) * y * y * y * y - T(160) * y * y + T(120)); };
assert(compareFloatingPoint(std::experimental::hermite(0, x), h0(x)));
assert(compareFloatingPoint(std::experimental::hermite(1, x), h1(x)));
@@ -77,10 +73,9 @@ void testRecurrenceRelation(T x, T RelTolerance, T AbsTolerance) {
for (unsigned n = 1; n < MaxN; ++n) {
const T HermiteNext = std::experimental::hermite(n + 1, x);
const T HermiteNextRecurrence =
- T(2) * x * std::experimental::hermite(n, x) -
- T(2) * T(n) * std::experimental::hermite(n - 1, x);
+ T(2) * x * std::experimental::hermite(n, x) - T(2) * T(n) * std::experimental::hermite(n - 1, x);
const T Tolerance = AbsTolerance + std::abs(HermiteNext) * RelTolerance;
- const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
+ const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
if (std::isinf(HermiteNext))
break;
@@ -88,9 +83,9 @@ void testRecurrenceRelation(T x, T RelTolerance, T AbsTolerance) {
}
}
-template <class T> void testRecurrenceRelation(T RelTolerance, T AbsTolerance) {
- const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
- T(0.1), T(0.5), T(1.0)};
+template <class T>
+void testRecurrenceRelation(T RelTolerance, T AbsTolerance) {
+ const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0), T(0.1), T(0.5), T(1.0)};
for (T x : Samples)
testRecurrenceRelation(x, RelTolerance, AbsTolerance);
}
@@ -99,7 +94,8 @@ template <class T> void testRecurrenceRelation(T RelTolerance, T AbsTolerance) {
/// Salzer, Herbert E., Ruth Zucker, and Ruth Capuano.
/// Table of the zeros and weight factors of the first twenty Hermite
/// polynomials. US Government Printing Office, 1952.
-template <class T> std::vector<T> getHermiteRoots(unsigned n) {
+template <class T>
+std::vector<T> getHermiteRoots(unsigned n) {
if (n == 0u)
return {};
if (n == 1u)
@@ -107,40 +103,22 @@ template <class T> std::vector<T> getHermiteRoots(unsigned n) {
if (n == 2u)
return {T(0.707106781186548)};
if (n == 3u)
- return {T(0),
- T(1.224744871391589)};
+ return {T(0), T(1.224744871391589)};
if (n == 4u)
- return {T(0.524647623275290),
- T(1.650680123885785)};
+ return {T(0.524647623275290), T(1.650680123885785)};
if (n == 5u)
- return {T(0), T(0.958572464613819),
- T(2.020182870456086)};
+ return {T(0), T(0.958572464613819), T(2.020182870456086)};
if (n == 6u)
- return {T(0.436077411927617),
- T(1.335849074013697),
- T(2.350604973674492)};
+ return {T(0.436077411927617), T(1.335849074013697), T(2.350604973674492)};
if (n == 7u)
- return {T(0),
- T(0.816287882858965),
- T(1.673551628767471),
- T(2.651961356835233)};
+ return {T(0), T(0.816287882858965), T(1.673551628767471), T(2.651961356835233)};
if (n == 8u)
- return {T(0.381186990207322),
- T(1.157193712446780),
- T(1.981656756695843),
- T(2.930637420257244)};
+ return {T(0.381186990207322), T(1.157193712446780), T(1.981656756695843), T(2.930637420257244)};
if (n == 9u)
- return {T(0),
- T(0.723551018752838),
- T(1.468553289216668),
- T(2.266580584531843),
- T(3.190993201781528)};
+ return {T(0), T(0.723551018752838), T(1.468553289216668), T(2.266580584531843), T(3.190993201781528)};
if (n == 10u)
- return {T(0.342901327223705),
- T(1.036610829789514),
- T(1.756683649299882),
- T(2.532731674232790),
- T(3.436159118837738)};
+ return {
+ T(0.342901327223705), T(1.036610829789514), T(1.756683649299882), T(2.532731674232790), T(3.436159118837738)};
if (n == 11u)
return {T(0),
T(0.65680956682100),
@@ -244,7 +222,8 @@ template <class T> std::vector<T> getHermiteRoots(unsigned n) {
/// \param [in] Tolerance of the root. This value must be smaller than
/// the smallest difference between adjacent roots in the given range
/// with n <= 20.
-template <class T> void testHermiteRoots(T Tolerance) {
+template <class T>
+void testHermiteRoots(T Tolerance) {
for (unsigned n = 0; n <= 20u; ++n) {
const auto Roots = getHermiteRoots<T>(n);
for (T x : Roots) {
@@ -261,8 +240,7 @@ template <class T> void testHermiteRoots(T Tolerance) {
template <class T>
void testHermite(const T AbsTolerance, const T RelTolerance) {
testHermiteNaNPropagation<T>();
- const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0),
- T(0.1), T(0.5), T(1.0)};
+ const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0), T(0.1), T(0.5), T(1.0)};
for (T x : Samples) {
testHermiteNotNaN(x);
@@ -272,7 +250,7 @@ void testHermite(const T AbsTolerance, const T RelTolerance) {
#endif
-int main(int, char **) {
+int main(int, char**) {
#if _LIBCPP_STD_VER > 14
testHermite<float>(1e-6f, 1e-6f);
testHermite<double>(1e-9, 1e-9);
>From 98a943867a653f284c5c1b1a71cdef9c0bf12d8b Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Mon, 22 Apr 2024 13:31:39 +0200
Subject: [PATCH 23/76] cleanup preprocessor usage
---
libcxx/include/experimental/__math/hermite.h | 4 ++--
libcxx/include/experimental/math | 5 ++---
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index b95e7a084ff87..23bc7b452cdfe 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -15,9 +15,9 @@
#ifndef _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
#define _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
-#include <cmath>
+#include <cmath> // std::isnan
#include <experimental/__config>
-#include <limits>
+#include <limits> // std::numeric_limits
/// \return the hermite polynomial \f$ H_{n}(x) \f$
/// \note The implementation is based on the recurrence formula
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 604a573281666..3b0703fb4bca5 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -14,10 +14,9 @@
// to indicate conformance to the International Standard ISO/IEC JTC 1/SC 22/WG 21 N3060
// #define __STDCPP_MATH_SPEC_FUNCS__ 201003L
-#include <cmath>
#include <experimental/__config>
-#if _LIBCPP_STD_VER > 14
+#if _LIBCPP_STD_VER >= 17
# include <experimental/__math/hermite.h>
@@ -34,6 +33,6 @@ inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x)
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
-#endif // _LIBCPP_STD_VER > 14
+#endif // _LIBCPP_STD_VER >= 17
#endif // _LIBCPP_EXPERIMENTAL_MATH
>From 5ec76d7dcc7142c7cd87e31d7dbe3ea3c306dd05 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 23 Apr 2024 23:11:33 +0200
Subject: [PATCH 24/76] sufficient additional overloads by LWG 3234
---
libcxx/include/experimental/math | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 3b0703fb4bca5..5161381be0b61 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -24,12 +24,16 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __libcpp_hermite(__n, __x); }
-inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) {
+inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
// use double internally -- float is too prone to overflow!
return static_cast<float>(__libcpp_hermite(__n, static_cast<double>(__x)));
}
-inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
>From 2e9052979cb876adaf4486e01bcc5d78e22a5022 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 24 Apr 2024 15:13:21 +0200
Subject: [PATCH 25/76] simplify hermite(float)
---
libcxx/include/experimental/math | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 5161381be0b61..2c633ff32df6d 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -26,7 +26,7 @@ inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return _
inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
// use double internally -- float is too prone to overflow!
- return static_cast<float>(__libcpp_hermite(__n, static_cast<double>(__x)));
+ return static_cast<float>(hermite(__n, static_cast<double>(__x)));
}
inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
>From 349e5a69bd439970574e1b997fd3fa90d9509ea4 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 24 Apr 2024 15:14:04 +0200
Subject: [PATCH 26/76] implement: template<class Integer> double
hermite(unsigned, Integer)
---
libcxx/include/experimental/math | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 2c633ff32df6d..21cf2a00d92fe 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -19,6 +19,7 @@
#if _LIBCPP_STD_VER >= 17
# include <experimental/__math/hermite.h>
+# include <type_traits> // enable_if_t, is_integral_v
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
@@ -35,6 +36,12 @@ inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return he
inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
+template < class _Integer >
+_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
+ // use double internally -- see C++17 standard - 29.9.1.2.2
+ return hermite(__n, static_cast<double>(__x));
+}
+
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
#endif // _LIBCPP_STD_VER >= 17
>From b3a6ff535aecfa9e0250545695e2bd5374c3d5fe Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 24 Apr 2024 15:21:01 +0200
Subject: [PATCH 27/76] remove old comment
---
libcxx/include/experimental/math | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
index 21cf2a00d92fe..b7847d5037bb6 100644
--- a/libcxx/include/experimental/math
+++ b/libcxx/include/experimental/math
@@ -10,10 +10,6 @@
#ifndef _LIBCPP_EXPERIMENTAL_MATH
#define _LIBCPP_EXPERIMENTAL_MATH
-// The following macro name shall be conditionally defined by the implementation
-// to indicate conformance to the International Standard ISO/IEC JTC 1/SC 22/WG 21 N3060
-// #define __STDCPP_MATH_SPEC_FUNCS__ 201003L
-
#include <experimental/__config>
#if _LIBCPP_STD_VER >= 17
>From e5214cb398e1effb12b3b797768ceb02fd2ad795 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 24 Apr 2024 15:26:58 +0200
Subject: [PATCH 28/76] make use of Lit: // UNSUPPORTED: c++XX
---
libcxx/test/std/experimental/math/hermite.pass.cpp | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/libcxx/test/std/experimental/math/hermite.pass.cpp b/libcxx/test/std/experimental/math/hermite.pass.cpp
index 6347da68fe22d..27c25ffb737c7 100644
--- a/libcxx/test/std/experimental/math/hermite.pass.cpp
+++ b/libcxx/test/std/experimental/math/hermite.pass.cpp
@@ -14,7 +14,7 @@
#include <limits>
#include <vector>
-#if _LIBCPP_STD_VER > 14
+// UNSUPPORTED: c++03, c++11, c++14
template <class T>
void testHermiteNaNPropagation() {
@@ -248,10 +248,7 @@ void testHermite(const T AbsTolerance, const T RelTolerance) {
}
}
-#endif
-
int main(int, char**) {
-#if _LIBCPP_STD_VER > 14
testHermite<float>(1e-6f, 1e-6f);
testHermite<double>(1e-9, 1e-9);
testHermite<long double>(1e-12l, 1e-12l);
@@ -263,6 +260,6 @@ int main(int, char**) {
testHermiteRoots<float>(1e-6f);
testHermiteRoots<double>(1e-9);
testHermiteRoots<long double>(1e-10l);
-#endif
+
return 0;
}
>From 1854b838a57902d2cab29376667bd4065d24216c Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 24 Apr 2024 22:00:29 +0200
Subject: [PATCH 29/76] cleanup tests
---
.../std/experimental/math/hermite.pass.cpp | 88 +++++++++++++------
1 file changed, 63 insertions(+), 25 deletions(-)
diff --git a/libcxx/test/std/experimental/math/hermite.pass.cpp b/libcxx/test/std/experimental/math/hermite.pass.cpp
index 27c25ffb737c7..dc4f7163808eb 100644
--- a/libcxx/test/std/experimental/math/hermite.pass.cpp
+++ b/libcxx/test/std/experimental/math/hermite.pass.cpp
@@ -13,15 +13,21 @@
#include <iostream>
#include <limits>
#include <vector>
+#include <array>
+
+#include <assert_macros.h>
// UNSUPPORTED: c++03, c++11, c++14
+namespace {
+namespace ex = std::experimental;
+
template <class T>
void testHermiteNaNPropagation() {
const unsigned MaxN = 127;
const T x = std::numeric_limits<T>::quiet_NaN();
for (unsigned n = 0; n <= MaxN; ++n) {
- assert(std::isnan(std::experimental::hermite(n, x)));
+ assert(std::isnan(ex::hermite(n, x)));
}
}
@@ -30,7 +36,7 @@ void testHermiteNotNaN(const T x) {
assert(!std::isnan(x));
const unsigned MaxN = 127;
for (unsigned n = 0; n <= MaxN; ++n) {
- assert(!std::isnan(std::experimental::hermite(n, x)));
+ assert(!std::isnan(ex::hermite(n, x)));
}
}
@@ -55,12 +61,12 @@ void testHermiteAnalytic(const T x, const T AbsTolerance, const T RelTolerance)
const auto h4 = [](T y) { return (T(16) * y * y * y * y - T(48) * y * y + T(12)); };
const auto h5 = [](T y) { return y * (T(32) * y * y * y * y - T(160) * y * y + T(120)); };
- assert(compareFloatingPoint(std::experimental::hermite(0, x), h0(x)));
- assert(compareFloatingPoint(std::experimental::hermite(1, x), h1(x)));
- assert(compareFloatingPoint(std::experimental::hermite(2, x), h2(x)));
- assert(compareFloatingPoint(std::experimental::hermite(3, x), h3(x)));
- assert(compareFloatingPoint(std::experimental::hermite(4, x), h4(x)));
- assert(compareFloatingPoint(std::experimental::hermite(5, x), h5(x)));
+ assert(compareFloatingPoint(ex::hermite(0, x), h0(x)));
+ assert(compareFloatingPoint(ex::hermite(1, x), h1(x)));
+ assert(compareFloatingPoint(ex::hermite(2, x), h2(x)));
+ assert(compareFloatingPoint(ex::hermite(3, x), h3(x)));
+ assert(compareFloatingPoint(ex::hermite(4, x), h4(x)));
+ assert(compareFloatingPoint(ex::hermite(5, x), h5(x)));
}
/// \details This method checks if the following recurrence relation holds:
@@ -68,14 +74,13 @@ void testHermiteAnalytic(const T x, const T AbsTolerance, const T RelTolerance)
/// H_{n+1}(x) = 2x H_{n}(x) - 2n H_{n-1}(x)
/// \f]
template <class T>
-void testRecurrenceRelation(T x, T RelTolerance, T AbsTolerance) {
+void testRecurrenceRelation(T x, T AbsTolerance, T RelTolerance) {
const unsigned MaxN = 127;
for (unsigned n = 1; n < MaxN; ++n) {
- const T HermiteNext = std::experimental::hermite(n + 1, x);
- const T HermiteNextRecurrence =
- T(2) * x * std::experimental::hermite(n, x) - T(2) * T(n) * std::experimental::hermite(n - 1, x);
- const T Tolerance = AbsTolerance + std::abs(HermiteNext) * RelTolerance;
- const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
+ const T HermiteNext = ex::hermite(n + 1, x);
+ const T HermiteNextRecurrence = T(2) * (x * ex::hermite(n, x) - T(n) * ex::hermite(n - 1, x));
+ const T Tolerance = AbsTolerance + std::abs(HermiteNext) * RelTolerance;
+ const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
if (std::isinf(HermiteNext))
break;
@@ -84,10 +89,10 @@ void testRecurrenceRelation(T x, T RelTolerance, T AbsTolerance) {
}
template <class T>
-void testRecurrenceRelation(T RelTolerance, T AbsTolerance) {
+void testRecurrenceRelation(T AbsTolerance, T RelTolerance) {
const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0), T(0.1), T(0.5), T(1.0)};
for (T x : Samples)
- testRecurrenceRelation(x, RelTolerance, AbsTolerance);
+ testRecurrenceRelation(x, AbsTolerance, RelTolerance);
}
/// \note Roots are taken from
@@ -229,10 +234,8 @@ void testHermiteRoots(T Tolerance) {
for (T x : Roots) {
// the roots are symmetric: if x is a root, so is -x
if (x > T(0))
- assert(std::signbit(std::experimental::hermite(n, -x + Tolerance)) !=
- std::signbit(std::experimental::hermite(n, -x - Tolerance)));
- assert(std::signbit(std::experimental::hermite(n, x + Tolerance)) !=
- std::signbit(std::experimental::hermite(n, x - Tolerance)));
+ assert(std::signbit(ex::hermite(n, -x + Tolerance)) != std::signbit(ex::hermite(n, -x - Tolerance)));
+ assert(std::signbit(ex::hermite(n, x + Tolerance)) != std::signbit(ex::hermite(n, x - Tolerance)));
}
}
}
@@ -248,18 +251,53 @@ void testHermite(const T AbsTolerance, const T RelTolerance) {
}
}
+template <class Integer>
+void testHermiteByInteger() {
+ const unsigned nMax = 128;
+ for (unsigned n = 0; n < nMax; ++n)
+ for (Integer x : {-1, 0, 1})
+ assert(ex::hermite(n, x) == ex::hermite(n, static_cast<double>(x)));
+}
+
+void testHermiteF() {
+ const unsigned nMax = 128;
+ const std::array samples{-1.0f, -0.5f, -0.1f, 0.0f, 0.1f, 0.5f, 1.0f};
+
+ for (unsigned n = 0; n < nMax; ++n)
+ for (float x : samples)
+ assert(ex::hermite(n, x) == ex::hermitef(n, x));
+}
+
+void testHermiteL() {
+ const unsigned nMax = 128;
+ const std::array samples{-1.0l, -0.5l, -0.1l, 0.0l, 0.1l, 0.5l, 1.0l};
+
+ for (unsigned n = 0; n < nMax; ++n)
+ for (long double x : samples)
+ assert(ex::hermite(n, x) == ex::hermitel(n, x));
+}
+} // namespace
+
int main(int, char**) {
- testHermite<float>(1e-6f, 1e-6f);
- testHermite<double>(1e-9, 1e-9);
+ testHermite<float>(1e-5f, 1e-5f);
+ testHermite<double>(1e-11, 1e-11);
testHermite<long double>(1e-12l, 1e-12l);
- testRecurrenceRelation<float>(1e-6f, 1e-6f);
- testRecurrenceRelation<double>(1e-9, 1e-9);
+ testHermiteF();
+ testHermiteL();
+
+ testRecurrenceRelation<float>(1e-5f, 1e-5f);
+ testRecurrenceRelation<double>(1e-11, 1e-11);
testRecurrenceRelation<long double>(1e-12l, 1e-12l);
- testHermiteRoots<float>(1e-6f);
+ testHermiteRoots<float>(1e-5f);
testHermiteRoots<double>(1e-9);
testHermiteRoots<long double>(1e-10l);
+ testHermiteByInteger<short>();
+ testHermiteByInteger<int>();
+ testHermiteByInteger<long>();
+ testHermiteByInteger<long long>();
+
return 0;
}
>From 2c72621167ff4ac8c1e9e9f74193dfd40782a48b Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 24 Apr 2024 22:05:25 +0200
Subject: [PATCH 30/76] update docs/Status
---
libcxx/docs/Status/Cxx17Papers.csv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv
index 8952391afc83b..ea01c9eec1479 100644
--- a/libcxx/docs/Status/Cxx17Papers.csv
+++ b/libcxx/docs/Status/Cxx17Papers.csv
@@ -26,7 +26,7 @@
"`P0013R1 <https://wg21.link/p0013r1>`__","LWG","Logical type traits rev 2","Kona","|Complete|","3.8"
"","","","","",""
"`P0024R2 <https://wg21.link/P0024R2>`__","LWG","The Parallelism TS Should be Standardized","Jacksonville","|Partial|",""
-"`P0226R1 <https://wg21.link/P0226R1>`__","LWG","Mathematical Special Functions for C++17","Jacksonville","",""
+"`P0226R1 <https://wg21.link/P0226R1>`__","LWG","Mathematical Special Functions for C++17","Jacksonville","|In Progress|",""
"`P0220R1 <https://wg21.link/P0220R1>`__","LWG","Adopt Library Fundamentals V1 TS Components for C++17","Jacksonville","|Complete|","16.0"
"`P0218R1 <https://wg21.link/P0218R1>`__","LWG","Adopt the File System TS for C++17","Jacksonville","|Complete|","7.0"
"`P0033R1 <https://wg21.link/P0033R1>`__","LWG","Re-enabling shared_from_this","Jacksonville","|Complete|","3.9"
>From 20def2e3c3a5c7af41f9180e249a8df21ba72298 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Thu, 25 Apr 2024 15:05:21 +0200
Subject: [PATCH 31/76] modulemap include private headers
---
libcxx/include/module.modulemap | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index eb0e4de920ab9..9beb9c823a850 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -522,6 +522,8 @@ module std_experimental [system] {
export *
}
module math {
+ module hermite { private header "experimental/__math/hermite.h" }
+
header "experimental/math"
export *
}
>From a85b2bc71c075137926978ad5ab464dcd77f9171 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 14:32:31 +0200
Subject: [PATCH 32/76] remove doxygen style file comment
---
libcxx/include/experimental/__math/hermite.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
index 23bc7b452cdfe..7fecfae514131 100644
--- a/libcxx/include/experimental/__math/hermite.h
+++ b/libcxx/include/experimental/__math/hermite.h
@@ -6,11 +6,6 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file contains the internal implementations of std::hermite.
-///
-//===----------------------------------------------------------------------===//
#ifndef _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
#define _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
>From 94435bec53e4b1e54d948869cb6ba15012e4570f Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 22:33:58 +0200
Subject: [PATCH 33/76] move out of experimental/
---
libcxx/include/CMakeLists.txt | 2 -
libcxx/include/cmath | 47 +++++++++++++++++++
libcxx/include/experimental/__math/hermite.h | 44 -----------------
libcxx/include/experimental/math | 45 ------------------
libcxx/include/module.modulemap | 6 ---
.../math => numerics/c.math}/hermite.pass.cpp | 34 +++++++-------
6 files changed, 63 insertions(+), 115 deletions(-)
delete mode 100644 libcxx/include/experimental/__math/hermite.h
delete mode 100644 libcxx/include/experimental/math
rename libcxx/test/std/{experimental/math => numerics/c.math}/hermite.pass.cpp (88%)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 30c00e033fe1b..4ecd834c5382a 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -922,7 +922,6 @@ set(files
execution
expected
experimental/__config
- experimental/__math/hermite.h
experimental/__simd/aligned_tag.h
experimental/__simd/declaration.h
experimental/__simd/reference.h
@@ -933,7 +932,6 @@ set(files
experimental/__simd/utility.h
experimental/__simd/vec_ext.h
experimental/iterator
- experimental/math
experimental/memory
experimental/propagate_const
experimental/simd
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index dd194bbb55896..bf2009d1b453d 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -765,6 +765,53 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _
return __builtin_scalbn(__x, __exp);
}
+#if _LIBCPP_STD_VER >= 17
+
+/// \return the Hermite polynomial \f$ H_n(x) \f$
+/// \note The implementation is based on the recurrence formula
+/// \f[
+/// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}
+/// \f]
+/// Press, William H., et al. Numerical recipes 3rd edition: The art of
+/// scientific computing. Cambridge university press, 2007, p. 183.
+template <class _Real>
+_Real __libcpp_hermite(unsigned __n, _Real __x) {
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ if (0 == __n)
+ return 1;
+
+ _Real __H_nPrev{1};
+ _Real __H_n = 2 * __x;
+ for (unsigned __i = 1; __i < __n; ++__i) {
+ const _Real __H_nNext = 2 * (__x * __H_n - __i * __H_nPrev);
+ __H_nPrev = __H_n;
+ __H_n = __H_nNext;
+ }
+ return __H_n;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __libcpp_hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
+ // use double internally -- float is too prone to overflow!
+ return static_cast<float>(hermite(__n, static_cast<double>(__x)));
+}
+
+inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
+
+template < class _Integer >
+_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
+ // use double internally -- see C++17 standard - 29.9.1.2.2
+ return hermite(__n, static_cast<double>(__x));
+}
+#endif // _LIBCPP_STD_VER >= 17
+
#if _LIBCPP_STD_VER >= 20
template <typename _Fp>
_LIBCPP_HIDE_FROM_ABI constexpr _Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept {
diff --git a/libcxx/include/experimental/__math/hermite.h b/libcxx/include/experimental/__math/hermite.h
deleted file mode 100644
index 7fecfae514131..0000000000000
--- a/libcxx/include/experimental/__math/hermite.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
-#define _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
-
-#include <cmath> // std::isnan
-#include <experimental/__config>
-#include <limits> // std::numeric_limits
-
-/// \return the hermite polynomial \f$ H_{n}(x) \f$
-/// \note The implementation is based on the recurrence formula
-/// \f[
-/// H_{n+1}(x) = 2x H_{n}(x) - 2 n H_{n-1}
-/// \f]
-/// Press, William H., et al. Numerical recipes 3rd edition: The art of
-/// scientific computing. Cambridge university press, 2007, p. 183.
-template <class _Real>
-_Real __libcpp_hermite_recurrence(const unsigned __n, const _Real __x) {
- if (0 == __n)
- return 1;
-
- _Real __H_nPrev{1};
- _Real __H_n = 2 * __x;
- for (unsigned __i = 1; __i < __n; ++__i) {
- const _Real __H_nNext = 2 * (__x * __H_n - __i * __H_nPrev);
- __H_nPrev = __H_n;
- __H_n = __H_nNext;
- }
- return __H_n;
-}
-
-template <class _Real>
-_Real __libcpp_hermite(const unsigned __n, const _Real __x) {
- return std::isnan(__x) ? std::numeric_limits<_Real>::quiet_NaN() : __libcpp_hermite_recurrence(__n, __x);
-}
-
-#endif // _LIBCPP_EXPERIMENTAL___MATH_HERMITE_H
diff --git a/libcxx/include/experimental/math b/libcxx/include/experimental/math
deleted file mode 100644
index b7847d5037bb6..0000000000000
--- a/libcxx/include/experimental/math
+++ /dev/null
@@ -1,45 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP_EXPERIMENTAL_MATH
-#define _LIBCPP_EXPERIMENTAL_MATH
-
-#include <experimental/__config>
-
-#if _LIBCPP_STD_VER >= 17
-
-# include <experimental/__math/hermite.h>
-# include <type_traits> // enable_if_t, is_integral_v
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
-
-inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __libcpp_hermite(__n, __x); }
-
-inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
- // use double internally -- float is too prone to overflow!
- return static_cast<float>(hermite(__n, static_cast<double>(__x)));
-}
-
-inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
-
-inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return hermite(__n, __x); }
-
-inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
-
-template < class _Integer >
-_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
- // use double internally -- see C++17 standard - 29.9.1.2.2
- return hermite(__n, static_cast<double>(__x));
-}
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL
-
-#endif // _LIBCPP_STD_VER >= 17
-
-#endif // _LIBCPP_EXPERIMENTAL_MATH
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 9beb9c823a850..64652c8307c9e 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -521,12 +521,6 @@ module std_experimental [system] {
header "experimental/iterator"
export *
}
- module math {
- module hermite { private header "experimental/__math/hermite.h" }
-
- header "experimental/math"
- export *
- }
module memory {
header "experimental/memory"
export *
diff --git a/libcxx/test/std/experimental/math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
similarity index 88%
rename from libcxx/test/std/experimental/math/hermite.pass.cpp
rename to libcxx/test/std/numerics/c.math/hermite.pass.cpp
index dc4f7163808eb..1067f431dbff7 100644
--- a/libcxx/test/std/experimental/math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -9,7 +9,7 @@
// <experimental/cmath>
#include <cassert>
-#include <experimental/math>
+#include <cmath>
#include <iostream>
#include <limits>
#include <vector>
@@ -20,14 +20,12 @@
// UNSUPPORTED: c++03, c++11, c++14
namespace {
-namespace ex = std::experimental;
-
template <class T>
void testHermiteNaNPropagation() {
const unsigned MaxN = 127;
const T x = std::numeric_limits<T>::quiet_NaN();
for (unsigned n = 0; n <= MaxN; ++n) {
- assert(std::isnan(ex::hermite(n, x)));
+ assert(std::isnan(std::hermite(n, x)));
}
}
@@ -36,7 +34,7 @@ void testHermiteNotNaN(const T x) {
assert(!std::isnan(x));
const unsigned MaxN = 127;
for (unsigned n = 0; n <= MaxN; ++n) {
- assert(!std::isnan(ex::hermite(n, x)));
+ assert(!std::isnan(std::hermite(n, x)));
}
}
@@ -61,12 +59,12 @@ void testHermiteAnalytic(const T x, const T AbsTolerance, const T RelTolerance)
const auto h4 = [](T y) { return (T(16) * y * y * y * y - T(48) * y * y + T(12)); };
const auto h5 = [](T y) { return y * (T(32) * y * y * y * y - T(160) * y * y + T(120)); };
- assert(compareFloatingPoint(ex::hermite(0, x), h0(x)));
- assert(compareFloatingPoint(ex::hermite(1, x), h1(x)));
- assert(compareFloatingPoint(ex::hermite(2, x), h2(x)));
- assert(compareFloatingPoint(ex::hermite(3, x), h3(x)));
- assert(compareFloatingPoint(ex::hermite(4, x), h4(x)));
- assert(compareFloatingPoint(ex::hermite(5, x), h5(x)));
+ assert(compareFloatingPoint(std::hermite(0, x), h0(x)));
+ assert(compareFloatingPoint(std::hermite(1, x), h1(x)));
+ assert(compareFloatingPoint(std::hermite(2, x), h2(x)));
+ assert(compareFloatingPoint(std::hermite(3, x), h3(x)));
+ assert(compareFloatingPoint(std::hermite(4, x), h4(x)));
+ assert(compareFloatingPoint(std::hermite(5, x), h5(x)));
}
/// \details This method checks if the following recurrence relation holds:
@@ -77,8 +75,8 @@ template <class T>
void testRecurrenceRelation(T x, T AbsTolerance, T RelTolerance) {
const unsigned MaxN = 127;
for (unsigned n = 1; n < MaxN; ++n) {
- const T HermiteNext = ex::hermite(n + 1, x);
- const T HermiteNextRecurrence = T(2) * (x * ex::hermite(n, x) - T(n) * ex::hermite(n - 1, x));
+ const T HermiteNext = std::hermite(n + 1, x);
+ const T HermiteNextRecurrence = T(2) * (x * std::hermite(n, x) - T(n) * std::hermite(n - 1, x));
const T Tolerance = AbsTolerance + std::abs(HermiteNext) * RelTolerance;
const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
@@ -234,8 +232,8 @@ void testHermiteRoots(T Tolerance) {
for (T x : Roots) {
// the roots are symmetric: if x is a root, so is -x
if (x > T(0))
- assert(std::signbit(ex::hermite(n, -x + Tolerance)) != std::signbit(ex::hermite(n, -x - Tolerance)));
- assert(std::signbit(ex::hermite(n, x + Tolerance)) != std::signbit(ex::hermite(n, x - Tolerance)));
+ assert(std::signbit(std::hermite(n, -x + Tolerance)) != std::signbit(std::hermite(n, -x - Tolerance)));
+ assert(std::signbit(std::hermite(n, x + Tolerance)) != std::signbit(std::hermite(n, x - Tolerance)));
}
}
}
@@ -256,7 +254,7 @@ void testHermiteByInteger() {
const unsigned nMax = 128;
for (unsigned n = 0; n < nMax; ++n)
for (Integer x : {-1, 0, 1})
- assert(ex::hermite(n, x) == ex::hermite(n, static_cast<double>(x)));
+ assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
}
void testHermiteF() {
@@ -265,7 +263,7 @@ void testHermiteF() {
for (unsigned n = 0; n < nMax; ++n)
for (float x : samples)
- assert(ex::hermite(n, x) == ex::hermitef(n, x));
+ assert(std::hermite(n, x) == std::hermitef(n, x));
}
void testHermiteL() {
@@ -274,7 +272,7 @@ void testHermiteL() {
for (unsigned n = 0; n < nMax; ++n)
for (long double x : samples)
- assert(ex::hermite(n, x) == ex::hermitel(n, x));
+ assert(std::hermite(n, x) == std::hermitel(n, x));
}
} // namespace
>From be6b88c7f3d70ab5922e0f49477ac9e4ae380e6f Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 22:36:08 +0200
Subject: [PATCH 34/76] all functions need _LIBCPP_HIDE_FROM_API
---
libcxx/include/cmath | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index bf2009d1b453d..a4bc4c6f16fa5 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -775,7 +775,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _
/// Press, William H., et al. Numerical recipes 3rd edition: The art of
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
-_Real __libcpp_hermite(unsigned __n, _Real __x) {
+_LIBCPP_HIDE_FROM_ABI _Real __libcpp_hermite(unsigned __n, _Real __x) {
if (std::isnan(__x))
return std::numeric_limits<_Real>::quiet_NaN();
>From 33f4108d0468b70bdbf6ded73ee83e24a59bede3 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 22:40:19 +0200
Subject: [PATCH 35/76] remove `std::` similar to other surrounding code
---
libcxx/include/cmath | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index a4bc4c6f16fa5..0e35229ab0143 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -776,8 +776,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
_LIBCPP_HIDE_FROM_ABI _Real __libcpp_hermite(unsigned __n, _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
+ if (isnan(__x))
+ return numeric_limits<_Real>::quiet_NaN();
if (0 == __n)
return 1;
@@ -806,7 +806,7 @@ inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return he
inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
template < class _Integer >
-_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
+_LIBCPP_HIDE_FROM_ABI enable_if_t<is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
// use double internally -- see C++17 standard - 29.9.1.2.2
return hermite(__n, static_cast<double>(__x));
}
>From d1226cdd95646e1fd7cb2435c3ca0e004a6ad14c Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 22:42:32 +0200
Subject: [PATCH 36/76] include missing header: type_traits/is_integral
---
libcxx/include/cmath | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 0e35229ab0143..4172e7640caaa 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -309,6 +309,7 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_floating_point.h>
+#include <__type_traits/is_integral.h>
#include <__type_traits/is_same.h>
#include <__type_traits/promote.h>
#include <__type_traits/remove_cv.h>
>From e2e2da87bf5b5ade98eba92946eb23804fc7fa5a Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 22:48:20 +0200
Subject: [PATCH 37/76] test: place Lit comment correctly
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 1067f431dbff7..e26a4d9542da8 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// <experimental/cmath>
+// UNSUPPORTED: c++03, c++11, c++14
#include <cassert>
#include <cmath>
@@ -17,7 +17,6 @@
#include <assert_macros.h>
-// UNSUPPORTED: c++03, c++11, c++14
namespace {
template <class T>
>From c9fa9b4fdd63d1feb94e1d5fc29145649df01107 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 22:49:44 +0200
Subject: [PATCH 38/76] don't use yoda conditional
---
libcxx/include/cmath | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 4172e7640caaa..d21e3d56135a6 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -780,7 +780,7 @@ _LIBCPP_HIDE_FROM_ABI _Real __libcpp_hermite(unsigned __n, _Real __x) {
if (isnan(__x))
return numeric_limits<_Real>::quiet_NaN();
- if (0 == __n)
+ if (__n == 0)
return 1;
_Real __H_nPrev{1};
>From 947071a5777e6114c2b852f619b6e05e664e7071 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 23:09:36 +0200
Subject: [PATCH 39/76] edits according to mentioned style issues
---
libcxx/include/cmath | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index d21e3d56135a6..2e2745388e24e 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -780,15 +780,16 @@ _LIBCPP_HIDE_FROM_ABI _Real __libcpp_hermite(unsigned __n, _Real __x) {
if (isnan(__x))
return numeric_limits<_Real>::quiet_NaN();
+ _Real __H_0{1};
if (__n == 0)
- return 1;
+ return __H_0;
- _Real __H_nPrev{1};
- _Real __H_n = 2 * __x;
+ _Real __H_n_prev = __H_0;
+ _Real __H_n = 2 * __x;
for (unsigned __i = 1; __i < __n; ++__i) {
- const _Real __H_nNext = 2 * (__x * __H_n - __i * __H_nPrev);
- __H_nPrev = __H_n;
- __H_n = __H_nNext;
+ _Real __H_n_next = 2 * (__x * __H_n - __i * __H_n_prev);
+ __H_n_prev = __H_n;
+ __H_n = __H_n_next;
}
return __H_n;
}
>From 40404493dc222d161dd46853a295d2117b1d137b Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 23:13:19 +0200
Subject: [PATCH 40/76] shorten internal hermite function's name
---
libcxx/include/cmath | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 2e2745388e24e..072c4dc45eea9 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -776,7 +776,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _
/// Press, William H., et al. Numerical recipes 3rd edition: The art of
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
-_LIBCPP_HIDE_FROM_ABI _Real __libcpp_hermite(unsigned __n, _Real __x) {
+_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
if (isnan(__x))
return numeric_limits<_Real>::quiet_NaN();
@@ -794,14 +794,14 @@ _LIBCPP_HIDE_FROM_ABI _Real __libcpp_hermite(unsigned __n, _Real __x) {
return __H_n;
}
-inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __libcpp_hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __hermite(__n, __x); }
inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
// use double internally -- float is too prone to overflow!
return static_cast<float>(hermite(__n, static_cast<double>(__x)));
}
-inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __libcpp_hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __hermite(__n, __x); }
inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return hermite(__n, __x); }
>From d4debd5f7751154cca1271c7f6a0c0979ed0c52b Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Fri, 26 Apr 2024 23:16:25 +0200
Subject: [PATCH 41/76] style format of template argument
---
libcxx/include/cmath | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 072c4dc45eea9..c2c5829652987 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -807,7 +807,7 @@ inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return he
inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
-template < class _Integer >
+template <class _Integer>
_LIBCPP_HIDE_FROM_ABI enable_if_t<is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
// use double internally -- see C++17 standard - 29.9.1.2.2
return hermite(__n, static_cast<double>(__x));
>From 925349eced1575b1d3fbe1442b68ffc79d4f9f9b Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sat, 27 Apr 2024 12:45:41 +0200
Subject: [PATCH 42/76] fully qualify function calls
---
libcxx/include/cmath | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index c2c5829652987..f54ffa903f2b9 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -777,8 +777,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _
/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
- if (isnan(__x))
- return numeric_limits<_Real>::quiet_NaN();
+ if (std::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
_Real __H_0{1};
if (__n == 0)
@@ -794,23 +794,23 @@ _LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
return __H_n;
}
-inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return __hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return std::__hermite(__n, __x); }
inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
// use double internally -- float is too prone to overflow!
- return static_cast<float>(hermite(__n, static_cast<double>(__x)));
+ return static_cast<float>(std::hermite(__n, static_cast<double>(__x)));
}
-inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return __hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return std::__hermite(__n, __x); }
-inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return std::hermite(__n, __x); }
-inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return hermite(__n, __x); }
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return std::hermite(__n, __x); }
template <class _Integer>
-_LIBCPP_HIDE_FROM_ABI enable_if_t<is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
+_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
// use double internally -- see C++17 standard - 29.9.1.2.2
- return hermite(__n, static_cast<double>(__x));
+ return std::hermite(__n, static_cast<double>(__x));
}
#endif // _LIBCPP_STD_VER >= 17
>From be9c82e4313161d850a066817ea85f2f23e20725 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sat, 27 Apr 2024 22:32:02 +0200
Subject: [PATCH 43/76] test: style changes, renaming, etc.
---
.../test/std/numerics/c.math/hermite.pass.cpp | 236 +++++++++---------
1 file changed, 123 insertions(+), 113 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index e26a4d9542da8..397046219bb1f 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -10,86 +10,95 @@
#include <cassert>
#include <cmath>
-#include <iostream>
#include <limits>
#include <vector>
#include <array>
#include <assert_macros.h>
-
namespace {
+
+inline constexpr unsigned MAX_N = 128;
+
template <class T>
-void testHermiteNaNPropagation() {
- const unsigned MaxN = 127;
- const T x = std::numeric_limits<T>::quiet_NaN();
- for (unsigned n = 0; n <= MaxN; ++n) {
- assert(std::isnan(std::hermite(n, x)));
- }
+std::array<T, 7> sample_points() {
+ return {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0};
+}
+
+template <class T>
+void test_NaN_propagation() {
+ T NaN = std::numeric_limits<T>::quiet_NaN();
+ for (unsigned n = 0; n < MAX_N; ++n)
+ assert(std::isnan(std::hermite(n, NaN)));
}
template <class T>
-void testHermiteNotNaN(const T x) {
+void test_not_NaN(T x) {
assert(!std::isnan(x));
- const unsigned MaxN = 127;
- for (unsigned n = 0; n <= MaxN; ++n) {
+ for (unsigned n = 0; n < MAX_N; ++n)
assert(!std::isnan(std::hermite(n, x)));
- }
}
template <class T>
-void testHermiteAnalytic(const T x, const T AbsTolerance, const T RelTolerance) {
- assert(!std::isnan(x));
- const auto compareFloatingPoint = [AbsTolerance, RelTolerance](const T Result, const T Expected) {
- if (std::isinf(Expected) && std::isinf(Result))
+struct CompareFloatingValues {
+ T abs_tol;
+ T rel_tol;
+
+ bool operator()(T result, T expected) const {
+ if (std::isinf(expected) && std::isinf(result))
return true;
- if (std::isnan(Expected) || std::isnan(Result))
+ if (std::isnan(expected) || std::isnan(result))
return false;
- const T Tolerance = AbsTolerance + std::abs(Expected) * RelTolerance;
- return std::abs(Result - Expected) < Tolerance;
- };
+ T tol = abs_tol + std::abs(expected) * rel_tol;
+ return std::abs(result - expected) < tol;
+ }
+};
+
+template <class T>
+void test_analytic_solution(T x, T abs_tol, T rel_tol) {
+ assert(!std::isnan(x));
- const auto h0 = [](T) { return T(1); };
- const auto h1 = [](T y) { return T(2) * y; };
- const auto h2 = [](T y) { return T(4) * y * y - T(2); };
- const auto h3 = [](T y) { return y * (T(8) * y * y - T(12)); };
- const auto h4 = [](T y) { return (T(16) * y * y * y * y - T(48) * y * y + T(12)); };
- const auto h5 = [](T y) { return y * (T(32) * y * y * y * y - T(160) * y * y + T(120)); };
-
- assert(compareFloatingPoint(std::hermite(0, x), h0(x)));
- assert(compareFloatingPoint(std::hermite(1, x), h1(x)));
- assert(compareFloatingPoint(std::hermite(2, x), h2(x)));
- assert(compareFloatingPoint(std::hermite(3, x), h3(x)));
- assert(compareFloatingPoint(std::hermite(4, x), h4(x)));
- assert(compareFloatingPoint(std::hermite(5, x), h5(x)));
+ const auto h0 = [](T) -> T { return 1; };
+ const auto h1 = [](T y) -> T { return 2 * y; };
+ const auto h2 = [](T y) -> T { return 4 * y * y - 2; };
+ const auto h3 = [](T y) -> T { return y * (8 * y * y - 12); };
+ const auto h4 = [](T y) -> T { return (16 * std::pow(y, 4) - 48 * y * y + 12); };
+ const auto h5 = [](T y) -> T { return y * (32 * std::pow(y, 4) - 160 * y * y + 120); };
+
+ const CompareFloatingValues<T> compare{.abs_tol = abs_tol, .rel_tol = rel_tol};
+ assert(compare(std::hermite(0, x), h0(x)));
+ assert(compare(std::hermite(1, x), h1(x)));
+ assert(compare(std::hermite(2, x), h2(x)));
+ assert(compare(std::hermite(3, x), h3(x)));
+ assert(compare(std::hermite(4, x), h4(x)));
+ assert(compare(std::hermite(5, x), h5(x)));
}
/// \details This method checks if the following recurrence relation holds:
/// \f[
-/// H_{n+1}(x) = 2x H_{n}(x) - 2n H_{n-1}(x)
+/// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
/// \f]
template <class T>
-void testRecurrenceRelation(T x, T AbsTolerance, T RelTolerance) {
- const unsigned MaxN = 127;
- for (unsigned n = 1; n < MaxN; ++n) {
- const T HermiteNext = std::hermite(n + 1, x);
- const T HermiteNextRecurrence = T(2) * (x * std::hermite(n, x) - T(n) * std::hermite(n - 1, x));
- const T Tolerance = AbsTolerance + std::abs(HermiteNext) * RelTolerance;
- const T Error = std::abs(HermiteNextRecurrence - HermiteNext);
-
- if (std::isinf(HermiteNext))
+void test_recurrence_relation(T x, T abs_tol, T rel_tol) {
+ assert(!std::isnan(x));
+
+ const CompareFloatingValues<T> compare{.abs_tol = abs_tol, .rel_tol = rel_tol};
+ for (unsigned n = 1; n < MAX_N - 1; ++n) {
+ T H_next = std::hermite(n + 1, x);
+ T H_next_recurrence = 2 * (x * std::hermite(n, x) - n * std::hermite(n - 1, x));
+
+ if (std::isinf(H_next))
break;
- assert(Error < Tolerance);
+ assert(compare(H_next, H_next_recurrence));
}
}
template <class T>
-void testRecurrenceRelation(T AbsTolerance, T RelTolerance) {
- const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0), T(0.1), T(0.5), T(1.0)};
- for (T x : Samples)
- testRecurrenceRelation(x, AbsTolerance, RelTolerance);
+void test_recurrence_relation(T abs_tol, T rel_tol) {
+ for (T x : sample_points<T>())
+ test_recurrence_relation(x, abs_tol, rel_tol);
}
/// \note Roots are taken from
@@ -97,31 +106,32 @@ void testRecurrenceRelation(T AbsTolerance, T RelTolerance) {
/// Table of the zeros and weight factors of the first twenty Hermite
/// polynomials. US Government Printing Office, 1952.
template <class T>
-std::vector<T> getHermiteRoots(unsigned n) {
- if (n == 0u)
+std::vector<T> get_roots(unsigned n) {
+ switch (n) {
+ case 0:
return {};
- if (n == 1u)
+ case 1:
return {T(0)};
- if (n == 2u)
+ case 2:
return {T(0.707106781186548)};
- if (n == 3u)
+ case 3:
return {T(0), T(1.224744871391589)};
- if (n == 4u)
+ case 4:
return {T(0.524647623275290), T(1.650680123885785)};
- if (n == 5u)
+ case 5:
return {T(0), T(0.958572464613819), T(2.020182870456086)};
- if (n == 6u)
+ case 6:
return {T(0.436077411927617), T(1.335849074013697), T(2.350604973674492)};
- if (n == 7u)
+ case 7:
return {T(0), T(0.816287882858965), T(1.673551628767471), T(2.651961356835233)};
- if (n == 8u)
+ case 8:
return {T(0.381186990207322), T(1.157193712446780), T(1.981656756695843), T(2.930637420257244)};
- if (n == 9u)
+ case 9:
return {T(0), T(0.723551018752838), T(1.468553289216668), T(2.266580584531843), T(3.190993201781528)};
- if (n == 10u)
+ case 10:
return {
T(0.342901327223705), T(1.036610829789514), T(1.756683649299882), T(2.532731674232790), T(3.436159118837738)};
- if (n == 11u)
+ case 11:
return {T(0),
T(0.65680956682100),
T(1.326557084494933),
@@ -129,7 +139,7 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(2.783290099781652),
T(3.668470846559583)};
- if (n == 12u)
+ case 12:
return {T(0.314240376254359),
T(0.947788391240164),
T(1.597682635152605),
@@ -137,7 +147,7 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.020637025120890),
T(3.889724897869782)};
- if (n == 13u)
+ case 13:
return {T(0),
T(0.605763879171060),
T(1.220055036590748),
@@ -146,7 +156,7 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.246608978372410),
T(4.101337596178640)};
- if (n == 14u)
+ case 14:
return {T(0.29174551067256),
T(0.87871378732940),
T(1.47668273114114),
@@ -155,7 +165,7 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.46265693360227),
T(4.30444857047363)};
- if (n == 15u)
+ case 15:
return {T(0.00000000000000),
T(0.56506958325558),
T(1.13611558521092),
@@ -165,7 +175,7 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.66995037340445),
T(4.49999070730939)};
- if (n == 16u)
+ case 16:
return {T(0.27348104613815),
T(0.82295144914466),
T(1.38025853919888),
@@ -175,7 +185,7 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.86944790486012),
T(4.68873893930582)};
- if (n == 17u)
+ case 17:
return {T(0),
T(0.5316330013427),
T(1.0676487257435),
@@ -185,7 +195,8 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.3789320911415),
T(4.0619466758755),
T(4.8713451936744)};
- if (n == 18u)
+
+ case 18:
return {T(0.2582677505191),
T(0.7766829192674),
T(1.3009208583896),
@@ -195,7 +206,8 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.5737690684863),
T(4.2481178735681),
T(5.0483640088745)};
- if (n == 19u)
+
+ case 19:
return {T(0),
T(0.5035201634239),
T(1.0103683871343),
@@ -206,7 +218,8 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(3.7621873519640),
T(4.4285328066038),
T(5.2202716905375)};
- if (n == 20u)
+
+ case 20:
return {T(0.2453407083009),
T(0.7374737285454),
T(1.2340762153953),
@@ -218,83 +231,80 @@ std::vector<T> getHermiteRoots(unsigned n) {
T(4.6036824495507),
T(5.3874808900112)};
- return {};
+ default:
+ throw "Roots of Hermite polynomial of order " + std::to_string(n) + " not implemented!\n";
+ }
}
/// \param [in] Tolerance of the root. This value must be smaller than
/// the smallest difference between adjacent roots in the given range
/// with n <= 20.
template <class T>
-void testHermiteRoots(T Tolerance) {
+void test_roots(T Tolerance) {
+ const auto is_sign_change = [Tolerance](unsigned n, T x) -> bool {
+ return std::hermite(n, x - Tolerance) * std::hermite(n, x + Tolerance) < 0;
+ };
+
for (unsigned n = 0; n <= 20u; ++n) {
- const auto Roots = getHermiteRoots<T>(n);
- for (T x : Roots) {
+ for (T x : get_roots<T>(n)) {
// the roots are symmetric: if x is a root, so is -x
- if (x > T(0))
- assert(std::signbit(std::hermite(n, -x + Tolerance)) != std::signbit(std::hermite(n, -x - Tolerance)));
- assert(std::signbit(std::hermite(n, x + Tolerance)) != std::signbit(std::hermite(n, x - Tolerance)));
+ if (x > 0)
+ assert(is_sign_change(n, -x));
+ assert(is_sign_change(n, x));
}
}
}
template <class T>
-void testHermite(const T AbsTolerance, const T RelTolerance) {
- testHermiteNaNPropagation<T>();
- const T Samples[] = {T(-1.0), T(-0.5), T(-0.1), T(0.0), T(0.1), T(0.5), T(1.0)};
+void test_hermite(T abs_tol, T rel_tol) {
+ test_NaN_propagation<T>();
- for (T x : Samples) {
- testHermiteNotNaN(x);
- testHermiteAnalytic(x, AbsTolerance, RelTolerance);
+ for (T x : sample_points<T>()) {
+ test_not_NaN(x);
+ test_analytic_solution(x, abs_tol, rel_tol);
}
}
template <class Integer>
-void testHermiteByInteger() {
- const unsigned nMax = 128;
- for (unsigned n = 0; n < nMax; ++n)
+void test_integers() {
+ for (unsigned n = 0; n < MAX_N; ++n)
for (Integer x : {-1, 0, 1})
assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
}
-void testHermiteF() {
- const unsigned nMax = 128;
- const std::array samples{-1.0f, -0.5f, -0.1f, 0.0f, 0.1f, 0.5f, 1.0f};
-
- for (unsigned n = 0; n < nMax; ++n)
- for (float x : samples)
+void test_hermitef() {
+ for (unsigned n = 0; n < MAX_N; ++n)
+ for (float x : sample_points<float>())
assert(std::hermite(n, x) == std::hermitef(n, x));
}
-void testHermiteL() {
- const unsigned nMax = 128;
- const std::array samples{-1.0l, -0.5l, -0.1l, 0.0l, 0.1l, 0.5l, 1.0l};
-
- for (unsigned n = 0; n < nMax; ++n)
- for (long double x : samples)
+void test_hermitel() {
+ for (unsigned n = 0; n < MAX_N; ++n)
+ for (long double x : sample_points<long double>())
assert(std::hermite(n, x) == std::hermitel(n, x));
}
} // namespace
int main(int, char**) {
- testHermite<float>(1e-5f, 1e-5f);
- testHermite<double>(1e-11, 1e-11);
- testHermite<long double>(1e-12l, 1e-12l);
+ test_hermite<float>(1e-5f, 1e-5f);
+ test_hermite<double>(1e-11, 1e-11);
+ test_hermite<long double>(1e-12l, 1e-12l);
- testHermiteF();
- testHermiteL();
+ test_hermitef();
+ test_hermitel();
- testRecurrenceRelation<float>(1e-5f, 1e-5f);
- testRecurrenceRelation<double>(1e-11, 1e-11);
- testRecurrenceRelation<long double>(1e-12l, 1e-12l);
+ test_recurrence_relation<float>(1e-5f, 1e-5f);
+ test_recurrence_relation<double>(1e-11, 1e-11);
+ test_recurrence_relation<long double>(1e-12l, 1e-12l);
- testHermiteRoots<float>(1e-5f);
- testHermiteRoots<double>(1e-9);
- testHermiteRoots<long double>(1e-10l);
+ test_roots<float>(1e-5f);
+ test_roots<double>(1e-9);
+ test_roots<long double>(1e-10l);
- testHermiteByInteger<short>();
- testHermiteByInteger<int>();
- testHermiteByInteger<long>();
- testHermiteByInteger<long long>();
+ test_integers<short>();
+ test_integers<int>();
+ test_integers<long>();
+ test_integers<long long>();
return 0;
}
>From 18a320a0f523d1939262d1cfc633da6e5fae4870 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sun, 28 Apr 2024 15:18:05 +0200
Subject: [PATCH 44/76] status page
---
libcxx/docs/Status/SpecialMath.rst | 37 ++++++++++++++++++++++
libcxx/docs/Status/SpecialMathPapers.csv | 2 ++
libcxx/docs/Status/SpecialMathProjects.csv | 22 +++++++++++++
3 files changed, 61 insertions(+)
create mode 100644 libcxx/docs/Status/SpecialMath.rst
create mode 100644 libcxx/docs/Status/SpecialMathPapers.csv
create mode 100644 libcxx/docs/Status/SpecialMathProjects.csv
diff --git a/libcxx/docs/Status/SpecialMath.rst b/libcxx/docs/Status/SpecialMath.rst
new file mode 100644
index 0000000000000..28045f3290fdd
--- /dev/null
+++ b/libcxx/docs/Status/SpecialMath.rst
@@ -0,0 +1,37 @@
+.. special-math-status:
+
+======================================================
+libc++ Mathematical Special Functions Status (P0226R1)
+======================================================
+
+.. include:: ../Helpers/Styles.rst
+
+.. contents::
+ :local:
+
+Overview
+========
+
+This document contains the status of the C++17 mathematical special functions implementation in libc++.
+It is used to track both the status of the sub-projects of the effort and who is assigned to these sub-projects.
+This avoids duplicating effort.
+
+If you are interested in contributing to this effort, please send a message
+to the #libcxx channel in the LLVM discord. Please *do not* start working
+on any items below that has already been assigned to someone else.
+
+Sub-projects in the Implementation Effort
+=========================================
+
+.. csv-table::
+ :file: SpecialMathProjects.csv
+ :header-rows: 1
+ :widths: auto
+
+Paper and Issue Status
+======================
+
+.. csv-table::
+ :file: SpecialMathPapers.csv
+ :header-rows: 1
+ :widths: auto
diff --git a/libcxx/docs/Status/SpecialMathPapers.csv b/libcxx/docs/Status/SpecialMathPapers.csv
new file mode 100644
index 0000000000000..be00c63e6fe3f
--- /dev/null
+++ b/libcxx/docs/Status/SpecialMathPapers.csv
@@ -0,0 +1,2 @@
+Number,Name,Standard,Assignee,Status,First released version
+`P0226 <https://wg21.link/P0226>`_,"Mathematical Special Functions for C++17","C++17",,"|In Progress|"
diff --git a/libcxx/docs/Status/SpecialMathProjects.csv b/libcxx/docs/Status/SpecialMathProjects.csv
new file mode 100644
index 0000000000000..57be6c746c590
--- /dev/null
+++ b/libcxx/docs/Status/SpecialMathProjects.csv
@@ -0,0 +1,22 @@
+Section,Description,Assignee,Complete
+| `[sf.cmath.assoc.laguerre] <https://wg21.link/sf.cmath.assoc.laguerre>`_, std::assoc_laguerre, None, |Not Started|
+| `[sf.cmath.assoc.legendre] <https://wg21.link/sf.cmath.assoc.legendre>`_, std::assoc_legendre, None, |Not Started|
+| `[sf.cmath.beta] <https://wg21.link/sf.cmath.beta>`_, std::beta, None, |Not Started|
+| `[sf.cmath.comp.ellint.1] <https://wg21.link/sf.cmath.comp.ellint.1>`_, std::comp_ellint_1, None, |Not Started|
+| `[sf.cmath.comp.ellint.2] <https://wg21.link/sf.cmath.comp.ellint.2>`_, std::comp_ellint_2, None, |Not Started|
+| `[sf.cmath.comp.ellint.3] <https://wg21.link/sf.cmath.comp.ellint.3>`_, std::comp_ellint_3, None, |Not Started|
+| `[sf.cmath.cyl.bessel.i] <https://wg21.link/sf.cmath.cyl.bessel.i>`_, std::cyl_bessel_i, None, |Not Started|
+| `[sf.cmath.cyl.bessel.j] <https://wg21.link/sf.cmath.cyl.bessel.j>`_, std::cyl_bessel_j, None, |Not Started|
+| `[sf.cmath.cyl.bessel.k] <https://wg21.link/sf.cmath.cyl.bessel.k>`_, std::cyl_bessel_k, None, |Not Started|
+| `[sf.cmath.cyl.neumann] <https://wg21.link/sf.cmath.cyl.neumann>`_, std::cyl_neumann, None, |Not Started|
+| `[sf.cmath.ellint.1] <https://wg21.link/sf.cmath.ellint.1>`_, std::ellint_1, None, |Not Started|
+| `[sf.cmath.ellint.2] <https://wg21.link/sf.cmath.ellint.2>`_, std::ellint_2, None, |Not Started|
+| `[sf.cmath.ellint.3] <https://wg21.link/sf.cmath.ellint.3>`_, std::ellint_3, None, |Not Started|
+| `[sf.cmath.expint] <https://wg21.link/sf.cmath.expint>`_, std::expint, None, |Not Started|
+| `[sf.cmath.hermite] <https://wg21.link/sf.cmath.hermite>`_, std::hermite, None, |Complete|
+| `[sf.cmath.laguerre] <https://wg21.link/sf.cmath.laguerre>`_, std::laguerre, None, |Not Started|
+| `[sf.cmath.legendre] <https://wg21.link/sf.cmath.legendre>`_, std::legendre, None, |Not Started|
+| `[sf.cmath.riemann.zeta] <https://wg21.link/sf.cmath.riemann.zeta>`_, std::riemann_zeta, None, |Not Started|
+| `[sf.cmath.sph.bessel] <https://wg21.link/sf.cmath.sph.bessel>`_, std::sph_bessel, None, |Not Started|
+| `[sf.cmath.sph.legendre] <https://wg21.link/sf.cmath.sph.legendre>`_, std::sph_legendre, None, |Not Started|
+| `[sf.cmath.sph.neumann] <https://wg21.link/sf.cmath.sph.neumann>`_, std::sph_neumann, None, |Not Started|
>From fc667d6e28dc4b4ec139d42cc36bb2b1414f879a Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sun, 28 Apr 2024 15:21:44 +0200
Subject: [PATCH 45/76] remove dead code: lit header comments
---
libcxx/utils/libcxx/header_information.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index 690458887460a..bccae353b0c6b 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -56,7 +56,6 @@
"cwchar": "// UNSUPPORTED: no-wide-characters",
"cwctype": "// UNSUPPORTED: no-wide-characters",
"experimental/iterator": "// UNSUPPORTED: c++03",
- "experimental/math": "// UNSUPPORTED: c++03, c++11, c++14",
"experimental/propagate_const": "// UNSUPPORTED: c++03",
"experimental/simd": "// UNSUPPORTED: c++03",
"experimental/type_traits": "// UNSUPPORTED: c++03",
>From ca87828caa9ce8ed32203f9ddd9e9203c3e630d9 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sun, 28 Apr 2024 15:23:27 +0200
Subject: [PATCH 46/76] remove comment about integer->double conversion
---
libcxx/include/cmath | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index f54ffa903f2b9..10f3f75c44c8c 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -809,7 +809,6 @@ inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x)
template <class _Integer>
_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
- // use double internally -- see C++17 standard - 29.9.1.2.2
return std::hermite(__n, static_cast<double>(__x));
}
#endif // _LIBCPP_STD_VER >= 17
>From 3b947d166c12ec210bbb448c4fd69fac9e7efc10 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sun, 28 Apr 2024 19:36:20 +0200
Subject: [PATCH 47/76] specify implementation-defined behavior: hermite(n,x)
for n>=128
---
libcxx/docs/ImplementationDefinedBehavior.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/libcxx/docs/ImplementationDefinedBehavior.rst b/libcxx/docs/ImplementationDefinedBehavior.rst
index 3000bb7cfa468..f0ef733fc2c55 100644
--- a/libcxx/docs/ImplementationDefinedBehavior.rst
+++ b/libcxx/docs/ImplementationDefinedBehavior.rst
@@ -51,6 +51,17 @@ Libc++ determines that a stream is Unicode-capable terminal by:
<http://eel.is/c++draft/print.fun#7>`_. This function is used for other
``std::print`` overloads that don't take an ``ostream&`` argument.
+`[sf.cmath] <https://wg21.link/sf.cmath>`_ Mathematical Special Functions: Large indices
+----------------------------------------------------------------------------------------
+
+Most functions within the Mathematical Special Functions section contain integral indices.
+The Standard specifies the result for larger indices as implementation-defined.
+Libc++ pursuits reasonable results by choosing the same formulas as for indices below that threshold.
+E.g.
+
+- ``std::hermite(unsigned n, T x)`` for ``n >= 128``
+
+
Listed in the index of implementation-defined behavior
======================================================
>From 51f82a50b9007edbb000cfcdcc353dfc28cb8ab2 Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sun, 28 Apr 2024 22:08:11 +0200
Subject: [PATCH 48/76] hermite(unsigned, _Integer): changed SFINAE usage
---
libcxx/include/cmath | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 10f3f75c44c8c..677e0a6588887 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -807,8 +807,8 @@ inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return st
inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return std::hermite(__n, __x); }
-template <class _Integer>
-_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
+template <class _Integer, std::enable_if_t<std::is_integral_v<_Integer>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, _Integer __x) {
return std::hermite(__n, static_cast<double>(__x));
}
#endif // _LIBCPP_STD_VER >= 17
>From 1c99003d0810f817ebbc44e8549e2e847714cf5a Mon Sep 17 00:00:00 2001
From: Paul <>
Date: Sun, 28 Apr 2024 23:05:55 +0200
Subject: [PATCH 49/76] link status page from general C++17 status page
---
libcxx/docs/Status/Cxx17.rst | 1 +
libcxx/docs/Status/Cxx17Papers.csv | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/Cxx17.rst b/libcxx/docs/Status/Cxx17.rst
index 99bfc7da962bd..48e6e248ff290 100644
--- a/libcxx/docs/Status/Cxx17.rst
+++ b/libcxx/docs/Status/Cxx17.rst
@@ -41,6 +41,7 @@ Paper Status
.. note::
.. [#note-P0067] P0067: ``std::(to|from)_chars`` for integrals has been available since version 7.0. ``std::to_chars`` for ``float`` and ``double`` since version 14.0 ``std::to_chars`` for ``long double`` uses the implementation for ``double``.
+ .. [#note-P0226] P0226: Progress is tracked `here <https://https://libcxx.llvm.org/Status/SpecialMath.html>`_.
.. [#note-P0607] P0607: The parts of P0607 that are not done are the ``<regex>`` bits.
.. [#note-P0154] P0154: This is currently not implemented for clang because clang does not implement the required macros.
.. [#note-P0452] P0452: The changes to ``std::transform_inclusive_scan`` and ``std::transform_exclusive_scan`` have not yet been implemented.
diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv
index ea01c9eec1479..694e8a6376407 100644
--- a/libcxx/docs/Status/Cxx17Papers.csv
+++ b/libcxx/docs/Status/Cxx17Papers.csv
@@ -26,7 +26,7 @@
"`P0013R1 <https://wg21.link/p0013r1>`__","LWG","Logical type traits rev 2","Kona","|Complete|","3.8"
"","","","","",""
"`P0024R2 <https://wg21.link/P0024R2>`__","LWG","The Parallelism TS Should be Standardized","Jacksonville","|Partial|",""
-"`P0226R1 <https://wg21.link/P0226R1>`__","LWG","Mathematical Special Functions for C++17","Jacksonville","|In Progress|",""
+"`P0226R1 <https://wg21.link/P0226R1>`__","LWG","Mathematical Special Functions for C++17","Jacksonville","|In Progress| [#note-P0226]_",""
"`P0220R1 <https://wg21.link/P0220R1>`__","LWG","Adopt Library Fundamentals V1 TS Components for C++17","Jacksonville","|Complete|","16.0"
"`P0218R1 <https://wg21.link/P0218R1>`__","LWG","Adopt the File System TS for C++17","Jacksonville","|Complete|","7.0"
"`P0033R1 <https://wg21.link/P0033R1>`__","LWG","Re-enabling shared_from_this","Jacksonville","|Complete|","3.9"
>From 8cf1c8585c95e8eec0315d6b1e6419ed5f63ba0f Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 20:42:39 +0200
Subject: [PATCH 50/76] move implementation from include/cmath to
include/__math/special_functions.h
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__math/special_functions.h | 74 +++++++++++++++++++++++
libcxx/include/cmath | 49 +--------------
libcxx/include/module.modulemap | 1 +
4 files changed, 77 insertions(+), 48 deletions(-)
create mode 100644 libcxx/include/__math/special_functions.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 4ecd834c5382a..5c523a56ba991 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -515,6 +515,7 @@ set(files
__math/remainder.h
__math/roots.h
__math/rounding_functions.h
+ __math/special_functions.h
__math/traits.h
__math/trigonometric_functions.h
__mbstate_t.h
diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h
new file mode 100644
index 0000000000000..ee82a76940e4b
--- /dev/null
+++ b/libcxx/include/__math/special_functions.h
@@ -0,0 +1,74 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MATH_SPECIAL_FUNCTIONS_H
+#define _LIBCPP___MATH_SPECIAL_FUNCTIONS_H
+
+#include <__config>
+#include <__math/traits.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_integral.h>
+#include <limits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 17
+
+/// \return the Hermite polynomial \f$ H_n(x) \f$
+/// \note The implementation is based on the recurrence formula
+/// \f[
+/// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}
+/// \f]
+/// Press, William H., et al. Numerical recipes 3rd edition: The art of
+/// scientific computing. Cambridge university press, 2007, p. 183.
+template <class _Real>
+_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
+ if (__math::isnan(__x))
+ return std::numeric_limits<_Real>::quiet_NaN();
+
+ _Real __H_0{1};
+ if (__n == 0)
+ return __H_0;
+
+ _Real __H_n_prev = __H_0;
+ _Real __H_n = 2 * __x;
+ for (unsigned __i = 1; __i < __n; ++__i) {
+ _Real __H_n_next = 2 * (__x * __H_n - __i * __H_n_prev);
+ __H_n_prev = __H_n;
+ __H_n = __H_n_next;
+ }
+ return __H_n;
+}
+
+inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return std::__hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
+ // use double internally -- float is too prone to overflow!
+ return static_cast<float>(std::hermite(__n, static_cast<double>(__x)));
+}
+
+inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return std::__hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return std::hermite(__n, __x); }
+
+inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return std::hermite(__n, __x); }
+
+template <class _Integer, std::enable_if_t<std::is_integral_v<_Integer>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, _Integer __x) {
+ return std::hermite(__n, static_cast<double>(__x));
+}
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___MATH_SPECIAL_FUNCTIONS_H
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 677e0a6588887..acfcb93fb40a4 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -309,13 +309,13 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_floating_point.h>
-#include <__type_traits/is_integral.h>
#include <__type_traits/is_same.h>
#include <__type_traits/promote.h>
#include <__type_traits/remove_cv.h>
#include <limits>
#include <version>
+#include <__math/special_functions.h>
#include <math.h>
#ifndef _LIBCPP_MATH_H
@@ -766,53 +766,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp _
return __builtin_scalbn(__x, __exp);
}
-#if _LIBCPP_STD_VER >= 17
-
-/// \return the Hermite polynomial \f$ H_n(x) \f$
-/// \note The implementation is based on the recurrence formula
-/// \f[
-/// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}
-/// \f]
-/// Press, William H., et al. Numerical recipes 3rd edition: The art of
-/// scientific computing. Cambridge university press, 2007, p. 183.
-template <class _Real>
-_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
- if (std::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
-
- _Real __H_0{1};
- if (__n == 0)
- return __H_0;
-
- _Real __H_n_prev = __H_0;
- _Real __H_n = 2 * __x;
- for (unsigned __i = 1; __i < __n; ++__i) {
- _Real __H_n_next = 2 * (__x * __H_n - __i * __H_n_prev);
- __H_n_prev = __H_n;
- __H_n = __H_n_next;
- }
- return __H_n;
-}
-
-inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return std::__hermite(__n, __x); }
-
-inline _LIBCPP_HIDE_FROM_ABI float hermite(unsigned __n, float __x) {
- // use double internally -- float is too prone to overflow!
- return static_cast<float>(std::hermite(__n, static_cast<double>(__x)));
-}
-
-inline _LIBCPP_HIDE_FROM_ABI long double hermite(unsigned __n, long double __x) { return std::__hermite(__n, __x); }
-
-inline _LIBCPP_HIDE_FROM_ABI float hermitef(unsigned __n, float __x) { return std::hermite(__n, __x); }
-
-inline _LIBCPP_HIDE_FROM_ABI long double hermitel(unsigned __n, long double __x) { return std::hermite(__n, __x); }
-
-template <class _Integer, std::enable_if_t<std::is_integral_v<_Integer>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, _Integer __x) {
- return std::hermite(__n, static_cast<double>(__x));
-}
-#endif // _LIBCPP_STD_VER >= 17
-
#if _LIBCPP_STD_VER >= 20
template <typename _Fp>
_LIBCPP_HIDE_FROM_ABI constexpr _Fp __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept {
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 64652c8307c9e..1e26ce11e65b0 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1486,6 +1486,7 @@ module std_private_math_modulo [system] { header "__mat
module std_private_math_remainder [system] { header "__math/remainder.h" }
module std_private_math_roots [system] { header "__math/roots.h" }
module std_private_math_rounding_functions [system] { header "__math/rounding_functions.h" }
+module std_private_math_special_functions [system] { header "__math/special_functions.h" }
module std_private_math_traits [system] { header "__math/traits.h" }
module std_private_math_trigonometric_functions [system] { header "__math/trigonometric_functions.h" }
>From 7f003acbf6ea08551450c4b1bb3024b2b8635ded Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 20:46:14 +0200
Subject: [PATCH 51/76] simplify NaN handling (no conversion)
---
libcxx/include/__math/special_functions.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h
index ee82a76940e4b..ac2c69c3df85b 100644
--- a/libcxx/include/__math/special_functions.h
+++ b/libcxx/include/__math/special_functions.h
@@ -14,7 +14,6 @@
#include <__math/traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_integral.h>
-#include <limits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -34,7 +33,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Real>
_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
if (__math::isnan(__x))
- return std::numeric_limits<_Real>::quiet_NaN();
+ return __x;
_Real __H_0{1};
if (__n == 0)
>From 7d8c06d72513ed293d731915dfbb50dd001f912d Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:03:17 +0200
Subject: [PATCH 52/76] simplify status documentation: single paper needs no
table
---
libcxx/docs/Status/SpecialMath.rst | 8 +++-----
libcxx/docs/Status/SpecialMathPapers.csv | 2 --
2 files changed, 3 insertions(+), 7 deletions(-)
delete mode 100644 libcxx/docs/Status/SpecialMathPapers.csv
diff --git a/libcxx/docs/Status/SpecialMath.rst b/libcxx/docs/Status/SpecialMath.rst
index 28045f3290fdd..fcc9f03e3ae64 100644
--- a/libcxx/docs/Status/SpecialMath.rst
+++ b/libcxx/docs/Status/SpecialMath.rst
@@ -13,7 +13,7 @@ Overview
========
This document contains the status of the C++17 mathematical special functions implementation in libc++.
-It is used to track both the status of the sub-projects of the effort and who is assigned to these sub-projects.
+It is used to track both the status of the sub-projects of the effort and who is assigned to these sub-projects.
This avoids duplicating effort.
If you are interested in contributing to this effort, please send a message
@@ -31,7 +31,5 @@ Sub-projects in the Implementation Effort
Paper and Issue Status
======================
-.. csv-table::
- :file: SpecialMathPapers.csv
- :header-rows: 1
- :widths: auto
+The underlying paper is `Mathematical Special Functions for C++17 (P0226) <https://wg21.link/P0226>`_ and is included in C++17.
+Implementation is *In Progress*.
diff --git a/libcxx/docs/Status/SpecialMathPapers.csv b/libcxx/docs/Status/SpecialMathPapers.csv
deleted file mode 100644
index be00c63e6fe3f..0000000000000
--- a/libcxx/docs/Status/SpecialMathPapers.csv
+++ /dev/null
@@ -1,2 +0,0 @@
-Number,Name,Standard,Assignee,Status,First released version
-`P0226 <https://wg21.link/P0226>`_,"Mathematical Special Functions for C++17","C++17",,"|In Progress|"
>From 62841f461e4c913fcdf43fa737757b1b36d8e3c2 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:05:39 +0200
Subject: [PATCH 53/76] assign std::hermite to myself
---
libcxx/docs/Status/SpecialMathProjects.csv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/SpecialMathProjects.csv b/libcxx/docs/Status/SpecialMathProjects.csv
index 57be6c746c590..f964e79de91d3 100644
--- a/libcxx/docs/Status/SpecialMathProjects.csv
+++ b/libcxx/docs/Status/SpecialMathProjects.csv
@@ -13,7 +13,7 @@ Section,Description,Assignee,Complete
| `[sf.cmath.ellint.2] <https://wg21.link/sf.cmath.ellint.2>`_, std::ellint_2, None, |Not Started|
| `[sf.cmath.ellint.3] <https://wg21.link/sf.cmath.ellint.3>`_, std::ellint_3, None, |Not Started|
| `[sf.cmath.expint] <https://wg21.link/sf.cmath.expint>`_, std::expint, None, |Not Started|
-| `[sf.cmath.hermite] <https://wg21.link/sf.cmath.hermite>`_, std::hermite, None, |Complete|
+| `[sf.cmath.hermite] <https://wg21.link/sf.cmath.hermite>`_, std::hermite, Paul Xi Cao, |Complete|
| `[sf.cmath.laguerre] <https://wg21.link/sf.cmath.laguerre>`_, std::laguerre, None, |Not Started|
| `[sf.cmath.legendre] <https://wg21.link/sf.cmath.legendre>`_, std::legendre, None, |Not Started|
| `[sf.cmath.riemann.zeta] <https://wg21.link/sf.cmath.riemann.zeta>`_, std::riemann_zeta, None, |Not Started|
>From 71dcd12a17d321d46af15f13e7f9d3ee02604940 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:08:27 +0200
Subject: [PATCH 54/76] remove anonymous namespace in test file
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 397046219bb1f..8f40839b0c663 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -16,8 +16,6 @@
#include <assert_macros.h>
-namespace {
-
inline constexpr unsigned MAX_N = 128;
template <class T>
@@ -283,7 +281,6 @@ void test_hermitel() {
for (long double x : sample_points<long double>())
assert(std::hermite(n, x) == std::hermitel(n, x));
}
-} // namespace
int main(int, char**) {
test_hermite<float>(1e-5f, 1e-5f);
>From 976309af4d8b289d2b55d9b68437203ed5536618 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:17:04 +0200
Subject: [PATCH 55/76] test: add synopsis
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 8f40839b0c663..b026f48a8267c 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -7,6 +7,16 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
+// <cmath>
+
+// Tests std::hermite and its related functions:
+// double hermite( unsigned n, double x);
+// float hermite( unsigned n, float x);
+// long double hermite( unsigned n, long double x);
+// float hermitef(unsigned n, float x);
+// long double hermitel(unsigned n, long double x);
+// template <class Integer>
+// double hermite( unsigned n, Integer x);
#include <cassert>
#include <cmath>
>From b42cd04c8b872c0d05fbbf81824c08ffc7103220 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:17:38 +0200
Subject: [PATCH 56/76] test: remove unused include
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index b026f48a8267c..08500aaa56579 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -24,8 +24,6 @@
#include <vector>
#include <array>
-#include <assert_macros.h>
-
inline constexpr unsigned MAX_N = 128;
template <class T>
>From 840321277748f8d62682e6d92420e0b1ac39848e Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Tue, 30 Apr 2024 21:19:48 +0200
Subject: [PATCH 57/76] test: sort includes
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 08500aaa56579..e10cb3b76475a 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -18,11 +18,11 @@
// template <class Integer>
// double hermite( unsigned n, Integer x);
+#include <array>
#include <cassert>
#include <cmath>
#include <limits>
#include <vector>
-#include <array>
inline constexpr unsigned MAX_N = 128;
>From 8b57a634c764c2aef653106fbb6b762663f9cf75 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Fri, 3 May 2024 22:05:33 +0200
Subject: [PATCH 58/76] test: refactor/style change. only test<T>() within
main()
---
.../test/std/numerics/c.math/hermite.pass.cpp | 226 +++++++++---------
1 file changed, 109 insertions(+), 117 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index e10cb3b76475a..7b178b009c8d6 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -31,82 +31,38 @@ std::array<T, 7> sample_points() {
return {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0};
}
-template <class T>
-void test_NaN_propagation() {
- T NaN = std::numeric_limits<T>::quiet_NaN();
- for (unsigned n = 0; n < MAX_N; ++n)
- assert(std::isnan(std::hermite(n, NaN)));
-}
-
-template <class T>
-void test_not_NaN(T x) {
- assert(!std::isnan(x));
- for (unsigned n = 0; n < MAX_N; ++n)
- assert(!std::isnan(std::hermite(n, x)));
-}
-
-template <class T>
-struct CompareFloatingValues {
- T abs_tol;
- T rel_tol;
+template <class Real>
+class CompareFloatingValues {
+private:
+ Real abs_tol;
+ Real rel_tol;
+
+public:
+ CompareFloatingValues() {
+ abs_tol = []() -> Real {
+ if (std::is_same_v<Real, float>)
+ return 1e-5f;
+ else if (std::is_same_v<Real, double>)
+ return 1e-11;
+ else
+ return 1e-12l;
+ }();
+
+ rel_tol = abs_tol;
+ }
- bool operator()(T result, T expected) const {
+ bool operator()(Real result, Real expected) const {
if (std::isinf(expected) && std::isinf(result))
- return true;
+ return result == expected;
if (std::isnan(expected) || std::isnan(result))
return false;
- T tol = abs_tol + std::abs(expected) * rel_tol;
+ Real tol = abs_tol + std::abs(expected) * rel_tol;
return std::abs(result - expected) < tol;
}
};
-template <class T>
-void test_analytic_solution(T x, T abs_tol, T rel_tol) {
- assert(!std::isnan(x));
-
- const auto h0 = [](T) -> T { return 1; };
- const auto h1 = [](T y) -> T { return 2 * y; };
- const auto h2 = [](T y) -> T { return 4 * y * y - 2; };
- const auto h3 = [](T y) -> T { return y * (8 * y * y - 12); };
- const auto h4 = [](T y) -> T { return (16 * std::pow(y, 4) - 48 * y * y + 12); };
- const auto h5 = [](T y) -> T { return y * (32 * std::pow(y, 4) - 160 * y * y + 120); };
-
- const CompareFloatingValues<T> compare{.abs_tol = abs_tol, .rel_tol = rel_tol};
- assert(compare(std::hermite(0, x), h0(x)));
- assert(compare(std::hermite(1, x), h1(x)));
- assert(compare(std::hermite(2, x), h2(x)));
- assert(compare(std::hermite(3, x), h3(x)));
- assert(compare(std::hermite(4, x), h4(x)));
- assert(compare(std::hermite(5, x), h5(x)));
-}
-
-/// \details This method checks if the following recurrence relation holds:
-/// \f[
-/// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
-/// \f]
-template <class T>
-void test_recurrence_relation(T x, T abs_tol, T rel_tol) {
- assert(!std::isnan(x));
-
- const CompareFloatingValues<T> compare{.abs_tol = abs_tol, .rel_tol = rel_tol};
- for (unsigned n = 1; n < MAX_N - 1; ++n) {
- T H_next = std::hermite(n + 1, x);
- T H_next_recurrence = 2 * (x * std::hermite(n, x) - n * std::hermite(n - 1, x));
-
- if (std::isinf(H_next))
- break;
- assert(compare(H_next, H_next_recurrence));
- }
-}
-
-template <class T>
-void test_recurrence_relation(T abs_tol, T rel_tol) {
- for (T x : sample_points<T>())
- test_recurrence_relation(x, abs_tol, rel_tol);
-}
-
/// \note Roots are taken from
/// Salzer, Herbert E., Ruth Zucker, and Ruth Capuano.
/// Table of the zeros and weight factors of the first twenty Hermite
@@ -242,74 +198,110 @@ std::vector<T> get_roots(unsigned n) {
}
}
-/// \param [in] Tolerance of the root. This value must be smaller than
-/// the smallest difference between adjacent roots in the given range
-/// with n <= 20.
-template <class T>
-void test_roots(T Tolerance) {
- const auto is_sign_change = [Tolerance](unsigned n, T x) -> bool {
- return std::hermite(n, x - Tolerance) * std::hermite(n, x + Tolerance) < 0;
- };
-
- for (unsigned n = 0; n <= 20u; ++n) {
- for (T x : get_roots<T>(n)) {
- // the roots are symmetric: if x is a root, so is -x
- if (x > 0)
- assert(is_sign_change(n, -x));
- assert(is_sign_change(n, x));
+template <class Real>
+void test() {
+ { // checks if NaNs are reported correctly (i.e. output == input for input == NaN)
+ using nl = std::numeric_limits<Real>;
+ for (Real NaN : {nl::quiet_NaN(), nl::signaling_NaN()})
+ for (unsigned n = 0; n < MAX_N; ++n)
+ assert(std::isnan(std::hermite(n, NaN)));
+ }
+
+ { // simple sample points for n=0..127 should not produce NaNs.
+ for (Real x : sample_points<Real>())
+ for (unsigned n = 0; n < MAX_N; ++n)
+ assert(!std::isnan(std::hermite(n, x)));
+ }
+
+ { // checks std::hermite(n, x) for n=0..5 against analytic polynoms
+ const auto h0 = [](Real) -> Real { return 1; };
+ const auto h1 = [](Real y) -> Real { return 2 * y; };
+ const auto h2 = [](Real y) -> Real { return 4 * y * y - 2; };
+ const auto h3 = [](Real y) -> Real { return y * (8 * y * y - 12); };
+ const auto h4 = [](Real y) -> Real { return (16 * std::pow(y, 4) - 48 * y * y + 12); };
+ const auto h5 = [](Real y) -> Real { return y * (32 * std::pow(y, 4) - 160 * y * y + 120); };
+
+ for (Real x : sample_points<Real>()) {
+ const CompareFloatingValues<Real> compare;
+ assert(compare(std::hermite(0, x), h0(x)));
+ assert(compare(std::hermite(1, x), h1(x)));
+ assert(compare(std::hermite(2, x), h2(x)));
+ assert(compare(std::hermite(3, x), h3(x)));
+ assert(compare(std::hermite(4, x), h4(x)));
+ assert(compare(std::hermite(5, x), h5(x)));
}
}
-}
-template <class T>
-void test_hermite(T abs_tol, T rel_tol) {
- test_NaN_propagation<T>();
+ { // checks std::hermitef for bitwise equality with std::hermite(unsigned, float)
+ if constexpr (std::is_same_v<Real, float>)
+ for (unsigned n = 0; n < MAX_N; ++n)
+ for (float x : sample_points<float>())
+ assert(std::hermite(n, x) == std::hermitef(n, x));
+ }
+
+ { // checks std::hermitel for bitwise equality with std::hermite(unsigned, long double)
+ if constexpr (std::is_same_v<Real, long double>)
+ for (unsigned n = 0; n < MAX_N; ++n)
+ for (long double x : sample_points<long double>())
+ assert(std::hermite(n, x) == std::hermitel(n, x));
+ }
- for (T x : sample_points<T>()) {
- test_not_NaN(x);
- test_analytic_solution(x, abs_tol, rel_tol);
+ { // Checks if the characteristic recurrence relation holds: H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
+ for (Real x : sample_points<Real>()) {
+ for (unsigned n = 1; n < MAX_N - 1; ++n) {
+ Real H_next = std::hermite(n + 1, x);
+ Real H_next_recurrence = 2 * (x * std::hermite(n, x) - n * std::hermite(n - 1, x));
+
+ if (std::isinf(H_next))
+ break;
+ const CompareFloatingValues<Real> compare;
+ assert(compare(H_next, H_next_recurrence));
+ }
+ }
+ }
+
+ { // sanity checks: hermite polynoms need to change signs at (simple) roots. checked upto order n<=20.
+
+ // root tolerance: must be smaller than the smallest difference between adjacent roots
+ Real tol = []() -> Real {
+ if (std::is_same_v<Real, float>)
+ return 1e-5f;
+ else if (std::is_same_v<Real, double>)
+ return 1e-9;
+ else
+ return 1e-10l;
+ }();
+
+ const auto is_sign_change = [tol](unsigned n, Real x) -> bool {
+ return std::hermite(n, x - tol) * std::hermite(n, x + tol) < 0;
+ };
+
+ for (unsigned n = 0; n <= 20u; ++n) {
+ for (Real x : get_roots<Real>(n)) {
+ // the roots are symmetric: if x is a root, so is -x
+ if (x > 0)
+ assert(is_sign_change(n, -x));
+ assert(is_sign_change(n, x));
+ }
+ }
}
}
template <class Integer>
void test_integers() {
+ // checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
for (unsigned n = 0; n < MAX_N; ++n)
for (Integer x : {-1, 0, 1})
assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
}
-void test_hermitef() {
- for (unsigned n = 0; n < MAX_N; ++n)
- for (float x : sample_points<float>())
- assert(std::hermite(n, x) == std::hermitef(n, x));
-}
-
-void test_hermitel() {
- for (unsigned n = 0; n < MAX_N; ++n)
- for (long double x : sample_points<long double>())
- assert(std::hermite(n, x) == std::hermitel(n, x));
-}
-
-int main(int, char**) {
- test_hermite<float>(1e-5f, 1e-5f);
- test_hermite<double>(1e-11, 1e-11);
- test_hermite<long double>(1e-12l, 1e-12l);
-
- test_hermitef();
- test_hermitel();
-
- test_recurrence_relation<float>(1e-5f, 1e-5f);
- test_recurrence_relation<double>(1e-11, 1e-11);
- test_recurrence_relation<long double>(1e-12l, 1e-12l);
-
- test_roots<float>(1e-5f);
- test_roots<double>(1e-9);
- test_roots<long double>(1e-10l);
+int main() {
+ test<float>();
+ test<double>();
+ test<long double>();
test_integers<short>();
test_integers<int>();
test_integers<long>();
test_integers<long long>();
-
- return 0;
}
>From 95f2a2498dcaf6117c99c4cc8259f2d570cce6f8 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Fri, 3 May 2024 22:12:41 +0200
Subject: [PATCH 59/76] test: make use of types::for_each
---
.../test/std/numerics/c.math/hermite.pass.cpp | 35 +++++++++++--------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 7b178b009c8d6..5a740af7ae0e9 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -24,6 +24,8 @@
#include <limits>
#include <vector>
+#include "type_algorithms.h"
+
inline constexpr unsigned MAX_N = 128;
template <class T>
@@ -287,21 +289,24 @@ void test() {
}
}
-template <class Integer>
-void test_integers() {
- // checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
- for (unsigned n = 0; n < MAX_N; ++n)
- for (Integer x : {-1, 0, 1})
- assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
-}
+struct TestFloat {
+ template <class Real>
+ void operator()() {
+ test<Real>();
+ }
+};
+
+struct TestInt {
+ template <class Integer>
+ void operator()() {
+ // checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
+ for (unsigned n = 0; n < MAX_N; ++n)
+ for (Integer x : {-1, 0, 1})
+ assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
+ }
+};
int main() {
- test<float>();
- test<double>();
- test<long double>();
-
- test_integers<short>();
- test_integers<int>();
- test_integers<long>();
- test_integers<long long>();
+ types::for_each(types::floating_point_types(), TestFloat());
+ types::for_each(types::type_list<short, int, long, long long>(), TestInt());
}
>From 3ddac0b30dd81aae5482b759de59be269678d36c Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Fri, 3 May 2024 22:30:44 +0200
Subject: [PATCH 60/76] test: replace exception throwing by assert
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 5a740af7ae0e9..32d538eee42c3 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -196,7 +196,7 @@ std::vector<T> get_roots(unsigned n) {
T(5.3874808900112)};
default:
- throw "Roots of Hermite polynomial of order " + std::to_string(n) + " not implemented!\n";
+ assert(0);
}
}
>From 0098ee77a763ea393f0993037e9d93aab2a209c9 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 13:40:40 +0200
Subject: [PATCH 61/76] test: additional sample points with abs(x)>1
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 32d538eee42c3..5f32158a261f3 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -29,8 +29,8 @@
inline constexpr unsigned MAX_N = 128;
template <class T>
-std::array<T, 7> sample_points() {
- return {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0};
+std::array<T, 11> sample_points() {
+ return {-12.34, -7.42, -1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 5.67, 15.67};
}
template <class Real>
>From c94fad9ba48a4bb4149ab5cc8f97e1a2a3ac34f4 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 19:02:30 +0200
Subject: [PATCH 62/76] test: checks for x=+-inf as input
---
.../test/std/numerics/c.math/hermite.pass.cpp | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 5f32158a261f3..f718ff30b1b7d 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -287,6 +287,27 @@ void test() {
}
}
}
+
+ { // check input infinity is handled correctly
+ Real inf = std::numeric_limits<Real>::infinity();
+ for (unsigned n = 1; n < MAX_N; ++n) {
+ assert(std::hermite(n, +inf) == inf);
+ assert(std::hermite(n, -inf) == ((n & 1) ? -inf : inf));
+ }
+ }
+
+ { // check: if overflow occurs that it is mapped to the correct infinity
+ Real inf = std::numeric_limits<Real>::infinity();
+ for (unsigned n = 0; n < MAX_N; ++n) {
+ // Q: why x=140?
+ // A: H_127(140) overflows even 8-byte double
+ if (Real y = std::hermite(n, Real{140}); !std::isfinite(y))
+ assert(y == inf);
+
+ if (Real y = std::hermite(n, Real{-140}); !std::isfinite(y))
+ assert(y == ((n & 1) ? -inf : inf));
+ }
+ }
}
struct TestFloat {
>From 511b45679ab65dc3efca81abc976c27711a5df9a Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 19:04:06 +0200
Subject: [PATCH 63/76] handle overflows
---
libcxx/include/__math/special_functions.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h
index ac2c69c3df85b..60ad6e173e417 100644
--- a/libcxx/include/__math/special_functions.h
+++ b/libcxx/include/__math/special_functions.h
@@ -11,9 +11,11 @@
#define _LIBCPP___MATH_SPECIAL_FUNCTIONS_H
#include <__config>
+#include <__math/copysign.h>
#include <__math/traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_integral.h>
+#include <limits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -46,6 +48,14 @@ _LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
__H_n_prev = __H_n;
__H_n = __H_n_next;
}
+
+ if (!__math::isfinite(__H_n)) {
+ // Overflow occured. Two possible cases:
+ // n is odd: return infinity of the same sign as x.
+ // n is even: return +Inf
+ _Real inf = std::numeric_limits<_Real>::infinity();
+ return (__n & 1) ? __math::copysign(inf, __x) : inf;
+ }
return __H_n;
}
>From 84b7b87e968831265f000f008016fbfd3473f258 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 19:13:25 +0200
Subject: [PATCH 64/76] index.rst: add special math status page to TOC
---
libcxx/docs/index.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/docs/index.rst b/libcxx/docs/index.rst
index 743f99297d17d..621057b9605d0 100644
--- a/libcxx/docs/index.rst
+++ b/libcxx/docs/index.rst
@@ -53,6 +53,7 @@ Getting Started with libc++
Status/PSTL
Status/Ranges
Status/Spaceship
+ Status/SpecialMath
Status/Zip
@@ -71,7 +72,7 @@ iOS, watchOS, and tvOS, Google Search, the Android operating system, and FreeBSD
user base of over 1 billion daily active users.
Since its inception, libc++ has focused on delivering high performance, standards-conformance, and portability. It has
-been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14,
+been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14,
with C++17, C++20, C++23, and C++26 features being actively developed and making steady progress.
libc++ is continuously integrated and tested on a wide range of platforms and configurations, ensuring its reliability
>From 6b28fc59cc674f15075ec058ac6e3b1b217747bc Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 19:16:52 +0200
Subject: [PATCH 65/76] cmath.inc: uncomment std::hermite functions
---
libcxx/modules/std/cmath.inc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/modules/std/cmath.inc b/libcxx/modules/std/cmath.inc
index 0fe887447ad85..eaa07bba561a9 100644
--- a/libcxx/modules/std/cmath.inc
+++ b/libcxx/modules/std/cmath.inc
@@ -334,12 +334,14 @@ export namespace std {
using std::expint;
using std::expintf;
using std::expintl;
+#endif
// [sf.cmath.hermite], Hermite polynomials
using std::hermite;
using std::hermitef;
using std::hermitel;
+#if 0
// [sf.cmath.laguerre], Laguerre polynomials
using std::laguerre;
using std::laguerref;
>From 58ff841509fefa04784d788af4b8e6f18c84d5dd Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 19:23:21 +0200
Subject: [PATCH 66/76] cmath: added implemented functions to synopsis
---
libcxx/include/cmath | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index acfcb93fb40a4..60dca1453dd81 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -204,6 +204,12 @@ floating_point fmin (arithmetic x, arithmetic y);
float fminf(float x, float y);
long double fminl(long double x, long double y);
+double hermite(unsigned n, double x); // C++17
+float hermite(unsigned n, float x); // C++17
+long double hermite(unsigned n, long double x); // C++17
+template <class Integer>
+double hermite(unsigned n, Integer x); // C++17
+
floating_point hypot (arithmetic x, arithmetic y);
float hypotf(float x, float y);
long double hypotl(long double x, long double y);
>From 492c4c8e3574f787b0d5f07e66502799052f2cd1 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 20:37:13 +0200
Subject: [PATCH 67/76] cmath: add hermite{l,f} to synopsis
---
libcxx/include/cmath | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/include/cmath b/libcxx/include/cmath
index 60dca1453dd81..c53dc1050fda7 100644
--- a/libcxx/include/cmath
+++ b/libcxx/include/cmath
@@ -207,6 +207,8 @@ long double fminl(long double x, long double y);
double hermite(unsigned n, double x); // C++17
float hermite(unsigned n, float x); // C++17
long double hermite(unsigned n, long double x); // C++17
+float hermitef(unsigned n, float x); // C++17
+long double hermitel(unsigned n, long double x); // C++17
template <class Integer>
double hermite(unsigned n, Integer x); // C++17
>From 67b0da98f2a62422683135a61cd4e14f56770582 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 20:40:28 +0200
Subject: [PATCH 68/76] test: format test's synopsis
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index f718ff30b1b7d..b3ab7f2d58895 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -7,16 +7,16 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14
+
// <cmath>
-// Tests std::hermite and its related functions:
-// double hermite( unsigned n, double x);
-// float hermite( unsigned n, float x);
-// long double hermite( unsigned n, long double x);
-// float hermitef(unsigned n, float x);
-// long double hermitel(unsigned n, long double x);
-// template <class Integer>
-// double hermite( unsigned n, Integer x);
+// double hermite(unsigned n, double x);
+// float hermite(unsigned n, float x);
+// long double hermite(unsigned n, long double x);
+// float hermitef(unsigned n, float x);
+// long double hermitel(unsigned n, long double x);
+// template <class Integer>
+// double hermite(unsigned n, Integer x);
#include <array>
#include <cassert>
>From d4ea6088dca10dde0cfc21ad25ec3df218955c8c Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 20:56:00 +0200
Subject: [PATCH 69/76] get rid of doxygen-style comments
---
libcxx/include/__math/special_functions.h | 13 ++++++-------
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 8 ++++----
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h
index 60ad6e173e417..7e30e5e750be3 100644
--- a/libcxx/include/__math/special_functions.h
+++ b/libcxx/include/__math/special_functions.h
@@ -25,15 +25,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17
-/// \return the Hermite polynomial \f$ H_n(x) \f$
-/// \note The implementation is based on the recurrence formula
-/// \f[
-/// H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}
-/// \f]
-/// Press, William H., et al. Numerical recipes 3rd edition: The art of
-/// scientific computing. Cambridge university press, 2007, p. 183.
template <class _Real>
_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
+ // The Hermite polynomial H_n(x).
+ // The implementation is based on the recurrence formula: H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}.
+ // Press, William H., et al. Numerical recipes 3rd edition: The art of scientific computing.
+ // Cambridge university press, 2007, p. 183.
+
if (__math::isnan(__x))
return __x;
@@ -76,6 +74,7 @@ template <class _Integer, std::enable_if_t<std::is_integral_v<_Integer>, int> =
_LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, _Integer __x) {
return std::hermite(__n, static_cast<double>(__x));
}
+
#endif // _LIBCPP_STD_VER >= 17
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index b3ab7f2d58895..e5d7b42fe28fa 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -65,10 +65,10 @@ class CompareFloatingValues {
}
};
-/// \note Roots are taken from
-/// Salzer, Herbert E., Ruth Zucker, and Ruth Capuano.
-/// Table of the zeros and weight factors of the first twenty Hermite
-/// polynomials. US Government Printing Office, 1952.
+// Roots are taken from
+// Salzer, Herbert E., Ruth Zucker, and Ruth Capuano.
+// Table of the zeros and weight factors of the first twenty Hermite
+// polynomials. US Government Printing Office, 1952.
template <class T>
std::vector<T> get_roots(unsigned n) {
switch (n) {
>From df4eadfa73f14831d6cd1bd045d5f5081dea31d6 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 21:03:43 +0200
Subject: [PATCH 70/76] test: renamed MAX_N to g_max_n
---
.../test/std/numerics/c.math/hermite.pass.cpp | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index e5d7b42fe28fa..65aba486085e2 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -26,7 +26,7 @@
#include "type_algorithms.h"
-inline constexpr unsigned MAX_N = 128;
+inline constexpr unsigned g_max_n = 128;
template <class T>
std::array<T, 11> sample_points() {
@@ -205,13 +205,13 @@ void test() {
{ // checks if NaNs are reported correctly (i.e. output == input for input == NaN)
using nl = std::numeric_limits<Real>;
for (Real NaN : {nl::quiet_NaN(), nl::signaling_NaN()})
- for (unsigned n = 0; n < MAX_N; ++n)
+ for (unsigned n = 0; n < g_max_n; ++n)
assert(std::isnan(std::hermite(n, NaN)));
}
{ // simple sample points for n=0..127 should not produce NaNs.
for (Real x : sample_points<Real>())
- for (unsigned n = 0; n < MAX_N; ++n)
+ for (unsigned n = 0; n < g_max_n; ++n)
assert(!std::isnan(std::hermite(n, x)));
}
@@ -236,21 +236,21 @@ void test() {
{ // checks std::hermitef for bitwise equality with std::hermite(unsigned, float)
if constexpr (std::is_same_v<Real, float>)
- for (unsigned n = 0; n < MAX_N; ++n)
+ for (unsigned n = 0; n < g_max_n; ++n)
for (float x : sample_points<float>())
assert(std::hermite(n, x) == std::hermitef(n, x));
}
{ // checks std::hermitel for bitwise equality with std::hermite(unsigned, long double)
if constexpr (std::is_same_v<Real, long double>)
- for (unsigned n = 0; n < MAX_N; ++n)
+ for (unsigned n = 0; n < g_max_n; ++n)
for (long double x : sample_points<long double>())
assert(std::hermite(n, x) == std::hermitel(n, x));
}
{ // Checks if the characteristic recurrence relation holds: H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
for (Real x : sample_points<Real>()) {
- for (unsigned n = 1; n < MAX_N - 1; ++n) {
+ for (unsigned n = 1; n < g_max_n - 1; ++n) {
Real H_next = std::hermite(n + 1, x);
Real H_next_recurrence = 2 * (x * std::hermite(n, x) - n * std::hermite(n - 1, x));
@@ -290,7 +290,7 @@ void test() {
{ // check input infinity is handled correctly
Real inf = std::numeric_limits<Real>::infinity();
- for (unsigned n = 1; n < MAX_N; ++n) {
+ for (unsigned n = 1; n < g_max_n; ++n) {
assert(std::hermite(n, +inf) == inf);
assert(std::hermite(n, -inf) == ((n & 1) ? -inf : inf));
}
@@ -298,7 +298,7 @@ void test() {
{ // check: if overflow occurs that it is mapped to the correct infinity
Real inf = std::numeric_limits<Real>::infinity();
- for (unsigned n = 0; n < MAX_N; ++n) {
+ for (unsigned n = 0; n < g_max_n; ++n) {
// Q: why x=140?
// A: H_127(140) overflows even 8-byte double
if (Real y = std::hermite(n, Real{140}); !std::isfinite(y))
@@ -321,7 +321,7 @@ struct TestInt {
template <class Integer>
void operator()() {
// checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
- for (unsigned n = 0; n < MAX_N; ++n)
+ for (unsigned n = 0; n < g_max_n; ++n)
for (Integer x : {-1, 0, 1})
assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
}
>From 293dd2ba1c8a9f88aadddfb36936ba7d6f01ddc2 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sat, 4 May 2024 21:09:12 +0200
Subject: [PATCH 71/76] test: assert(false) instead of assert(0)
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 65aba486085e2..e8e536801ba42 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -196,7 +196,7 @@ std::vector<T> get_roots(unsigned n) {
T(5.3874808900112)};
default:
- assert(0);
+ assert(false);
}
}
>From 55ec209c8a261e8a48cbefc7a63e0ca776905b90 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Wed, 8 May 2024 23:52:23 +0200
Subject: [PATCH 72/76] test: inf result for finite input
---
.../test/std/numerics/c.math/hermite.pass.cpp | 25 ++++++++++++-------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index e8e536801ba42..59b25038f48e9 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -297,15 +297,22 @@ void test() {
}
{ // check: if overflow occurs that it is mapped to the correct infinity
- Real inf = std::numeric_limits<Real>::infinity();
- for (unsigned n = 0; n < g_max_n; ++n) {
- // Q: why x=140?
- // A: H_127(140) overflows even 8-byte double
- if (Real y = std::hermite(n, Real{140}); !std::isfinite(y))
- assert(y == inf);
-
- if (Real y = std::hermite(n, Real{-140}); !std::isfinite(y))
- assert(y == ((n & 1) ? -inf : inf));
+ if constexpr (std::is_same_v<Real, double>) {
+ // Q: Why only double?
+ // A: The numeric values (e.g. overflow threshold `n`) below are different for other types.
+ static_assert(sizeof(double) == 8);
+ for (unsigned n = 0; n < g_max_n; ++n) {
+ // Q: Why n=111 and x=300?
+ // A: Both are chosen s.t. the first overlow occurs for some `n<g_max_n`.
+ if (n < 111) {
+ assert(std::isfinite(std::hermite(n, +300.0)));
+ assert(std::isfinite(std::hermite(n, -300.0)));
+ } else {
+ double inf = std::numeric_limits<double>::infinity();
+ assert(std::hermite(n, +300.0) == inf);
+ assert(std::hermite(n, -300.0) == ((n & 1) ? -inf : inf));
+ }
+ }
}
}
}
>From 9034e5f3cbe87fda1a22668a7547b0614b77fddc Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Fri, 10 May 2024 21:45:55 +0200
Subject: [PATCH 73/76] rename to use ugly name: inf -> __inf
---
libcxx/include/__math/special_functions.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h
index 7e30e5e750be3..ff83b637876ea 100644
--- a/libcxx/include/__math/special_functions.h
+++ b/libcxx/include/__math/special_functions.h
@@ -51,8 +51,8 @@ _LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
// Overflow occured. Two possible cases:
// n is odd: return infinity of the same sign as x.
// n is even: return +Inf
- _Real inf = std::numeric_limits<_Real>::infinity();
- return (__n & 1) ? __math::copysign(inf, __x) : inf;
+ _Real __inf = std::numeric_limits<_Real>::infinity();
+ return (__n & 1) ? __math::copysign(__inf, __x) : __inf;
}
return __H_n;
}
>From 928fc89bcf4204f191172503b890b1638f193886 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Fri, 10 May 2024 21:46:52 +0200
Subject: [PATCH 74/76] silence clang-tidy warning about variable name in math
code
---
libcxx/include/__math/special_functions.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/include/__math/special_functions.h b/libcxx/include/__math/special_functions.h
index ff83b637876ea..0b1c753a659ad 100644
--- a/libcxx/include/__math/special_functions.h
+++ b/libcxx/include/__math/special_functions.h
@@ -32,6 +32,7 @@ _LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
// Press, William H., et al. Numerical recipes 3rd edition: The art of scientific computing.
// Cambridge university press, 2007, p. 183.
+ // NOLINTBEGIN(readability-identifier-naming)
if (__math::isnan(__x))
return __x;
@@ -55,6 +56,7 @@ _LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
return (__n & 1) ? __math::copysign(__inf, __x) : __inf;
}
return __H_n;
+ // NOLINTEND(readability-identifier-naming)
}
inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return std::__hermite(__n, __x); }
>From c74f36ee89ccc21208f6e94c847ed63f4c6f4d84 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Sun, 12 May 2024 23:32:30 +0200
Subject: [PATCH 75/76] test: add more values for integeral x
---
libcxx/test/std/numerics/c.math/hermite.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/numerics/c.math/hermite.pass.cpp b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
index 59b25038f48e9..6d4aa697434c6 100644
--- a/libcxx/test/std/numerics/c.math/hermite.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/hermite.pass.cpp
@@ -329,7 +329,7 @@ struct TestInt {
void operator()() {
// checks that std::hermite(unsigned, Integer) actually wraps std::hermite(unsigned, double)
for (unsigned n = 0; n < g_max_n; ++n)
- for (Integer x : {-1, 0, 1})
+ for (Integer x : {-42, -7, -5, -1, 0, 1, 5, 7, 42})
assert(std::hermite(n, x) == std::hermite(n, static_cast<double>(x)));
}
};
>From 165fc118554d4be52898020fbe6edf108e41a217 Mon Sep 17 00:00:00 2001
From: Paul <{ID}+{username}@users.noreply.github.com>
Date: Thu, 16 May 2024 22:18:32 +0200
Subject: [PATCH 76/76] export functions for module usage
---
libcxx/modules/std.compat/cmath.inc | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/modules/std.compat/cmath.inc b/libcxx/modules/std.compat/cmath.inc
index de5379275c5fa..bd9e7f5b9df3e 100644
--- a/libcxx/modules/std.compat/cmath.inc
+++ b/libcxx/modules/std.compat/cmath.inc
@@ -265,4 +265,7 @@ export {
using ::signbit;
// [sf.cmath], mathematical special functions
+ using ::hermite;
+ using ::hermitef;
+ using ::hermitel;
} // export
More information about the libcxx-commits
mailing list