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

Conversation

PaulXiCao
Copy link
Contributor

@PaulXiCao PaulXiCao commented Apr 24, 2024

Implementing the Hermite polynomials which are part of C++17's mathematical special functions. The goal is to get early feedback which will make implementing the other functions easier. Integration of functions in chunks (e.g. std::hermite at first, then std::laguerre, etc.) might make sense as well (also see note on boost.math below).

I started out from this abandoned merge request: https://reviews.llvm.org/D58876 .

The C++23 standard defines them in-terms of /* floating-point type */ arguments. I have not looked into that.

Note, there is still an ongoing discussion on discourse whether importing boost.math is an option.

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@PaulXiCao
Copy link
Contributor Author

@mordante I would be thankful for feedback on this implementation.

@mordante mordante self-assigned this Apr 24, 2024
@Zingam
Copy link
Contributor

Zingam commented Apr 25, 2024

You should prefix your PR's title with something like [libc++] or [libc++][math], etc.

@PaulXiCao PaulXiCao changed the title Mathematical Special Functions: Hermite Polynomial [libc++][math] Mathematical Special Functions: Hermite Polynomial Apr 25, 2024
#if _LIBCPP_STD_VER >= 17

# include <experimental/__math/hermite.h>
# include <type_traits> // enable_if_t, is_integral_v
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't do reviews usually due to my incompetence but here are my 2 cents.

I believe we do includes unconditionally. We also include the granularized headers e.g. enable_if.h, instead of type_traits? Or is it required by the standard to include it?

Copy link
Member

Choose a reason for hiding this comment

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

@Zingam you're always free to do reviews.

This comment is correct the include should be unconditional and please use the granularized headers. (Headers mandated by the standard should be in the top-level header. I would be extremely surprised when type_traits is mandated.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks!

@PaulXiCao I'd recommend to check recent PRs and their comments as a general guide for style and recent best practices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea! Will do so.

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

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

Thanks a lot for working on this!
I mainly focused on the libc++ specific parts of the implementation.

#if _LIBCPP_STD_VER >= 17

# include <experimental/__math/hermite.h>
# include <type_traits> // enable_if_t, is_integral_v
Copy link
Member

Choose a reason for hiding this comment

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

@Zingam you're always free to do reviews.

This comment is correct the include should be unconditional and please use the granularized headers. (Headers mandated by the standard should be in the top-level header. I would be extremely surprised when type_traits is mandated.)

@Zingam
Copy link
Contributor

Zingam commented Apr 26, 2024

@PaulXiCao It may be useful to add a status page to track the progress and assignments.
https://libcxx.llvm.org/#getting-started-with-libc

@PaulXiCao PaulXiCao marked this pull request as ready for review April 27, 2024 20:36
@PaulXiCao PaulXiCao requested a review from a team as a code owner April 27, 2024 20:36
Comment on lines 810 to 811
template <class _Integer>
_LIBCPP_HIDE_FROM_ABI std::enable_if_t<std::is_integral_v<_Integer>, double> hermite(unsigned int __n, _Integer __x) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
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 int __n, _Integer __x) {

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 do not have too much experience with TMP. Could you elaborate on the advantage of your proposed change? Introducing an unused template argument type int seems strange to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just found other code which also uses the style you suggested (e.g. libcxx/include/__math/abs.h#L37). I will implement the change you suggested, but would still welcome your thoughts on this :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 51f82a50b9007edbb000cfcdcc353dfc28cb8ab2.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's nothing inherently wrong about return type SFINAE. It's just that the enable_if_t<..., int> = 0 version works everywhere. Return type SFINAE doesn't work on constructors, enable_if_t<...>* = nullptr doesn't work in C++03 etc. This avoids confusion on which version should be used in which case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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 ("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(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.

return __H_n;
}

inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return std::__hermite(__n, __x); }
Copy link
Contributor

Choose a reason for hiding this comment

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

Not attached: should the mathematical special functions be in the dylib? I expect this will be quite a bit of code, and it would be nice to be consistent between the special functions.

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 cannot anticipate how much code that will be nor what the threshold is when we should be using dynamic libraries. Could we make that switch with a later integration, e.g. once the LOC exceed some threshold?

Copy link
Contributor

Choose a reason for hiding this comment

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

Moving code into the dylib has quite a few consequences and may change design considerations, so I don't think we should wait until some later point. Unless we want to make the functions experimental for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I will need to look into that. Can you point me in some direction? Documentation or other sample code?

Copy link
Contributor Author

@PaulXiCao PaulXiCao May 3, 2024

Choose a reason for hiding this comment

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

From a discussion with @mordante (please feel free to comment if I misunderstood something):

  • This function is quite small and probably does not need to go into the dylib.
  • Large code or special template magic could be moved there.
  • Concerning the other special math functions: I assume they probably will not contain too much code nor any special template magic.
  • We still have the option in the future to move other special math functions into the dylib even though this one might stay in the header.

if (std::isnan(__x))
return std::numeric_limits<_Real>::quiet_NaN();

_Real __H_0{1};
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does the standard make n >= 128 implementation-defined?

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 could only speculate. Not sure where to find information on that...

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably somewhere deep within the archives of wg21. I hope @lntue has some insight here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have no idea why they put that in the standard. My guess is that some might implement the recurrence relation without multiply-by-2 part, and then scale the final results by 2^n. For n >= 128, 2^128 exceeds the range of float type, so this way of computing hermite polynomials might not support n >= 128 for float.

Copy link
Contributor

Choose a reason for hiding this comment

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

See https://wg21.link/n1884. TLDR: the function changes so rapidly that it's difficult to even get the correct sign.

@PaulXiCao
Copy link
Contributor Author

@PaulXiCao It may be useful to add a status page to track the progress and assignments. https://libcxx.llvm.org/#getting-started-with-libc

Done in 18a320a0f523d1939262d1cfc633da6e5fae4870.

return __H_n;
}

inline _LIBCPP_HIDE_FROM_ABI double hermite(unsigned __n, double __x) { return std::__hermite(__n, __x); }
Copy link
Contributor

Choose a reason for hiding this comment

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

Moving code into the dylib has quite a few consequences and may change design considerations, so I don't think we should wait until some later point. Unless we want to make the functions experimental for now.


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?

} // namespace

int main(int, char**) {
test_hermite<float>(1e-5f, 1e-5f);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please refactor the tests to the style

template <class T>
void test() {
  { // Write what the test checks
    // put the test here
  }

  { // and the next test
    // some code
  }
}

We generally use this in new tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do I understand you correctly that the main should only call 3 test<T>(); functions (for T=float, double, long double)?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, exactly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in 8b57a634c764c2aef653106fbb6b762663f9cf75.

__H_n_prev = __H_n;
__H_n = __H_n_next;
}
return __H_n;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we could have somewhat accurate overflow detection here with:

if (std::isnan(__H_n)) {
  // Overflow.
  if (n & 1)
    // n is odd, return infinity of the same sign as x.
    return std::copysign(std::numeric_limits<_Real>::infinity(), x);
  // n is even, return +Inf
  return std::numeric_limits<_real>::infinity();
}
return __H_n;

Copy link
Contributor Author

@PaulXiCao PaulXiCao Apr 30, 2024

Choose a reason for hiding this comment

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

I need to think about this a bit more. Alternating Infs is definitely true in the limit x goes to infinity, but I believe there is also a possibility for an overflow because of large n. The problem is that the polynomials are oscillating and one probably cannot easily tell the correct sign for a small x but larger n. (One needs to know between which roots the x lies...)

Copy link
Contributor

Choose a reason for hiding this comment

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

+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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could make use of your proposed code snippet at the entry of the function, e.g.

_LIBCPP_HIDE_FROM_ABI _Real __hermite(unsigned __n, _Real __x) {
  if (std::isnan(__x))
    return __x;
  if (std::isinf(__x)) {
    // ... your proposed overflow handling
  }
  // ...

Though I am unsure of the importance of handling std::hermite(n, +-Inf) correctly. Personally I would not expect correct output for such an input (informally known as "garbage in, garbage out" ;D).
Let me know if this is worth implementing.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking of something like this:
https://godbolt.org/z/7MaYYzob9

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks good. Can I ask why you check for std::isnan instead of std::isinf? I believe I have seen examples where at some n the next 2 results were Inf and then turned to NaN. If I find some more time I will try to find such an example.

Copy link
Contributor

Choose a reason for hiding this comment

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

So I think for finite __x, if some intermediate __H_n is Inf, it is "correctly" overflowed (I might need to prove it or if it is not right, find some counter example). So checking isnan should be enough. OTOH, probably we should just use !std::isfinite(__H_n) instead.

Copy link
Contributor Author

@PaulXiCao PaulXiCao May 4, 2024

Choose a reason for hiding this comment

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

I looked some more into possible overflows. First thing to notice is that double overflows at ~1e308.
Hermite polynomial H_127 does not reach such large values inbetween any roots but only for larger x:

  • largest root is at x=~16
  • function values previous to the last root are significantly below the overflow threshold, i.e. |H_127(x)| < ~1e190 for |x| < ~16
  • overflow threshold is reached at roughly: H_127(x=140)~1e308
  • (one can see this from this wolframalpha log-log-plot)

For polynomials of smaller order it is even more extreme (e.g. largest root is smaller and overflow happens at even larger x).
I would not take polynomials of higher order into this discussion as their result is deemed implementation-defined by the Standard. Thus, possibly slowing down code for n<128 because of arguments for n>=128 seems strange.

My conclusion: I believe your initial suggestion is enough (e.g. checking the value of __H_n after the loop). Using !std::isfinite() also seems the approriate check here.

I will probably push a change similar to hermite2 as in this godbolt. (hermite is the current implementation, and hermite1 the one you proposed in the previous godbolt.)

(This whole argument assumes atleast 8 byte double. Is this valid?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in 511b45679ab65dc3efca81abc976c27711a5df9a.

Copy link
Contributor

Choose a reason for hiding this comment

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

SGTM


template <class T>
std::array<T, 7> sample_points() {
return {-1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0};
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add some sample points that have magnitude > 1 and +- Inf?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, makes sense. I'll look into that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 0098ee77a763ea393f0993037e9d93aab2a209c9 (for points with magnitude >1) and c94fad9ba48a4bb4149ab5cc8f97e1a2a3ac34f4 (for +-Inf).


#include "type_algorithms.h"

inline constexpr unsigned MAX_N = 128;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
inline constexpr unsigned MAX_N = 128;
constexpr unsigned MAX_N = 128;

Nit: constexpr implies inline.
https://eel.is/c++draft/dcl.constexpr#:constexpr
Usually we don't put an explicit inline on templates and constexpr for that matter.

Copy link
Member

Choose a reason for hiding this comment

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

This is not a function or a static data member, so it's not implicit inline.

For templates we use both with and without inline and there is not strong preference.

For functions some people have a strong preference to use inline constexpr; and the inline is redundant.

Typically we don't use capitalized constants.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed the constant to g_max_n in df4eadfa73f14831d6cd1bd045d5f5081dea31d6. Unsure if this is the correct naming scheme as I did not find another file with an example. Let me know if it should be changed to something else.

case 0:
return {};
case 1:
return {T(0)};
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return {T(0)};
return {T{0}};

Is there any reason for () vs {}?

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 want to use the same style on this line as in the following ones. And the next lines need to perform a narrowing conversion (e.g. return {T(0.707106781186548)}; for T=float). Using braces I assumed that the compiler or some tool (e.g. clang-tidy) would throw warnings. Let me know if this is baseless.

Comment on lines 26 to 29
/// \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) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe there was a comment already that we don't use doxygen comments. I think you should move that comment inside the function body.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in d4ea6088dca10dde0cfc21ad25ec3df218955c8c.


#include "type_algorithms.h"

inline constexpr unsigned MAX_N = 128;
Copy link
Member

Choose a reason for hiding this comment

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

This is not a function or a static data member, so it's not implicit inline.

For templates we use both with and without inline and there is not strong preference.

For functions some people have a strong preference to use inline constexpr; and the inline is redundant.

Typically we don't use capitalized constants.

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

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

@lntue Thanks for your help reviewing! Can you approve the patch when you feel it's correct from the math point of view? I'll look at the libc++ specifics.

The patch seems mostly good to me.

}

{ // check input infinity is handled correctly
Real inf = std::numeric_limits<Real>::infinity();
Copy link
Member

Choose a reason for hiding this comment

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

I would like some infinity tests that use finite values as input.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Implemented in 55ec209c8a261e8a48cbefc7a63e0ca776905b90. This contains only tests for T=double. It is dependent on the size of the type. long double can be different on other platforms which would result in quite messy test code. Let me know if I should generalize this test some more.

Copy link
Contributor

@lntue lntue left a comment

Choose a reason for hiding this comment

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

The math part looks good to me! Thanks!

@efriedma-quic
Copy link
Collaborator

Should the documentation record the known error in ulps of the computed result? See, for comparison, https://libc.llvm.org/math/index.html .

@PaulXiCao
Copy link
Contributor Author

PaulXiCao commented May 16, 2024

Should the documentation record the known error in ulps of the computed result? See, for comparison, https://libc.llvm.org/math/index.html .

If I see that correctly the cited page lists functions (e.g. sin) vs input type (e.g. float) and their correctness, i.e. errors counted in ULP for each rounding mode.

For any non-trivial implementation this is mostly calculated by comparing the result with a reference implementation, e.g. an implementation using larger floating-point types or a multi-precision library. I assume they did the same there?

This worst-case analysis only holds any meaning for well chosen sample points. We would need to decide what a common input range is. (Sounds difficult for a general-purpose library.)

All of this is quite tedious and complicated. Which is why it probably has not been done for most of the "Higher Math Functions" in libc? (The table is almost empty.)

A plain documentation by creating a similar table for the "Mathematical Special Functions" only filled with "N/A" does not yield any benefit from my point of view.

@efriedma-quic @intue I would be interested in your opinions on this topic.

@efriedma-quic
Copy link
Collaborator

The empty squares in that table are stuff that hasn't been implemented in llvm-libc yet. (llvm-libc is, in general, currently a work in progress.) glibc also has a similar table in their documentation.

For "float" inputs, in some cases you can probably figure out the worst-case error across the whole range by brute force. For wider inputs, you'd need some combination of random sampling, and brute-force of a few carefully chosen small intervals, yes.

@PaulXiCao
Copy link
Contributor Author

There is also another option: We could consider splitting off the correctness documentation into its own issue/merge request.

My thoughts:

  • There is no real reason why everything must be handled in one pr.
  • Correctness documentation seems to be a more involved issue which will probably need quite some discussion.
  • There are other pr waiting for this integration (e.g. std::legendre).
  • On the flip-side: There is the possibility that it might be pushed to some backlog and not get fixed in the foreseeable future.

@mordante
Copy link
Member

There is also another option: We could consider splitting off the correctness documentation into its own issue/merge request.

My thoughts:

* There is no real reason why everything must be handled in one pr.

* Correctness documentation seems to be a more involved issue which will probably need quite some discussion.

* There are other pr waiting for this integration (e.g. `std::legendre`).

* On the flip-side: There is the possibility that it might be pushed to some backlog and not get fixed in the foreseeable future.

In libc++ we have not added this documentation for other math functions. For example lerp. so I don't feel this should be a blocker for this patch.

It would be nice to do in a separate patch.

PS I just restarted to build.

@efriedma-quic
Copy link
Collaborator

I'm less concerned about the documentation, and more concerned that you've done the underlying analysis to prove the implementation actually has the numerical properties you want over the defined range. If you skip that analysis, you end up with issues like #92782.

@PaulXiCao PaulXiCao force-pushed the specialMath_hermite branch from a5c72d8 to 7cb43b0 Compare July 12, 2024 17:41
@PaulXiCao
Copy link
Contributor Author

The CI failure is unrelated to your patch. I wanted to commit this patch but I noticed your e-mail address is hidden. Could you make this visible?

@mordante I added my email to each commit.

Thanks! I see one Apple build failure. I'm not sure it's related so I started to other CI runners.

The other builds pass. Could you rebase to make sure the apple build is indeed a fluke. The number of errors it gives makes me uncomfortable to merge without a new run.

@mordante I rebased to the current main branch.

@mordante
Copy link
Member

The CI is green. However it seems GitHub wants to merge with a noreply email address, so it seems your address is still hidden.

@PaulXiCao
Copy link
Contributor Author

PaulXiCao commented Jul 16, 2024

The CI is green. However it seems GitHub wants to merge with a noreply email address, so it seems your address is still hidden.

@mordante I updated my profile and it now has a public email. Hope that helps. Sorry about the issues..

@Zingam
Copy link
Contributor

Zingam commented Jul 16, 2024

Why does this PR have so few CI checks?

@mordante
Copy link
Member

The CI is green. However it seems GitHub wants to merge with a noreply email address, so it seems your address is still hidden.

@mordante I updated my profile and it now has a public email. Hope that helps. Sorry about the issues..

No problem, I just verified and your e-mail is visible now, thanks.

Can you have a look at @philnik777's last comment.

Why does this PR have so few CI checks?

I expect since the last failure was apple only.

@PaulXiCao
Copy link
Contributor Author

Can you have a look at @philnik777's last comment.

@mordante Fixed the issue.

@mordante mordante merged commit af0d731 into llvm:main Jul 20, 2024
55 checks passed
Copy link

@PaulXiCao Congratulations on having your first Pull Request (PR) merged into the LLVM Project!

Your changes will be combined with recent changes from other authors, then tested
by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR.

Please check whether problems have been caused by your change specifically, as
the builds can include changes from many authors. It is not uncommon for your
change to be included in a build that fails due to someone else's changes, or
infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail here.

If your change does cause a problem, it may be reverted, or you can revert it yourself.
This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are working as expected, well done!

@mordante
Copy link
Member

Thanks a lot again for working on this! I expect it will be faster to get the other functions in.

@PaulXiCao PaulXiCao deleted the specialMath_hermite branch July 20, 2024 18:13
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
…9982)

Summary:
Implementing the Hermite polynomials which are part of C++17's
mathematical special functions. The goal is to get early feedback which
will make implementing the other functions easier. Integration of
functions in chunks (e.g. `std::hermite` at first, then `std::laguerre`,
etc.) might make sense as well (also see note on boost.math below).

I started out from this abandoned merge request:
https://reviews.llvm.org/D58876 .

The C++23 standard defines them in-terms of `/* floating-point type */`
arguments. I have not looked into that.

Note, there is still an ongoing discussion on discourse whether
importing boost.math is an option.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251212
zibi2 added a commit that referenced this pull request Aug 7, 2024
The HEX float on z/OS does not have infinity nor NaN. In addition, the
limits are smaller before the overflow occurs in mathematical
calculations. This PR accounts for this.

FYI, this LIT test was recently added in PR
[89982](#89982)
blueboxd pushed a commit to blueboxd/libcxx that referenced this pull request Apr 19, 2025
The HEX float on z/OS does not have infinity nor NaN. In addition, the
limits are smaller before the overflow occurs in mathematical
calculations. This PR accounts for this.

FYI, this LIT test was recently added in PR
[89982](llvm/llvm-project#89982)

NOKEYCHECK=True
GitOrigin-RevId: f343fee8c5c9526b3cf62ee6d450c44b69a47e87
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants