Skip to content

Commit 572c4eb

Browse files
committed
ENH: make device2 default to float32 (but still support float64)
This way, "device2" mimics a pytorch CPU device (supports f64, defaults to f32), and "no_float64" mimics an MPS device (does not support double precision at all). While at it, fix the logic in asarray: whether a device does or does not support a dtype is different from what is the default dtype for this device. The the decision on the latter should not depend on the former.
1 parent a15c7bc commit 572c4eb

3 files changed

Lines changed: 37 additions & 17 deletions

File tree

array_api_strict/_creation_functions.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,22 @@ def asarray(
110110
# numpy default dtype may differ; if so, adjust the dtype
111111
if dtype is None and device is not None:
112112
res_dtype = DType(res.dtype)
113-
if not device_supports_dtype(device, res_dtype):
114-
# The dtype selected by Numpy might not be the default dtype
115-
# on this device. If the dtype is not supported by the device we
116-
# try to find one that is, aka the default dtype of this device.
117-
from ._data_type_functions import isdtype
118-
if isdtype(res_dtype, "bool"):
119-
target_dtype = DType("bool")
120-
elif isdtype(res_dtype, "integral"):
121-
target_dtype = get_default_dtypes(device)["integral"]
122-
elif isdtype(res_dtype, "real floating"):
123-
target_dtype = get_default_dtypes(device)["real floating"]
124-
elif isdtype(res_dtype, "complex floating"):
125-
target_dtype = get_default_dtypes(device)["complex floating"]
126-
else:
127-
raise ValueError(f"{res_dtype = } not understood.")
113+
# The dtype selected by Numpy might not be the default dtype
114+
# on this device. We thus find the default dtype for the dtype "kind", and
115+
# cast to the device-appropriate default.
116+
from ._data_type_functions import isdtype
117+
if isdtype(res_dtype, "bool"):
118+
target_dtype = DType("bool")
119+
elif isdtype(res_dtype, "integral"):
120+
target_dtype = get_default_dtypes(device)["integral"]
121+
elif isdtype(res_dtype, "real floating"):
122+
target_dtype = get_default_dtypes(device)["real floating"]
123+
elif isdtype(res_dtype, "complex floating"):
124+
target_dtype = get_default_dtypes(device)["complex floating"]
125+
else:
126+
raise ValueError(f"{res_dtype = } not understood.")
128127

129-
res = res.astype(target_dtype._np_dtype)
128+
res = res.astype(target_dtype._np_dtype)
130129

131130
return Array._new(res, device=device)
132131

array_api_strict/_devices.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ def check_device(device: Device | None) -> None:
7878

7979
def get_default_dtypes(device: Device | None = None) -> dict[str, DType]:
8080
if device == NO_FLOAT64_DEVICE:
81+
# mimic an MPS device which does not have float64 at all
82+
return {
83+
"real floating": float32,
84+
"complex floating": complex64,
85+
"integral": int64,
86+
"indexing": int64,
87+
}
88+
elif device == Device('device2'):
89+
# mimic a torch CPU device: support float64 but default to float32
8190
return {
8291
"real floating": float32,
8392
"complex floating": complex64,

array_api_strict/tests/test_creation_functions.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
zeros,
2323
zeros_like,
2424
)
25-
from .._dtypes import float32, float64, bool as xp_bool
25+
from .._dtypes import float32, float64, complex64, bool as xp_bool
2626
from .._array_object import Array
2727
from .._devices import CPU_DEVICE, ALL_DEVICES, Device
2828
from .._info import __array_namespace_info__
@@ -356,6 +356,18 @@ def test_asarray(self):
356356
asarray(src, device=device)
357357

358358

359+
def test_asarray_device_2():
360+
# device2 allows float64 but defaults to float32
361+
x = asarray([1.0], device=Device('device2'))
362+
assert x.dtype == float32
363+
364+
x = asarray([1j], device=Device('device2'))
365+
assert x.dtype == complex64
366+
367+
y = asarray([1.0], device=Device('device2'), dtype=float64)
368+
assert y.dtype == float64
369+
370+
359371
@pytest.mark.parametrize("api_version", ['2021.12', '2022.12', '2023.12'])
360372
def from_dlpack_2023_12(api_version):
361373
if api_version != '2022.12':

0 commit comments

Comments
 (0)