-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
ENH: Add the 'heaviside' ufunc. #8795
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
Conversation
Whoops, I forgot that I asked about this on the mailing list two years ago: https://mail.scipy.org/pipermail/numpy-discussion/2015-February/072183.html (nabble: http://numpy-discussion.10968.n7.nabble.com/Any-interest-in-a-heaviside-ufunc-td39641.html) |
Implementation seems sound to me, but I share some of the sentiments in the mailing list about whether |
I think this would be a reasonable addition. The other versions of the Heaviside function (unitstep functions) are easy to implement, but this version with .5 at zero is not so straight forward. Of the various signal waveforms, rectangular, hat, etc., this is probably the only one that belongs in numpy. |
How hard would it be to allow default values in ufuncs? A default of 0.5 seems useful to me? |
Perhaps, but I think this is likely to catch people out, and so being explicit would be better. Defaults on ufuncs (and also, gufuncs) is something that might be useful elsewhere though |
Also, perhaps worth linking to the wikipedia page about the choice of |
I note that the .5 value also comes from Fourier series of piecewise smooth functions with discrete discontinuities, which you can see, along with the Gibbs phenomenon, from convolution with the Dirichlet kernels, |
@seberg I think adding arguments to ufuncs will be a problem. |
4887433
to
bf83345
Compare
I added a "References" section to the docstring, with a link to the Wikipedia article. Adding default values for arguments doesn't appear to be possible with the existing ufunc-generating machinery. (A big +1 for the enhancement request, though.) |
return h0; | ||
} | ||
else if (x < 0) { | ||
return (@type@) 0.0; |
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 like to use integer values for these, but I expect the compiler can also optimize the cast away just as easily for the double values.
I think dealing with multiple types would be a problem in general. With scalar defaults the same kind casting rules would probably work in this case where the only valid types are floats. Although it would still be a problem for scalar values of |
OK, let's put this in. Thanks @WarrenWeckesser . |
@WarrenWeckesser There is probably no reason not to allow integer types here, that way if |
@charris, do you mean something like |
This needs to be listed in the documentation somewhere too, presumably |
@eric-wieser Looks like it should be in I'll get started on a new pull request to update the docs and handle integers. |
@charris (or anyone else): Can you recommend an existing ufunc implementation similar to I'll keep poking at this, but some pointers might save me some time. |
Might my changes in #8774 help? If you name your functions the right thing, I don't think you need any real work in |
Thanks. I don't plan on implementing the code for handling generic Python objects. I've been using the following in
(I have no problem dropping the specialized code for the unsigned integers if that seems like overkill.) What is the appropriate way to add this to |
My point was that exposing a function called |
Good timing! After looking at your pull request some more, I was just coming to that realization. That code looks very boilerplate-ish. I guess I expected code at that level to be generated by the python script, especially after implementing the "float only" code without making such changes. |
Yeah, to be honest I wasn't aware that the way you're doing it was possible either, so I guess we're even there. But the way I'm doing it is consistent with how |
@charris wrote
How important do folks think it is that the function return an integer array if the inputs are all integers? Currently it always returns floats. I started looking into this, but I hit a steeper section of the ufunc implementation learning curve, and then got caught up in other things. It could be changed after the next release, but that means there would be a change in behavior of, for example, |
Four weeks ago ;) Seriously, all I want is to finish up |
On my machine, compiling In [1]: x = np.random.randn(100000)
In [2]: %timeit np.heaviside(x, 0)
1.31 ms ± 58.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [3]: %timeit np.where(x > 0, 1.0, 0.0)
658 µs ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [4]: %timeit (x>0).astype(x.dtype)
172 µs ± 34.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) Right now, it would seemingly be better to have defined Possible improvements:
|
One more possible improvement to add to the list:
|
I wonder if this shouldn't be in scipy.signals Moreover it could make sense to have also a parameter for "delayed" heaviside function. PS: sorry for noise... about delayed heaviside function...
does the trick (for a 4s delay) |
I was messing around with numpy ufuncs, and figured the Heaviside step function that I was experimenting with might actually be a useful addition to numpy. This answer on stackoverflow has gotten a few upvotes, so there are some folks out there who would find it useful.