test_half.py 23 KB

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