BUG: do not change the dtype in asarray(array_from_another_library)#223
Open
ev-br wants to merge 1 commit into
Open
BUG: do not change the dtype in asarray(array_from_another_library)#223ev-br wants to merge 1 commit into
ev-br wants to merge 1 commit into
Conversation
Consider
>>> x = np.asarray(3, dtype=np.float32)
>>> y = xp.asarray(x, device=xp.Device("device1"))
>>> y.dtype == xp.float32
Since `x` is an array, the dtype of `y` must match the dtype of `x`,
not be the default dtype of the device of `y`!
In fact, this is the behavior in 2.5, so restore it.
The fix follows from the difference between 2.5 and 2.6:
- in 2.5, we called `res = np.array(...)` and wrapped `res` into an xp-array
- in 2.6, we additionally select adjust the dtype to match the default for the device.
The last part should be gated:
- if `obj` is an array_like python object, it does not have a .dtype attribute,
thus we adjust res.dtype (this is new in 2.6)
- if `obj` is a array from numpy or pytorch CPU (i.e. numpy conversion succeeds),
`res.dtype` is a numpy analog of `obj.dtype`, so we honor that (this is
what 2.6 broke, and we fix here)
- if `obj` has a dtype attribute but numpy fails to convert it (so `obj`
is a GPU array or a pydata sparse array etc), calling `np.array(obj)` fails with
an exception, and we never reach the dtype adjustment stage anyway
(and this is unchanged from 2.5).
$ git diff 2.5..2.6 -- array_api_strict/_creation_functions.py
... snip ...
@@ -108,6 +106,27 @@ def asarray(
raise OverflowError("Integer out of bounds for array dtypes")
res = np.array(obj, dtype=_np_dtype, copy=copy)
+
+ # numpy default dtype may differ; if so, adjust the dtype
+ if dtype is None and device is not None:
+ res_dtype = DType(res.dtype)
+ # The dtype selected by Numpy might not be the default dtype
+ # on this device. We thus find the default dtype for the dtype "kind", and
+ # cast to the device-appropriate default.
+ from ._data_type_functions import isdtype
+ if isdtype(res_dtype, "bool"):
+ target_dtype = DType("bool")
+ elif isdtype(res_dtype, "integral"):
+ target_dtype = get_default_dtypes(device)["integral"]
+ elif isdtype(res_dtype, "real floating"):
+ target_dtype = get_default_dtypes(device)["real floating"]
+ elif isdtype(res_dtype, "complex floating"):
+ target_dtype = get_default_dtypes(device)["complex floating"]
+ else:
+ raise ValueError(f"{res_dtype = } not understood.")
+
+ res = res.astype(target_dtype._np_dtype)
+
return Array._new(res, device=device)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes gh-222
Consider
Since
xis an array, the dtype ofymust match the dtype ofx, not be the default dtype of the device ofy!In fact, this is the behavior in 2.5, so restore it. The fix follows from the difference between 2.5 and 2.6:
res = np.array(...)and wrappedresinto an xp-arrayThe last part should be gated:
objis an array_like python object, it does not have a .dtype attribute, thus we adjust res.dtype (this is new in 2.6)objis a array from numpy or pytorch CPU (i.e. numpy conversion succeeds),res.dtypeis a numpy analog ofobj.dtype, so we honor that (this is what 2.6 broke, and we fix here)objhas a dtype attribute but numpy fails to convert it (soobjis a GPU array or a pydata sparse array etc), callingnp.array(obj)fails with an exception, and we never reach the dtype adjustment stage anyway (and this is unchanged from 2.5).