Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_half.py594 linesDownload Raw Back to tests
1import platform
2
3import pytest
4
5import numpy as np
6from numpy import float16, float32, float64, uint16
7from numpy.testing import IS_WASM, assert_, assert_equal
8
9
10def assert_raises_fpe(strmatch, callable, *args, **kwargs):
11    try:
12        callable(*args, **kwargs)
13    except FloatingPointError as exc:
14        assert_(str(exc).find(strmatch) >= 0,
15                f"Did not raise floating point {strmatch} error")
16    else:
17        assert_(False,
18                f"Did not raise floating point {strmatch} error")
19
20class TestHalf:
21    def _create_arrays_all(self):
22        # An array of all possible float16 values
23        all_f16 = np.arange(0x10000, dtype=uint16)
24        all_f16 = all_f16.view(float16)
25
26        # NaN value can cause an invalid FP exception if HW is being used
27        with np.errstate(invalid='ignore'):
28            all_f32 = np.array(all_f16, dtype=float32)
29            all_f64 = np.array(all_f16, dtype=float64)
30        return all_f16, all_f32, all_f64
31
32    def _create_arrays_nonan(self):
33        # An array of all non-NaN float16 values, in sorted order
34        nonan_f16 = np.concatenate(
35                                (np.arange(0xfc00, 0x7fff, -1, dtype=uint16),
36                                 np.arange(0x0000, 0x7c01, 1, dtype=uint16)))
37        nonan_f16 = nonan_f16.view(float16)
38        nonan_f32 = np.array(nonan_f16, dtype=float32)
39        nonan_f64 = np.array(nonan_f16, dtype=float64)
40        return nonan_f16, nonan_f32, nonan_f64
41
42    def _create_arrays_finite(self):
43        nonan_f16, nonan_f32, nonan_f64 = self._create_arrays_nonan()
44        finite_f16 = nonan_f16[1:-1]
45        finite_f32 = nonan_f32[1:-1]
46        finite_f64 = nonan_f64[1:-1]
47        return finite_f16, finite_f32, finite_f64
48
49    def test_half_conversions(self):
50        """Checks that all 16-bit values survive conversion
51           to/from 32-bit and 64-bit float"""
52        # Because the underlying routines preserve the NaN bits, every
53        # value is preserved when converting to/from other floats.
54        all_f16, all_f32, all_f64 = self._create_arrays_all()
55        nonan_f16, _, _ = self._create_arrays_nonan()
56
57        # Convert from float32 back to float16
58        with np.errstate(invalid='ignore'):
59            b = np.array(all_f32, dtype=float16)
60        # avoid testing NaNs due to differing bit patterns in Q/S NaNs
61        b_nn = b == b
62        assert_equal(all_f16[b_nn].view(dtype=uint16),
63                     b[b_nn].view(dtype=uint16))
64
65        # Convert from float64 back to float16
66        with np.errstate(invalid='ignore'):
67            b = np.array(all_f64, dtype=float16)
68        b_nn = b == b
69        assert_equal(all_f16[b_nn].view(dtype=uint16),
70                     b[b_nn].view(dtype=uint16))
71
72        # Convert float16 to longdouble and back
73        # This doesn't necessarily preserve the extra NaN bits,
74        # so exclude NaNs.
75        a_ld = np.array(nonan_f16, dtype=np.longdouble)
76        b = np.array(a_ld, dtype=float16)
77        assert_equal(nonan_f16.view(dtype=uint16),
78                     b.view(dtype=uint16))
79
80        # Check the range for which all integers can be represented
81        i_int = np.arange(-2048, 2049)
82        i_f16 = np.array(i_int, dtype=float16)
83        j = np.array(i_f16, dtype=int)
84        assert_equal(i_int, j)
85
86    @pytest.mark.parametrize("string_dt", ["S", "U"])
87    def test_half_conversion_to_string(self, string_dt):
88        # Currently uses S/U32 (which is sufficient for float32)
89        expected_dt = np.dtype(f"{string_dt}32")
90        assert np.promote_types(np.float16, string_dt) == expected_dt
91        assert np.promote_types(string_dt, np.float16) == expected_dt
92
93        arr = np.ones(3, dtype=np.float16).astype(string_dt)
94        assert arr.dtype == expected_dt
95
96    @pytest.mark.parametrize("dtype", ["S", "U", object])
97    def test_to_half_cast_error(self, dtype):
98        arr = np.array(["3M"], dtype=dtype)
99        with pytest.raises(ValueError):
100            arr.astype(np.float16)
101
102        arr = np.array(["23490349034"], dtype=dtype)
103        with np.errstate(all="warn"):
104            with pytest.warns(RuntimeWarning):
105                arr.astype(np.float16)
106
107        with np.errstate(all="raise"):
108            with pytest.raises(FloatingPointError):
109                arr.astype(np.float16)
110
111    @pytest.mark.parametrize("string_dt", ["S", "U"])
112    def test_half_conversion_from_string(self, string_dt):
113        string = np.array("3.1416", dtype=string_dt)
114        assert string.astype(np.float16) == np.array(3.1416, dtype=np.float16)
115
116    @pytest.mark.parametrize("offset", [None, "up", "down"])
117    @pytest.mark.parametrize("shift", [None, "up", "down"])
118    @pytest.mark.parametrize("float_t", [np.float32, np.float64])
119    def test_half_conversion_rounding(self, float_t, shift, offset):
120        # Assumes that round to even is used during casting.
121        max_pattern = np.float16(np.finfo(np.float16).max).view(np.uint16)
122
123        # Test all (positive) finite numbers, denormals are most interesting
124        # however:
125        f16s_patterns = np.arange(0, max_pattern + 1, dtype=np.uint16)
126        f16s_float = f16s_patterns.view(np.float16).astype(float_t)
127
128        # Shift the values by half a bit up or a down (or do not shift),
129        if shift == "up":
130            f16s_float = 0.5 * (f16s_float[:-1] + f16s_float[1:])[1:]
131        elif shift == "down":
132            f16s_float = 0.5 * (f16s_float[:-1] + f16s_float[1:])[:-1]
133        else:
134            f16s_float = f16s_float[1:-1]
135
136        # Increase the float by a minimal value:
137        if offset == "up":
138            f16s_float = np.nextafter(f16s_float, float_t(np.inf))
139        elif offset == "down":
140            f16s_float = np.nextafter(f16s_float, float_t(-np.inf))
141
142        # Convert back to float16 and its bit pattern:
143        res_patterns = f16s_float.astype(np.float16).view(np.uint16)
144
145        # The above calculation tries the original values, or the exact
146        # midpoints between the float16 values. It then further offsets them
147        # by as little as possible. If no offset occurs, "round to even"
148        # logic will be necessary, an arbitrarily small offset should cause
149        # normal up/down rounding always.
150
151        # Calculate the expected pattern:
152        cmp_patterns = f16s_patterns[1:-1].copy()
153
154        if shift == "down" and offset != "up":
155            shift_pattern = -1
156        elif shift == "up" and offset != "down":
157            shift_pattern = 1
158        else:
159            # There cannot be a shift, either shift is None, so all rounding
160            # will go back to original, or shift is reduced by offset too much.
161            shift_pattern = 0
162
163        # If rounding occurs, is it normal rounding or round to even?
164        if offset is None:
165            # Round to even occurs, modify only non-even, cast to allow + (-1)
166            cmp_patterns[0::2].view(np.int16)[...] += shift_pattern
167        else:
168            cmp_patterns.view(np.int16)[...] += shift_pattern
169
170        assert_equal(res_patterns, cmp_patterns)
171
172    @pytest.mark.parametrize(["float_t", "uint_t", "bits"],
173                             [(np.float32, np.uint32, 23),
174                              (np.float64, np.uint64, 52)])
175    def test_half_conversion_denormal_round_even(self, float_t, uint_t, bits):
176        # Test specifically that all bits are considered when deciding
177        # whether round to even should occur (i.e. no bits are lost at the
178        # end. Compare also gh-12721. The most bits can get lost for the
179        # smallest denormal:
180        smallest_value = np.uint16(1).view(np.float16).astype(float_t)
181        assert smallest_value == 2**-24
182
183        # Will be rounded to zero based on round to even rule:
184        rounded_to_zero = smallest_value / float_t(2)
185        assert rounded_to_zero.astype(np.float16) == 0
186
187        # The significand will be all 0 for the float_t, test that we do not
188        # lose the lower ones of these:
189        for i in range(bits):
190            # slightly increasing the value should make it round up:
191            larger_pattern = rounded_to_zero.view(uint_t) | uint_t(1 << i)
192            larger_value = larger_pattern.view(float_t)
193            assert larger_value.astype(np.float16) == smallest_value
194
195    def test_nans_infs(self):
196        all_f16, all_f32, _ = self._create_arrays_all()
197        with np.errstate(all='ignore'):
198            # Check some of the ufuncs
199            assert_equal(np.isnan(all_f16), np.isnan(all_f32))
200            assert_equal(np.isinf(all_f16), np.isinf(all_f32))
201            assert_equal(np.isfinite(all_f16), np.isfinite(all_f32))
202            assert_equal(np.signbit(all_f16), np.signbit(all_f32))
203            assert_equal(np.spacing(float16(65504)), np.inf)
204
205            # Check comparisons of all values with NaN
206            nan = float16(np.nan)
207
208            assert_(not (all_f16 == nan).any())
209            assert_(not (nan == all_f16).any())
210
211            assert_((all_f16 != nan).all())
212            assert_((nan != all_f16).all())
213
214            assert_(not (all_f16 < nan).any())
215            assert_(not (nan < all_f16).any())
216
217            assert_(not (all_f16 <= nan).any())
218            assert_(not (nan <= all_f16).any())
219
220            assert_(not (all_f16 > nan).any())
221            assert_(not (nan > all_f16).any())
222
223            assert_(not (all_f16 >= nan).any())
224            assert_(not (nan >= all_f16).any())
225
226    def test_half_values(self):
227        """Confirms a small number of known half values"""
228        a = np.array([1.0, -1.0,
229                      2.0, -2.0,
230                      0.0999755859375, 0.333251953125,  # 1/10, 1/3
231                      65504, -65504,           # Maximum magnitude
232                      2.0**(-14), -2.0**(-14),  # Minimum normal
233                      2.0**(-24), -2.0**(-24),  # Minimum subnormal
234                      0, -1 / 1e1000,            # Signed zeros
235                      np.inf, -np.inf])
236        b = np.array([0x3c00, 0xbc00,
237                      0x4000, 0xc000,
238                      0x2e66, 0x3555,
239                      0x7bff, 0xfbff,
240                      0x0400, 0x8400,
241                      0x0001, 0x8001,
242                      0x0000, 0x8000,
243                      0x7c00, 0xfc00], dtype=uint16)
244        b = b.view(dtype=float16)
245        assert_equal(a, b)
246
247    def test_half_rounding(self):
248        """Checks that rounding when converting to half is correct"""
249        a = np.array([2.0**-25 + 2.0**-35,  # Rounds to minimum subnormal
250                      2.0**-25,       # Underflows to zero (nearest even mode)
251                      2.0**-26,       # Underflows to zero
252                      1.0 + 2.0**-11 + 2.0**-16,  # rounds to 1.0+2**(-10)
253                      1.0 + 2.0**-11,   # rounds to 1.0 (nearest even mode)
254                      1.0 + 2.0**-12,   # rounds to 1.0
255                      65519,          # rounds to 65504
256                      65520],         # rounds to inf
257                      dtype=float64)
258        rounded = [2.0**-24,
259                   0.0,
260                   0.0,
261                   1.0 + 2.0**(-10),
262                   1.0,
263                   1.0,
264                   65504,
265                   np.inf]
266
267        # Check float64->float16 rounding
268        with np.errstate(over="ignore"):
269            b = np.array(a, dtype=float16)
270        assert_equal(b, rounded)
271
272        # Check float32->float16 rounding
273        a = np.array(a, dtype=float32)
274        with np.errstate(over="ignore"):
275            b = np.array(a, dtype=float16)
276        assert_equal(b, rounded)
277
278    def test_half_correctness(self):
279        """Take every finite float16, and check the casting functions with
280           a manual conversion."""
281        finite_f16, finite_f32, finite_f64 = self._create_arrays_finite()
282
283        # Create an array of all finite float16s
284        a_bits = finite_f16.view(dtype=uint16)
285
286        # Convert to 64-bit float manually
287        a_sgn = (-1.0)**((a_bits & 0x8000) >> 15)
288        a_exp = np.array((a_bits & 0x7c00) >> 10, dtype=np.int32) - 15
289        a_man = (a_bits & 0x03ff) * 2.0**(-10)
290        # Implicit bit of normalized floats
291        a_man[a_exp != -15] += 1
292        # Denormalized exponent is -14
293        a_exp[a_exp == -15] = -14
294
295        a_manual = a_sgn * a_man * 2.0**a_exp
296
297        a32_fail = np.nonzero(finite_f32 != a_manual)[0]
298        if len(a32_fail) != 0:
299            bad_index = a32_fail[0]
300            assert_equal(finite_f32, a_manual,
301                 "First non-equal is half value 0x%x -> %g != %g" %
302                            (a_bits[bad_index],
303                             finite_f32[bad_index],
304                             a_manual[bad_index]))
305
306        a64_fail = np.nonzero(finite_f64 != a_manual)[0]
307        if len(a64_fail) != 0:
308            bad_index = a64_fail[0]
309            assert_equal(finite_f64, a_manual,
310                 "First non-equal is half value 0x%x -> %g != %g" %
311                            (a_bits[bad_index],
312                             finite_f64[bad_index],
313                             a_manual[bad_index]))
314
315    def test_half_ordering(self):
316        """Make sure comparisons are working right"""
317        nonan_f16, _, _ = self._create_arrays_nonan()
318
319        # All non-NaN float16 values in reverse order
320        a = nonan_f16[::-1].copy()
321
322        # 32-bit float copy
323        b = np.array(a, dtype=float32)
324
325        # Should sort the same
326        a.sort()
327        b.sort()
328        assert_equal(a, b)
329
330        # Comparisons should work
331        assert_((a[:-1] <= a[1:]).all())
332        assert_(not (a[:-1] > a[1:]).any())
333        assert_((a[1:] >= a[:-1]).all())
334        assert_(not (a[1:] < a[:-1]).any())
335        # All != except for +/-0
336        assert_equal(np.nonzero(a[:-1] < a[1:])[0].size, a.size - 2)
337        assert_equal(np.nonzero(a[1:] > a[:-1])[0].size, a.size - 2)
338
339    def test_half_funcs(self):
340        """Test the various ArrFuncs"""
341
342        # fill
343        assert_equal(np.arange(10, dtype=float16),
344                     np.arange(10, dtype=float32))
345
346        # fillwithscalar
347        a = np.zeros((5,), dtype=float16)
348        a.fill(1)
349        assert_equal(a, np.ones((5,), dtype=float16))
350
351        # nonzero and copyswap
352        a = np.array([0, 0, -1, -1 / 1e20, 0, 2.0**-24, 7.629e-6], dtype=float16)
353        assert_equal(a.nonzero()[0],
354                     [2, 5, 6])
355        a = a.byteswap()
356        a = a.view(a.dtype.newbyteorder())
357        assert_equal(a.nonzero()[0],
358                     [2, 5, 6])
359
360        # dot
361        a = np.arange(0, 10, 0.5, dtype=float16)
362        b = np.ones((20,), dtype=float16)
363        assert_equal(np.dot(a, b),
364                     95)
365
366        # argmax
367        a = np.array([0, -np.inf, -2, 0.5, 12.55, 7.3, 2.1, 12.4], dtype=float16)
368        assert_equal(a.argmax(),
369                     4)
370        a = np.array([0, -np.inf, -2, np.inf, 12.55, np.nan, 2.1, 12.4], dtype=float16)
371        assert_equal(a.argmax(),
372                     5)
373
374        # getitem
375        a = np.arange(10, dtype=float16)
376        for i in range(10):
377            assert_equal(a.item(i), i)
378
379    def test_spacing_nextafter(self):
380        """Test np.spacing and np.nextafter"""
381        # All non-negative finite #'s
382        a = np.arange(0x7c00, dtype=uint16)
383        hinf = np.array((np.inf,), dtype=float16)
384        hnan = np.array((np.nan,), dtype=float16)
385        a_f16 = a.view(dtype=float16)
386
387        assert_equal(np.spacing(a_f16[:-1]), a_f16[1:] - a_f16[:-1])
388
389        assert_equal(np.nextafter(a_f16[:-1], hinf), a_f16[1:])
390        assert_equal(np.nextafter(a_f16[0], -hinf), -a_f16[1])
391        assert_equal(np.nextafter(a_f16[1:], -hinf), a_f16[:-1])
392
393        assert_equal(np.nextafter(hinf, a_f16), a_f16[-1])
394        assert_equal(np.nextafter(-hinf, a_f16), -a_f16[-1])
395
396        assert_equal(np.nextafter(hinf, hinf), hinf)
397        assert_equal(np.nextafter(hinf, -hinf), a_f16[-1])
398        assert_equal(np.nextafter(-hinf, hinf), -a_f16[-1])
399        assert_equal(np.nextafter(-hinf, -hinf), -hinf)
400
401        assert_equal(np.nextafter(a_f16, hnan), hnan[0])
402        assert_equal(np.nextafter(hnan, a_f16), hnan[0])
403
404        assert_equal(np.nextafter(hnan, hnan), hnan)
405        assert_equal(np.nextafter(hinf, hnan), hnan)
406        assert_equal(np.nextafter(hnan, hinf), hnan)
407
408        # switch to negatives
409        a |= 0x8000
410
411        assert_equal(np.spacing(a_f16[0]), np.spacing(a_f16[1]))
412        assert_equal(np.spacing(a_f16[1:]), a_f16[:-1] - a_f16[1:])
413
414        assert_equal(np.nextafter(a_f16[0], hinf), -a_f16[1])
415        assert_equal(np.nextafter(a_f16[1:], hinf), a_f16[:-1])
416        assert_equal(np.nextafter(a_f16[:-1], -hinf), a_f16[1:])
417
418        assert_equal(np.nextafter(hinf, a_f16), -a_f16[-1])
419        assert_equal(np.nextafter(-hinf, a_f16), a_f16[-1])
420
421        assert_equal(np.nextafter(a_f16, hnan), hnan[0])
422        assert_equal(np.nextafter(hnan, a_f16), hnan[0])
423
424    def test_half_ufuncs(self):
425        """Test the various ufuncs"""
426
427        a = np.array([0, 1, 2, 4, 2], dtype=float16)
428        b = np.array([-2, 5, 1, 4, 3], dtype=float16)
429        c = np.array([0, -1, -np.inf, np.nan, 6], dtype=float16)
430
431        assert_equal(np.add(a, b), [-2, 6, 3, 8, 5])
432        assert_equal(np.subtract(a, b), [2, -4, 1, 0, -1])
433        assert_equal(np.multiply(a, b), [0, 5, 2, 16, 6])
434        assert_equal(np.divide(a, b), [0, 0.199951171875, 2, 1, 0.66650390625])
435
436        assert_equal(np.equal(a, b), [False, False, False, True, False])
437        assert_equal(np.not_equal(a, b), [True, True, True, False, True])
438        assert_equal(np.less(a, b), [False, True, False, False, True])
439        assert_equal(np.less_equal(a, b), [False, True, False, True, True])
440        assert_equal(np.greater(a, b), [True, False, True, False, False])
441        assert_equal(np.greater_equal(a, b), [True, False, True, True, False])
442        assert_equal(np.logical_and(a, b), [False, True, True, True, True])
443        assert_equal(np.logical_or(a, b), [True, True, True, True, True])
444        assert_equal(np.logical_xor(a, b), [True, False, False, False, False])
445        assert_equal(np.logical_not(a), [True, False, False, False, False])
446
447        assert_equal(np.isnan(c), [False, False, False, True, False])
448        assert_equal(np.isinf(c), [False, False, True, False, False])
449        assert_equal(np.isfinite(c), [True, True, False, False, True])
450        assert_equal(np.signbit(b), [True, False, False, False, False])
451
452        assert_equal(np.copysign(b, a), [2, 5, 1, 4, 3])
453
454        assert_equal(np.maximum(a, b), [0, 5, 2, 4, 3])
455
456        x = np.maximum(b, c)
457        assert_(np.isnan(x[3]))
458        x[3] = 0
459        assert_equal(x, [0, 5, 1, 0, 6])
460
461        assert_equal(np.minimum(a, b), [-2, 1, 1, 4, 2])
462
463        x = np.minimum(b, c)
464        assert_(np.isnan(x[3]))
465        x[3] = 0
466        assert_equal(x, [-2, -1, -np.inf, 0, 3])
467
468        assert_equal(np.fmax(a, b), [0, 5, 2, 4, 3])
469        assert_equal(np.fmax(b, c), [0, 5, 1, 4, 6])
470        assert_equal(np.fmin(a, b), [-2, 1, 1, 4, 2])
471        assert_equal(np.fmin(b, c), [-2, -1, -np.inf, 4, 3])
472
473        assert_equal(np.floor_divide(a, b), [0, 0, 2, 1, 0])
474        assert_equal(np.remainder(a, b), [0, 1, 0, 0, 2])
475        assert_equal(np.divmod(a, b), ([0, 0, 2, 1, 0], [0, 1, 0, 0, 2]))
476        assert_equal(np.square(b), [4, 25, 1, 16, 9])
477        assert_equal(np.reciprocal(b), [-0.5, 0.199951171875, 1, 0.25, 0.333251953125])
478        assert_equal(np.ones_like(b), [1, 1, 1, 1, 1])
479        assert_equal(np.conjugate(b), b)
480        assert_equal(np.absolute(b), [2, 5, 1, 4, 3])
481        assert_equal(np.negative(b), [2, -5, -1, -4, -3])
482        assert_equal(np.positive(b), b)
483        assert_equal(np.sign(b), [-1, 1, 1, 1, 1])
484        assert_equal(np.modf(b), ([0, 0, 0, 0, 0], b))
485        assert_equal(np.frexp(b), ([-0.5, 0.625, 0.5, 0.5, 0.75], [2, 3, 1, 3, 2]))
486        assert_equal(np.ldexp(b, [0, 1, 2, 4, 2]), [-2, 10, 4, 64, 12])
487
488    def test_half_coercion(self):
489        """Test that half gets coerced properly with the other types"""
490        a16 = np.array((1,), dtype=float16)
491        a32 = np.array((1,), dtype=float32)
492        b16 = float16(1)
493        b32 = float32(1)
494
495        assert np.power(a16, 2).dtype == float16
496        assert np.power(a16, 2.0).dtype == float16
497        assert np.power(a16, b16).dtype == float16
498        assert np.power(a16, b32).dtype == float32
499        assert np.power(a16, a16).dtype == float16
500        assert np.power(a16, a32).dtype == float32
501
502        assert np.power(b16, 2).dtype == float16
503        assert np.power(b16, 2.0).dtype == float16
504        assert np.power(b16, b16).dtype, float16
505        assert np.power(b16, b32).dtype, float32
506        assert np.power(b16, a16).dtype, float16
507        assert np.power(b16, a32).dtype, float32
508
509        assert np.power(a32, a16).dtype == float32
510        assert np.power(a32, b16).dtype == float32
511        assert np.power(b32, a16).dtype == float32
512        assert np.power(b32, b16).dtype == float32
513
514    @pytest.mark.skipif(platform.machine() == "armv5tel",
515                        reason="See gh-413.")
516    @pytest.mark.skipif(IS_WASM,
517                        reason="fp exceptions don't work in wasm.")
518    def test_half_fpe(self):
519        with np.errstate(all='raise'):
520            sx16 = np.array((1e-4,), dtype=float16)
521            bx16 = np.array((1e4,), dtype=float16)
522            sy16 = float16(1e-4)
523            by16 = float16(1e4)
524
525            # Underflow errors
526            assert_raises_fpe('underflow', lambda a, b: a * b, sx16, sx16)
527            assert_raises_fpe('underflow', lambda a, b: a * b, sx16, sy16)
528            assert_raises_fpe('underflow', lambda a, b: a * b, sy16, sx16)
529            assert_raises_fpe('underflow', lambda a, b: a * b, sy16, sy16)
530            assert_raises_fpe('underflow', lambda a, b: a / b, sx16, bx16)
531            assert_raises_fpe('underflow', lambda a, b: a / b, sx16, by16)
532            assert_raises_fpe('underflow', lambda a, b: a / b, sy16, bx16)
533            assert_raises_fpe('underflow', lambda a, b: a / b, sy16, by16)
534            assert_raises_fpe('underflow', lambda a, b: a / b,
535                                             float16(2.**-14), float16(2**11))
536            assert_raises_fpe('underflow', lambda a, b: a / b,
537                                             float16(-2.**-14), float16(2**11))
538            assert_raises_fpe('underflow', lambda a, b: a / b,
539                                             float16(2.**-14 + 2**-24), float16(2))
540            assert_raises_fpe('underflow', lambda a, b: a / b,
541                                             float16(-2.**-14 - 2**-24), float16(2))
542            assert_raises_fpe('underflow', lambda a, b: a / b,
543                                             float16(2.**-14 + 2**-23), float16(4))
544
545            # Overflow errors
546            assert_raises_fpe('overflow', lambda a, b: a * b, bx16, bx16)
547            assert_raises_fpe('overflow', lambda a, b: a * b, bx16, by16)
548            assert_raises_fpe('overflow', lambda a, b: a * b, by16, bx16)
549            assert_raises_fpe('overflow', lambda a, b: a * b, by16, by16)
550            assert_raises_fpe('overflow', lambda a, b: a / b, bx16, sx16)
551            assert_raises_fpe('overflow', lambda a, b: a / b, bx16, sy16)
552            assert_raises_fpe('overflow', lambda a, b: a / b, by16, sx16)
553            assert_raises_fpe('overflow', lambda a, b: a / b, by16, sy16)
554            assert_raises_fpe('overflow', lambda a, b: a + b,
555                                             float16(65504), float16(17))
556            assert_raises_fpe('overflow', lambda a, b: a - b,
557                                             float16(-65504), float16(17))
558            assert_raises_fpe('overflow', np.nextafter, float16(65504), float16(np.inf))
559            assert_raises_fpe('overflow', np.nextafter, float16(-65504), float16(-np.inf))  # noqa: E501
560            assert_raises_fpe('overflow', np.spacing, float16(65504))
561
562            # Invalid value errors
563            assert_raises_fpe('invalid', np.divide, float16(np.inf), float16(np.inf))
564            assert_raises_fpe('invalid', np.spacing, float16(np.inf))
565            assert_raises_fpe('invalid', np.spacing, float16(np.nan))
566
567            # These should not raise
568            float16(65472) + float16(32)
569            float16(2**-13) / float16(2)
570            float16(2**-14) / float16(2**10)
571            np.spacing(float16(-65504))
572            np.nextafter(float16(65504), float16(-np.inf))
573            np.nextafter(float16(-65504), float16(np.inf))
574            np.nextafter(float16(np.inf), float16(0))
575            np.nextafter(float16(-np.inf), float16(0))
576            np.nextafter(float16(0), float16(np.nan))
577            np.nextafter(float16(np.nan), float16(0))
578            float16(2**-14) / float16(2**10)
579            float16(-2**-14) / float16(2**10)
580            float16(2**-14 + 2**-23) / float16(2)
581            float16(-2**-14 - 2**-23) / float16(2)
582
583    def test_half_array_interface(self):
584        """Test that half is compatible with __array_interface__"""
585        class Dummy:
586            pass
587
588        a = np.ones((1,), dtype=float16)
589        b = Dummy()
590        b.__array_interface__ = a.__array_interface__
591        c = np.array(b)
592        assert_(c.dtype == float16)
593        assert_equal(a, c)
594 
codekingpro/portable-devtools · Team Ai