[libcxx-commits] [libcxx] [libc++][math] Mathematical Special Functions: Hermite Polynomial (PR #89982)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat May 4 12:51:10 PDT 2024


================
@@ -765,6 +766,54 @@ _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>
+_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
----------------
PaulXiCao wrote:

Is `std::is_integral` the correct concept to check? I am wondering as it would also allow types that seem unreasonable/indicative of wrong usage, e.g. `bool`.
>From [cppreference.com](https://en.cppreference.com/w/cpp/numeric/special_functions/hermite) ("Notes" section): _"They only need to be sufficient to ensure that for their argument num of integer type, std::hermite(int_num, num) has the same effect as std::hermite(int_num, static_cast<double>(num))."_
>From the C++23 Standard
* 28.7.1.3: _"...where arguments of integer type are considered to have the same floating-point conversion rank as double. ..."_. This defines that `std::hermite(n,x)` should also accept integer values for its `x` argument. 
* Integer types are defined in 6.8.2. and do not contain `bool`.

https://github.com/llvm/llvm-project/pull/89982


More information about the libcxx-commits mailing list