ENH: Replace ITKNetlib/SLATEC with std and Eigen special functions#6512
ENH: Replace ITKNetlib/SLATEC with std and Eigen special functions#6512hjmjohnson wants to merge 4 commits into
Conversation
Phase-5 proof: Eigen vs netlib/SLATEC special functions (issue #6498)Verdict. Two-axis comparison (lower is better on both)Accuracy = max / mean relative error vs a 50-digit mpmath reference over the
Gamma grid: a ∈ {0.5,1,2,3.5,5,11,25,50} × x ∈ {0.1,0.5,0.9,1.0,1.5,3.0}·a EnvironmentApple M3 Max, macOS 26.5.1, Apple clang 21.0.0, Reproducer
|
cba6e09 to
af0605f
Compare
|
@greptile review |
|
| Filename | Overview |
|---|---|
| Modules/Core/Common/include/itkSpecialFunctions.h | New public header exposing IncompleteGammaP and RegularizedIncompleteBeta via Eigen numext; template wrappers with static_assert guard are correct |
| Modules/Numerics/Statistics/src/itkChiSquareDistribution.cxx | Replaces dgami_/dgamma_ SLATEC calls with std::tgamma and Math::IncompleteGammaP; argument mapping (dofon2, xon2) is mathematically equivalent |
| Modules/Numerics/Statistics/src/itkTDistribution.cxx | Replaces dbetai_/dgamma_ with Math::RegularizedIncompleteBeta and std::exp(lgamma-lgamma); argument order (pin,qin,bx) matches old SLATEC signature; lgamma-difference avoids overflow at large dof |
| Modules/Numerics/Statistics/test/itkTDistributionGTest.cxx | Full GTest replacement of itkTDistributionTest covering CDF/InverseCDF for dof=1 and dof=11, parameter-vector API, wrong-parameter throws, and variance semantics; tolerances match Eigen accuracy |
| Modules/Core/Common/test/itkSpecialFunctionsGTest.cxx | New GTest with SciPy reference values, boundary identities, beta symmetry, and float overload coverage for both new wrappers |
| Modules/Numerics/Statistics/itk-module.cmake | Removes ITKNetlib from ITKStatistics DEPENDS; ITKCommon (which now owns itkSpecialFunctions.h) is already a dependency |
| Modules/ThirdParty/Eigen3/UpdateFromUpstream.sh | Registers unsupported/Eigen/SpecialFunctions and its src/ tree in the upstream-sync script so future Eigen bumps carry the module |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
subgraph ITKCommon ["ITKCommon (new)"]
SF["itkSpecialFunctions.h\nIncompleteGammaP\nRegularizedIncompleteBeta"]
E["Eigen::numext::igamma\nEigen::numext::betainc"]
SF --> E
end
subgraph ITKStatistics
CHI["itkChiSquareDistribution.cxx\nPDF: std::tgamma\nCDF: IncompleteGammaP"]
TDIST["itkTDistribution.cxx\nPDF: exp(lgamma-lgamma)\nCDF: RegularizedIncompleteBeta"]
end
subgraph OLD ["Removed: ITKNetlib / SLATEC"]
NET["dgamma_\ndgami_\ndbetai_"]
end
SF --> CHI
SF --> TDIST
OLD -. replaced .-> CHI
OLD -. replaced .-> TDIST
subgraph TESTS
SFTEST["itkSpecialFunctionsGTest\n(SciPy reference, boundaries,\nbeta symmetry, float overload)"]
TDTEST["itkTDistributionGTest\n(CDF/InvCDF dof=1,11,\nparam APIs, throws, variance)"]
end
SF --> SFTEST
TDIST --> TDTEST
CHI --> TDTEST
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
subgraph ITKCommon ["ITKCommon (new)"]
SF["itkSpecialFunctions.h\nIncompleteGammaP\nRegularizedIncompleteBeta"]
E["Eigen::numext::igamma\nEigen::numext::betainc"]
SF --> E
end
subgraph ITKStatistics
CHI["itkChiSquareDistribution.cxx\nPDF: std::tgamma\nCDF: IncompleteGammaP"]
TDIST["itkTDistribution.cxx\nPDF: exp(lgamma-lgamma)\nCDF: RegularizedIncompleteBeta"]
end
subgraph OLD ["Removed: ITKNetlib / SLATEC"]
NET["dgamma_\ndgami_\ndbetai_"]
end
SF --> CHI
SF --> TDIST
OLD -. replaced .-> CHI
OLD -. replaced .-> TDIST
subgraph TESTS
SFTEST["itkSpecialFunctionsGTest\n(SciPy reference, boundaries,\nbeta symmetry, float overload)"]
TDTEST["itkTDistributionGTest\n(CDF/InvCDF dof=1,11,\nparam APIs, throws, variance)"]
end
SF --> SFTEST
TDIST --> TDTEST
CHI --> TDTEST
Reviews (3): Last reviewed commit: "ENH: Add GoogleTests for itk::Math speci..." | Re-trigger Greptile
|
Awesome! Great work! Why are the stdlib gamma functions used directly but the Eigen gamma and beta functions are? Was there an issue with direct use of the Eigen functions? |
@blowekamp There is no functional issue with the Eigen calls — Eigen::numext::igamma/betainc work fine called directly. The split is a deliberate API-boundary choice, not a workaround: RULE: Use std:: whenever possible to minimize maintenance burden. (avoiding transitive Eigen exposure in the distribution TUs (cf. #6230). When Eigen simply aliases c++17 features (i.e. in some Eigen API predate pre c++11, or 14, or 17 was a local algorithm, now is simple std:: reference).
|
af0605f to
d0c9e0e
Compare
|
⛔ Blocked on #6514 (CI-ordering only — no code dependency). The red #6514 ("COMP,BUG: Fix IODCMTK test include paths", approved) fixes it. Once it lands I'll rebase this branch onto the fixed |
d0c9e0e to
8b27bee
Compare
Add the Eigen SpecialFunctions module (scalar numext::igamma and numext::betainc) to the itkeigen tree and register its paths in UpdateFromUpstream.sh so the next Eigen re-sync preserves it. Enables an Eigen-backed replacement for the netlib/SLATEC special functions used by ITKStatistics (issue InsightSoftwareConsortium#6498).
…ctions Replace the netlib/SLATEC special-function calls in the chi-square and Student-t distributions with std::tgamma and the Eigen-backed itk::Math::IncompleteGammaP and itk::Math::RegularizedIncompleteBeta.
Drop the ITKNetlib dependency from ITKStatistics and delete the Modules/ThirdParty/Netlib module; its vendored netlib/SLATEC routines no longer have any consumer. Closes InsightSoftwareConsortium#6498.
Add itkSpecialFunctionsGTest validating IncompleteGammaP and RegularizedIncompleteBeta against SciPy references (boundary, beta symmetry, float overload), and scavenge the legacy itkTDistributionTest into itkTDistributionGTest exercising the Eigen-backed Student-t path.
|
The mac failures are fixed in already merged PR. |
8b27bee to
29b5019
Compare
Replaces the vendored netlib/SLATEC special functions used by the
ITKStatisticschi-square and Student-t distributions withstd::tgammaandthe Eigen-backed
itk::Math::IncompleteGammaP/RegularizedIncompleteBeta,and removes the now-unused
ITKNetlibthird-party module. Closes #6498.Aligns with the VNL/netlib → Eigen numerics direction (#6403, #6230); follows
the deprecation/benchmark pattern of #6441 and #6454.
What changed
SpecialFunctionsmodule (scalarnumext::igamma,numext::betainc) and registered it inUpdateFromUpstream.sh.itkSpecialFunctions.h(itk::Math::IncompleteGammaP,RegularizedIncompleteBeta).itkChiSquareDistribution/itkTDistribution: Γ →std::tgamma; theincomplete gamma/beta calls → the new Eigen-backed API.
ITKNetlibfromITKStatisticsdeps and deletedModules/ThirdParty/Netlib(~3,800 lines of Fortran-era C).itkSpecialFunctionsGTest(vs SciPy references); legacyitkTDistributionTestscavenged intoitkTDistributionGTest.Phase-5 benchmark: Eigen vs SLATEC (50-digit mpmath truth)
stdis preferred where available (Γ →std::tgamma); Eigen backs the twofunctions with no std equivalent. Both replacements are far more than accurate
enough for the probability distributions (the distribution GTests pass at
1e-14 CDF / 1e-12 inverse).
Eigen wins both axes for the incomplete gamma. For the incomplete beta it is
~8.7× faster with a last-digit accuracy trade (3.0e-14 vs 7.5e-15, both
tens-of-ULP) — accepted because #6498 retires the module entirely and the
difference is irrelevant at the distribution level. Apple M3 Max, clang 21,
-O3, single-thread, median of 25×20000.