blob: 4e918fbb2ff7af01ca7924cb416964abecb7b2b6 [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes284d9272007-12-10 22:28:56 +00003import os
Michael W. Hudsonba283e22005-05-27 15:23:20 +00004from test import test_support
Christian Heimes6f341092008-04-18 23:13:07 +00005import math
Mark Dickinson7103aa42008-07-15 19:08:33 +00006from math import isinf, isnan, copysign, ldexp
Christian Heimes6f341092008-04-18 23:13:07 +00007import operator
Mark Dickinsonbd15a062009-11-18 19:33:35 +00008import random
9import fractions
10import sys
Michael W. Hudsonba283e22005-05-27 15:23:20 +000011
Christian Heimes6f341092008-04-18 23:13:07 +000012INF = float("inf")
13NAN = float("nan")
Christian Heimes0a8143f2007-12-18 23:22:54 +000014
Mark Dickinson61a0d052009-04-29 21:57:15 +000015#locate file with float format test values
16test_dir = os.path.dirname(__file__) or os.curdir
17format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
18
Benjamin Peterson979395b2008-05-03 21:35:18 +000019class GeneralFloatCases(unittest.TestCase):
20
21 def test_float(self):
22 self.assertEqual(float(3.14), 3.14)
23 self.assertEqual(float(314), 314.0)
24 self.assertEqual(float(314L), 314.0)
25 self.assertEqual(float(" 3.14 "), 3.14)
26 self.assertRaises(ValueError, float, " 0x3.1 ")
27 self.assertRaises(ValueError, float, " -0x3.p-1 ")
28 self.assertRaises(ValueError, float, " +0x3.p-1 ")
29 self.assertRaises(ValueError, float, "++3.14")
30 self.assertRaises(ValueError, float, "+-3.14")
31 self.assertRaises(ValueError, float, "-+3.14")
32 self.assertRaises(ValueError, float, "--3.14")
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +000033 if test_support.have_unicode:
Benjamin Peterson979395b2008-05-03 21:35:18 +000034 self.assertEqual(float(unicode(" 3.14 ")), 3.14)
35 self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
Benjamin Peterson979395b2008-05-03 21:35:18 +000036
Mark Dickinson53e9fa42009-10-27 22:09:33 +000037 # extra long strings should no longer be a problem
38 # (in 2.6, long unicode inputs to float raised ValueError)
39 float('.' + '1'*1000)
40 float(unicode('.' + '1'*1000))
41
Benjamin Peterson979395b2008-05-03 21:35:18 +000042 @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
43 def test_float_with_comma(self):
44 # set locale to something that doesn't use '.' for the decimal point
45 # float must not accept the locale specific decimal point but
46 # it still has to accept the normal python syntac
47 import locale
48 if not locale.localeconv()['decimal_point'] == ',':
49 return
50
51 self.assertEqual(float(" 3.14 "), 3.14)
52 self.assertEqual(float("+3.14 "), 3.14)
53 self.assertEqual(float("-3.14 "), -3.14)
54 self.assertEqual(float(".14 "), .14)
55 self.assertEqual(float("3. "), 3.0)
56 self.assertEqual(float("3.e3 "), 3000.0)
57 self.assertEqual(float("3.2e3 "), 3200.0)
58 self.assertEqual(float("2.5e-1 "), 0.25)
59 self.assertEqual(float("5e-1"), 0.5)
60 self.assertRaises(ValueError, float, " 3,14 ")
61 self.assertRaises(ValueError, float, " +3,14 ")
62 self.assertRaises(ValueError, float, " -3,14 ")
63 self.assertRaises(ValueError, float, " 0x3.1 ")
64 self.assertRaises(ValueError, float, " -0x3.p-1 ")
65 self.assertRaises(ValueError, float, " +0x3.p-1 ")
66 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersona853a892008-09-06 23:19:15 +000067 self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
Benjamin Peterson979395b2008-05-03 21:35:18 +000068
69 def test_floatconversion(self):
70 # Make sure that calls to __float__() work properly
71 class Foo0:
72 def __float__(self):
73 return 42.
74
75 class Foo1(object):
76 def __float__(self):
77 return 42.
78
79 class Foo2(float):
80 def __float__(self):
81 return 42.
82
83 class Foo3(float):
84 def __new__(cls, value=0.):
85 return float.__new__(cls, 2*value)
86
87 def __float__(self):
88 return self
89
90 class Foo4(float):
91 def __float__(self):
92 return 42
93
Benjamin Peterson99d36f12009-04-15 21:26:36 +000094 # Issue 5759: __float__ not called on str subclasses (though it is on
95 # unicode subclasses).
96 class FooStr(str):
97 def __float__(self):
98 return float(str(self)) + 1
99
100 class FooUnicode(unicode):
101 def __float__(self):
102 return float(unicode(self)) + 1
103
Benjamin Peterson979395b2008-05-03 21:35:18 +0000104 self.assertAlmostEqual(float(Foo0()), 42.)
105 self.assertAlmostEqual(float(Foo1()), 42.)
106 self.assertAlmostEqual(float(Foo2()), 42.)
107 self.assertAlmostEqual(float(Foo3(21)), 42.)
108 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson99d36f12009-04-15 21:26:36 +0000109 self.assertAlmostEqual(float(FooUnicode('8')), 9.)
110 self.assertAlmostEqual(float(FooStr('8')), 9.)
Benjamin Peterson979395b2008-05-03 21:35:18 +0000111
112 def test_floatasratio(self):
113 for f, ratio in [
114 (0.875, (7, 8)),
115 (-0.875, (-7, 8)),
116 (0.0, (0, 1)),
117 (11.5, (23, 2)),
118 ]:
119 self.assertEqual(f.as_integer_ratio(), ratio)
120
121 for i in range(10000):
122 f = random.random()
123 f *= 10 ** random.randint(-100, 100)
124 n, d = f.as_integer_ratio()
125 self.assertEqual(float(n).__truediv__(d), f)
126
127 R = fractions.Fraction
128 self.assertEqual(R(0, 1),
129 R(*float(0.0).as_integer_ratio()))
130 self.assertEqual(R(5, 2),
131 R(*float(2.5).as_integer_ratio()))
132 self.assertEqual(R(1, 2),
133 R(*float(0.5).as_integer_ratio()))
134 self.assertEqual(R(4728779608739021, 2251799813685248),
135 R(*float(2.1).as_integer_ratio()))
136 self.assertEqual(R(-4728779608739021, 2251799813685248),
137 R(*float(-2.1).as_integer_ratio()))
138 self.assertEqual(R(-2100, 1),
139 R(*float(-2100.0).as_integer_ratio()))
140
141 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
142 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
143 self.assertRaises(ValueError, float('nan').as_integer_ratio)
144
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000145class FormatFunctionsTestCase(unittest.TestCase):
146
147 def setUp(self):
148 self.save_formats = {'double':float.__getformat__('double'),
149 'float':float.__getformat__('float')}
150
151 def tearDown(self):
152 float.__setformat__('double', self.save_formats['double'])
153 float.__setformat__('float', self.save_formats['float'])
154
155 def test_getformat(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000156 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000157 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000158 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000159 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
160 self.assertRaises(ValueError, float.__getformat__, 'chicken')
161 self.assertRaises(TypeError, float.__getformat__, 1)
162
163 def test_setformat(self):
164 for t in 'double', 'float':
165 float.__setformat__(t, 'unknown')
166 if self.save_formats[t] == 'IEEE, big-endian':
167 self.assertRaises(ValueError, float.__setformat__,
168 t, 'IEEE, little-endian')
169 elif self.save_formats[t] == 'IEEE, little-endian':
170 self.assertRaises(ValueError, float.__setformat__,
171 t, 'IEEE, big-endian')
172 else:
173 self.assertRaises(ValueError, float.__setformat__,
174 t, 'IEEE, big-endian')
175 self.assertRaises(ValueError, float.__setformat__,
176 t, 'IEEE, little-endian')
177 self.assertRaises(ValueError, float.__setformat__,
178 t, 'chicken')
179 self.assertRaises(ValueError, float.__setformat__,
180 'chicken', 'unknown')
181
182BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
183LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
184BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
185LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
186
187BE_FLOAT_INF = '\x7f\x80\x00\x00'
188LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
189BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
190LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
191
192# on non-IEEE platforms, attempting to unpack a bit pattern
193# representing an infinity or a NaN should raise an exception.
194
195class UnknownFormatTestCase(unittest.TestCase):
196 def setUp(self):
197 self.save_formats = {'double':float.__getformat__('double'),
198 'float':float.__getformat__('float')}
199 float.__setformat__('double', 'unknown')
200 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000201
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000202 def tearDown(self):
203 float.__setformat__('double', self.save_formats['double'])
204 float.__setformat__('float', self.save_formats['float'])
205
206 def test_double_specials_dont_unpack(self):
207 for fmt, data in [('>d', BE_DOUBLE_INF),
208 ('>d', BE_DOUBLE_NAN),
209 ('<d', LE_DOUBLE_INF),
210 ('<d', LE_DOUBLE_NAN)]:
211 self.assertRaises(ValueError, struct.unpack, fmt, data)
212
213 def test_float_specials_dont_unpack(self):
214 for fmt, data in [('>f', BE_FLOAT_INF),
215 ('>f', BE_FLOAT_NAN),
216 ('<f', LE_FLOAT_INF),
217 ('<f', LE_FLOAT_NAN)]:
218 self.assertRaises(ValueError, struct.unpack, fmt, data)
219
220
221# on an IEEE platform, all we guarantee is that bit patterns
222# representing infinities or NaNs do not raise an exception; all else
223# is accident (today).
Alex Martellid8672aa2007-08-22 21:14:17 +0000224# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000225
226class IEEEFormatTestCase(unittest.TestCase):
227 if float.__getformat__("double").startswith("IEEE"):
228 def test_double_specials_do_unpack(self):
229 for fmt, data in [('>d', BE_DOUBLE_INF),
230 ('>d', BE_DOUBLE_NAN),
231 ('<d', LE_DOUBLE_INF),
232 ('<d', LE_DOUBLE_NAN)]:
233 struct.unpack(fmt, data)
234
235 if float.__getformat__("float").startswith("IEEE"):
236 def test_float_specials_do_unpack(self):
237 for fmt, data in [('>f', BE_FLOAT_INF),
238 ('>f', BE_FLOAT_NAN),
239 ('<f', LE_FLOAT_INF),
240 ('<f', LE_FLOAT_NAN)]:
241 struct.unpack(fmt, data)
242
Alex Martellid8672aa2007-08-22 21:14:17 +0000243 if float.__getformat__("double").startswith("IEEE"):
244 def test_negative_zero(self):
245 import math
246 def pos_pos():
247 return 0.0, math.atan2(0.0, -1)
248 def pos_neg():
249 return 0.0, math.atan2(-0.0, -1)
250 def neg_pos():
251 return -0.0, math.atan2(0.0, -1)
252 def neg_neg():
253 return -0.0, math.atan2(-0.0, -1)
254 self.assertEquals(pos_pos(), neg_pos())
255 self.assertEquals(pos_neg(), neg_neg())
256
Guido van Rossum3b835492008-01-05 00:59:59 +0000257 if float.__getformat__("double").startswith("IEEE"):
258 def test_underflow_sign(self):
259 import math
260 # check that -1e-1000 gives -0.0, not 0.0
261 self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
262 self.assertEquals(math.atan2(float('-1e-1000'), -1),
263 math.atan2(-0.0, -1))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000264
Eric Smitha985a3a2009-05-05 18:26:08 +0000265 def test_format(self):
266 # these should be rewritten to use both format(x, spec) and
267 # x.__format__(spec)
268
269 self.assertEqual(format(0.0, 'f'), '0.000000')
270
271 # the default is 'g', except for empty format spec
272 self.assertEqual(format(0.0, ''), '0.0')
273 self.assertEqual(format(0.01, ''), '0.01')
274 self.assertEqual(format(0.01, 'g'), '0.01')
275
276 # empty presentation type should format in the same way as str
277 # (issue 5920)
278 x = 100/7.
279 self.assertEqual(format(x, ''), str(x))
280 self.assertEqual(format(x, '-'), str(x))
281 self.assertEqual(format(x, '>'), str(x))
282 self.assertEqual(format(x, '2'), str(x))
283
284 self.assertEqual(format(1.0, 'f'), '1.000000')
285
286 self.assertEqual(format(-1.0, 'f'), '-1.000000')
287
288 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
289 self.assertEqual(format(-1.0, ' f'), '-1.000000')
290 self.assertEqual(format( 1.0, '+f'), '+1.000000')
291 self.assertEqual(format(-1.0, '+f'), '-1.000000')
292
293 # % formatting
294 self.assertEqual(format(-1.0, '%'), '-100.000000%')
295
296 # conversion to string should fail
297 self.assertRaises(ValueError, format, 3.0, "s")
298
299 # other format specifiers shouldn't work on floats,
300 # in particular int specifiers
301 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
302 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
303 if not format_spec in 'eEfFgGn%':
304 self.assertRaises(ValueError, format, 0.0, format_spec)
305 self.assertRaises(ValueError, format, 1.0, format_spec)
306 self.assertRaises(ValueError, format, -1.0, format_spec)
307 self.assertRaises(ValueError, format, 1e100, format_spec)
308 self.assertRaises(ValueError, format, -1e100, format_spec)
309 self.assertRaises(ValueError, format, 1e-100, format_spec)
310 self.assertRaises(ValueError, format, -1e-100, format_spec)
311
Mark Dickinson61a0d052009-04-29 21:57:15 +0000312 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
313 "test requires IEEE 754 doubles")
314 def test_format_testfile(self):
315 for line in open(format_testfile):
316 if line.startswith('--'):
317 continue
318 line = line.strip()
319 if not line:
320 continue
321
322 lhs, rhs = map(str.strip, line.split('->'))
323 fmt, arg = lhs.split()
324 self.assertEqual(fmt % float(arg), rhs)
325 self.assertEqual(fmt % -float(arg), '-' + rhs)
326
Mark Dickinson92fcc9c2009-04-29 20:41:00 +0000327 def test_issue5864(self):
328 self.assertEquals(format(123.456, '.4'), '123.5')
329 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
330 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
331
Christian Heimes284d9272007-12-10 22:28:56 +0000332class ReprTestCase(unittest.TestCase):
333 def test_repr(self):
334 floats_file = open(os.path.join(os.path.split(__file__)[0],
335 'floating_points.txt'))
336 for line in floats_file:
337 line = line.strip()
338 if not line or line.startswith('#'):
339 continue
340 v = eval(line)
341 self.assertEqual(v, eval(repr(v)))
342 floats_file.close()
343
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000344@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
345 "test requires IEEE 754 doubles")
346class RoundTestCase(unittest.TestCase):
347 def test_second_argument_type(self):
348 # any type with an __index__ method should be permitted as
349 # a second argument
350 self.assertAlmostEqual(round(12.34, True), 12.3)
351
352 class MyIndex(object):
353 def __index__(self): return 4
354 self.assertAlmostEqual(round(-0.123456, MyIndex()), -0.1235)
355 # but floats should be illegal
356 self.assertRaises(TypeError, round, 3.14159, 2.0)
357
358 def test_inf_nan(self):
359 # rounding an infinity or nan returns the same number;
360 # (in py3k, rounding an infinity or nan raises an error,
361 # since the result can't be represented as a long).
362 self.assertEqual(round(INF), INF)
363 self.assertEqual(round(-INF), -INF)
364 self.assertTrue(math.isnan(round(NAN)))
365 for n in range(-5, 5):
366 self.assertEqual(round(INF, n), INF)
367 self.assertEqual(round(-INF, n), -INF)
368 self.assertTrue(math.isnan(round(NAN, n)))
369
Mark Dickinsonbce78372009-11-24 10:54:58 +0000370 self.assertRaises(TypeError, round, INF, 0.0)
371 self.assertRaises(TypeError, round, -INF, 1.0)
372 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
373 self.assertRaises(TypeError, round, -0.0, 1j)
374
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000375 def test_large_n(self):
376 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
377 self.assertEqual(round(123.456, n), 123.456)
378 self.assertEqual(round(-123.456, n), -123.456)
379 self.assertEqual(round(1e300, n), 1e300)
380 self.assertEqual(round(1e-320, n), 1e-320)
381 self.assertEqual(round(1e150, 300), 1e150)
382 self.assertEqual(round(1e300, 307), 1e300)
383 self.assertEqual(round(-3.1415, 308), -3.1415)
384 self.assertEqual(round(1e150, 309), 1e150)
385 self.assertEqual(round(1.4e-315, 315), 1e-315)
386
387 def test_small_n(self):
388 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
389 self.assertEqual(round(123.456, n), 0.0)
390 self.assertEqual(round(-123.456, n), -0.0)
391 self.assertEqual(round(1e300, n), 0.0)
392 self.assertEqual(round(1e-320, n), 0.0)
393
394 def test_overflow(self):
395 self.assertRaises(OverflowError, round, 1.6e308, -308)
396 self.assertRaises(OverflowError, round, -1.7e308, -308)
397
398 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
399 "test applies only when using short float repr style")
400 def test_previous_round_bugs(self):
401 # particular cases that have occurred in bug reports
402 self.assertEqual(round(562949953421312.5, 1),
403 562949953421312.5)
404 self.assertEqual(round(56294995342131.5, 3),
405 56294995342131.5)
406
407 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
408 "test applies only when using short float repr style")
409 def test_halfway_cases(self):
410 # Halfway cases need special attention, since the current
411 # implementation has to deal with them specially. Note that
412 # 2.x rounds halfway values up (i.e., away from zero) while
413 # 3.x does round-half-to-even.
414 self.assertAlmostEqual(round(0.125, 2), 0.13)
415 self.assertAlmostEqual(round(0.375, 2), 0.38)
416 self.assertAlmostEqual(round(0.625, 2), 0.63)
417 self.assertAlmostEqual(round(0.875, 2), 0.88)
418 self.assertAlmostEqual(round(-0.125, 2), -0.13)
419 self.assertAlmostEqual(round(-0.375, 2), -0.38)
420 self.assertAlmostEqual(round(-0.625, 2), -0.63)
421 self.assertAlmostEqual(round(-0.875, 2), -0.88)
422
423 self.assertAlmostEqual(round(0.25, 1), 0.3)
424 self.assertAlmostEqual(round(0.75, 1), 0.8)
425 self.assertAlmostEqual(round(-0.25, 1), -0.3)
426 self.assertAlmostEqual(round(-0.75, 1), -0.8)
427
428 self.assertEqual(round(-6.5, 0), -7.0)
429 self.assertEqual(round(-5.5, 0), -6.0)
430 self.assertEqual(round(-1.5, 0), -2.0)
431 self.assertEqual(round(-0.5, 0), -1.0)
432 self.assertEqual(round(0.5, 0), 1.0)
433 self.assertEqual(round(1.5, 0), 2.0)
434 self.assertEqual(round(2.5, 0), 3.0)
435 self.assertEqual(round(3.5, 0), 4.0)
436 self.assertEqual(round(4.5, 0), 5.0)
437 self.assertEqual(round(5.5, 0), 6.0)
438 self.assertEqual(round(6.5, 0), 7.0)
439
440 # same but without an explicit second argument; in 3.x these
441 # will give integers
442 self.assertEqual(round(-6.5), -7.0)
443 self.assertEqual(round(-5.5), -6.0)
444 self.assertEqual(round(-1.5), -2.0)
445 self.assertEqual(round(-0.5), -1.0)
446 self.assertEqual(round(0.5), 1.0)
447 self.assertEqual(round(1.5), 2.0)
448 self.assertEqual(round(2.5), 3.0)
449 self.assertEqual(round(3.5), 4.0)
450 self.assertEqual(round(4.5), 5.0)
451 self.assertEqual(round(5.5), 6.0)
452 self.assertEqual(round(6.5), 7.0)
453
454 self.assertEqual(round(-25.0, -1), -30.0)
455 self.assertEqual(round(-15.0, -1), -20.0)
456 self.assertEqual(round(-5.0, -1), -10.0)
457 self.assertEqual(round(5.0, -1), 10.0)
458 self.assertEqual(round(15.0, -1), 20.0)
459 self.assertEqual(round(25.0, -1), 30.0)
460 self.assertEqual(round(35.0, -1), 40.0)
461 self.assertEqual(round(45.0, -1), 50.0)
462 self.assertEqual(round(55.0, -1), 60.0)
463 self.assertEqual(round(65.0, -1), 70.0)
464 self.assertEqual(round(75.0, -1), 80.0)
465 self.assertEqual(round(85.0, -1), 90.0)
466 self.assertEqual(round(95.0, -1), 100.0)
467 self.assertEqual(round(12325.0, -1), 12330.0)
468
469 self.assertEqual(round(350.0, -2), 400.0)
470 self.assertEqual(round(450.0, -2), 500.0)
471
472 self.assertAlmostEqual(round(0.5e21, -21), 1e21)
473 self.assertAlmostEqual(round(1.5e21, -21), 2e21)
474 self.assertAlmostEqual(round(2.5e21, -21), 3e21)
475 self.assertAlmostEqual(round(5.5e21, -21), 6e21)
476 self.assertAlmostEqual(round(8.5e21, -21), 9e21)
477
478 self.assertAlmostEqual(round(-1.5e22, -22), -2e22)
479 self.assertAlmostEqual(round(-0.5e22, -22), -1e22)
480 self.assertAlmostEqual(round(0.5e22, -22), 1e22)
481 self.assertAlmostEqual(round(1.5e22, -22), 2e22)
482
483
Christian Heimes0a8143f2007-12-18 23:22:54 +0000484# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000485# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000486class InfNanTest(unittest.TestCase):
487 def test_inf_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000488 self.assertTrue(isinf(float("inf")))
489 self.assertTrue(isinf(float("+inf")))
490 self.assertTrue(isinf(float("-inf")))
491 self.assertTrue(isinf(float("infinity")))
492 self.assertTrue(isinf(float("+infinity")))
493 self.assertTrue(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000494
495 self.assertEqual(repr(float("inf")), "inf")
496 self.assertEqual(repr(float("+inf")), "inf")
497 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000498 self.assertEqual(repr(float("infinity")), "inf")
499 self.assertEqual(repr(float("+infinity")), "inf")
500 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000501
502 self.assertEqual(repr(float("INF")), "inf")
503 self.assertEqual(repr(float("+Inf")), "inf")
504 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000505 self.assertEqual(repr(float("Infinity")), "inf")
506 self.assertEqual(repr(float("+iNfInItY")), "inf")
507 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000508
509 self.assertEqual(str(float("inf")), "inf")
510 self.assertEqual(str(float("+inf")), "inf")
511 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000512 self.assertEqual(str(float("infinity")), "inf")
513 self.assertEqual(str(float("+infinity")), "inf")
514 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000515
516 self.assertRaises(ValueError, float, "info")
517 self.assertRaises(ValueError, float, "+info")
518 self.assertRaises(ValueError, float, "-info")
519 self.assertRaises(ValueError, float, "in")
520 self.assertRaises(ValueError, float, "+in")
521 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000522 self.assertRaises(ValueError, float, "infinit")
523 self.assertRaises(ValueError, float, "+Infin")
524 self.assertRaises(ValueError, float, "-INFI")
525 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000526
527 def test_inf_as_str(self):
528 self.assertEqual(repr(1e300 * 1e300), "inf")
529 self.assertEqual(repr(-1e300 * 1e300), "-inf")
530
531 self.assertEqual(str(1e300 * 1e300), "inf")
532 self.assertEqual(str(-1e300 * 1e300), "-inf")
533
534 def test_nan_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000535 self.assertTrue(isnan(float("nan")))
536 self.assertTrue(isnan(float("+nan")))
537 self.assertTrue(isnan(float("-nan")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000538
539 self.assertEqual(repr(float("nan")), "nan")
540 self.assertEqual(repr(float("+nan")), "nan")
541 self.assertEqual(repr(float("-nan")), "nan")
542
543 self.assertEqual(repr(float("NAN")), "nan")
544 self.assertEqual(repr(float("+NAn")), "nan")
545 self.assertEqual(repr(float("-NaN")), "nan")
546
547 self.assertEqual(str(float("nan")), "nan")
548 self.assertEqual(str(float("+nan")), "nan")
549 self.assertEqual(str(float("-nan")), "nan")
550
551 self.assertRaises(ValueError, float, "nana")
552 self.assertRaises(ValueError, float, "+nana")
553 self.assertRaises(ValueError, float, "-nana")
554 self.assertRaises(ValueError, float, "na")
555 self.assertRaises(ValueError, float, "+na")
556 self.assertRaises(ValueError, float, "-na")
557
558 def test_nan_as_str(self):
559 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
560 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
561
562 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
563 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000564
Christian Heimes6f341092008-04-18 23:13:07 +0000565 def notest_float_nan(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000566 self.assertTrue(NAN.is_nan())
567 self.assertFalse(INF.is_nan())
568 self.assertFalse((0.).is_nan())
Christian Heimes6f341092008-04-18 23:13:07 +0000569
570 def notest_float_inf(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000571 self.assertTrue(INF.is_inf())
572 self.assertFalse(NAN.is_inf())
573 self.assertFalse((0.).is_inf())
Christian Heimes6f341092008-04-18 23:13:07 +0000574
Mark Dickinson7103aa42008-07-15 19:08:33 +0000575fromHex = float.fromhex
576toHex = float.hex
577class HexFloatTestCase(unittest.TestCase):
578 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
579 MIN = fromHex('0x1p-1022') # min normal
580 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
581 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
582
583 def identical(self, x, y):
584 # check that floats x and y are identical, or that both
585 # are NaNs
586 if isnan(x) or isnan(y):
587 if isnan(x) == isnan(y):
588 return
589 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
590 return
591 self.fail('%r not identical to %r' % (x, y))
592
593 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000594 self.identical(self.MIN, ldexp(1.0, -1022))
595 self.identical(self.TINY, ldexp(1.0, -1074))
596 self.identical(self.EPS, ldexp(1.0, -52))
597 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000598
599 def test_invalid_inputs(self):
600 invalid_inputs = [
601 'infi', # misspelt infinities and nans
602 '-Infinit',
603 '++inf',
604 '-+Inf',
605 '--nan',
606 '+-NaN',
607 'snan',
608 'NaNs',
609 'nna',
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000610 'an',
611 'nf',
612 'nfinity',
613 'inity',
614 'iinity',
Mark Dickinson7103aa42008-07-15 19:08:33 +0000615 '0xnan',
616 '',
617 ' ',
618 'x1.0p0',
619 '0xX1.0p0',
620 '+ 0x1.0p0', # internal whitespace
621 '- 0x1.0p0',
622 '0 x1.0p0',
623 '0x 1.0p0',
624 '0x1 2.0p0',
625 '+0x1 .0p0',
626 '0x1. 0p0',
627 '-0x1.0 1p0',
628 '-0x1.0 p0',
629 '+0x1.0p +0',
630 '0x1.0p -0',
631 '0x1.0p 0',
632 '+0x1.0p+ 0',
633 '-0x1.0p- 0',
634 '++0x1.0p-0', # double signs
635 '--0x1.0p0',
636 '+-0x1.0p+0',
637 '-+0x1.0p0',
638 '0x1.0p++0',
639 '+0x1.0p+-0',
640 '-0x1.0p-+0',
641 '0x1.0p--0',
642 '0x1.0.p0',
643 '0x.p0', # no hex digits before or after point
644 '0x1,p0', # wrong decimal point character
645 '0x1pa',
646 u'0x1p\uff10', # fullwidth Unicode digits
647 u'\uff10x1p0',
648 u'0x\uff11p0',
649 u'0x1.\uff10p0',
650 '0x1p0 \n 0x2p0',
651 '0x1p0\0 0x1p0', # embedded null byte is not end of string
652 ]
653 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000654 try:
655 result = fromHex(x)
656 except ValueError:
657 pass
658 else:
659 self.fail('Expected float.fromhex(%r) to raise ValueError; '
660 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000661
662
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000663 def test_whitespace(self):
664 value_pairs = [
665 ('inf', INF),
666 ('-Infinity', -INF),
667 ('nan', NAN),
668 ('1.0', 1.0),
669 ('-0x.2', -0.125),
670 ('-0.0', -0.0)
671 ]
672 whitespace = [
673 '',
674 ' ',
675 '\t',
676 '\n',
677 '\n \t',
678 '\f',
679 '\v',
680 '\r'
681 ]
682 for inp, expected in value_pairs:
683 for lead in whitespace:
684 for trail in whitespace:
685 got = fromHex(lead + inp + trail)
686 self.identical(got, expected)
687
688
Mark Dickinson7103aa42008-07-15 19:08:33 +0000689 def test_from_hex(self):
690 MIN = self.MIN;
691 MAX = self.MAX;
692 TINY = self.TINY;
693 EPS = self.EPS;
694
695 # two spellings of infinity, with optional signs; case-insensitive
696 self.identical(fromHex('inf'), INF)
697 self.identical(fromHex('+Inf'), INF)
698 self.identical(fromHex('-INF'), -INF)
699 self.identical(fromHex('iNf'), INF)
700 self.identical(fromHex('Infinity'), INF)
701 self.identical(fromHex('+INFINITY'), INF)
702 self.identical(fromHex('-infinity'), -INF)
703 self.identical(fromHex('-iNFiNitY'), -INF)
704
705 # nans with optional sign; case insensitive
706 self.identical(fromHex('nan'), NAN)
707 self.identical(fromHex('+NaN'), NAN)
708 self.identical(fromHex('-NaN'), NAN)
709 self.identical(fromHex('-nAN'), NAN)
710
711 # variations in input format
712 self.identical(fromHex('1'), 1.0)
713 self.identical(fromHex('+1'), 1.0)
714 self.identical(fromHex('1.'), 1.0)
715 self.identical(fromHex('1.0'), 1.0)
716 self.identical(fromHex('1.0p0'), 1.0)
717 self.identical(fromHex('01'), 1.0)
718 self.identical(fromHex('01.'), 1.0)
719 self.identical(fromHex('0x1'), 1.0)
720 self.identical(fromHex('0x1.'), 1.0)
721 self.identical(fromHex('0x1.0'), 1.0)
722 self.identical(fromHex('+0x1.0'), 1.0)
723 self.identical(fromHex('0x1p0'), 1.0)
724 self.identical(fromHex('0X1p0'), 1.0)
725 self.identical(fromHex('0X1P0'), 1.0)
726 self.identical(fromHex('0x1P0'), 1.0)
727 self.identical(fromHex('0x1.p0'), 1.0)
728 self.identical(fromHex('0x1.0p0'), 1.0)
729 self.identical(fromHex('0x.1p4'), 1.0)
730 self.identical(fromHex('0x.1p04'), 1.0)
731 self.identical(fromHex('0x.1p004'), 1.0)
732 self.identical(fromHex('0x1p+0'), 1.0)
733 self.identical(fromHex('0x1P-0'), 1.0)
734 self.identical(fromHex('+0x1p0'), 1.0)
735 self.identical(fromHex('0x01p0'), 1.0)
736 self.identical(fromHex('0x1p00'), 1.0)
737 self.identical(fromHex(u'0x1p0'), 1.0)
738 self.identical(fromHex(' 0x1p0 '), 1.0)
739 self.identical(fromHex('\n 0x1p0'), 1.0)
740 self.identical(fromHex('0x1p0 \t'), 1.0)
741 self.identical(fromHex('0xap0'), 10.0)
742 self.identical(fromHex('0xAp0'), 10.0)
743 self.identical(fromHex('0xaP0'), 10.0)
744 self.identical(fromHex('0xAP0'), 10.0)
745 self.identical(fromHex('0xbep0'), 190.0)
746 self.identical(fromHex('0xBep0'), 190.0)
747 self.identical(fromHex('0xbEp0'), 190.0)
748 self.identical(fromHex('0XBE0P-4'), 190.0)
749 self.identical(fromHex('0xBEp0'), 190.0)
750 self.identical(fromHex('0xB.Ep4'), 190.0)
751 self.identical(fromHex('0x.BEp8'), 190.0)
752 self.identical(fromHex('0x.0BEp12'), 190.0)
753
754 # moving the point around
755 pi = fromHex('0x1.921fb54442d18p1')
756 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
757 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
758 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
759 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
760 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
761 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
762 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
763 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
764 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
765 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
766 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
767 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
768 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
769 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
770 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
771 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
772 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
773 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
774 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
775 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
776 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
777 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
778 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
779 # ...
780 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
781 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
782 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
783 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
784 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
785 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
786 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
787 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
788 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
789
790
791 # results that should overflow...
792 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
793 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
794 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
795 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
796 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
797 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
798 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
799 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
800 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
801 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
802 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
803 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
804 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
805 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
806 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
807 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
808 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
809 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
810 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
811
812 # ...and those that round to +-max float
813 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
814 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
815 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
816
817 # zeros
818 self.identical(fromHex('0x0p0'), 0.0)
819 self.identical(fromHex('0x0p1000'), 0.0)
820 self.identical(fromHex('-0x0p1023'), -0.0)
821 self.identical(fromHex('0X0p1024'), 0.0)
822 self.identical(fromHex('-0x0p1025'), -0.0)
823 self.identical(fromHex('0X0p2000'), 0.0)
824 self.identical(fromHex('0x0p123456789123456789'), 0.0)
825 self.identical(fromHex('-0X0p-0'), -0.0)
826 self.identical(fromHex('-0X0p-1000'), -0.0)
827 self.identical(fromHex('0x0p-1023'), 0.0)
828 self.identical(fromHex('-0X0p-1024'), -0.0)
829 self.identical(fromHex('-0x0p-1025'), -0.0)
830 self.identical(fromHex('-0x0p-1072'), -0.0)
831 self.identical(fromHex('0X0p-1073'), 0.0)
832 self.identical(fromHex('-0x0p-1074'), -0.0)
833 self.identical(fromHex('0x0p-1075'), 0.0)
834 self.identical(fromHex('0X0p-1076'), 0.0)
835 self.identical(fromHex('-0X0p-2000'), -0.0)
836 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
837
838 # values that should underflow to 0
839 self.identical(fromHex('0X1p-1075'), 0.0)
840 self.identical(fromHex('-0X1p-1075'), -0.0)
841 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
842 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
843 self.identical(fromHex('-0x1.1p-1075'), -TINY)
844 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
845
846 # check round-half-even is working correctly near 0 ...
847 self.identical(fromHex('0x1p-1076'), 0.0)
848 self.identical(fromHex('0X2p-1076'), 0.0)
849 self.identical(fromHex('0X3p-1076'), TINY)
850 self.identical(fromHex('0x4p-1076'), TINY)
851 self.identical(fromHex('0X5p-1076'), TINY)
852 self.identical(fromHex('0X6p-1076'), 2*TINY)
853 self.identical(fromHex('0x7p-1076'), 2*TINY)
854 self.identical(fromHex('0X8p-1076'), 2*TINY)
855 self.identical(fromHex('0X9p-1076'), 2*TINY)
856 self.identical(fromHex('0xap-1076'), 2*TINY)
857 self.identical(fromHex('0Xbp-1076'), 3*TINY)
858 self.identical(fromHex('0xcp-1076'), 3*TINY)
859 self.identical(fromHex('0Xdp-1076'), 3*TINY)
860 self.identical(fromHex('0Xep-1076'), 4*TINY)
861 self.identical(fromHex('0xfp-1076'), 4*TINY)
862 self.identical(fromHex('0x10p-1076'), 4*TINY)
863 self.identical(fromHex('-0x1p-1076'), -0.0)
864 self.identical(fromHex('-0X2p-1076'), -0.0)
865 self.identical(fromHex('-0x3p-1076'), -TINY)
866 self.identical(fromHex('-0X4p-1076'), -TINY)
867 self.identical(fromHex('-0x5p-1076'), -TINY)
868 self.identical(fromHex('-0x6p-1076'), -2*TINY)
869 self.identical(fromHex('-0X7p-1076'), -2*TINY)
870 self.identical(fromHex('-0X8p-1076'), -2*TINY)
871 self.identical(fromHex('-0X9p-1076'), -2*TINY)
872 self.identical(fromHex('-0Xap-1076'), -2*TINY)
873 self.identical(fromHex('-0xbp-1076'), -3*TINY)
874 self.identical(fromHex('-0xcp-1076'), -3*TINY)
875 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
876 self.identical(fromHex('-0xep-1076'), -4*TINY)
877 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
878 self.identical(fromHex('-0X10p-1076'), -4*TINY)
879
880 # ... and near MIN ...
881 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
882 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
883 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
884 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
885 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
886 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
887 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
888 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
889 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
890 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
891 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
892 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
893 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
894 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
895 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
896 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
897 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
898 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
899 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
900 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
901 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
902 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
903 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
904 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
905 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
906 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
907 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
908 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
909 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
910 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
911 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
912 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
913 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
914 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
915
916 # ... and near 1.0.
917 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
918 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
919 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
920 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
921 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
922 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
923 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
924 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
925 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
926 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
927 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
928 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
929 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
930 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
931 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
932 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
933 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
934 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
935 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
936 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
937 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
938 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
939 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
940 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
941 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
942 1.0)
943 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
944 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
945 1+EPS)
946 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
947 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
948 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
949 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
950 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
951 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
952 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
953 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
954 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
955 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
956 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
957 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
958 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
959 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
960 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
961 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
962 1.0+EPS)
963 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
964 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
965 1.0+2*EPS)
966 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
967 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
968 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
969 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
970 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
971 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
972 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
973 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
974
975 def test_roundtrip(self):
976 def roundtrip(x):
977 return fromHex(toHex(x))
978
979 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
980 self.identical(x, roundtrip(x))
981 self.identical(-x, roundtrip(-x))
982
983 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
984 import random
985 for i in xrange(10000):
986 e = random.randrange(-1200, 1200)
987 m = random.random()
988 s = random.choice([1.0, -1.0])
989 try:
990 x = s*ldexp(m, e)
991 except OverflowError:
992 pass
993 else:
994 self.identical(x, fromHex(toHex(x)))
995
Christian Heimes6f341092008-04-18 23:13:07 +0000996
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000997def test_main():
998 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +0000999 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001000 FormatFunctionsTestCase,
1001 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +00001002 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001003 ReprTestCase,
Mark Dickinsonbd15a062009-11-18 19:33:35 +00001004 RoundTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001005 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +00001006 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +00001007 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001008
1009if __name__ == '__main__':
1010 test_main()