Files
pytorch/test/torch_np/test_scalars_0D_arrays.py

136 lines
3.7 KiB
Python

# Owner(s): ["module: dynamo"]
"""
Basic tests to assert and illustrate the behavior around the decision to use 0D
arrays in place of array scalars.
Extensive tests of this sort of functionality is in numpy_tests/core/*scalar*
Also test the isscalar function (which is deliberately a bit more lax).
"""
from torch.testing._internal.common_utils import (
instantiate_parametrized_tests,
parametrize,
run_tests,
subtest,
TEST_WITH_TORCHDYNAMO,
TestCase,
xfailIfTorchDynamo,
)
if TEST_WITH_TORCHDYNAMO:
import numpy as np
from numpy.testing import assert_equal
else:
import torch._numpy as np
from torch._numpy.testing import assert_equal
parametrize_value = parametrize(
"value",
[
subtest(np.int64(42), name="int64"),
subtest(np.array(42), name="array"),
subtest(np.asarray(42), name="asarray"),
subtest(np.asarray(np.int64(42)), name="asarray_int"),
],
)
@instantiate_parametrized_tests
class TestArrayScalars(TestCase):
@parametrize_value
def test_array_scalar_basic(self, value):
assert value.ndim == 0
assert value.shape == ()
assert value.size == 1
assert value.dtype == np.dtype("int64")
@parametrize_value
def test_conversion_to_int(self, value):
py_scalar = int(value)
assert py_scalar == 42
assert isinstance(py_scalar, int)
assert not isinstance(value, int)
@parametrize_value
def test_decay_to_py_scalar(self, value):
# NumPy distinguishes array scalars and 0D arrays. For instance
# `scalar * list` is equivalent to `int(scalar) * list`, but
# `0D array * list` is equivalent to `0D array * np.asarray(list)`.
# Our scalars follow 0D array behavior (because they are 0D arrays)
lst = [1, 2, 3]
product = value * lst
assert isinstance(product, np.ndarray)
assert product.shape == (3,)
assert_equal(product, [42, 42 * 2, 42 * 3])
# repeat with right-mulitply
product = lst * value
assert isinstance(product, np.ndarray)
assert product.shape == (3,)
assert_equal(product, [42, 42 * 2, 42 * 3])
def test_scalar_comparisons(self):
scalar = np.int64(42)
arr = np.array(42)
assert arr == scalar
assert arr >= scalar
assert arr <= scalar
assert scalar == 42
assert arr == 42
# @xfailIfTorchDynamo
@instantiate_parametrized_tests
class TestIsScalar(TestCase):
#
# np.isscalar(...) checks that its argument is a numeric object with exactly one element.
#
# This differs from NumPy which also requires that shape == ().
#
scalars = [
subtest(42, "literal"),
subtest(int(42.0), "int"),
subtest(np.float32(42), "float32"),
subtest(np.array(42), "array_0D", decorators=[xfailIfTorchDynamo]),
subtest([42], "list", decorators=[xfailIfTorchDynamo]),
subtest([[42]], "list-list", decorators=[xfailIfTorchDynamo]),
subtest(np.array([42]), "array_1D", decorators=[xfailIfTorchDynamo]),
subtest(np.array([[42]]), "array_2D", decorators=[xfailIfTorchDynamo]),
]
import math
not_scalars = [
int,
np.float32,
subtest("s", decorators=[xfailIfTorchDynamo]),
subtest("string", decorators=[xfailIfTorchDynamo]),
(),
[],
math.sin,
np,
np.transpose,
[1, 2],
np.asarray([1, 2]),
np.float32([1, 2]),
]
@parametrize("value", scalars)
def test_is_scalar(self, value):
assert np.isscalar(value)
@parametrize("value", not_scalars)
def test_is_not_scalar(self, value):
assert not np.isscalar(value)
if __name__ == "__main__":
run_tests()