BUG: incorrect temp elision for new-style (NEP 43) user-defined dtypes#31193
Conversation
|
Thanks, seems right! FWIW I think it is OK to change |
|
Nice, thanks for looking into this! I think it is probably good enough to reject only parametric dtypes here? I.e. with other dtypes we assume that things are fine. |
|
Just pushed a new fix which doesn't check |
|
I am sorry, I remembered last night late and re-remembering only right now... But what slipped my mind completely is that the (I would be happy to broadening it up to the newer EDIT: If it's annoying, I may just push it later. |
|
No problem, I will try changing |
|
The macro fix seems to work equally well, both for my custom dtype test suite and the numpy test suite. |
|
Thanks. Yeah, it seems like anything would be guess-work, while usually true, weird promotion could always happen. @SwayamInSync maybe you have time for a quick look. I pushed one more hot-fix for the single case that looked like it might cause regressions here. I.e. that Now, it seems for NumPy For a better fix, I think we could:
The above would mean that |
That's related to a different issue which also affects my complex fixed-point dtype: there is no way to inform numpy that my type is complex, so it assumes it is real and uses the trivial implementation of |
#30984 included ufuncs for |
|
Good to know! Is there a similar ufunc for |
|
Yes pretty sure |
| { | ||
| if (PyArray_ISCOMPLEX(self) || PyArray_ISOBJECT(self) || | ||
| PyArray_ISUSERDEF(self)) { | ||
| PyArray_ISUSERDEF(self) || !NPY_DT_is_legacy(PyArray_DESCR(self))) { |
There was a problem hiding this comment.
Thanks @seberg this works well. LGTM
Also noticed in quaddtype's we don't have test for quad_arr.conj() (we use np.conj which directly through the ufunc dispatch machinery and works)
|
Thanks for having a look @SwayamInSync, I'll put this in then. I'll try to follow up with something that makes this work better for I think we can backport this @charris, but if it doesn't matter to @MaartenBaert then I don't mind either way. |
#31193) Co-authored-by: Maarten Baert <maarten.baert@keysight.com> Co-authored-by: Sebastian Berg <sebastianb@nvidia.com>
BUG: incorrect temp elision for new-style (NEP 43) user-defined dtypes (#31193)
PR summary
can_elide_temp()intemp_elide.cincorrectly identifies new-style user-defined dtypes as numeric types eligible for in-place buffer reuse. For large arrays this silently rewritesa*a + b*binto(a*a) += (b*b), which raises aTypeErrorwhen the result dtype of the in-place add does not match the pre-allocated buffer.I encountered this bug while implementing a custom fixed-point dtype, which automatically increases its bit width on every operation as required to avoid overflow. Since addition increases the bit width by one, attempting to reuse the temporary buffer results in an incompatible destination dtype being provided to the
addufunc and raises aTypeError.The root cause is that
PyArray_ISNUMBERevaluates totruefor new-style user dtypes since it checks(type) <= NPY_CLONGDOUBLEandtype_num = -1for these types.This could be fixed either in
PyArray_ISNUMBER(probably more correct, but may have unexpected side effects) or with a minimal extra check incan_elide_temp(the approach used by the PR). Let me know if you'd like me to fixPyArray_ISNUMBERinstead.AI Disclosure
This bug was identified and fixed by Claude Sonnet 4.6, and then reviewed by me.
Full AI-generated explanation: https://gist.github.com/MaartenBaert/7540176c4005d26a0b292baefbec8519