-
-
Notifications
You must be signed in to change notification settings - Fork 12k
ENH: Added support for arrays with dtype=object to np.isinf, np.isnan, np.isfinite
#10820
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
| docstrings.get('numpy.core.umath.isfinite'), | ||
| None, | ||
| TD(inexact, out='?'), | ||
| TD(noint, out='?'), |
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 happens if I have multiple overlapping TD calls? e.g., if I hadn't deleted the line TD(inexact, out='?') here.
| assert_raises(TypeError, test_nan) | ||
|
|
||
|
|
||
| class _CustomFloat(object): |
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.
If there is already an implementation of mocks like these somewhere, I would be happy to get rid of 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.
Can you use unittest.mock?
numpy/core/src/umath/loops.c.src
Outdated
| int v; | ||
|
|
||
| UNARY_LOOP { | ||
| PyObject *in1 = *(PyObject **)ip1; |
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 am almost 100% sure that I don't need to Py_INCREF(in1) here or anywhere else, but I feel like someone should verify that since I do pass it to PyFloat_AsDouble and PyComplex_AsCComplex down the line.
numpy/core/src/umath/loops.c.src
Outdated
| if (cplx.real == -1.0 && cplx.imag == 0.0 && PyErr_Occurred()) { | ||
| PyErr_Format(PyExc_TypeError, "must be real or complex number, not %s", | ||
| Py_TYPE(in1)->tp_name); | ||
| break; |
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 a corresponding Py_DECREF(in1) need to go here? (see above)
numpy/core/src/umath/loops.c.src
Outdated
| else { | ||
| v = @func@(dbl) != 0; | ||
| } | ||
| *((npy_bool *)op1) = v; |
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 a corresponding Py_DECREF(in1) need to go here? (see above)
|
I think this would be a little cleaner via |
Nothing seemed worth adding to the docs of the functions themselves.
1787c1a to
30928b5
Compare
|
@eric-wieser. I have moved the implementation to I added support for integers (objects implementing I've added a couple more comments to my code about concerns that I have with the correctness. |
doc/release/1.14.0-notes.rst
Outdated
| .. _c-api: https://github.com/numpy/numpy/blob/master/doc/source/reference/c-api.array.rst | ||
| .. _how-to-extend: https://github.com/numpy/numpy/blob/master/doc/source/user/c-info.how-to-extend.rst | ||
| Support for ``dtype=object`` in ``isinf``, ``isnan``, ``isfinite`` | ||
| Support for ``dtype=object`` in ``isnan``, ``isinf``, ``isfinite`` |
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.
Rebase mistake
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.
Fixed
|
Note this duplicates #6320 - you might want to compare to the approach used there |
| Ufunc(1, 1, None, | ||
| docstrings.get('numpy.core.umath.isnan'), | ||
| None, | ||
| TD(inexact, out='?'), |
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 happens if I have multiple overlapping TD calls? e.g., if this line read TD(noint, out='?'), making conflicting protoypes for dtype=object?
| if(i1 == NULL) { | ||
| return NULL; | ||
| } | ||
| else { |
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 am almost 100% sure that I don't need to Py_INCREF(i1) here or anywhere else, but I feel like someone should verify that since I do pass it to PyFloat_AsDouble, PyComplex_AsCComplex, etc down the line.
Just because all my tests pass does not mean that the refcounting is done correctly here.
| return PyNumber_Absolute(tmp); | ||
| } | ||
|
|
||
| /* Utility used to check if a number is an integer or has an __int__/__long__ method */ |
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.
An alternative implementation is suggested by https://stackoverflow.com/a/49562820/2988730. However, using PyNumber_Long/PyNumber_Int will allow converstion of strings and objects with just __trunc__ but no __float__, which I don't think we want.
|
@eric-wieser I agree that this should defer to #6320. I especially like the part where the result is always I will leave this around for a bit longer to see if anyone can give me more pointers. In the meantime, I will go work on adding |
Sounds good to me. Maybe add loops for the integer types too. I think there's a dead PR for that somewhere too. |
|
@eric-wieser Let me know if you find it. That was one of the questions I had at the top. At least for the three functions that I have here, you don't even need a loop, just a boolean array of all ones. Is that something that ufuncs can easily support? |
|
You just write a loop that ignores its inputs and writes ones to the output. |
Still looking, but found a related one for bools: #12988 |
|
@madphysicist would you like to continue with this? The release note should be rewritten as a fragment in |
|
@mattip. Eventually. I'm going to have to re-familiarize myself with what I did here first. |
|
Closing. This has been around for quite a while and has not moved very far. Please reopen if you want to pursue the idea. |
The loops check if the object has a
__float__or__complex__method, then handle the object as usual. Preference is given to__float__in all cases. This is a preliminary step to make sure I understand the basics of how to add to aufunc, so please grade harshly! The next step will be addingdatetimeandtimedeltasupport tonp.isfinite, in preparation for adding support tonp.histogram.Two questions arise:
isinite,isinf,isnannot optimized to always returnTrueregardless of the input data?a. Am I correct to assume that the values are actually cast to floating point before running through the normal loop?
b. Is there any desire to change this? Or conversely, any motivation not to?
isneginfandisposinfnot ufuncs likeisinf? There does not appear to be any major issue except a minor break in backwards compatibility where the second parameter would be renamed fromytoout.