this repo has no description
1#!/usr/bin/env python3
2# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
3# WARNING: This is a temporary copy of code from the cpython library to
4# facilitate bringup. Please file a task for anything you change!
5# flake8: noqa
6# fmt: off
7
8import fractions
9import operator
10import os
11import random
12import sys
13import struct
14import time
15import unittest
16
17from test import support
18from test.test_grammar import (VALID_UNDERSCORE_LITERALS,
19 INVALID_UNDERSCORE_LITERALS)
20from math import isinf, isnan, copysign, ldexp
21
22from test_support import cpython_only
23
24INF = float("inf")
25NAN = float("nan")
26
27have_getformat = hasattr(float, "__getformat__")
28requires_getformat = unittest.skipUnless(have_getformat,
29 "requires __getformat__")
30# TODO(T89800492)
31requires_setformat = unittest.skipUnless(hasattr(float, "__setformat__")
32 and sys.implementation.name != "skybison",
33 "requires __setformat__")
34
35#locate file with float format test values
36test_dir = os.path.dirname(__file__) or os.curdir
37format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
38
39class FloatSubclass(float):
40 pass
41
42class OtherFloatSubclass(float):
43 pass
44
45class GeneralFloatCases(unittest.TestCase):
46 # TODO(T89786301)
47 @cpython_only
48 def test_float(self):
49 self.assertEqual(float(3.14), 3.14)
50 self.assertEqual(float(314), 314.0)
51 self.assertEqual(float(" 3.14 "), 3.14)
52 self.assertRaises(ValueError, float, " 0x3.1 ")
53 self.assertRaises(ValueError, float, " -0x3.p-1 ")
54 self.assertRaises(ValueError, float, " +0x3.p-1 ")
55 self.assertRaises(ValueError, float, "++3.14")
56 self.assertRaises(ValueError, float, "+-3.14")
57 self.assertRaises(ValueError, float, "-+3.14")
58 self.assertRaises(ValueError, float, "--3.14")
59 self.assertRaises(ValueError, float, ".nan")
60 self.assertRaises(ValueError, float, "+.inf")
61 self.assertRaises(ValueError, float, ".")
62 self.assertRaises(ValueError, float, "-.")
63 self.assertRaises(TypeError, float, {})
64 self.assertRaisesRegex(TypeError, "not 'dict'", float, {})
65 # Lone surrogate
66 self.assertRaises(ValueError, float, '\uD8F0')
67 # check that we don't accept alternate exponent markers
68 self.assertRaises(ValueError, float, "-1.7d29")
69 self.assertRaises(ValueError, float, "3D-14")
70 self.assertEqual(float(" \u0663.\u0661\u0664 "), 3.14)
71 # TODO(T89787952): Pyro syntax error
72 # self.assertEqual(float("\N{EM SPACE}3.14\N{EN SPACE}"), 3.14)
73 # extra long strings should not be a problem
74 float(b'.' + b'1'*1000)
75 float('.' + '1'*1000)
76 # Invalid unicode string
77 # See bpo-34087
78 self.assertRaises(ValueError, float, '\u3053\u3093\u306b\u3061\u306f')
79
80 # TODO(T89786448)
81 @cpython_only
82 def test_underscores(self):
83 for lit in VALID_UNDERSCORE_LITERALS:
84 if not any(ch in lit for ch in 'jJxXoObB'):
85 self.assertEqual(float(lit), eval(lit))
86 self.assertEqual(float(lit), float(lit.replace('_', '')))
87 for lit in INVALID_UNDERSCORE_LITERALS:
88 if lit in ('0_7', '09_99'): # octals are not recognized here
89 continue
90 if not any(ch in lit for ch in 'jJxXoObB'):
91 self.assertRaises(ValueError, float, lit)
92 # Additional test cases; nan and inf are never valid as literals,
93 # only in the float() constructor, but we don't allow underscores
94 # in or around them.
95 self.assertRaises(ValueError, float, '_NaN')
96 self.assertRaises(ValueError, float, 'Na_N')
97 self.assertRaises(ValueError, float, 'IN_F')
98 self.assertRaises(ValueError, float, '-_INF')
99 self.assertRaises(ValueError, float, '-INF_')
100 # Check that we handle bytes values correctly.
101 self.assertRaises(ValueError, float, b'0_.\xff9')
102
103 # TODO(T89801927): [pyro] Implement float_new_from_byteslike_func
104 @cpython_only
105 def test_non_numeric_input_types(self):
106 # Test possible non-numeric types for the argument x, including
107 # subclasses of the explicitly documented accepted types.
108 class CustomStr(str): pass
109 class CustomBytes(bytes): pass
110 class CustomByteArray(bytearray): pass
111
112 factories = [
113 bytes,
114 bytearray,
115 lambda b: CustomStr(b.decode()),
116 CustomBytes,
117 CustomByteArray,
118 memoryview,
119 ]
120 try:
121 from array import array
122 except ImportError:
123 pass
124 else:
125 factories.append(lambda b: array('B', b))
126
127 for f in factories:
128 x = f(b" 3.14 ")
129 with self.subTest(type(x)):
130 self.assertEqual(float(x), 3.14)
131 with self.assertRaisesRegex(ValueError, "could not convert"):
132 float(f(b'A' * 0x10))
133
134 # TODO(T89801927): [pyro] Implement float_new_from_byteslike_func
135 @cpython_only
136 def test_float_memoryview(self):
137 self.assertEqual(float(memoryview(b'12.3')[1:4]), 2.3)
138 self.assertEqual(float(memoryview(b'12.3\x00')[1:4]), 2.3)
139 self.assertEqual(float(memoryview(b'12.3 ')[1:4]), 2.3)
140 self.assertEqual(float(memoryview(b'12.3A')[1:4]), 2.3)
141 self.assertEqual(float(memoryview(b'12.34')[1:4]), 2.3)
142
143 # TODO(T89786553)
144 @cpython_only
145 def test_error_message(self):
146 def check(s):
147 with self.assertRaises(ValueError, msg='float(%r)' % (s,)) as cm:
148 float(s)
149 self.assertEqual(str(cm.exception),
150 'could not convert string to float: %r' % (s,))
151
152 check('\xbd')
153 check('123\xbd')
154 check(' 123 456 ')
155 check(b' 123 456 ')
156
157 # non-ascii digits (error came from non-digit '!')
158 check('\u0663\u0661\u0664!')
159 # embedded NUL
160 check('123\x00')
161 check('123\x00 245')
162 check('123\x00245')
163 # byte string with embedded NUL
164 check(b'123\x00')
165 # non-UTF-8 byte string
166 check(b'123\xa0')
167
168 # TODO(T89786632)
169 @cpython_only
170 @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
171 def test_float_with_comma(self):
172 # set locale to something that doesn't use '.' for the decimal point
173 # float must not accept the locale specific decimal point but
174 # it still has to accept the normal python syntax
175 import locale
176 if not locale.localeconv()['decimal_point'] == ',':
177 self.skipTest('decimal_point is not ","')
178
179 self.assertEqual(float(" 3.14 "), 3.14)
180 self.assertEqual(float("+3.14 "), 3.14)
181 self.assertEqual(float("-3.14 "), -3.14)
182 self.assertEqual(float(".14 "), .14)
183 self.assertEqual(float("3. "), 3.0)
184 self.assertEqual(float("3.e3 "), 3000.0)
185 self.assertEqual(float("3.2e3 "), 3200.0)
186 self.assertEqual(float("2.5e-1 "), 0.25)
187 self.assertEqual(float("5e-1"), 0.5)
188 self.assertRaises(ValueError, float, " 3,14 ")
189 self.assertRaises(ValueError, float, " +3,14 ")
190 self.assertRaises(ValueError, float, " -3,14 ")
191 self.assertRaises(ValueError, float, " 0x3.1 ")
192 self.assertRaises(ValueError, float, " -0x3.p-1 ")
193 self.assertRaises(ValueError, float, " +0x3.p-1 ")
194 self.assertEqual(float(" 25.e-1 "), 2.5)
195 self.assertAlmostEqual(float(" .25e-1 "), .025)
196
197 # TODO(T89786859)
198 @cpython_only
199 def test_floatconversion(self):
200 # Make sure that calls to __float__() work properly
201 class Foo1(object):
202 def __float__(self):
203 return 42.
204
205 class Foo2(float):
206 def __float__(self):
207 return 42.
208
209 class Foo3(float):
210 def __new__(cls, value=0.):
211 return float.__new__(cls, 2*value)
212
213 def __float__(self):
214 return self
215
216 class Foo4(float):
217 def __float__(self):
218 return 42
219
220 # Issue 5759: __float__ not called on str subclasses (though it is on
221 # unicode subclasses).
222 class FooStr(str):
223 def __float__(self):
224 return float(str(self)) + 1
225
226 self.assertEqual(float(Foo1()), 42.)
227 self.assertEqual(float(Foo2()), 42.)
228 with self.assertWarns(DeprecationWarning):
229 self.assertEqual(float(Foo3(21)), 42.)
230 self.assertRaises(TypeError, float, Foo4(42))
231 self.assertEqual(float(FooStr('8')), 9.)
232
233 class Foo5:
234 def __float__(self):
235 return ""
236 self.assertRaises(TypeError, time.sleep, Foo5())
237
238 # Issue #24731
239 class F:
240 def __float__(self):
241 return OtherFloatSubclass(42.)
242 with self.assertWarns(DeprecationWarning):
243 self.assertEqual(float(F()), 42.)
244 with self.assertWarns(DeprecationWarning):
245 self.assertIs(type(float(F())), float)
246 with self.assertWarns(DeprecationWarning):
247 self.assertEqual(FloatSubclass(F()), 42.)
248 with self.assertWarns(DeprecationWarning):
249 self.assertIs(type(FloatSubclass(F())), FloatSubclass)
250
251 class MyIndex:
252 def __init__(self, value):
253 self.value = value
254 def __index__(self):
255 return self.value
256
257 self.assertEqual(float(MyIndex(42)), 42.0)
258 self.assertRaises(OverflowError, float, MyIndex(2**2000))
259
260 class MyInt:
261 def __int__(self):
262 return 42
263
264 self.assertRaises(TypeError, float, MyInt())
265
266 def test_keyword_args(self):
267 with self.assertRaisesRegex(TypeError, 'keyword argument'):
268 float(x='3.14')
269
270 def test_is_integer(self):
271 self.assertFalse((1.1).is_integer())
272 self.assertTrue((1.).is_integer())
273 self.assertFalse(float("nan").is_integer())
274 self.assertFalse(float("inf").is_integer())
275
276 def test_floatasratio(self):
277 for f, ratio in [
278 (0.875, (7, 8)),
279 (-0.875, (-7, 8)),
280 (0.0, (0, 1)),
281 (11.5, (23, 2)),
282 ]:
283 self.assertEqual(f.as_integer_ratio(), ratio)
284
285 for i in range(10000):
286 f = random.random()
287 f *= 10 ** random.randint(-100, 100)
288 n, d = f.as_integer_ratio()
289 self.assertEqual(float(n).__truediv__(d), f)
290
291 R = fractions.Fraction
292 self.assertEqual(R(0, 1),
293 R(*float(0.0).as_integer_ratio()))
294 self.assertEqual(R(5, 2),
295 R(*float(2.5).as_integer_ratio()))
296 self.assertEqual(R(1, 2),
297 R(*float(0.5).as_integer_ratio()))
298 self.assertEqual(R(4728779608739021, 2251799813685248),
299 R(*float(2.1).as_integer_ratio()))
300 self.assertEqual(R(-4728779608739021, 2251799813685248),
301 R(*float(-2.1).as_integer_ratio()))
302 self.assertEqual(R(-2100, 1),
303 R(*float(-2100.0).as_integer_ratio()))
304
305 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
306 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
307 self.assertRaises(ValueError, float('nan').as_integer_ratio)
308
309 def test_float_containment(self):
310 floats = (INF, -INF, 0.0, 1.0, NAN)
311 for f in floats:
312 self.assertIn(f, [f])
313 self.assertIn(f, (f,))
314 self.assertIn(f, {f})
315 self.assertIn(f, {f: None})
316 self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
317 self.assertIn(f, floats)
318
319 for f in floats:
320 # nonidentical containers, same type, same contents
321 self.assertTrue([f] == [f], "[%r] != [%r]" % (f, f))
322 self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f))
323 self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f))
324 self.assertTrue({f : None} == {f: None}, "{%r : None} != "
325 "{%r : None}" % (f, f))
326
327 # identical containers
328 l, t, s, d = [f], (f,), {f}, {f: None}
329 self.assertTrue(l == l, "[%r] not equal to itself" % f)
330 self.assertTrue(t == t, "(%r,) not equal to itself" % f)
331 self.assertTrue(s == s, "{%r} not equal to itself" % f)
332 self.assertTrue(d == d, "{%r : None} not equal to itself" % f)
333
334 def assertEqualAndEqualSign(self, a, b):
335 # fail unless a == b and a and b have the same sign bit;
336 # the only difference from assertEqual is that this test
337 # distinguishes -0.0 and 0.0.
338 self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b)))
339
340 @support.requires_IEEE_754
341 def test_float_mod(self):
342 # Check behaviour of % operator for IEEE 754 special cases.
343 # In particular, check signs of zeros.
344 mod = operator.mod
345
346 self.assertEqualAndEqualSign(mod(-1.0, 1.0), 0.0)
347 self.assertEqualAndEqualSign(mod(-1e-100, 1.0), 1.0)
348 self.assertEqualAndEqualSign(mod(-0.0, 1.0), 0.0)
349 self.assertEqualAndEqualSign(mod(0.0, 1.0), 0.0)
350 self.assertEqualAndEqualSign(mod(1e-100, 1.0), 1e-100)
351 self.assertEqualAndEqualSign(mod(1.0, 1.0), 0.0)
352
353 self.assertEqualAndEqualSign(mod(-1.0, -1.0), -0.0)
354 self.assertEqualAndEqualSign(mod(-1e-100, -1.0), -1e-100)
355 self.assertEqualAndEqualSign(mod(-0.0, -1.0), -0.0)
356 self.assertEqualAndEqualSign(mod(0.0, -1.0), -0.0)
357 self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0)
358 self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0)
359
360 # TODO(T89786982)
361 @cpython_only
362 @support.requires_IEEE_754
363 def test_float_pow(self):
364 # test builtin pow and ** operator for IEEE 754 special cases.
365 # Special cases taken from section F.9.4.4 of the C99 specification
366
367 for pow_op in pow, operator.pow:
368 # x**NAN is NAN for any x except 1
369 self.assertTrue(isnan(pow_op(-INF, NAN)))
370 self.assertTrue(isnan(pow_op(-2.0, NAN)))
371 self.assertTrue(isnan(pow_op(-1.0, NAN)))
372 self.assertTrue(isnan(pow_op(-0.5, NAN)))
373 self.assertTrue(isnan(pow_op(-0.0, NAN)))
374 self.assertTrue(isnan(pow_op(0.0, NAN)))
375 self.assertTrue(isnan(pow_op(0.5, NAN)))
376 self.assertTrue(isnan(pow_op(2.0, NAN)))
377 self.assertTrue(isnan(pow_op(INF, NAN)))
378 self.assertTrue(isnan(pow_op(NAN, NAN)))
379
380 # NAN**y is NAN for any y except +-0
381 self.assertTrue(isnan(pow_op(NAN, -INF)))
382 self.assertTrue(isnan(pow_op(NAN, -2.0)))
383 self.assertTrue(isnan(pow_op(NAN, -1.0)))
384 self.assertTrue(isnan(pow_op(NAN, -0.5)))
385 self.assertTrue(isnan(pow_op(NAN, 0.5)))
386 self.assertTrue(isnan(pow_op(NAN, 1.0)))
387 self.assertTrue(isnan(pow_op(NAN, 2.0)))
388 self.assertTrue(isnan(pow_op(NAN, INF)))
389
390 # (+-0)**y raises ZeroDivisionError for y a negative odd integer
391 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0)
392 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0)
393
394 # (+-0)**y raises ZeroDivisionError for y finite and negative
395 # but not an odd integer
396 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0)
397 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5)
398 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0)
399 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5)
400
401 # (+-0)**y is +-0 for y a positive odd integer
402 self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0)
403 self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0)
404
405 # (+-0)**y is 0 for y finite and positive but not an odd integer
406 self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0)
407 self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0)
408 self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0)
409 self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0)
410
411 # (-1)**+-inf is 1
412 self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0)
413 self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0)
414
415 # 1**y is 1 for any y, even if y is an infinity or nan
416 self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0)
417 self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0)
418 self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0)
419 self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0)
420 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
421 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
422 self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0)
423 self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0)
424 self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0)
425 self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0)
426 self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0)
427
428 # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan
429 self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0)
430 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
431 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
432 self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0)
433 self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0)
434 self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0)
435 self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0)
436 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
437 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
438 self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0)
439 self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0)
440 self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0)
441 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
442 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
443 self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0)
444 self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0)
445 self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0)
446 self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0)
447 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
448 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
449 self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0)
450 self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0)
451
452 # x**y defers to complex pow for finite negative x and
453 # non-integral y.
454 self.assertEqual(type(pow_op(-2.0, -0.5)), complex)
455 self.assertEqual(type(pow_op(-2.0, 0.5)), complex)
456 self.assertEqual(type(pow_op(-1.0, -0.5)), complex)
457 self.assertEqual(type(pow_op(-1.0, 0.5)), complex)
458 self.assertEqual(type(pow_op(-0.5, -0.5)), complex)
459 self.assertEqual(type(pow_op(-0.5, 0.5)), complex)
460
461 # x**-INF is INF for abs(x) < 1
462 self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF)
463 self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF)
464 self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF)
465 self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF)
466
467 # x**-INF is 0 for abs(x) > 1
468 self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0)
469 self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0)
470 self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0)
471 self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0)
472
473 # x**INF is 0 for abs(x) < 1
474 self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0)
475 self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0)
476 self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0)
477 self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0)
478
479 # x**INF is INF for abs(x) > 1
480 self.assertEqualAndEqualSign(pow_op(-INF, INF), INF)
481 self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF)
482 self.assertEqualAndEqualSign(pow_op(2.0, INF), INF)
483 self.assertEqualAndEqualSign(pow_op(INF, INF), INF)
484
485 # (-INF)**y is -0.0 for y a negative odd integer
486 self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0)
487
488 # (-INF)**y is 0.0 for y negative but not an odd integer
489 self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0)
490 self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0)
491
492 # (-INF)**y is -INF for y a positive odd integer
493 self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF)
494
495 # (-INF)**y is INF for y positive but not an odd integer
496 self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF)
497 self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF)
498
499 # INF**y is INF for y positive
500 self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF)
501 self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF)
502 self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF)
503
504 # INF**y is 0.0 for y negative
505 self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0)
506 self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0)
507 self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0)
508
509 # basic checks not covered by the special cases above
510 self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25)
511 self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5)
512 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
513 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
514 self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0)
515 self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0)
516 self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0)
517 self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0)
518 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
519 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
520 self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0)
521 self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0)
522 self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25)
523 self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5)
524 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
525 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
526 self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0)
527 self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0)
528
529 # 1 ** large and -1 ** large; some libms apparently
530 # have problems with these
531 self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0)
532 self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0)
533 self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0)
534 self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0)
535
536 # check sign for results that underflow to 0
537 self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0)
538 self.assertEqual(type(pow_op(-2.0, -2000.5)), complex)
539 self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0)
540 self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0)
541 self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0)
542 self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0)
543 self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0)
544 self.assertEqual(type(pow_op(-0.5, 2000.5)), complex)
545 self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0)
546 self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0)
547 self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0)
548 self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0)
549
550 # check we don't raise an exception for subnormal results,
551 # and validate signs. Tests currently disabled, since
552 # they fail on systems where a subnormal result from pow
553 # is flushed to zero (e.g. Debian/ia64.)
554 #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315)
555 #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315)
556 #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315)
557 #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315)
558 #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315)
559 #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315)
560 #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
561 #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
562
563
564@requires_setformat
565class FormatFunctionsTestCase(unittest.TestCase):
566
567 def setUp(self):
568 self.save_formats = {'double':float.__getformat__('double'),
569 'float':float.__getformat__('float')}
570
571 def tearDown(self):
572 float.__setformat__('double', self.save_formats['double'])
573 float.__setformat__('float', self.save_formats['float'])
574
575 def test_getformat(self):
576 self.assertIn(float.__getformat__('double'),
577 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
578 self.assertIn(float.__getformat__('float'),
579 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
580 self.assertRaises(ValueError, float.__getformat__, 'chicken')
581 self.assertRaises(TypeError, float.__getformat__, 1)
582
583 def test_setformat(self):
584 for t in 'double', 'float':
585 float.__setformat__(t, 'unknown')
586 if self.save_formats[t] == 'IEEE, big-endian':
587 self.assertRaises(ValueError, float.__setformat__,
588 t, 'IEEE, little-endian')
589 elif self.save_formats[t] == 'IEEE, little-endian':
590 self.assertRaises(ValueError, float.__setformat__,
591 t, 'IEEE, big-endian')
592 else:
593 self.assertRaises(ValueError, float.__setformat__,
594 t, 'IEEE, big-endian')
595 self.assertRaises(ValueError, float.__setformat__,
596 t, 'IEEE, little-endian')
597 self.assertRaises(ValueError, float.__setformat__,
598 t, 'chicken')
599 self.assertRaises(ValueError, float.__setformat__,
600 'chicken', 'unknown')
601
602BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
603LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
604BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
605LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
606
607BE_FLOAT_INF = b'\x7f\x80\x00\x00'
608LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
609BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
610LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
611
612# on non-IEEE platforms, attempting to unpack a bit pattern
613# representing an infinity or a NaN should raise an exception.
614
615@requires_setformat
616class UnknownFormatTestCase(unittest.TestCase):
617 def setUp(self):
618 self.save_formats = {'double':float.__getformat__('double'),
619 'float':float.__getformat__('float')}
620 float.__setformat__('double', 'unknown')
621 float.__setformat__('float', 'unknown')
622
623 def tearDown(self):
624 float.__setformat__('double', self.save_formats['double'])
625 float.__setformat__('float', self.save_formats['float'])
626
627 def test_double_specials_dont_unpack(self):
628 for fmt, data in [('>d', BE_DOUBLE_INF),
629 ('>d', BE_DOUBLE_NAN),
630 ('<d', LE_DOUBLE_INF),
631 ('<d', LE_DOUBLE_NAN)]:
632 self.assertRaises(ValueError, struct.unpack, fmt, data)
633
634 def test_float_specials_dont_unpack(self):
635 for fmt, data in [('>f', BE_FLOAT_INF),
636 ('>f', BE_FLOAT_NAN),
637 ('<f', LE_FLOAT_INF),
638 ('<f', LE_FLOAT_NAN)]:
639 self.assertRaises(ValueError, struct.unpack, fmt, data)
640
641
642# on an IEEE platform, all we guarantee is that bit patterns
643# representing infinities or NaNs do not raise an exception; all else
644# is accident (today).
645# let's also try to guarantee that -0.0 and 0.0 don't get confused.
646
647class IEEEFormatTestCase(unittest.TestCase):
648
649 @support.requires_IEEE_754
650 def test_double_specials_do_unpack(self):
651 for fmt, data in [('>d', BE_DOUBLE_INF),
652 ('>d', BE_DOUBLE_NAN),
653 ('<d', LE_DOUBLE_INF),
654 ('<d', LE_DOUBLE_NAN)]:
655 struct.unpack(fmt, data)
656
657 @support.requires_IEEE_754
658 def test_float_specials_do_unpack(self):
659 for fmt, data in [('>f', BE_FLOAT_INF),
660 ('>f', BE_FLOAT_NAN),
661 ('<f', LE_FLOAT_INF),
662 ('<f', LE_FLOAT_NAN)]:
663 struct.unpack(fmt, data)
664
665 # TODO(T85846583): [Pyro 3.8] PEP-384 _testcapi
666 @cpython_only
667 @support.requires_IEEE_754
668 def test_serialized_float_rounding(self):
669 from _testcapi import FLT_MAX
670 self.assertEqual(struct.pack("<f", 3.40282356e38), struct.pack("<f", FLT_MAX))
671 self.assertEqual(struct.pack("<f", -3.40282356e38), struct.pack("<f", -FLT_MAX))
672
673class FormatTestCase(unittest.TestCase):
674
675 def test_format(self):
676 # these should be rewritten to use both format(x, spec) and
677 # x.__format__(spec)
678
679 self.assertEqual(format(0.0, 'f'), '0.000000')
680
681 # the default is 'g', except for empty format spec
682 self.assertEqual(format(0.0, ''), '0.0')
683 self.assertEqual(format(0.01, ''), '0.01')
684 self.assertEqual(format(0.01, 'g'), '0.01')
685
686 # empty presentation type should format in the same way as str
687 # (issue 5920)
688 x = 100/7.
689 self.assertEqual(format(x, ''), str(x))
690 self.assertEqual(format(x, '-'), str(x))
691 self.assertEqual(format(x, '>'), str(x))
692 self.assertEqual(format(x, '2'), str(x))
693
694 self.assertEqual(format(1.0, 'f'), '1.000000')
695
696 self.assertEqual(format(-1.0, 'f'), '-1.000000')
697
698 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
699 self.assertEqual(format(-1.0, ' f'), '-1.000000')
700 self.assertEqual(format( 1.0, '+f'), '+1.000000')
701 self.assertEqual(format(-1.0, '+f'), '-1.000000')
702
703 # % formatting
704 self.assertEqual(format(-1.0, '%'), '-100.000000%')
705
706 # conversion to string should fail
707 self.assertRaises(ValueError, format, 3.0, "s")
708
709 # other format specifiers shouldn't work on floats,
710 # in particular int specifiers
711 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
712 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
713 if not format_spec in 'eEfFgGn%':
714 self.assertRaises(ValueError, format, 0.0, format_spec)
715 self.assertRaises(ValueError, format, 1.0, format_spec)
716 self.assertRaises(ValueError, format, -1.0, format_spec)
717 self.assertRaises(ValueError, format, 1e100, format_spec)
718 self.assertRaises(ValueError, format, -1e100, format_spec)
719 self.assertRaises(ValueError, format, 1e-100, format_spec)
720 self.assertRaises(ValueError, format, -1e-100, format_spec)
721
722 # issue 3382
723 self.assertEqual(format(NAN, 'f'), 'nan')
724 self.assertEqual(format(NAN, 'F'), 'NAN')
725 self.assertEqual(format(INF, 'f'), 'inf')
726 self.assertEqual(format(INF, 'F'), 'INF')
727
728 @support.requires_IEEE_754
729 def test_format_testfile(self):
730 with open(format_testfile) as testfile:
731 for line in testfile:
732 if line.startswith('--'):
733 continue
734 line = line.strip()
735 if not line:
736 continue
737
738 lhs, rhs = map(str.strip, line.split('->'))
739 fmt, arg = lhs.split()
740 self.assertEqual(fmt % float(arg), rhs)
741 self.assertEqual(fmt % -float(arg), '-' + rhs)
742
743 def test_issue5864(self):
744 self.assertEqual(format(123.456, '.4'), '123.5')
745 self.assertEqual(format(1234.56, '.4'), '1.235e+03')
746 self.assertEqual(format(12345.6, '.4'), '1.235e+04')
747
748 def test_issue35560(self):
749 self.assertEqual(format(123.0, '00'), '123.0')
750 self.assertEqual(format(123.34, '00f'), '123.340000')
751 self.assertEqual(format(123.34, '00e'), '1.233400e+02')
752 self.assertEqual(format(123.34, '00g'), '123.34')
753 self.assertEqual(format(123.34, '00.10f'), '123.3400000000')
754 self.assertEqual(format(123.34, '00.10e'), '1.2334000000e+02')
755 self.assertEqual(format(123.34, '00.10g'), '123.34')
756 self.assertEqual(format(123.34, '01f'), '123.340000')
757
758 self.assertEqual(format(-123.0, '00'), '-123.0')
759 self.assertEqual(format(-123.34, '00f'), '-123.340000')
760 self.assertEqual(format(-123.34, '00e'), '-1.233400e+02')
761 self.assertEqual(format(-123.34, '00g'), '-123.34')
762 self.assertEqual(format(-123.34, '00.10f'), '-123.3400000000')
763 self.assertEqual(format(-123.34, '00.10f'), '-123.3400000000')
764 self.assertEqual(format(-123.34, '00.10e'), '-1.2334000000e+02')
765 self.assertEqual(format(-123.34, '00.10g'), '-123.34')
766
767class ReprTestCase(unittest.TestCase):
768 # TODO(T89787302)
769 @cpython_only
770 def test_repr(self):
771 with open(os.path.join(os.path.split(__file__)[0],
772 'floating_points.txt')) as floats_file:
773 for line in floats_file:
774 line = line.strip()
775 if not line or line.startswith('#'):
776 continue
777 v = eval(line)
778 self.assertEqual(v, eval(repr(v)))
779
780 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
781 "applies only when using short float repr style")
782 def test_short_repr(self):
783 # test short float repr introduced in Python 3.1. One aspect
784 # of this repr is that we get some degree of str -> float ->
785 # str roundtripping. In particular, for any numeric string
786 # containing 15 or fewer significant digits, those exact same
787 # digits (modulo trailing zeros) should appear in the output.
788 # No more repr(0.03) -> "0.029999999999999999"!
789
790 test_strings = [
791 # output always includes *either* a decimal point and at
792 # least one digit after that point, or an exponent.
793 '0.0',
794 '1.0',
795 '0.01',
796 '0.02',
797 '0.03',
798 '0.04',
799 '0.05',
800 '1.23456789',
801 '10.0',
802 '100.0',
803 # values >= 1e16 get an exponent...
804 '1000000000000000.0',
805 '9999999999999990.0',
806 '1e+16',
807 '1e+17',
808 # ... and so do values < 1e-4
809 '0.001',
810 '0.001001',
811 '0.00010000000000001',
812 '0.0001',
813 '9.999999999999e-05',
814 '1e-05',
815 # values designed to provoke failure if the FPU rounding
816 # precision isn't set correctly
817 '8.72293771110361e+25',
818 '7.47005307342313e+26',
819 '2.86438000439698e+28',
820 '8.89142905246179e+28',
821 '3.08578087079232e+35',
822 ]
823
824 for s in test_strings:
825 negs = '-'+s
826 self.assertEqual(s, repr(float(s)))
827 self.assertEqual(negs, repr(float(negs)))
828 # Since Python 3.2, repr and str are identical
829 self.assertEqual(repr(float(s)), str(float(s)))
830 self.assertEqual(repr(float(negs)), str(float(negs)))
831
832@support.requires_IEEE_754
833class RoundTestCase(unittest.TestCase):
834
835 def test_inf_nan(self):
836 self.assertRaises(OverflowError, round, INF)
837 self.assertRaises(OverflowError, round, -INF)
838 self.assertRaises(ValueError, round, NAN)
839 self.assertRaises(TypeError, round, INF, 0.0)
840 self.assertRaises(TypeError, round, -INF, 1.0)
841 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
842 self.assertRaises(TypeError, round, -0.0, 1j)
843
844 def test_large_n(self):
845 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
846 self.assertEqual(round(123.456, n), 123.456)
847 self.assertEqual(round(-123.456, n), -123.456)
848 self.assertEqual(round(1e300, n), 1e300)
849 self.assertEqual(round(1e-320, n), 1e-320)
850 self.assertEqual(round(1e150, 300), 1e150)
851 self.assertEqual(round(1e300, 307), 1e300)
852 self.assertEqual(round(-3.1415, 308), -3.1415)
853 self.assertEqual(round(1e150, 309), 1e150)
854 self.assertEqual(round(1.4e-315, 315), 1e-315)
855
856 def test_small_n(self):
857 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
858 self.assertEqual(round(123.456, n), 0.0)
859 self.assertEqual(round(-123.456, n), -0.0)
860 self.assertEqual(round(1e300, n), 0.0)
861 self.assertEqual(round(1e-320, n), 0.0)
862
863 def test_overflow(self):
864 self.assertRaises(OverflowError, round, 1.6e308, -308)
865 self.assertRaises(OverflowError, round, -1.7e308, -308)
866
867 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
868 "applies only when using short float repr style")
869 def test_previous_round_bugs(self):
870 # particular cases that have occurred in bug reports
871 self.assertEqual(round(562949953421312.5, 1),
872 562949953421312.5)
873 self.assertEqual(round(56294995342131.5, 3),
874 56294995342131.5)
875 # round-half-even
876 self.assertEqual(round(25.0, -1), 20.0)
877 self.assertEqual(round(35.0, -1), 40.0)
878 self.assertEqual(round(45.0, -1), 40.0)
879 self.assertEqual(round(55.0, -1), 60.0)
880 self.assertEqual(round(65.0, -1), 60.0)
881 self.assertEqual(round(75.0, -1), 80.0)
882 self.assertEqual(round(85.0, -1), 80.0)
883 self.assertEqual(round(95.0, -1), 100.0)
884
885 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
886 "applies only when using short float repr style")
887 def test_matches_float_format(self):
888 # round should give the same results as float formatting
889 for i in range(500):
890 x = i/1000.
891 self.assertEqual(float(format(x, '.0f')), round(x, 0))
892 self.assertEqual(float(format(x, '.1f')), round(x, 1))
893 self.assertEqual(float(format(x, '.2f')), round(x, 2))
894 self.assertEqual(float(format(x, '.3f')), round(x, 3))
895
896 for i in range(5, 5000, 10):
897 x = i/1000.
898 self.assertEqual(float(format(x, '.0f')), round(x, 0))
899 self.assertEqual(float(format(x, '.1f')), round(x, 1))
900 self.assertEqual(float(format(x, '.2f')), round(x, 2))
901 self.assertEqual(float(format(x, '.3f')), round(x, 3))
902
903 for i in range(500):
904 x = random.random()
905 self.assertEqual(float(format(x, '.0f')), round(x, 0))
906 self.assertEqual(float(format(x, '.1f')), round(x, 1))
907 self.assertEqual(float(format(x, '.2f')), round(x, 2))
908 self.assertEqual(float(format(x, '.3f')), round(x, 3))
909
910 def test_format_specials(self):
911 # Test formatting of nans and infs.
912
913 def test(fmt, value, expected):
914 # Test with both % and format().
915 self.assertEqual(fmt % value, expected, fmt)
916 fmt = fmt[1:] # strip off the %
917 self.assertEqual(format(value, fmt), expected, fmt)
918
919 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
920 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
921 pfmt = '%+' + fmt[1:]
922 sfmt = '% ' + fmt[1:]
923 test(fmt, INF, 'inf')
924 test(fmt, -INF, '-inf')
925 test(fmt, NAN, 'nan')
926 test(fmt, -NAN, 'nan')
927 # When asking for a sign, it's always provided. nans are
928 # always positive.
929 test(pfmt, INF, '+inf')
930 test(pfmt, -INF, '-inf')
931 test(pfmt, NAN, '+nan')
932 test(pfmt, -NAN, '+nan')
933 # When using ' ' for a sign code, only infs can be negative.
934 # Others have a space.
935 test(sfmt, INF, ' inf')
936 test(sfmt, -INF, '-inf')
937 test(sfmt, NAN, ' nan')
938 test(sfmt, -NAN, ' nan')
939
940 def test_None_ndigits(self):
941 for x in round(1.23), round(1.23, None), round(1.23, ndigits=None):
942 self.assertEqual(x, 1)
943 self.assertIsInstance(x, int)
944 for x in round(1.78), round(1.78, None), round(1.78, ndigits=None):
945 self.assertEqual(x, 2)
946 self.assertIsInstance(x, int)
947
948
949# Beginning with Python 2.6 float has cross platform compatible
950# ways to create and represent inf and nan
951class InfNanTest(unittest.TestCase):
952 # TODO(T89787673)
953 @cpython_only
954 def test_inf_from_str(self):
955 self.assertTrue(isinf(float("inf")))
956 self.assertTrue(isinf(float("+inf")))
957 self.assertTrue(isinf(float("-inf")))
958 self.assertTrue(isinf(float("infinity")))
959 self.assertTrue(isinf(float("+infinity")))
960 self.assertTrue(isinf(float("-infinity")))
961
962 self.assertEqual(repr(float("inf")), "inf")
963 self.assertEqual(repr(float("+inf")), "inf")
964 self.assertEqual(repr(float("-inf")), "-inf")
965 self.assertEqual(repr(float("infinity")), "inf")
966 self.assertEqual(repr(float("+infinity")), "inf")
967 self.assertEqual(repr(float("-infinity")), "-inf")
968
969 self.assertEqual(repr(float("INF")), "inf")
970 self.assertEqual(repr(float("+Inf")), "inf")
971 self.assertEqual(repr(float("-iNF")), "-inf")
972 self.assertEqual(repr(float("Infinity")), "inf")
973 self.assertEqual(repr(float("+iNfInItY")), "inf")
974 self.assertEqual(repr(float("-INFINITY")), "-inf")
975
976 self.assertEqual(str(float("inf")), "inf")
977 self.assertEqual(str(float("+inf")), "inf")
978 self.assertEqual(str(float("-inf")), "-inf")
979 self.assertEqual(str(float("infinity")), "inf")
980 self.assertEqual(str(float("+infinity")), "inf")
981 self.assertEqual(str(float("-infinity")), "-inf")
982
983 self.assertRaises(ValueError, float, "info")
984 self.assertRaises(ValueError, float, "+info")
985 self.assertRaises(ValueError, float, "-info")
986 self.assertRaises(ValueError, float, "in")
987 self.assertRaises(ValueError, float, "+in")
988 self.assertRaises(ValueError, float, "-in")
989 self.assertRaises(ValueError, float, "infinit")
990 self.assertRaises(ValueError, float, "+Infin")
991 self.assertRaises(ValueError, float, "-INFI")
992 self.assertRaises(ValueError, float, "infinitys")
993
994 self.assertRaises(ValueError, float, "++Inf")
995 self.assertRaises(ValueError, float, "-+inf")
996 self.assertRaises(ValueError, float, "+-infinity")
997 self.assertRaises(ValueError, float, "--Infinity")
998
999 def test_inf_as_str(self):
1000 self.assertEqual(repr(1e300 * 1e300), "inf")
1001 self.assertEqual(repr(-1e300 * 1e300), "-inf")
1002
1003 self.assertEqual(str(1e300 * 1e300), "inf")
1004 self.assertEqual(str(-1e300 * 1e300), "-inf")
1005
1006 def test_nan_from_str(self):
1007 self.assertTrue(isnan(float("nan")))
1008 self.assertTrue(isnan(float("+nan")))
1009 self.assertTrue(isnan(float("-nan")))
1010
1011 self.assertEqual(repr(float("nan")), "nan")
1012 self.assertEqual(repr(float("+nan")), "nan")
1013 self.assertEqual(repr(float("-nan")), "nan")
1014
1015 self.assertEqual(repr(float("NAN")), "nan")
1016 self.assertEqual(repr(float("+NAn")), "nan")
1017 self.assertEqual(repr(float("-NaN")), "nan")
1018
1019 self.assertEqual(str(float("nan")), "nan")
1020 self.assertEqual(str(float("+nan")), "nan")
1021 self.assertEqual(str(float("-nan")), "nan")
1022
1023 self.assertRaises(ValueError, float, "nana")
1024 self.assertRaises(ValueError, float, "+nana")
1025 self.assertRaises(ValueError, float, "-nana")
1026 self.assertRaises(ValueError, float, "na")
1027 self.assertRaises(ValueError, float, "+na")
1028 self.assertRaises(ValueError, float, "-na")
1029
1030 self.assertRaises(ValueError, float, "++nan")
1031 self.assertRaises(ValueError, float, "-+NAN")
1032 self.assertRaises(ValueError, float, "+-NaN")
1033 self.assertRaises(ValueError, float, "--nAn")
1034
1035 def test_nan_as_str(self):
1036 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
1037 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
1038
1039 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
1040 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
1041
1042 def test_inf_signs(self):
1043 self.assertEqual(copysign(1.0, float('inf')), 1.0)
1044 self.assertEqual(copysign(1.0, float('-inf')), -1.0)
1045
1046 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
1047 "applies only when using short float repr style")
1048 def test_nan_signs(self):
1049 # When using the dtoa.c code, the sign of float('nan') should
1050 # be predictable.
1051 self.assertEqual(copysign(1.0, float('nan')), 1.0)
1052 self.assertEqual(copysign(1.0, float('-nan')), -1.0)
1053
1054
1055fromHex = float.fromhex
1056toHex = float.hex
1057class HexFloatTestCase(unittest.TestCase):
1058 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
1059 MIN = fromHex('0x1p-1022') # min normal
1060 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
1061 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
1062
1063 def identical(self, x, y):
1064 # check that floats x and y are identical, or that both
1065 # are NaNs
1066 if isnan(x) or isnan(y):
1067 if isnan(x) == isnan(y):
1068 return
1069 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
1070 return
1071 self.fail('%r not identical to %r' % (x, y))
1072
1073 def test_ends(self):
1074 self.identical(self.MIN, ldexp(1.0, -1022))
1075 self.identical(self.TINY, ldexp(1.0, -1074))
1076 self.identical(self.EPS, ldexp(1.0, -52))
1077 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
1078
1079 def test_invalid_inputs(self):
1080 invalid_inputs = [
1081 'infi', # misspelt infinities and nans
1082 '-Infinit',
1083 '++inf',
1084 '-+Inf',
1085 '--nan',
1086 '+-NaN',
1087 'snan',
1088 'NaNs',
1089 'nna',
1090 'an',
1091 'nf',
1092 'nfinity',
1093 'inity',
1094 'iinity',
1095 '0xnan',
1096 '',
1097 ' ',
1098 'x1.0p0',
1099 '0xX1.0p0',
1100 '+ 0x1.0p0', # internal whitespace
1101 '- 0x1.0p0',
1102 '0 x1.0p0',
1103 '0x 1.0p0',
1104 '0x1 2.0p0',
1105 '+0x1 .0p0',
1106 '0x1. 0p0',
1107 '-0x1.0 1p0',
1108 '-0x1.0 p0',
1109 '+0x1.0p +0',
1110 '0x1.0p -0',
1111 '0x1.0p 0',
1112 '+0x1.0p+ 0',
1113 '-0x1.0p- 0',
1114 '++0x1.0p-0', # double signs
1115 '--0x1.0p0',
1116 '+-0x1.0p+0',
1117 '-+0x1.0p0',
1118 '0x1.0p++0',
1119 '+0x1.0p+-0',
1120 '-0x1.0p-+0',
1121 '0x1.0p--0',
1122 '0x1.0.p0',
1123 '0x.p0', # no hex digits before or after point
1124 '0x1,p0', # wrong decimal point character
1125 '0x1pa',
1126 '0x1p\uff10', # fullwidth Unicode digits
1127 '\uff10x1p0',
1128 '0x\uff11p0',
1129 '0x1.\uff10p0',
1130 '0x1p0 \n 0x2p0',
1131 '0x1p0\0 0x1p0', # embedded null byte is not end of string
1132 ]
1133 for x in invalid_inputs:
1134 try:
1135 result = fromHex(x)
1136 except ValueError:
1137 pass
1138 else:
1139 self.fail('Expected float.fromhex(%r) to raise ValueError; '
1140 'got %r instead' % (x, result))
1141
1142
1143 def test_whitespace(self):
1144 value_pairs = [
1145 ('inf', INF),
1146 ('-Infinity', -INF),
1147 ('nan', NAN),
1148 ('1.0', 1.0),
1149 ('-0x.2', -0.125),
1150 ('-0.0', -0.0)
1151 ]
1152 whitespace = [
1153 '',
1154 ' ',
1155 '\t',
1156 '\n',
1157 '\n \t',
1158 '\f',
1159 '\v',
1160 '\r'
1161 ]
1162 for inp, expected in value_pairs:
1163 for lead in whitespace:
1164 for trail in whitespace:
1165 got = fromHex(lead + inp + trail)
1166 self.identical(got, expected)
1167
1168
1169 def test_from_hex(self):
1170 MIN = self.MIN;
1171 MAX = self.MAX;
1172 TINY = self.TINY;
1173 EPS = self.EPS;
1174
1175 # two spellings of infinity, with optional signs; case-insensitive
1176 self.identical(fromHex('inf'), INF)
1177 self.identical(fromHex('+Inf'), INF)
1178 self.identical(fromHex('-INF'), -INF)
1179 self.identical(fromHex('iNf'), INF)
1180 self.identical(fromHex('Infinity'), INF)
1181 self.identical(fromHex('+INFINITY'), INF)
1182 self.identical(fromHex('-infinity'), -INF)
1183 self.identical(fromHex('-iNFiNitY'), -INF)
1184
1185 # nans with optional sign; case insensitive
1186 self.identical(fromHex('nan'), NAN)
1187 self.identical(fromHex('+NaN'), NAN)
1188 self.identical(fromHex('-NaN'), NAN)
1189 self.identical(fromHex('-nAN'), NAN)
1190
1191 # variations in input format
1192 self.identical(fromHex('1'), 1.0)
1193 self.identical(fromHex('+1'), 1.0)
1194 self.identical(fromHex('1.'), 1.0)
1195 self.identical(fromHex('1.0'), 1.0)
1196 self.identical(fromHex('1.0p0'), 1.0)
1197 self.identical(fromHex('01'), 1.0)
1198 self.identical(fromHex('01.'), 1.0)
1199 self.identical(fromHex('0x1'), 1.0)
1200 self.identical(fromHex('0x1.'), 1.0)
1201 self.identical(fromHex('0x1.0'), 1.0)
1202 self.identical(fromHex('+0x1.0'), 1.0)
1203 self.identical(fromHex('0x1p0'), 1.0)
1204 self.identical(fromHex('0X1p0'), 1.0)
1205 self.identical(fromHex('0X1P0'), 1.0)
1206 self.identical(fromHex('0x1P0'), 1.0)
1207 self.identical(fromHex('0x1.p0'), 1.0)
1208 self.identical(fromHex('0x1.0p0'), 1.0)
1209 self.identical(fromHex('0x.1p4'), 1.0)
1210 self.identical(fromHex('0x.1p04'), 1.0)
1211 self.identical(fromHex('0x.1p004'), 1.0)
1212 self.identical(fromHex('0x1p+0'), 1.0)
1213 self.identical(fromHex('0x1P-0'), 1.0)
1214 self.identical(fromHex('+0x1p0'), 1.0)
1215 self.identical(fromHex('0x01p0'), 1.0)
1216 self.identical(fromHex('0x1p00'), 1.0)
1217 self.identical(fromHex(' 0x1p0 '), 1.0)
1218 self.identical(fromHex('\n 0x1p0'), 1.0)
1219 self.identical(fromHex('0x1p0 \t'), 1.0)
1220 self.identical(fromHex('0xap0'), 10.0)
1221 self.identical(fromHex('0xAp0'), 10.0)
1222 self.identical(fromHex('0xaP0'), 10.0)
1223 self.identical(fromHex('0xAP0'), 10.0)
1224 self.identical(fromHex('0xbep0'), 190.0)
1225 self.identical(fromHex('0xBep0'), 190.0)
1226 self.identical(fromHex('0xbEp0'), 190.0)
1227 self.identical(fromHex('0XBE0P-4'), 190.0)
1228 self.identical(fromHex('0xBEp0'), 190.0)
1229 self.identical(fromHex('0xB.Ep4'), 190.0)
1230 self.identical(fromHex('0x.BEp8'), 190.0)
1231 self.identical(fromHex('0x.0BEp12'), 190.0)
1232
1233 # moving the point around
1234 pi = fromHex('0x1.921fb54442d18p1')
1235 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
1236 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
1237 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
1238 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
1239 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
1240 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
1241 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
1242 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
1243 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
1244 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
1245 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
1246 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
1247 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
1248 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
1249 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
1250 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
1251 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
1252 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
1253 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
1254 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
1255 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
1256 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
1257 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
1258 # ...
1259 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
1260 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
1261 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
1262 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
1263 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
1264 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
1265 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
1266 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
1267 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
1268
1269
1270 # results that should overflow...
1271 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
1272 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
1273 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
1274 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
1275 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
1276 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
1277 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
1278 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
1279 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
1280 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
1281 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
1282 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
1283 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
1284 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
1285 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
1286 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
1287 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
1288 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
1289 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
1290
1291 # ...and those that round to +-max float
1292 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
1293 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
1294 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
1295
1296 # zeros
1297 self.identical(fromHex('0x0p0'), 0.0)
1298 self.identical(fromHex('0x0p1000'), 0.0)
1299 self.identical(fromHex('-0x0p1023'), -0.0)
1300 self.identical(fromHex('0X0p1024'), 0.0)
1301 self.identical(fromHex('-0x0p1025'), -0.0)
1302 self.identical(fromHex('0X0p2000'), 0.0)
1303 self.identical(fromHex('0x0p123456789123456789'), 0.0)
1304 self.identical(fromHex('-0X0p-0'), -0.0)
1305 self.identical(fromHex('-0X0p-1000'), -0.0)
1306 self.identical(fromHex('0x0p-1023'), 0.0)
1307 self.identical(fromHex('-0X0p-1024'), -0.0)
1308 self.identical(fromHex('-0x0p-1025'), -0.0)
1309 self.identical(fromHex('-0x0p-1072'), -0.0)
1310 self.identical(fromHex('0X0p-1073'), 0.0)
1311 self.identical(fromHex('-0x0p-1074'), -0.0)
1312 self.identical(fromHex('0x0p-1075'), 0.0)
1313 self.identical(fromHex('0X0p-1076'), 0.0)
1314 self.identical(fromHex('-0X0p-2000'), -0.0)
1315 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
1316
1317 # values that should underflow to 0
1318 self.identical(fromHex('0X1p-1075'), 0.0)
1319 self.identical(fromHex('-0X1p-1075'), -0.0)
1320 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
1321 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
1322 self.identical(fromHex('-0x1.1p-1075'), -TINY)
1323 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
1324
1325 # check round-half-even is working correctly near 0 ...
1326 self.identical(fromHex('0x1p-1076'), 0.0)
1327 self.identical(fromHex('0X2p-1076'), 0.0)
1328 self.identical(fromHex('0X3p-1076'), TINY)
1329 self.identical(fromHex('0x4p-1076'), TINY)
1330 self.identical(fromHex('0X5p-1076'), TINY)
1331 self.identical(fromHex('0X6p-1076'), 2*TINY)
1332 self.identical(fromHex('0x7p-1076'), 2*TINY)
1333 self.identical(fromHex('0X8p-1076'), 2*TINY)
1334 self.identical(fromHex('0X9p-1076'), 2*TINY)
1335 self.identical(fromHex('0xap-1076'), 2*TINY)
1336 self.identical(fromHex('0Xbp-1076'), 3*TINY)
1337 self.identical(fromHex('0xcp-1076'), 3*TINY)
1338 self.identical(fromHex('0Xdp-1076'), 3*TINY)
1339 self.identical(fromHex('0Xep-1076'), 4*TINY)
1340 self.identical(fromHex('0xfp-1076'), 4*TINY)
1341 self.identical(fromHex('0x10p-1076'), 4*TINY)
1342 self.identical(fromHex('-0x1p-1076'), -0.0)
1343 self.identical(fromHex('-0X2p-1076'), -0.0)
1344 self.identical(fromHex('-0x3p-1076'), -TINY)
1345 self.identical(fromHex('-0X4p-1076'), -TINY)
1346 self.identical(fromHex('-0x5p-1076'), -TINY)
1347 self.identical(fromHex('-0x6p-1076'), -2*TINY)
1348 self.identical(fromHex('-0X7p-1076'), -2*TINY)
1349 self.identical(fromHex('-0X8p-1076'), -2*TINY)
1350 self.identical(fromHex('-0X9p-1076'), -2*TINY)
1351 self.identical(fromHex('-0Xap-1076'), -2*TINY)
1352 self.identical(fromHex('-0xbp-1076'), -3*TINY)
1353 self.identical(fromHex('-0xcp-1076'), -3*TINY)
1354 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
1355 self.identical(fromHex('-0xep-1076'), -4*TINY)
1356 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
1357 self.identical(fromHex('-0X10p-1076'), -4*TINY)
1358
1359 # ... and near MIN ...
1360 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
1361 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
1362 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
1363 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
1364 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
1365 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
1366 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
1367 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
1368 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
1369 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
1370 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
1371 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
1372 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
1373 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
1374 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
1375 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
1376 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
1377 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
1378 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
1379 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
1380 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
1381 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
1382 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
1383 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
1384 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
1385 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
1386 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
1387 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
1388 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
1389 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
1390 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
1391 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
1392 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
1393 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
1394
1395 # ... and near 1.0.
1396 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
1397 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
1398 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
1399 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
1400 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
1401 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
1402 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
1403 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
1404 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
1405 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
1406 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
1407 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
1408 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
1409 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
1410 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
1411 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
1412 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
1413 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
1414 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
1415 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
1416 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
1417 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
1418 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
1419 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
1420 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
1421 1.0)
1422 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
1423 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
1424 1+EPS)
1425 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
1426 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
1427 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
1428 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
1429 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
1430 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
1431 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
1432 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
1433 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
1434 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
1435 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
1436 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
1437 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
1438 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
1439 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
1440 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
1441 1.0+EPS)
1442 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
1443 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
1444 1.0+2*EPS)
1445 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
1446 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
1447 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
1448 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
1449 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
1450 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
1451 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
1452 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
1453
1454 def test_roundtrip(self):
1455 def roundtrip(x):
1456 return fromHex(toHex(x))
1457
1458 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1459 self.identical(x, roundtrip(x))
1460 self.identical(-x, roundtrip(-x))
1461
1462 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1463 import random
1464 for i in range(10000):
1465 e = random.randrange(-1200, 1200)
1466 m = random.random()
1467 s = random.choice([1.0, -1.0])
1468 try:
1469 x = s*ldexp(m, e)
1470 except OverflowError:
1471 pass
1472 else:
1473 self.identical(x, fromHex(toHex(x)))
1474
1475 def test_subclass(self):
1476 class F(float):
1477 def __new__(cls, value):
1478 return float.__new__(cls, value + 1)
1479
1480 f = F.fromhex((1.5).hex())
1481 self.assertIs(type(f), F)
1482 self.assertEqual(f, 2.5)
1483
1484 class F2(float):
1485 def __init__(self, value):
1486 self.foo = 'bar'
1487
1488 f = F2.fromhex((1.5).hex())
1489 self.assertIs(type(f), F2)
1490 self.assertEqual(f, 1.5)
1491 self.assertEqual(getattr(f, 'foo', 'none'), 'bar')
1492
1493
1494if __name__ == '__main__':
1495 unittest.main()