Skip to content

DOC: numpy.result_type promotion "algorithm" is outdated #29821

@MustafaYounes1

Description

@MustafaYounes1

Describe the issue:

According to the API Reference, the algorithm of numpy.result_type determines the output type following these steps:

  1. Categories are determined by first checking which of boolean, integer (int/uint), or floating point (float/complex) the maximum kind of all the arrays and the scalars are.

  2. If there are only scalars or the maximum category of the scalars is higher than the maximum category of the arrays, the data types are combined with promote_types to produce the return value.

  3. Otherwise, min_scalar_type is called on each scalar, and the resulting data types are all combined with promote_types to produce the return value.

However, when it's provided with a Python scalar and an ndarray of the same category (e.g., int), it seems it completely ignores the scalar and outputs whatever datatype the ndarray has (and that contradicts the third point above; according to the doc, it should apply min_scalar_type on the scalar, and follow that with a call to promote_types).

However, when the provided scalar is a NumPy scalar, the behavior is different: what it seemingly does is only a call to promote_types

So, I'm wondering why the behavior is inconsistent on NumPy/Python scalars, and what exactly the role of min_scalar_type is in this context?

Please take a look at the provided code that shows this unexpected behaviour with a couple of examples.

Reproduce the code example:

import numpy as np

#############
# Example 1 #
#############

# Both the ndarray and the scalar are of the same category (int)

s = -129
a = np.empty(1, dtype='i1')

# Python Scalar & ndarray

# The following outputs 'int8' (completely ignoring the scalar)
print(np.result_type(s, a))

# according to the doc; it should have called:
print(np.promote_types(np.min_scalar_type(s), a.dtype))  # gives int16

# NumPy Scalar & ndarray

# gives 'int16' (seemingly only calls np.promote_types)
print(np.result_type(np.int16(s), a))  
 
#############
# Example 2 #
#############

# The ndarray has a higher category (float vs int)

s = np.iinfo(np.int64).max
a = np.empty(1, np.float32)

# Python Scalar & ndarray

# The following outputs 'float32' (completely ignoring the scalar)
print(np.result_type(s, a))

# according to the doc; it should have called:
print(np.promote_types(np.min_scalar_type(s), a.dtype))  # gives float64

# NumPy Scalar & ndarray

# gives 'float64' (seemingly only calls np.promote_types)
print(np.result_type(np.int64(1), a))

# Pay attention to the following: (np.min_scalar_type is not used at all)
print(np.min_scalar_type(np.int64(1)))  # gives uint8
print(np.promote_types(np.min_scalar_type(np.int64(1)), a.dtype)) # gives float32

Python and NumPy Versions:

Python: 3.11.5
NumPy: 2.3.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions