-
-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Open
Labels
23 - Wish List62 - Python APIChanges or additions to the Python API. Mailing list should usually be notified.Changes or additions to the Python API. Mailing list should usually be notified.
Description
If only given 0d inputs, even if they are of type ndarray, ufuncs will decay their output to a scalar via [()] (as noted in #4563, #5819). While we can't change this behavior now without creating signficant pain downstream, we could add a way to opt out of it.
#13100 raises a case where np.fix resorts to calling np.asanyarray(np.ceil(x, out=out)) in order to ensure that the result is an array. Unfortunately, this has a number of draw-backs:
- It discards duck-types, like
daskarrays - It changes the dtype of 0d object arrays containing array-likes
Proposed implementation:
- Create a new
np.leave_wrappedsentinel object that can be passed as anoutargument - Add support in
ufunc.__call__,np.take, ... for passingout=np.leave_wrappedmeaning "do not call PyArray_Return", causing the result to never be a scalar - Expose
PyArray_Returnto python asnp.core.unpack_scalar - Implement
np.fixas:
def fix(x, out=None):
if out is None:
do_unwrap = True
out = np.leave_wrapped
else:
do_unwrap = False
res = nx.ceil(x, out=out)
res = nx.floor(x, out=res, where=nx.greater_equal(x, 0, out=np.leave_wrapped))
if do_unwrap:
res = np.unpack_scalar(res) # PyArray_Return
return res
Original unpack_scalars=True proposal
unpack_scalars=True proposal- Add a new
unpack_scalars=Truekwarg toufunc.__call__,ufunc.reduce. WhenFalse, the current behavior of going throughPyArray_Returnis disabled. Alternative names:decay=Trueunpack_0d=Trueunpack_0d_ndarray=True(PyArray_Returnalready does not apply to subclasses)
- Add a new
np.unpack_scalar(arr)function to exposePyArray_Returnto python code. This would not be overloadable with__array_function__, since existing uses ofPyArray_Returnare also not.
With these changes, the current implementation of np.fix would change from:
def fix(x, out=None):
res = nx.asanyarray(nx.ceil(x, out=out))
res = nx.floor(x, out=res, where=nx.greater_equal(x, 0))
if out is None and type(res) is nx.ndarray:
res = res[()]
return resto
def fix(x, out=None, *, unpack_scalars=True):
res = nx.ceil(x, out=out, unpack_scalars=False)
res = nx.floor(x, out=res, where=nx.greater_equal(x, 0, unpack_scalars=False), unpack_scalars=False)
if unpack_scalars and out is None:
res = np.unpack_scalar(res)
return resDetails
If needed, I could promote this to an NEPMetadata
Metadata
Assignees
Labels
23 - Wish List62 - Python APIChanges or additions to the Python API. Mailing list should usually be notified.Changes or additions to the Python API. Mailing list should usually be notified.