8000 API: Introduce ``np.astype`` [Array API] by mtsokol · Pull Request #25079 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

API: Introduce np.astype [Array API] #25079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/release/upcoming_changes/25054.new_feature.rst
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, I noticed I misspelled PR number - fix is in #25054.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
`numpy.astype`
--------------

`numpy.astype` was added to provide an Array API compatible alternative to
`numpy.ndarray.astype` method.
7 changes: 0 additions & 7 deletions doc/source/reference/array_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,6 @@ The following functions are named differently in the array API
-


Function instead of method
~~~~~~~~~~~~~~~~~~~~~~~~~~

- ``astype`` is a function in the array API, whereas it is a method on
``ndarray`` in ``numpy``.


``linalg`` Namespace Differences
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions doc/source/reference/routines.array-creation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ From existing data
asanyarray
ascontiguousarray
asmatrix
astype
copy
frombuffer
from_dlpack
Expand Down
2 changes: 1 addition & 1 deletion numpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
arctan2, arctanh, argmax, argmin, argpartition, argsort, argwhere,
around, array, array2string, array_equal, array_equiv, array_repr,
array_str, asanyarray, asarray, ascontiguousarray, asfortranarray,
atleast_1d, atleast_2d, atleast_3d, base_repr, binary_repr,
astype, atleast_1d, atleast_2d, atleast_3d, base_repr, binary_repr,
bitwise_and, bitwise_count, bitwise_not, bitwise_or, bitwise_xor,
block, bool, bool_, broadcast, busday_count, busday_offset,
busdaycalendar, byte, bytes_, can_cast, cbrt, cdouble, ceil,
Expand Down
1 change: 1 addition & 0 deletions numpy/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ from numpy._core.numeric import (
isclose as isclose,
array_equal as array_equal,
array_equiv as array_equiv,
astype as astype,
)

from numpy._core.numerictypes import (
Expand Down
79 changes: 68 additions & 11 deletions numpy/_core/numeric.py
10000
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
from . import multiarray
from . import numerictypes as nt
from .multiarray import (
ALLOW_THREADS,
BUFSIZE, CLIP, MAXDIMS, MAY_SHARE_BOUNDS, MAY_SHARE_EXACT, RAISE,
WRAP, arange, array, asarray, asanyarray, ascontiguousarray,
asfortranarray, broadcast, can_cast,
concatenate, copyto, dot, dtype, empty,
empty_like, flatiter, frombuffer, from_dlpack, fromfile, fromiter,
fromstring, inner, lexsort, matmul, may_share_memory,
min_scalar_type, ndarray, nditer, nested_iters, promote_types,
putmask, result_type, shares_memory, vdot, where,
zeros, normalize_axis_index, _get_promotion_state, _set_promotion_state)
ALLOW_THREADS, BUFSIZE, CLIP, MAXDIMS, MAY_SHARE_BOUNDS, MAY_SHARE_EXACT,
RAISE, WRAP, arange, array, asarray, asanyarray, ascontiguousarray,
asfortranarray, broadcast, can_cast, concatenate, copyto, dot, dtype,
empty, empty_like, flatiter, frombuffer, from_dlpack, fromfile, fromiter,
fromstring, inner, lexsort, matmul, may_share_memory, min_scalar_type,
ndarray, nditer, nested_iters, promote_types, putmask, result_type,
shares_memory, vdot, where, zeros, normalize_axis_index,
_get_promotion_state, _set_promotion_state
)

from . import overrides
from . import umath
Expand All @@ -43,7 +42,7 @@
'arange', 'array', 'asarray', 'asanyarray', 'ascontiguousarray',
'asfortranarray', 'zeros', 'count_nonzero', 'empty', 'broadcast', 'dtype',
'fromstring', 'fromfile', 'frombuffer', 'from_dlpack', 'where',
'argwhere', 'copyto', 'concatenate', 'lexsort',
'argwhere', 'copyto', 'concatenate', 'lexsort', 'astype',
'can_cast', 'promote_types', 'min_scalar_type',
'result_type', 'isfortran', 'empty_like', 'zeros_like', 'ones_like',
'correlate', 'convolve', 'inner', 'dot', 'outer', 'vdot', 'roll',
Expand Down Expand Up @@ -2521,6 +2520,64 @@ def array_equiv(a1, a2):
return builtins.bool((a1 == a2).all())


def _astype_dispatcher(x, dtype, /, *, copy=None):
return (x, dtype)


@array_function_dispatch(_astype_dispatcher)
def astype(x, dtype, /, *, copy = True):
"""
Copies an array to a specified data type.

This function is an Array API compatible alternative to
`numpy.ndarray.astype`.

Parameters
----------
x : ndarray
Input NumPy array to cast. ``array_likes`` are explicitly not
supported here.
dtype : dtype
Data type of the result.
copy : bool, optional
Specifies whether to copy an array when the specified dtype matches
the data type of the input array ``x``. If ``True``, a newly allocated
array must always be returned. If ``False`` and the specified dtype
matches the data type of the input array, the input array must be
returned; otherwise, a newly allocated array must be returned.
Defaults to ``True``.

Returns
-------
out : ndarray
An array having the specified data type.

See Also
--------
ndarray.astype

Examples
--------
>>> arr = np.array([1, 2, 3]); arr
array([1, 2, 3])
>>> np.astype(arr, np.float64)
array([1., 2., 3.])

Non-copy case:

>>> arr = np.array([1, 2, 3])
>>> arr_noncpy = np.astype(arr, arr.dtype, copy=False)
>>> np.shares_memory(arr, arr_noncpy)
True

"""
if not isinstance(x, np.ndarray):
raise TypeError(
f"Input should be a NumPy array. It is a {type(x)} instead."
)
return x.astype(dtype, copy=copy)


inf = PINF
nan = NAN
False_ = nt.bool(False)
Expand Down
13 changes: 13 additions & 0 deletions numpy/_core/numeric.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -658,3 +658,16 @@ def isclose(
def array_equal(a1: ArrayLike, a2: ArrayLike, equal_nan: bool = ...) -> bool: ...

def array_equiv(a1: ArrayLike, a2: ArrayLike) -> bool: ...

@overload
def astype(
x: ArrayLike,
dtype: _DTypeLike[_SCT],
copy: bool = ...,
) -> NDArray[_SCT]: ...
@overload
def astype(
x: ArrayLike,
dtype: DTypeLike,
copy: bool = ...,
) -> NDArray[Any]: ...
20 changes: 20 additions & 0 deletions numpy/_core/tests/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -4023,3 +4023,23 @@ def test_zero_dimensional(self):
arr_0d = np.array(1)
ret = np.tensordot(arr_0d, arr_0d, ([], [])) # contracting no axes is well defined
assert_array_equal(ret, arr_0d)


class TestAsType:

def test_astype(self):
data = [[1, 2], [3, 4]]
actual = np.astype(
np.array(data, dtype=np.int64), np.uint32
)
expected = np.array(data, dtype=np.uint32)

assert_array_equal(actual, expected)
assert_equal(actual.dtype, expected.dtype)

assert np.shares_memory(
actual, np.astype(actual, actual.dtype, copy=False)
)

with pytest.raises(TypeError, match="Input should be a NumPy array"):
np.astype(data, np.float64)
2 changes: 2 additions & 0 deletions numpy/typing/tests/data/reveal/ndarray_conversion.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ assert_type(nd.astype(np.float64, "K", "unsafe"), npt.NDArray[np.float64])
assert_type(nd.astype(np.float64, "K", "unsafe", True), npt.NDArray[np.float64])
assert_type(nd.astype(np.float64, "K", "unsafe", True, True), npt.NDArray[np.float64])

assert_type(np.astype(nd, np.float64), npt.NDArray[np.float64])

# byteswap
assert_type(nd.byteswap(), npt.NDArray[np.int_])
assert_type(nd.byteswap(True), npt.NDArray[np.int_])
Expand Down
5 changes: 1 addition & 4 deletions tools/ci/array-api-skips.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ array_api_tests/test_creation_functions.py::test_asarray_scalars
# fft test suite is buggy as of 83f0bcdc
array_api_tests/test_fft.py

# missing isdtype, astype and finfo return type misalignment
# missing isdtype and finfo return type misalignment
array_api_tests/test_data_type_functions.py::test_finfo[float32]
array_api_tests/test_data_type_functions.py::test_isdtype
array_api_tests/test_data_type_functions.py::test_astype

# missing names
array_api_tests/test_has_names.py::test_has_names[linalg-matmul]
Expand All @@ -50,7 +49,6 @@ array_api_tests/test_has_names.py::test_has_names[linalg-vecdot]
array_api_tests/test_has_names.py::test_has_names[linalg-vector_norm]
array_api_tests/test_has_names.py::test_has_names[manipulation-concat]
array_api_tests/test_has_names.py::test_has_names[manipulation-permute_dims]
array_api_tests/test_has_names.py::test_has_names[data_type-astype]
array_api_tests/test_has_names.py::test_has_names[data_type-isdtype]
array_api_tests/test_has_names.py::test_has_names[elementwise-acos]
array_api_tests/test_has_names.py::test_has_names[elementwise-acosh]
Expand Down Expand Up @@ -96,7 +94,6 @@ array_api_tests/test_signatures.py::test_func_signature[permute_dims]
array_api_tests/test_signatures.py::test_func_signature[reshape]
array_api_tests/test_signatures.py::test_func_signature[argsort]
array_api_tests/test_signatures.py::test_func_signature[sort]
array_api_tests/test_signatures.py::test_func_signature[astype]
array_api_tests/test_signatures.py::test_func_signature[isdtype]
array_api_tests/test_signatures.py::test_func_signature[acos]
array_api_tests/test_signatures.py::test_func_signature[acosh]
Expand Down
0