Skip to content

feat: add support for scalars in result_type#873

Merged
kgryte merged 1 commit intodata-apis:mainfrom
kgryte:feat/result-type-scalars
Jan 6, 2025
Merged

feat: add support for scalars in result_type#873
kgryte merged 1 commit intodata-apis:mainfrom
kgryte:feat/result-type-scalars

Conversation

@kgryte
Copy link
Copy Markdown
Contributor

@kgryte kgryte commented Dec 12, 2024

This PR:

@kgryte kgryte added API change Changes to existing functions or objects in the API. topic: Type Promotion Type promotion. Needs Review Pull request which needs review. labels Dec 12, 2024
@kgryte kgryte added this to the v2024 milestone Dec 12, 2024
@kgryte kgryte removed the Needs Review Pull request which needs review. label Jan 6, 2025
@kgryte
Copy link
Copy Markdown
Contributor Author

kgryte commented Jan 6, 2025

As this PR has received one approval and follows changes proposed and discussed during workgroup meetings, I'll go ahead and merge. Any further refinements can be made in follow-up PRs. Thanks for reviewing, @lucascolley!

@kgryte kgryte merged commit 7757e67 into data-apis:main Jan 6, 2025
@kgryte kgryte deleted the feat/result-type-scalars branch January 6, 2025 18:29
@mdhaber
Copy link
Copy Markdown
Contributor

mdhaber commented Mar 17, 2026

Looking at the underlying issue, it doesn't seem to have come up, but I thought I'd check before opening a new one - was there an explicit decision to allow instances of Python scalars but NOT the types themselves (i.e., bool, int, float, complex)? It is easy enough to work around, but the feature seems natural to support, and not standardizing it allows gotchas like numpy/numpy#29821 (comment), in which the types follow different promotion rules than the instances (without a use-case in mind).

@kgryte
Copy link
Copy Markdown
Contributor Author

kgryte commented Mar 18, 2026

@mdhaber
Copy link
Copy Markdown
Contributor

mdhaber commented Mar 18, 2026

A strict reading of the standard suggests that this will fail:

import array_api_strict as xp
xp.result_type(xp.asarray(1), float)

and it does.

TypeError: result_type() inputs must be Array API arrays, dtypes, or scalars

float is not a dtype or a scalar; it is a Python type.

@kgryte
Copy link
Copy Markdown
Contributor Author

kgryte commented Mar 19, 2026

@mdhaber I added to the upcoming workgroup agenda.

@ev-br
Copy link
Copy Markdown
Member

ev-br commented Mar 19, 2026

A bit of due diligence for the support across array libraries:

In [5]: cupy.result_type(cupy.ones(3), float)
Out[5]: dtype('float64')

In [6]: torch.result_type(torch.ones(3), float)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 torch.result_type(torch.ones(3), float)

TypeError: result_type() received an invalid combination of arguments - got (Tensor, type), but expected one of:
 * (Tensor tensor, Tensor other)
      didn't match because some of the arguments have invalid types: (Tensor, type)
 * (Number scalar, Tensor tensor)
      didn't match because some of the arguments have invalid types: (Tensor, type)
 * (Tensor tensor, Number other)
      didn't match because some of the arguments have invalid types: (Tensor, type)
 * (Number scalar1, Number scalar2)
      didn't match because some of the arguments have invalid types: (Tensor, type)

In [7]: jnp.result_type(jnp.ones(3), float)
Out[7]: dtype('float32')

In [8]: np.result_type(np.ones(3), float)
Out[8]: dtype('float64')

@rgommers
Copy link
Copy Markdown
Member

I commented on the NumPy issue: I think @mdhaber makes a good point there. For the standard however, if NumPy is inconsistent with itself and might be changing behavior (or not), and if PyTorch doesn't support passing in the int/float types themselves, then probably it's unwise to change anything in the standard in the near future?

@asmeurer
Copy link
Copy Markdown
Member

I might be misunderstanding the use-case here, but you can easily go from a Python scalar type to an instance by calling it with no arguments

>>> int()
0
>>> float()
0.0
>>> bool()
False
>>> complex()
0j

@mdhaber
Copy link
Copy Markdown
Contributor

mdhaber commented Mar 19, 2026

Yes, it's easy to work around if you know to expect it. It just seemed accidental to accept arrays, scalars, and array dtypes but not scalar types. And it's surprising that the standard implicitly permits the behavior for scalars and scalar types to be different; this gotcha could easily lead to dtype bugs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API change Changes to existing functions or objects in the API. topic: Type Promotion Type promotion.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RFC: add support for scalar arguments in result_type

6 participants