Skip to content
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

feat: astype: accept a kind of data type #848

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
27 changes: 22 additions & 5 deletions src/array_api_stubs/_draft/data_type_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@


def astype(
x: array, dtype: dtype, /, *, copy: bool = True, device: Optional[device] = None
x: array,
dtype: Union[dtype, str],
/,
*,
copy: bool = True,
device: Optional[device] = None,
) -> array:
"""
Copies an array to a specified data type irrespective of :ref:`type-promotion` rules.
Copies an array to a specified data type irrespective of :ref:`type-promotion` rules, or to a *kind* of data type.

.. note::
Casting floating-point ``NaN`` and ``infinity`` values to integral data types is not specified and is implementation-dependent.
Expand All @@ -40,8 +45,12 @@ def astype(
----------
x: array
array to cast.
dtype: dtype
desired data type.
dtype: Union[dtype, str]
desired data type or kind of data type. Supported kinds are:

- ``'signed integer'``: signed integer data types (e.g., ``int8``, ``int16``, ``int32``, ``int64``).
- ``'complex floating'``: complex floating-point data types (e.g., ``complex64``, ``complex128``).
lucascolley marked this conversation as resolved.
Show resolved Hide resolved

copy: bool
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. Default: ``True``.
device: Optional[device]
Expand All @@ -50,7 +59,15 @@ def astype(
Returns
-------
out: array
an array having the specified data type. The returned array must have the same shape as ``x``.
For ``dtype`` a data type, an array having the specified data type.
For ``dtype`` a kind of data type:

- If ``x.dtype`` is already of that kind, the data type must be maintained.
- Otherwise, ``x`` should be cast to a data type of that kind, according to the type promotion rules (see :ref:`type-promotion`) and the above notes.
- Kinds must be interpreted as the lowest-precision standard data type of that kind for the purposes of type promotion. For example, ``astype(x, 'complex floating')`` will return an array with the data type ``complex64`` when ``x.dtype`` is ``float32``, since ``complex64`` is the result of promoting ``float32`` with the lowest-precision standard complex data type, ``complex64``.
Copy link
Member

Choose a reason for hiding this comment

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

The text you've added here seems to only be thinking about the case where the dtype argument is a string, but the dtype being an actual dtype object is also still supported.

Copy link
Member Author

Choose a reason for hiding this comment

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

Line 62 covers the dtype case. Do you have a suggestion to make it more clear?

Copy link
Contributor

Choose a reason for hiding this comment

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

@asmeurer Would you be willing to take a look at the latest text to determine whether this satisfies your concerns?

- Where type promotion is unspecified and thus implementation-specific, the result is also unspecified. For example, ``astype(x, 'complex floating')``, where ``x`` has data type ``int32``.
Copy link
Member

Choose a reason for hiding this comment

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

This is overly restrictive, and conflicts with the behavior specified above. The whole point of astype is to be able to do casts that aren't in the promotion table, like int -> float casts. In fact, I would say this whole line should be deleted as the above note already clearly talks about what is and isn't defined.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is overly restrictive, and conflicts with the behavior specified above. The whole point of astype is to be able to do casts that aren't in the promotion table, like int -> float casts

I think there is a misunderstanding - this point applies only in the case that a kind of data type is provided, as this is under the bullet list started on line 63.

Ralf suggested in #848 (comment) that it doesn't make sense to support kinds for which the resulting dtype would always be undefined, given that there are no type promotion rules to follow. Do you disagree?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with Aaron here. I've updated the wording accordingly. It should be possible, e.g., to be able to do astype(x, dtype="real floating") where x is int32 in order to return a float64 array. This conversion between dtype kinds is not part of type promotion rules, but has well-defined behavior, as int32 can be represented exactly in float64.

Copy link
Member Author

Choose a reason for hiding this comment

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

This conversion between dtype kinds is not part of type promotion rules, but has well-defined behavior, as int32 can be represented exactly in float64.

Okay, yes, that sounds right to me now.


The returned array must have the same shape as ``x``.

Notes
-----
Expand Down
Loading