Repository navigation
Add Struve functions H_nu and L_nu - #1633
Merged
Merged
Conversation
NAThompson
force-pushed
the
struve-functions
branch
from
November 5, 2026 06:08
9f7d808 to
285da1c
Compare
Real order and argument, with x-derivatives; K's integral uses exp_sinh's new opt-in compensated summation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NAThompson
force-pushed
the
struve-functions
branch
from
November 5, 2026 06:10
285da1c to
f3354f0
Compare
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the Struve function H_ν(x) and the modified Struve function L_ν(x) for real order and argument, with optional x-derivatives. "Struve H function" is on the feature wishlist in #303.
API.
struve_h(nu, x),struve_h(nu, x, &derivative),struve_h(nu, x, pol)andstruve_h(nu, x, &derivative, pol), and the same forstruve_l. Negative x is allowed for integer ν (by reflection); at x = 0 the result is 0, 2/π at ν = −1, or an overflow error where it is infinite.Method (switch points chosen from per-method error maps against MPFR):
exp_sinhwith a new opt-in compensated summation,exp_sinh(max_refinements, compensated = true); with the defaultfalsethe integrator is bit-identical to before (checked on 44 integrals, including complex, norm and finite-interval ones) and as fast.tgammaalone is up to 11 ulps off), and the rounding of ν + 1 and ν + 3/2 carried to first order.Accuracy (double, against MPFR at the exact double arguments; the envelope is max(1/2, κ/2) ulps with κ = |x f′/f|). Over ν ∈ [−20, 100] × x ∈ [10⁻², 10⁴], 282 of 38,400 pixels of H and 167 of L are outside the envelope. What remains:
cyl_neumann(about 7 ulps for Y₀ and Y₁ and up to 13 for negative orders).cpp_bin_float_50is within about 55× the envelope; float is computed in double.struve_h, |ulps| / envelopestruve_l, |ulps| / envelopestruve_h(1, x)struve_h(40.5, x)struve_h(-7.3, x)struve_l(-7.3, x)struve_l(10, x)Performance (google/benchmark, Apple M1 Pro, -O2,
reporting/performance/struve_performance.cpp):cyl_neumann, for comparisonexp_sinhwithcompensated = truecosts 8–28% more than without on the existing quadrature benchmarks.Under CUDA,
exp_sinh_detail.hppandsinh_sinh_detail.hppdefined__constant__tables with the same names in the same namespace, so no translation unit could include both;special_functions.hppnow does (throughstruve.hpp), soexp_sinh's CUDA section moves into its own nested namespace.References are generated by
reporting/accuracy/struve_reference.jl(BigFloat series, checked at two precisions and against an independent MPFR implementation).🤖 Generated with Claude Code