Skip to content

[libc++][math] Mathematical Special Functions: Hermite Polynomial #89982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 80 commits into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
37880b0
apply original diff from D58876
PaulXiCao Jul 7, 2024
f73bb1b
moved new files into math/
PaulXiCao Jul 7, 2024
5d6b824
cmake: fix include by adding new files to file listing
PaulXiCao Jul 7, 2024
b4a313a
move test files from internal libcxx/ into std/
PaulXiCao Jul 7, 2024
3871157
replace "_VSTD" by "std". similar to D117811
PaulXiCao Jul 7, 2024
4e50b18
replace deprecated _LIBCPP_INLINE_VISIBILITY by _LIBCPP_HIDE_FROM_ABI
PaulXiCao Jul 7, 2024
a158fe8
hermite tests succeed! (fixed compiler warning: shadowing variable)
PaulXiCao Jul 7, 2024
9938c1a
laguerre tests succeeds! (fixed compiler warning: shadowing variable)
PaulXiCao Jul 7, 2024
87b240d
legendre tests succeeds! (fixed compiler warning: shadowing variable)
PaulXiCao Jul 7, 2024
6add3f4
assoc_laguerre tests succeeds! (fixed compiler warning: shadowing var…
PaulXiCao Jul 7, 2024
d34933d
assoc_legendre tests succeeds! (fixed compiler warning: shadowing var…
PaulXiCao Jul 7, 2024
b13a000
hermite: fix documentation comment
PaulXiCao Jul 7, 2024
2333750
hermite: minor code changes: rename variables, brace initialization
PaulXiCao Jul 7, 2024
188edd1
create experimental/math module
PaulXiCao Jul 7, 2024
073ae40
set header info for lit
PaulXiCao Jul 7, 2024
8f4573b
keeping only hermite, i.e. remove laguerre, legendre
PaulXiCao Jul 7, 2024
622cb1a
remove explicit type conversions
PaulXiCao Jul 7, 2024
23ffb72
use more readable variable names
PaulXiCao Jul 7, 2024
390947d
make use of function template argument deduction
PaulXiCao Jul 7, 2024
f9b489b
constness of passed arguments
PaulXiCao Jul 7, 2024
cbcef27
unify return path via ternary op
PaulXiCao Jul 7, 2024
48268c9
clang format
PaulXiCao Jul 7, 2024
7c4a14a
cleanup preprocessor usage
PaulXiCao Jul 7, 2024
57cdb04
sufficient additional overloads by LWG 3234
PaulXiCao Jul 7, 2024
a42128e
simplify hermite(float)
PaulXiCao Jul 7, 2024
d0500d9
implement: template<class Integer> double hermite(unsigned, Integer)
PaulXiCao Jul 7, 2024
711a757
remove old comment
PaulXiCao Jul 7, 2024
ece1daf
make use of Lit: // UNSUPPORTED: c++XX
PaulXiCao Jul 7, 2024
5bba7f1
cleanup tests
PaulXiCao Jul 7, 2024
6f0006b
update docs/Status
PaulXiCao Jul 7, 2024
b60044d
modulemap include private headers
PaulXiCao Jul 7, 2024
e33c6d9
remove doxygen style file comment
PaulXiCao Jul 7, 2024
135e5e7
move out of experimental/
PaulXiCao Jul 7, 2024
161349b
all functions need _LIBCPP_HIDE_FROM_API
PaulXiCao Jul 7, 2024
f87416c
remove `std::` similar to other surrounding code
PaulXiCao Jul 7, 2024
12574b8
include missing header: type_traits/is_integral
PaulXiCao Jul 7, 2024
6199348
test: place Lit comment correctly
PaulXiCao Jul 7, 2024
6f5e9eb
don't use yoda conditional
PaulXiCao Jul 7, 2024
adbe52b
edits according to mentioned style issues
PaulXiCao Jul 7, 2024
aca72ce
shorten internal hermite function's name
PaulXiCao Jul 7, 2024
445f6b1
style format of template argument
PaulXiCao Jul 7, 2024
b2aa559
fully qualify function calls
PaulXiCao Jul 7, 2024
9fb7f78
test: style changes, renaming, etc.
PaulXiCao Jul 7, 2024
778d8ff
status page
PaulXiCao Jul 7, 2024
7a329b9
remove dead code: lit header comments
PaulXiCao Jul 7, 2024
1bc981b
remove comment about integer->double conversion
PaulXiCao Jul 7, 2024
d8e41c8
specify implementation-defined behavior: hermite(n,x) for n>=128
PaulXiCao Jul 7, 2024
df553a6
hermite(unsigned, _Integer): changed SFINAE usage
PaulXiCao Jul 7, 2024
9f11623
link status page from general C++17 status page
PaulXiCao Jul 7, 2024
d5b4b49
move implementation from include/cmath to include/__math/special_func…
PaulXiCao Jul 7, 2024
f77fd3c
simplify NaN handling (no conversion)
PaulXiCao Jul 7, 2024
68cee2f
simplify status documentation: single paper needs no table
PaulXiCao Jul 7, 2024
68eef29
assign std::hermite to myself
PaulXiCao Jul 7, 2024
379b6df
remove anonymous namespace in test file
PaulXiCao Jul 7, 2024
c0f15bf
test: add synopsis
PaulXiCao Jul 7, 2024
aaf8364
test: remove unused include
PaulXiCao Jul 7, 2024
c264bad
test: sort includes
PaulXiCao Jul 7, 2024
097d622
test: refactor/style change. only test<T>() within main()
PaulXiCao Jul 7, 2024
b5cee48
test: make use of types::for_each
PaulXiCao Jul 7, 2024
2275201
test: replace exception throwing by assert
PaulXiCao Jul 7, 2024
d69176d
test: additional sample points with abs(x)>1
PaulXiCao Jul 7, 2024
25f6c80
test: checks for x=+-inf as input
PaulXiCao Jul 7, 2024
6cd8c7f
handle overflows
PaulXiCao Jul 7, 2024
965dfb6
index.rst: add special math status page to TOC
PaulXiCao Jul 7, 2024
44b7b80
cmath.inc: uncomment std::hermite functions
PaulXiCao Jul 7, 2024
932e084
cmath: added implemented functions to synopsis
PaulXiCao Jul 7, 2024
473f600
cmath: add hermite{l,f} to synopsis
PaulXiCao Jul 7, 2024
6932143
test: format test's synopsis
PaulXiCao Jul 7, 2024
4af48df
get rid of doxygen-style comments
PaulXiCao Jul 7, 2024
8755100
test: renamed MAX_N to g_max_n
PaulXiCao Jul 7, 2024
4fe24ae
test: assert(false) instead of assert(0)
PaulXiCao Jul 7, 2024
34bd197
test: inf result for finite input
PaulXiCao Jul 7, 2024
4580bf0
rename to use ugly name: inf -> __inf
PaulXiCao Jul 7, 2024
d68145c
silence clang-tidy warning about variable name in math code
PaulXiCao Jul 7, 2024
1a66064
test: add more values for integeral x
PaulXiCao Jul 7, 2024
f01e17a
export functions for module usage
PaulXiCao Jul 7, 2024
bb43f5a
Revert "export functions for module usage"
PaulXiCao Jul 7, 2024
bc27d9c
Adds a work-around to pass the module tests.
PaulXiCao Jul 7, 2024
7cb43b0
fix test: unsupported case must also return a value
PaulXiCao Jul 7, 2024
6a6fce8
remove wrongly added code
PaulXiCao Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions libcxx/docs/ImplementationDefinedBehavior.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you checked whether the results actually make sense beyond 128?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only check upto n<128.
By the nature of it we can only check upto some finite value and this given value from the Standard seemed reasonable. Also note that our implementation does not distinguish between different orders (e.g. nothing like below/above any threshold). Do you think that we should increase the test coverage for the parameters?

E.g.

- ``std::hermite(unsigned n, T x)`` for ``n >= 128``


Listed in the index of implementation-defined behavior
======================================================

Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx17.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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: The required macros are only implemented as of clang 19.
.. [#note-P0452] P0452: The changes to ``std::transform_inclusive_scan`` and ``std::transform_exclusive_scan`` have not yet been implemented.
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx17Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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| [#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"
Expand Down
35 changes: 35 additions & 0 deletions libcxx/docs/Status/SpecialMath.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.. 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
======================

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*.
22 changes: 22 additions & 0 deletions libcxx/docs/Status/SpecialMathProjects.csv
Original file line number Diff line number Diff line change
@@ -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, 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|
| `[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|
1 change: 1 addition & 0 deletions libcxx/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Getting Started with libc++
Status/PSTL
Status/Ranges
Status/Spaceship
Status/SpecialMath
Status/Zip


Expand Down
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,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
Expand Down
84 changes: 84 additions & 0 deletions libcxx/include/__math/special_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// -*- 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/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
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17

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.

// NOLINTBEGIN(readability-identifier-naming)
if (__math::isnan(__x))
return __x;

_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;
}

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;
// NOLINTEND(readability-identifier-naming)
}

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
9 changes: 9 additions & 0 deletions libcxx/include/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ 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
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

floating_point hypot (arithmetic x, arithmetic y);
float hypotf(float x, float y);
long double hypotl(long double x, long double y);
Expand Down Expand Up @@ -315,6 +323,7 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept
#include <limits>
#include <version>

#include <__math/special_functions.h>
#include <math.h>

#ifndef _LIBCPP_MATH_H
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -1480,6 +1480,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" }

Expand Down
2 changes: 2 additions & 0 deletions libcxx/modules/std/cmath.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading