diff --git a/python/pyarrow/src/arrow/python/inference.cc b/python/pyarrow/src/arrow/python/inference.cc index 291cc421495..ea1514be5be 100644 --- a/python/pyarrow/src/arrow/python/inference.cc +++ b/python/pyarrow/src/arrow/python/inference.cc @@ -127,6 +127,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_PROMOTE(INT16); _NUMPY_UNIFY_PROMOTE(INT32); _NUMPY_UNIFY_PROMOTE(INT64); + _NUMPY_UNIFY_PROMOTE(FLOAT16); _NUMPY_UNIFY_PROMOTE(FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -140,6 +141,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_PROMOTE(INT32); _NUMPY_UNIFY_PROMOTE(INT64); _NUMPY_UNIFY_NOOP(UINT8); + _NUMPY_UNIFY_PROMOTE_TO(FLOAT16, FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -155,6 +157,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_PROMOTE(INT64); _NUMPY_UNIFY_NOOP(UINT8); _NUMPY_UNIFY_NOOP(UINT16); + _NUMPY_UNIFY_PROMOTE_TO(FLOAT16, FLOAT64); _NUMPY_UNIFY_PROMOTE_TO(FLOAT32, FLOAT64); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -171,6 +174,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_NOOP(UINT8); _NUMPY_UNIFY_NOOP(UINT16); _NUMPY_UNIFY_NOOP(UINT32); + _NUMPY_UNIFY_PROMOTE_TO(FLOAT16, FLOAT64); _NUMPY_UNIFY_PROMOTE_TO(FLOAT32, FLOAT64); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -183,6 +187,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_PROMOTE(UINT16); _NUMPY_UNIFY_PROMOTE(UINT32); _NUMPY_UNIFY_PROMOTE(UINT64); + _NUMPY_UNIFY_PROMOTE(FLOAT16); _NUMPY_UNIFY_PROMOTE(FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -195,6 +200,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_NOOP(UINT8); _NUMPY_UNIFY_PROMOTE(UINT32); _NUMPY_UNIFY_PROMOTE(UINT64); + _NUMPY_UNIFY_PROMOTE_TO(FLOAT16, FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -207,6 +213,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_NOOP(UINT8); _NUMPY_UNIFY_NOOP(UINT16); _NUMPY_UNIFY_PROMOTE(UINT64); + _NUMPY_UNIFY_PROMOTE_TO(FLOAT16, FLOAT64); _NUMPY_UNIFY_PROMOTE_TO(FLOAT32, FLOAT64); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -219,6 +226,7 @@ class NumPyDtypeUnifier { _NUMPY_UNIFY_NOOP(UINT8); _NUMPY_UNIFY_NOOP(UINT16); _NUMPY_UNIFY_NOOP(UINT32); + _NUMPY_UNIFY_PROMOTE_TO(FLOAT16, FLOAT64); _NUMPY_UNIFY_PROMOTE_TO(FLOAT32, FLOAT64); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: @@ -228,6 +236,14 @@ class NumPyDtypeUnifier { int Observe_FLOAT16(PyArray_Descr* descr, int dtype) { switch (dtype) { + _NUMPY_UNIFY_NOOP(INT8); + _NUMPY_UNIFY_NOOP(UINT8); + _NUMPY_UNIFY_PROMOTE_TO(INT16, FLOAT32); + _NUMPY_UNIFY_PROMOTE_TO(UINT16, FLOAT32); + _NUMPY_UNIFY_PROMOTE_TO(INT32, FLOAT64); + _NUMPY_UNIFY_PROMOTE_TO(UINT32, FLOAT64); + _NUMPY_UNIFY_PROMOTE_TO(INT64, FLOAT64); + _NUMPY_UNIFY_PROMOTE_TO(UINT64, FLOAT64); _NUMPY_UNIFY_PROMOTE(FLOAT32); _NUMPY_UNIFY_PROMOTE(FLOAT64); default: diff --git a/python/pyarrow/tests/test_convert_builtin.py b/python/pyarrow/tests/test_convert_builtin.py index 3ac7be88eaa..9ecdcda51f7 100644 --- a/python/pyarrow/tests/test_convert_builtin.py +++ b/python/pyarrow/tests/test_convert_builtin.py @@ -481,6 +481,20 @@ def test_numpy_scalars_mixed_type(): assert arr.equals(expected) +@pytest.mark.numpy +@pytest.mark.parametrize("int_type", [ + "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64" +]) +def test_numpy_scalars_mixed_float16_int(int_type): + # GH-25859: follow NumPy type promotion + int_scalar = getattr(np, int_type)(5) + expected_type = pa.from_numpy_dtype(np.result_type(np.float16, int_type)) + for data in ([np.float16(1.5), int_scalar], [int_scalar, np.float16(1.5)]): + arr = pa.array(data) + assert arr.type == expected_type + assert arr.to_pylist() == [float(x) for x in data] + + @pytest.mark.numpy @pytest.mark.xfail(reason="Type inference for uint64 not implemented", raises=OverflowError)