Improve perf of Legendre polynomial calculations #70
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.
The current code for calculating associated Legengre polynomials in G4LegendrePolynomial has two issues:
It is a recursive solution to a recurrence whose time grows exponentially without a cache/memoization.
The code can take a user-provided cache, but the user must be careful to supply a fresh cache for for each value of x or wrong results will be generated (silently).
This commit rewrites the G4LegendrePolynomial::EvalAssocLegendrePoly routine to address both of these issues:
It iteratively walks up from P[m,m,x] to P[l,m,x] in O(l-m) time.
It eliminates use of the cache entirely. A new signature without the cache has been introduced, and any call made with a cache falls through to this new one. The cache-bearing call has been retained in case any external callers rely on it.
There do not appear to be any references to this method in the Geant4 codebase itself that pass a non-null cache. The few references that do exist are in G4PolarizationTransition; these have been rewritten to use the cache-free call.
The list of special cases for small l and m values has been slightly expended (to negative m) and restructured as a case statement, primarily to improve readability. These have been retained since they appear to offer a modest performance benefit for these small cases.
This new method appears to perform better (often substantially better) than the old one over all tested parameters, even when a proper cache was used. It uses the same recurrence as the old method, and results seem identical.