-
Notifications
You must be signed in to change notification settings - Fork 101
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
Rewrite gamma_inc_taylor
and gamma_inc_asym
more concisely
#443
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #443 +/- ##
=======================================
Coverage 94.10% 94.11%
=======================================
Files 14 14
Lines 2935 2905 -30
=======================================
- Hits 2762 2734 -28
+ Misses 173 171 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Oops, left an |
I know I originally suggested it but it would still be nice to know why it was implemented in this way to begin with as it is quite unusual and we are really just relying on the strength of the original test set here. My last comment is just about the convergence check. My original suggestion (#442 (comment)) checked for relative tolerance where this just checks for absolute tolerance. It probably doesn't matter but if the final result is much smaller than 1 they could be different. (edit: relative check will be slower so not saying just to do it instead) |
Alright, thanks! :-) I reverted to the original version, with your smaller suggestions. I kept the other one on another branch, gamma-fix2, just in case. |
Sounds good 😊 I’ll let other people comment on what they think of the two versions. This version will allocate though which might not solve your initial problem. If you want to sum in reverse order your probably best bet is to to use @nexprs to remove the array then can sum in any order you want. I’m not for sure it’s really needed here though but it would be nice since we are putting in the effort to make this allocation free ! |
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
Ah, found an allocation-free way! Before I commit it:
|
Ah,
|
Bumping - any more work needed on this? |
What do I need to do to get this in? I have a couple bits of code that would really benefit from this change, and I'd like not to have to disable precompilation. |
@devmotion Is this good to merge? |
break | ||
end | ||
|
||
# compute first 21 terms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if summation in reverse order is necessary (something like #442 (comment) would be much simpler implementation-wise)? I wonder if there is any argument/comment regarding this choice in the original Fortran code - does anyone know where the current implementation was copied from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory better for numerical stability and precision to do it this way, because otherwise you can lose the accumulated effect of the small components when they're very much smaller than the large components, but I don't know in practice if/when it affects results of this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've found a couple possible sources, but I think I'm gathering that the impetus was to support arbitrarily low precision. Maybe with Float64 it works pretty much fine, which this package forces. But with lower precision, maybe the errors would add up too much if floating point math wasn't carefully managed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like @Sumegh-git and @simonbyrne were writing/reviewing the PR that introduced them, if they can comment :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does anyone know where the current implementation was copied from?
ACM TOMS (FREE ACCESS): https://dl.acm.org/doi/abs/10.1145/22721.23109
Fig. 2 in the paper shows the flowchart of the algorithm as a whole.
gamma_inc_taylor
: Equ. 15gamma_inc_asym
: Equ. 16
The original paper is mentioned in the code comments.
Perhaps those comments should be moved to the function documentation.
SpecialFunctions.jl/src/gamma_inc.jl
Lines 831 to 834 in fdf95ab
# Reference : 'Computation of the incomplete gamma function ratios and their inverse' by Armido R DiDonato, Alfred H Morris. | |
# Published in Journal: ACM Transactions on Mathematical Software (TOMS) | |
# Volume 12 Issue 4, Dec. 1986 Pages 377-393 | |
# doi>10.1145/22721.23109 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! In that case maybe this is the FORTRAN code itself? https://jblevins.org/mirror/amiller/inc_gam.f90
Just realized I have merge access now. Would anyone object if I merged it as-is? It's a strict improvement on the status quo, even if it could be improved further. All tests green. I'll wait a week if I don't hear anything. |
With respect to bumping the minimum version of Julia from 1.3 to 1.5, the CI is no longer even testing against < v1.6 |
Please merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
That was fixed in #478. |
Co-authored-by: CyHan <cyhan.dev@outlook.com>
ts = cumprod(ntuple(i -> (a - i) / x, Val(21))) | ||
|
||
# sum the smaller terms directly | ||
first_small_t = something(findfirst(x -> abs(x) < 1.0e-3, ts), 21) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good to avoid the heap allocation but this unconditionally computes all 21 elements and then subsequently does a search while the original breaks early while providing the index for free. Would it be possible to keep the benefits of the old implementation and still avoid the heap allocation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not one I was able to think of at the time, but it didn't seem to much matter in practice because the allocation was more expensive than the extra computations. I even tried a version that was a bit more conservative and in practice didn't seem to matter much at all on my system.
Many functions were translated directly from Fortran. This PR rewrites two of them using more concise Julia forms.
Ideally would like to eliminate the array allocation as well.(See #442) And now does!