-
Notifications
You must be signed in to change notification settings - Fork 11
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
Special half-integer branch for besselk
#46
Conversation
I see that one test is failing, but it doesn't have to do with the code in this PR and all tests relevant to this new code pass. I'm not really sure how to handle that. |
Thanks for contributing this!!! A few general ideas on how we want to handle this. Because this is so linked to the modified spherical bessel functions it would also be nice to have those defined. I've already given routines for the regular spherical bessel functions (https://github.com/JuliaMath/Bessels.jl/blob/master/src/sphericalbessel.jl) so having these linked would be nice (but probably in a separate PR). I guess having to call something like One thing is for very large orders it's probably more efficient to use the asymptotic expansion? I have defined something similar at ( Bessels.jl/src/sphericalbessel.jl Lines 136 to 145 in 0302204
|
Good points. This function I'm submitting literally is Also, a good call about checking for |
I think this definitely gives a solution for the modified spherical bessel function (only for integer orders) so we should probably define that as well. But I think I'm generally in favor of having that as a separate file (modifiedsphericalbessel.jl) and we can have the specialized half integer routines there. I think the general question is should we dispatch for half integer orders within the Line 233 in 0302204
besselk0 or besselkhalf.
Or would users look to the sphericalbesselk routines if they are using half integers of besselk? 🤷♂️ Also it does look like that test failure is related. It is failing at |
test/besselk_test.jl
Outdated
@@ -67,6 +67,12 @@ k1x_32 = besselk1x.(Float32.(x)) | |||
@test besselk(100, 3.9) ≈ SpecialFunctions.besselk(100, 3.9) | |||
@test besselk(100, 234.0) ≈ SpecialFunctions.besselk(100, 234.0) | |||
|
|||
# test half-integer orders: | |||
for v in (-3/2, -1/2, 1/2, 3/2, 5/2, 7/2, 9/2) |
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 think testing for larger orders and for more x values will be beneficial. These tests are so cheap and if we add other branches it will be nice to test around and after the cutoff.
Oof, you're right about the tests. Apologies for that. With regard to whether the branch should be in With regard to the comparison with the whole integer order, you're right that it's the same. Maybe better to re-use the code a bit more efficiently and use the existing recurrence function. I can look into that. Also, about modified spherical Bessels, I have never seen a non-integer order. NIST 10.47, the section on them, explicitly comments on the order only being an integer. Are there fractional-order spherical ones to worry about? If not, I would still be happy to move this function to a file and name it the spherical name (as well as the other checks you mention for I'm covered in meetings until the afternoon, but I won't let this PR languish, so will be on it soon. |
src/besselk.jl
Outdated
@@ -447,3 +447,5 @@ function besselk_vhalfint(v, x::T) where T | |||
end | |||
b1 | |||
end | |||
besselk_vhalfint_check(nu, x) = isinteger(nu-1/2) && (nu < 41.5) #@inline? |
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.
this will automatically inline.
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.
Good call. Will address in next commit.
Codecov Report
@@ Coverage Diff @@
## master #46 +/- ##
==========================================
- Coverage 93.79% 93.76% -0.04%
==========================================
Files 17 18 +1
Lines 1467 1491 +24
==========================================
+ Hits 1376 1398 +22
- Misses 91 93 +2
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
src/besselk.jl
Outdated
@@ -226,6 +226,9 @@ function besselk_positive_args(nu, x::T) where T <: Union{Float32, Float64} | |||
# dispatch to avoid uniform expansion when nu = 0 | |||
iszero(nu) && return besselk0(x) | |||
|
|||
# check if nu is a half-integer: | |||
besselk_vhalfint_check(nu, x) && return besselk_vhalfint(nu, x) |
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'm wondering if there's a better way to combine the large order checks? As in we check for large orders here besselk_vhalfint_check
and then after we check for large orders in besselik_debye_cutoff
so we are kind of doubling the checks.
It might make sense to have the debye_cutoff check come before, however, we don't want to dispatch for large arguments (x
) though so that would require some care.
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 crazy. I'll tinker with this and try to get rid of the extra check.
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.
One way is to just have the large order check within the besselk_vhalfint
which would avoid a check in the top level routine of besselk
and also make besselk_vhalfint
more generic (right now it is specialized to always do forward recurrence). So potentially if you want to call Bessels.besselk_vhalfint
you'd have the full routine?
Just some thoughts on this if we want to keep the half order check in the top level routine.
Do you know why that test seemed to fail? I notice it is passing now but it's because it's not dispatching to that method anymore. Funny enough - mathematica doesn't even give functions for I think the path forward (the code in general looks good) to merge this. Is to
|
Makes sense. I've just pushed another commit that moves things over. In the end if it's going to be its own function I re-implemented the spherical modified I'm confused about the CI failing, because all tests pass on my local branch. Also, with regard to whether the branch goes into the main With regard to why the tests were failing for a few |
the modified spherical bessel.
Really thanks for making these changes (I know it's a pain). I have something that will occupy me the rest of the day but one thought looking at the code now is it looks like it will give wrong results for negative orders if you call the routine directly. In the tests you put in you are calling the general Edit: Of course now there's a bunch of method errors 🤷♂️ |
…ne and add tests.
It's my pleasure to work this out. I spend all day fitting Matern functions and so I'll probably benefit the most of all the users of this package. Good catch on the negative order. I added a special check for that in the manual integer order routines where the negative sign wouldn't otherwise be handled correctly and also added some tests. Also, apologies for the method errors---my fault from the last overly quick commit. |
# = (...)*K_{|n| - 1/2} | ||
# = (...)*K_{|n|-1 + 1/2} | ||
# = k_{|n|-1} | ||
_nu = ifelse(nu<zero(nu), -one(nu)-nu, nu) |
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.
What do we want to do for negative arguments? Do you need these routines for complex arguments? We should probably throw domain error for now instead of giving a method error.
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.
Argh, you're right. Apologies, I'm just not in the headspace of implementing this as a full function that will get called on its own and stuff. I don't need this for complex args and I'd be happy to put in the same check/error you use on besselk
.
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.
No problem! Does NaN propagate through this as well? But I think the general structure of besselk for this is good. And we can add complex methods as we get to them.
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.
Another good catch. Just pushed something up that I think addresses both, although yet another branch due to an isnan
to avoid just getting the domain error.
Ok I've had time to look through this. I've made some changes but had some git issues which created a new branch. I'll merge this then fix those changes after. There are a couple of things I tried to fix.
I'll try to see if I can merge this into here real quick (I thought I was directly editing this.... but I guess not) |
Thanks for contributing this @cgeoga !!! Looking forward to the large argument expansions 😉 |
Amazing, thanks for all the improvements! Preparing the large argument expansion one now. |
Here is a PR that closes the discussion of #25. I've tried to format things in a way that is consistent with the rest of the code in terms of four space tabs, not lining up the equals signs, putting the two consts into the appropriate file, and adding tests. But I'm sure there's something I missed so please let me know what should be fixed.
I recognize that having another check of
isinteger(nu-1/2)
in everyBessels.besselk
call is probably not super exciting to you guys, but at least for stat people it is a branch that will get hit often and the speedup is pretty nice.After getting the hang of making these PRs with this easy one I'll follow up and make another one for the asymptotic expansion to use in the case of small
nu
and largex
, which I think will have some convincing speed gains.