[libcxx-commits] [libcxx] [libc++][math] Mathematical Special Functions: Hermite Polynomial (PR #89982)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Apr 30 11:53:50 PDT 2024
================
@@ -765,6 +766,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>
+_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;
----------------
lntue wrote:
+1 to everything in your comment.
- For the first point a simple non-trivial (might be not that useful) example is when `x = std::numeric_limits<_Real>::max()`, following the iterations, you will get that:
```
hermite(0, x) = 1.0
hermite(1, x) = +Inf
hermite(2, x) = +Inf
hermite(3, x) = NaN
...
```
and there are definitely more intricate cases.
- Another issue that we might want to address later is precision loss. I haven't looked into the stability of the iterations, but we might have catastrophic cancellation when `__x * __H_n ~ __i * __H_n_prev`. It is interesting to find some non-trivial examples, but we can defer dealing with this case to later PR.
https://github.com/llvm/llvm-project/pull/89982
More information about the libcxx-commits
mailing list