New methods exposing UFunc dtype resolution/promotion and internals
Hi all, I would like to expose more of the ufunc internals in the following PR: https://github.com/numpy/numpy/pull/22422/ There are three new proposed functions. I hope the first one can be generally useful while the last two are very specific (and thus underscored), but will hopefully become useful e.g. for Numba or numexpr. ufunc.resolve_dtypes(dtypes, *, signature=None, casting=None, reduction=False)  Allows you to find out what dtypes NumPy's implementation will use without executing a ufunc. For the full docs, see: https://output.circleartifacts.com/output/job/c8f72dd5f8fb448c8fd8d6182... Example from the docs: >>> int32 = np.dtype("int32") >>> float32 = np.dtype("float32") The typical ufunc call does not pass an output dtype. `np.add` has two inputs and one output, so leave the output as ``None`` (not provided): >>> np.add.resolve_dtypes((int32, float32, None)) (dtype('float64'), dtype('float64'), dtype('float64')) The loop found uses "float64" for all operands (including the output), the first input would be cast. ``resolve_dtypes`` supports "weak" handling for Python scalars by passing ``int``, ``float``, or ``complex``: >>> np.add.resolve_dtypes((float32, float, None)) (dtype('float32'), dtype('float32'), dtype('float32')) Where the Python ``float`` behaves samilar to a Python value ``0.0`` in a ufunc call. (See :ref:`NEP 50 <NEP50>` for details.) ufunc._resolve_dtypes_and_context(dtypes, *, signature=None, casting=None, reduction=False)  Identical to the above, but it additionally returns a "call_info" which allows access to the actual ufunc implmentation. ufunc._get_loop(call_info, /, *, fixed_strides=None)  Second function that is passed the `call_info` from the previous one. Both would normally be called (this is because it is the way NumPy must do it internally and allows most flexibility). After doing both calls, `call_info` can be used from C to directly access the C implementation. Flux in the CAPI are expected (for now). But for example Numba already releases new versions when NumPy releases a new version. Cheers, Sebastian
Hi again, On Tue, 20221025 at 11:41 +0200, Sebastian Berg wrote:
Hi all,
I would like to expose more of the ufunc internals in the following PR:
Just to note that this PR is now merged and scheduled for release (without any serious changes from the old announcement). That is adding a new function which can be called with: np.add.resolve_dtypes((np.dtype("f8"), np.dtype("f4"), None)) and then returns the actual dtypes used (most importantly the output one that is passed as `None` there). I hope the new API will be useful, but any lastminute concerns are of course welcome. We can always make it a bit more convenient later. It is really targeted at libraries or users like Numba. Cheers, Sebastian
There are three new proposed functions. I hope the first one can be generally useful while the last two are very specific (and thus underscored), but will hopefully become useful e.g. for Numba or numexpr.
ufunc.resolve_dtypes(dtypes, *, signature=None, casting=None, reduction=False) 
Allows you to find out what dtypes NumPy's implementation will use without executing a ufunc. For the full docs, see:
https://output.circleartifacts.com/output/job/c8f72dd5f8fb448c8fd8d6182...
Example from the docs:
>>> int32 = np.dtype("int32") >>> float32 = np.dtype("float32")
The typical ufunc call does not pass an output dtype. `np.add` has two inputs and one output, so leave the output as ``None`` (not provided):
>>> np.add.resolve_dtypes((int32, float32, None)) (dtype('float64'), dtype('float64'), dtype('float64'))
The loop found uses "float64" for all operands (including the output), the first input would be cast.
``resolve_dtypes`` supports "weak" handling for Python scalars by passing ``int``, ``float``, or ``complex``:
>>> np.add.resolve_dtypes((float32, float, None)) (dtype('float32'), dtype('float32'), dtype('float32'))
Where the Python ``float`` behaves samilar to a Python value ``0.0`` in a ufunc call. (See :ref:`NEP 50 <NEP50>` for details.)
ufunc._resolve_dtypes_and_context(dtypes, *, signature=None, casting=None, reduction=False)  Identical to the above, but it additionally returns a "call_info" which allows access to the actual ufunc implmentation.
ufunc._get_loop(call_info, /, *, fixed_strides=None)  Second function that is passed the `call_info` from the previous one. Both would normally be called (this is because it is the way NumPy must do it internally and allows most flexibility).
After doing both calls, `call_info` can be used from C to directly access the C implementation. Flux in the CAPI are expected (for now). But for example Numba already releases new versions when NumPy releases a new version.
Cheers,
Sebastian
_______________________________________________ NumPyDiscussion mailing list  numpydiscussion@python.org To unsubscribe send an email to numpydiscussionleave@python.org https://mail.python.org/mailman3/lists/numpydiscussion.python.org/ Member address: sebastian@sipsolutions.net
participants (1)

Sebastian Berg