Unnormalized sinc

The current implementation of sinc is the normalized one. I think it’s a good idea to also have the unnormalized one. I’m not sure what name to pick.
Would there be any interest in this function?

Note that this is the same sinc definition as the one used in Matlab, Numpy, and R. (But SymPy and Mathematica use the unnormalized definition.) It seems like most languages picked one definition and stuck with it, so I don’t see a pressing need to have both in Julia.

However, it wouldn’t be terrible to add something like this to the SpecialFunctions package. I can’t find a standard naming convention to distinguish the two, so it seems you’d have to make up something, perhaps sincu.

2 Likes

Ok will do.

The simplest implementation is probably sincu(x) = sinc(x/pi). Or should I just copy paste the sinc implementation and remove the pi multiplication?

I suggest the name “sphj0” since this function is the spherical bessel function of the first kind of order zero: https://en.wikipedia.org/wiki/Bessel_function#Spherical_Bessel_functions

To my mind, the only reason for defining a sincu special function would be to remove the cost of the division. If you just define sincu(x) = sinc(x/pi) there’s not much point — it’s just as easy (and probably clearer) for the caller to write sinc(x/pi) themselves. But even saving the cost of the division only saves about 10% of the time on my machine, so I still don’t think this is worth the effort.

3 Likes

I guess the reason to introduce it is to make it clear that the other is normalized.

I spent some time debugging my numerics until I realized that it’s normalized and that’s where the numbers were off due to that.

I’d say the main reason to define both the unnormalized and the normalized sinc functions is the same reason that both sin and sinpi are defined, namely the accuracy near multiples of pi and 1 respectively,

sinc(Float64(pi), normalized=false) should return approximately 3.9e-17 based on the difference between pi and Float64(pi).

I would use a keyword argument with the existing function rather than inventing a new name. Julia is probably smart enough to avoid any performance penalty.

4 Likes

Keyword argument is not a bad idea. Should I implement this?

Sorry for invoking an old post. But how does this discussion turns out? I’d like to have sinc = sin(x)/x to eliminate the cost of a division.

Is one division/multiplication of sin(x*pi) really that critical for you?

If yes, you could copy paste the code from Base.Math and remove the division.

Not at all. But if there is a better choice, why not use it?

I think that the main point is being able getting an exact result for rational multiples of pi: for the sine function, for instance, sinpi(1) == 0, while sin(1*Float64(pi)) != 0. sinc is similar.

This suggests that it makes sense to have the normalized version as the first-class object: defining sincu(x) = sinc(x/pi) is harmless (because at that point you have anyway an inexact x to start with) while defining sinc(x) = sincu(x*pi) will lose accuracy for rational values of x.

As for the naming, uniformity would suggest sincpi for the normalized version and sinc for the normalized version, in analogy to sinpi and sin, but I am afraid it is too late to revert the choice now.

1 Like

That really is a shame. That would have been such a consistent way of doing it.

Maybe that’s something that could be added to #36954 for 2.0?

3 Likes

I support the idea, of course, but I’m not sure if I should get more consensus before posting it there. Maybe there are other naming clashes that I am overlooking.

EDIT: also, there is the fact that this change isn’t simply introducing a new name and deprecating the old one; it actively breaks existing code in a way that cannot be fixed simply by adding a deprecation.

1 Like