-
Notifications
You must be signed in to change notification settings - Fork 2
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
Accuracy of bessel functions for larger arguments #4
Comments
Very good point, thank you! My Fortran implementation is not as polished as yours, though it gets pretty good performance already. I'll definitely put this improvement in the pipeline. BTW: Fortran has no elemental real(BK) function cos_sum(a,b)
real(BK), intent(in) :: a, b
real(BK) :: ca,sa,cb,sb
ca = cos(a)
sa = sin(a)
cb = cos(b)
sb = sin(b)
cos_sum = (ca*cb-sa*sb)
end function |
Ya there’s a couple of ways to do it but it pops up frequent enough that having a function for it will be helpful. It will be slightly slower of course but is much more accurate even near zeros. You could also reduce each argument within the sin first before adding them together. That will also significantly improve the accuracy. In general only one argument needs to be reduced as the other one is usually <pi. So that will be faster and Definitely more accurate than the naive case but unsure if it’s as accurate as approach above. Probably be similar depending on how good the argument reduction is done! |
That's indeed one of the reasons I try to keep whole packages within a single module file. I know many people don't like the approach and split packages into many files. But link time optimization in Fortran is usually pretty bad, and if your whole package is contained within the same file, any compilers will inline all these small functions, so, you get more readable code with no performance loss. |
Sounds good! I think just inserting your above code is fine. My comment was more so that this type of function pops up very frequently in all the Bessel function implementations so it's good to have a routine you like and can change easily. I don't think there's actually going to be much link-time optimization besides if your compiler will inline or not as this would be a strictly accuracy improvement at the cost of several nanoseconds. So that tradeoff is definitely up to you as this will contain more arithmetic operations 😄 This is essentially the outcome of delaying any floating point issues until the very end. All the arithmetic up to this point should be accurate to less than <1.5 ULP. So any numerical errors are mostly contained on this single line. Unfortunately, this line is very expensive even in the naive case compared to rest of routine so even a small change in this will be felt in the total routine. |
I was looking through the code and was curious how
fortran-bessels/src/bessels.f90
Line 100 in ee7e6f4
It's much better to do something like...
because it essentially acts as a range reduction putting the two values at similar magnitude. Therefore, when summed they lose less precision. We are working on a slightly different approach but if Fortran has a good function to give you both
sin
andcos
this could significantly improve the accuracy! It should only cost a few cycles but will be able to provide much better relative tolerances.The text was updated successfully, but these errors were encountered: