Skip to content

Commit d7af853

Browse files
committed
TST: Add more ScaledFloatDType tests
These tests are not quite as interesting, but also improve code coverage.
1 parent 13c313c commit d7af853

File tree

1 file changed

+88
-56
lines changed

1 file changed

+88
-56
lines changed

numpy/core/tests/test_custom_dtypes.py

Lines changed: 88 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,91 @@
22

33
import numpy as np
44
from numpy.testing import assert_array_equal
5-
6-
7-
SF = np.core._multiarray_umath._get_sfloat_dtype()
8-
9-
10-
@pytest.mark.parametrize("scaling", [1., -1., 2.])
11-
def test_scaled_float_from_floats(scaling):
12-
a = np.array([1., 2., 3.], dtype=SF(scaling))
13-
14-
assert a.dtype.get_scaling() == scaling
15-
assert_array_equal(scaling * a.view(np.float64), np.array([1., 2., 3.]))
16-
17-
18-
@pytest.mark.parametrize("scaling", [1., -1., 2.])
19-
def test_sfloat_from_float(scaling):
20-
a = np.array([1., 2., 3.]).astype(dtype=SF(scaling))
21-
22-
assert a.dtype.get_scaling() == scaling
23-
assert_array_equal(scaling * a.view(np.float64), np.array([1., 2., 3.]))
24-
25-
26-
def _get_array(scaling, aligned=True):
27-
if not aligned:
28-
a = np.empty(3*8 + 1, dtype=np.uint8)[1:]
29-
a = a.view(np.float64)
30-
a[:] = [1., 2., 3.]
31-
else:
32-
a = np.array([1., 2., 3.])
33-
34-
a *= 1./scaling # the casting code also uses the reciprocal.
35-
return a.view(SF(scaling))
36-
37-
38-
@pytest.mark.parametrize("aligned", [True, False])
39-
def test_sfloat_casts(aligned):
40-
a = _get_array(1., aligned)
41-
42-
assert np.can_cast(a, SF(-1.), casting="equiv")
43-
assert not np.can_cast(a, SF(-1.), casting="no")
44-
na = a.astype(SF(-1.))
45-
assert_array_equal(-1 * na.view(np.float64), a.view(np.float64))
46-
47-
assert np.can_cast(a, SF(2.), casting="same_kind")
48-
assert not np.can_cast(a, SF(2.), casting="safe")
49-
a2 = a.astype(SF(2.))
50-
assert_array_equal(2 * a2.view(np.float64), a.view(np.float64))
51-
52-
53-
@pytest.mark.parametrize("aligned", [True, False])
54-
def test_sfloat_cast_internal_errors(aligned):
55-
a = _get_array(2e300, aligned)
56-
57-
with pytest.raises(TypeError,
58-
match="error raised inside the core-loop: non-finite factor!"):
59-
a.astype(SF(2e-300))
60-
5+
from numpy.core._multiarray_umath import (
6+
_discover_array_parameters as discover_array_params, _get_sfloat_dtype)
7+
8+
9+
SF = _get_sfloat_dtype()
10+
11+
12+
class TestSFloat:
13+
def _get_array(self, scaling, aligned=True):
14+
if not aligned:
15+
a = np.empty(3*8 + 1, dtype=np.uint8)[1:]
16+
a = a.view(np.float64)
17+
a[:] = [1., 2., 3.]
18+
else:
19+
a = np.array([1., 2., 3.])
20+
21+
a *= 1./scaling # the casting code also uses the reciprocal.
22+
return a.view(SF(scaling))
23+
24+
def test_sfloat_rescaled(self):
25+
sf = SF(1.)
26+
sf2 = sf.scaled_by(2.)
27+
assert sf2.get_scaling() == 2.
28+
sf6 = sf2.scaled_by(3.)
29+
assert sf6.get_scaling() == 6.
30+
31+
def test_class_discovery(self):
32+
# This does not test much, since we always discover the scaling as 1.
33+
# But most of NumPy (when writing) does not understand DType classes
34+
dt, _ = discover_array_params([1., 2., 3.], dtype=SF)
35+
assert dt == SF(1.)
36+
37+
@pytest.mark.parametrize("scaling", [1., -1., 2.])
38+
def test_scaled_float_from_floats(self, scaling):
39+
a = np.array([1., 2., 3.], dtype=SF(scaling))
40+
41+
assert a.dtype.get_scaling() == scaling
42+
assert_array_equal(scaling * a.view(np.float64), [1., 2., 3.])
43+
44+
def test_repr(self):
45+
# Check the repr, mainly to cover the code paths:
46+
assert repr(SF(scaling=1.)) == "_ScaledFloatTestDType(scaling=1.0)"
47+
48+
@pytest.mark.parametrize("scaling", [1., -1., 2.])
49+
def test_sfloat_from_float(self, scaling):
50+
a = np.array([1., 2., 3.]).astype(dtype=SF(scaling))
51+
52+
assert a.dtype.get_scaling() == scaling
53+
assert_array_equal(scaling * a.view(np.float64), [1., 2., 3.])
54+
55+
@pytest.mark.parametrize("aligned", [True, False])
56+
@pytest.mark.parametrize("scaling", [1., -1., 2.])
57+
def test_sfloat_getitem(self, aligned, scaling):
58+
a = self._get_array(1., aligned)
59+
assert a.tolist() == [1., 2., 3.]
60+
61+
@pytest.mark.parametrize("aligned", [True, False])
62+
def test_sfloat_casts(self, aligned):
63+
a = self._get_array(1., aligned)
64+
65+
assert np.can_cast(a, SF(-1.), casting="equiv")
66+
assert not np.can_cast(a, SF(-1.), casting="no")
67+
na = a.astype(SF(-1.))
68+
assert_array_equal(-1 * na.view(np.float64), a.view(np.float64))
69+
70+
assert np.can_cast(a, SF(2.), casting="same_kind")
71+
assert not np.can_cast(a, SF(2.), casting="safe")
72+
a2 = a.astype(SF(2.))
73+
assert_array_equal(2 * a2.view(np.float64), a.view(np.float64))
74+
75+
@pytest.mark.parametrize("aligned", [True, False])
76+
def test_sfloat_cast_internal_errors(self, aligned):
77+
a = self._get_array(2e300, aligned)
78+
79+
with pytest.raises(TypeError,
80+
match="error raised inside the core-loop: non-finite factor!"):
81+
a.astype(SF(2e-300))
82+
83+
def test_sfloat_promotion(self):
84+
assert np.result_type(SF(2.), SF(3.)) == SF(3.)
85+
assert np.result_type(SF(3.), SF(2.)) == SF(3.)
86+
# Float64 -> SF(1.) and then promotes normally, so both of this work:
87+
assert np.result_type(SF(3.), np.float64) == SF(3.)
88+
assert np.result_type(np.float64, SF(0.5)) == SF(1.)
89+
90+
# Test an undefined promotion:
91+
with pytest.raises(TypeError):
92+
np.result_type(SF(1.), np.int64)

0 commit comments

Comments
 (0)