blob: 573cc7e6e1d24864c561d3425e1b1dff0c2b7fa7 [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
370 def test_large_n(self):
371 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
372 self.assertEqual(round(123.456, n), 123.456)
373 self.assertEqual(round(-123.456, n), -123.456)
374 self.assertEqual(round(1e300, n), 1e300)
375 self.assertEqual(round(1e-320, n), 1e-320)
376 self.assertEqual(round(1e150, 300), 1e150)
377 self.assertEqual(round(1e300, 307), 1e300)
378 self.assertEqual(round(-3.1415, 308), -3.1415)
379 self.assertEqual(round(1e150, 309), 1e150)
380 self.assertEqual(round(1.4e-315, 315), 1e-315)
381
382 def test_small_n(self):
383 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
384 self.assertEqual(round(123.456, n), 0.0)
385 self.assertEqual(round(-123.456, n), -0.0)
386 self.assertEqual(round(1e300, n), 0.0)
387 self.assertEqual(round(1e-320, n), 0.0)
388
389 def test_overflow(self):
390 self.assertRaises(OverflowError, round, 1.6e308, -308)
391 self.assertRaises(OverflowError, round, -1.7e308, -308)
392
393 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
394 "test applies only when using short float repr style")
395 def test_previous_round_bugs(self):
396 # particular cases that have occurred in bug reports
397 self.assertEqual(round(562949953421312.5, 1),
398 562949953421312.5)
399 self.assertEqual(round(56294995342131.5, 3),
400 56294995342131.5)
401
402 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
403 "test applies only when using short float repr style")
404 def test_halfway_cases(self):
405 # Halfway cases need special attention, since the current
406 # implementation has to deal with them specially. Note that
407 # 2.x rounds halfway values up (i.e., away from zero) while
408 # 3.x does round-half-to-even.
409 self.assertAlmostEqual(round(0.125, 2), 0.13)
410 self.assertAlmostEqual(round(0.375, 2), 0.38)
411 self.assertAlmostEqual(round(0.625, 2), 0.63)
412 self.assertAlmostEqual(round(0.875, 2), 0.88)
413 self.assertAlmostEqual(round(-0.125, 2), -0.13)
414 self.assertAlmostEqual(round(-0.375, 2), -0.38)
415 self.assertAlmostEqual(round(-0.625, 2), -0.63)
416 self.assertAlmostEqual(round(-0.875, 2), -0.88)
417
418 self.assertAlmostEqual(round(0.25, 1), 0.3)
419 self.assertAlmostEqual(round(0.75, 1), 0.8)
420 self.assertAlmostEqual(round(-0.25, 1), -0.3)
421 self.assertAlmostEqual(round(-0.75, 1), -0.8)
422
423 self.assertEqual(round(-6.5, 0), -7.0)
424 self.assertEqual(round(-5.5, 0), -6.0)
425 self.assertEqual(round(-1.5, 0), -2.0)
426 self.assertEqual(round(-0.5, 0), -1.0)
427 self.assertEqual(round(0.5, 0), 1.0)
428 self.assertEqual(round(1.5, 0), 2.0)
429 self.assertEqual(round(2.5, 0), 3.0)
430 self.assertEqual(round(3.5, 0), 4.0)
431 self.assertEqual(round(4.5, 0), 5.0)
432 self.assertEqual(round(5.5, 0), 6.0)
433 self.assertEqual(round(6.5, 0), 7.0)
434
435 # same but without an explicit second argument; in 3.x these
436 # will give integers
437 self.assertEqual(round(-6.5), -7.0)
438 self.assertEqual(round(-5.5), -6.0)
439 self.assertEqual(round(-1.5), -2.0)
440 self.assertEqual(round(-0.5), -1.0)
441 self.assertEqual(round(0.5), 1.0)
442 self.assertEqual(round(1.5), 2.0)
443 self.assertEqual(round(2.5), 3.0)
444 self.assertEqual(round(3.5), 4.0)
445 self.assertEqual(round(4.5), 5.0)
446 self.assertEqual(round(5.5), 6.0)
447 self.assertEqual(round(6.5), 7.0)
448
449 self.assertEqual(round(-25.0, -1), -30.0)
450 self.assertEqual(round(-15.0, -1), -20.0)
451 self.assertEqual(round(-5.0, -1), -10.0)
452 self.assertEqual(round(5.0, -1), 10.0)
453 self.assertEqual(round(15.0, -1), 20.0)
454 self.assertEqual(round(25.0, -1), 30.0)
455 self.assertEqual(round(35.0, -1), 40.0)
456 self.assertEqual(round(45.0, -1), 50.0)
457 self.assertEqual(round(55.0, -1), 60.0)
458 self.assertEqual(round(65.0, -1), 70.0)
459 self.assertEqual(round(75.0, -1), 80.0)
460 self.assertEqual(round(85.0, -1), 90.0)
461 self.assertEqual(round(95.0, -1), 100.0)
462 self.assertEqual(round(12325.0, -1), 12330.0)
463
464 self.assertEqual(round(350.0, -2), 400.0)
465 self.assertEqual(round(450.0, -2), 500.0)
466
467 self.assertAlmostEqual(round(0.5e21, -21), 1e21)
468 self.assertAlmostEqual(round(1.5e21, -21), 2e21)
469 self.assertAlmostEqual(round(2.5e21, -21), 3e21)
470 self.assertAlmostEqual(round(5.5e21, -21), 6e21)
471 self.assertAlmostEqual(round(8.5e21, -21), 9e21)
472
473 self.assertAlmostEqual(round(-1.5e22, -22), -2e22)
474 self.assertAlmostEqual(round(-0.5e22, -22), -1e22)
475 self.assertAlmostEqual(round(0.5e22, -22), 1e22)
476 self.assertAlmostEqual(round(1.5e22, -22), 2e22)
477
478
Christian Heimes0a8143f2007-12-18 23:22:54 +0000479# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000480# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000481class InfNanTest(unittest.TestCase):
482 def test_inf_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000483 self.assertTrue(isinf(float("inf")))
484 self.assertTrue(isinf(float("+inf")))
485 self.assertTrue(isinf(float("-inf")))
486 self.assertTrue(isinf(float("infinity")))
487 self.assertTrue(isinf(float("+infinity")))
488 self.assertTrue(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000489
490 self.assertEqual(repr(float("inf")), "inf")
491 self.assertEqual(repr(float("+inf")), "inf")
492 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000493 self.assertEqual(repr(float("infinity")), "inf")
494 self.assertEqual(repr(float("+infinity")), "inf")
495 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000496
497 self.assertEqual(repr(float("INF")), "inf")
498 self.assertEqual(repr(float("+Inf")), "inf")
499 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000500 self.assertEqual(repr(float("Infinity")), "inf")
501 self.assertEqual(repr(float("+iNfInItY")), "inf")
502 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000503
504 self.assertEqual(str(float("inf")), "inf")
505 self.assertEqual(str(float("+inf")), "inf")
506 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000507 self.assertEqual(str(float("infinity")), "inf")
508 self.assertEqual(str(float("+infinity")), "inf")
509 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000510
511 self.assertRaises(ValueError, float, "info")
512 self.assertRaises(ValueError, float, "+info")
513 self.assertRaises(ValueError, float, "-info")
514 self.assertRaises(ValueError, float, "in")
515 self.assertRaises(ValueError, float, "+in")
516 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000517 self.assertRaises(ValueError, float, "infinit")
518 self.assertRaises(ValueError, float, "+Infin")
519 self.assertRaises(ValueError, float, "-INFI")
520 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000521
522 def test_inf_as_str(self):
523 self.assertEqual(repr(1e300 * 1e300), "inf")
524 self.assertEqual(repr(-1e300 * 1e300), "-inf")
525
526 self.assertEqual(str(1e300 * 1e300), "inf")
527 self.assertEqual(str(-1e300 * 1e300), "-inf")
528
529 def test_nan_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000530 self.assertTrue(isnan(float("nan")))
531 self.assertTrue(isnan(float("+nan")))
532 self.assertTrue(isnan(float("-nan")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000533
534 self.assertEqual(repr(float("nan")), "nan")
535 self.assertEqual(repr(float("+nan")), "nan")
536 self.assertEqual(repr(float("-nan")), "nan")
537
538 self.assertEqual(repr(float("NAN")), "nan")
539 self.assertEqual(repr(float("+NAn")), "nan")
540 self.assertEqual(repr(float("-NaN")), "nan")
541
542 self.assertEqual(str(float("nan")), "nan")
543 self.assertEqual(str(float("+nan")), "nan")
544 self.assertEqual(str(float("-nan")), "nan")
545
546 self.assertRaises(ValueError, float, "nana")
547 self.assertRaises(ValueError, float, "+nana")
548 self.assertRaises(ValueError, float, "-nana")
549 self.assertRaises(ValueError, float, "na")
550 self.assertRaises(ValueError, float, "+na")
551 self.assertRaises(ValueError, float, "-na")
552
553 def test_nan_as_str(self):
554 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
555 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
556
557 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
558 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000559
Christian Heimes6f341092008-04-18 23:13:07 +0000560 def notest_float_nan(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000561 self.assertTrue(NAN.is_nan())
562 self.assertFalse(INF.is_nan())
563 self.assertFalse((0.).is_nan())
Christian Heimes6f341092008-04-18 23:13:07 +0000564
565 def notest_float_inf(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000566 self.assertTrue(INF.is_inf())
567 self.assertFalse(NAN.is_inf())
568 self.assertFalse((0.).is_inf())
Christian Heimes6f341092008-04-18 23:13:07 +0000569
Mark Dickinson7103aa42008-07-15 19:08:33 +0000570fromHex = float.fromhex
571toHex = float.hex
572class HexFloatTestCase(unittest.TestCase):
573 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
574 MIN = fromHex('0x1p-1022') # min normal
575 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
576 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
577
578 def identical(self, x, y):
579 # check that floats x and y are identical, or that both
580 # are NaNs
581 if isnan(x) or isnan(y):
582 if isnan(x) == isnan(y):
583 return
584 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
585 return
586 self.fail('%r not identical to %r' % (x, y))
587
588 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000589 self.identical(self.MIN, ldexp(1.0, -1022))
590 self.identical(self.TINY, ldexp(1.0, -1074))
591 self.identical(self.EPS, ldexp(1.0, -52))
592 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000593
594 def test_invalid_inputs(self):
595 invalid_inputs = [
596 'infi', # misspelt infinities and nans
597 '-Infinit',
598 '++inf',
599 '-+Inf',
600 '--nan',
601 '+-NaN',
602 'snan',
603 'NaNs',
604 'nna',
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000605 'an',
606 'nf',
607 'nfinity',
608 'inity',
609 'iinity',
Mark Dickinson7103aa42008-07-15 19:08:33 +0000610 '0xnan',
611 '',
612 ' ',
613 'x1.0p0',
614 '0xX1.0p0',
615 '+ 0x1.0p0', # internal whitespace
616 '- 0x1.0p0',
617 '0 x1.0p0',
618 '0x 1.0p0',
619 '0x1 2.0p0',
620 '+0x1 .0p0',
621 '0x1. 0p0',
622 '-0x1.0 1p0',
623 '-0x1.0 p0',
624 '+0x1.0p +0',
625 '0x1.0p -0',
626 '0x1.0p 0',
627 '+0x1.0p+ 0',
628 '-0x1.0p- 0',
629 '++0x1.0p-0', # double signs
630 '--0x1.0p0',
631 '+-0x1.0p+0',
632 '-+0x1.0p0',
633 '0x1.0p++0',
634 '+0x1.0p+-0',
635 '-0x1.0p-+0',
636 '0x1.0p--0',
637 '0x1.0.p0',
638 '0x.p0', # no hex digits before or after point
639 '0x1,p0', # wrong decimal point character
640 '0x1pa',
641 u'0x1p\uff10', # fullwidth Unicode digits
642 u'\uff10x1p0',
643 u'0x\uff11p0',
644 u'0x1.\uff10p0',
645 '0x1p0 \n 0x2p0',
646 '0x1p0\0 0x1p0', # embedded null byte is not end of string
647 ]
648 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000649 try:
650 result = fromHex(x)
651 except ValueError:
652 pass
653 else:
654 self.fail('Expected float.fromhex(%r) to raise ValueError; '
655 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000656
657
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000658 def test_whitespace(self):
659 value_pairs = [
660 ('inf', INF),
661 ('-Infinity', -INF),
662 ('nan', NAN),
663 ('1.0', 1.0),
664 ('-0x.2', -0.125),
665 ('-0.0', -0.0)
666 ]
667 whitespace = [
668 '',
669 ' ',
670 '\t',
671 '\n',
672 '\n \t',
673 '\f',
674 '\v',
675 '\r'
676 ]
677 for inp, expected in value_pairs:
678 for lead in whitespace:
679 for trail in whitespace:
680 got = fromHex(lead + inp + trail)
681 self.identical(got, expected)
682
683
Mark Dickinson7103aa42008-07-15 19:08:33 +0000684 def test_from_hex(self):
685 MIN = self.MIN;
686 MAX = self.MAX;
687 TINY = self.TINY;
688 EPS = self.EPS;
689
690 # two spellings of infinity, with optional signs; case-insensitive
691 self.identical(fromHex('inf'), INF)
692 self.identical(fromHex('+Inf'), INF)
693 self.identical(fromHex('-INF'), -INF)
694 self.identical(fromHex('iNf'), INF)
695 self.identical(fromHex('Infinity'), INF)
696 self.identical(fromHex('+INFINITY'), INF)
697 self.identical(fromHex('-infinity'), -INF)
698 self.identical(fromHex('-iNFiNitY'), -INF)
699
700 # nans with optional sign; case insensitive
701 self.identical(fromHex('nan'), NAN)
702 self.identical(fromHex('+NaN'), NAN)
703 self.identical(fromHex('-NaN'), NAN)
704 self.identical(fromHex('-nAN'), NAN)
705
706 # variations in input format
707 self.identical(fromHex('1'), 1.0)
708 self.identical(fromHex('+1'), 1.0)
709 self.identical(fromHex('1.'), 1.0)
710 self.identical(fromHex('1.0'), 1.0)
711 self.identical(fromHex('1.0p0'), 1.0)
712 self.identical(fromHex('01'), 1.0)
713 self.identical(fromHex('01.'), 1.0)
714 self.identical(fromHex('0x1'), 1.0)
715 self.identical(fromHex('0x1.'), 1.0)
716 self.identical(fromHex('0x1.0'), 1.0)
717 self.identical(fromHex('+0x1.0'), 1.0)
718 self.identical(fromHex('0x1p0'), 1.0)
719 self.identical(fromHex('0X1p0'), 1.0)
720 self.identical(fromHex('0X1P0'), 1.0)
721 self.identical(fromHex('0x1P0'), 1.0)
722 self.identical(fromHex('0x1.p0'), 1.0)
723 self.identical(fromHex('0x1.0p0'), 1.0)
724 self.identical(fromHex('0x.1p4'), 1.0)
725 self.identical(fromHex('0x.1p04'), 1.0)
726 self.identical(fromHex('0x.1p004'), 1.0)
727 self.identical(fromHex('0x1p+0'), 1.0)
728 self.identical(fromHex('0x1P-0'), 1.0)
729 self.identical(fromHex('+0x1p0'), 1.0)
730 self.identical(fromHex('0x01p0'), 1.0)
731 self.identical(fromHex('0x1p00'), 1.0)
732 self.identical(fromHex(u'0x1p0'), 1.0)
733 self.identical(fromHex(' 0x1p0 '), 1.0)
734 self.identical(fromHex('\n 0x1p0'), 1.0)
735 self.identical(fromHex('0x1p0 \t'), 1.0)
736 self.identical(fromHex('0xap0'), 10.0)
737 self.identical(fromHex('0xAp0'), 10.0)
738 self.identical(fromHex('0xaP0'), 10.0)
739 self.identical(fromHex('0xAP0'), 10.0)
740 self.identical(fromHex('0xbep0'), 190.0)
741 self.identical(fromHex('0xBep0'), 190.0)
742 self.identical(fromHex('0xbEp0'), 190.0)
743 self.identical(fromHex('0XBE0P-4'), 190.0)
744 self.identical(fromHex('0xBEp0'), 190.0)
745 self.identical(fromHex('0xB.Ep4'), 190.0)
746 self.identical(fromHex('0x.BEp8'), 190.0)
747 self.identical(fromHex('0x.0BEp12'), 190.0)
748
749 # moving the point around
750 pi = fromHex('0x1.921fb54442d18p1')
751 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
752 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
753 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
754 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
755 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
756 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
757 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
758 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
759 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
760 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
761 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
762 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
763 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
764 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
765 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
766 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
767 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
768 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
769 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
770 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
771 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
772 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
773 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
774 # ...
775 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
776 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
777 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
778 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
779 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
780 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
781 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
782 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
783 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
784
785
786 # results that should overflow...
787 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
788 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
789 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
790 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
791 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
792 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
793 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
794 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
795 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
796 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
797 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
798 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
799 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
800 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
801 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
802 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
803 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
804 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
805 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
806
807 # ...and those that round to +-max float
808 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
809 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
810 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
811
812 # zeros
813 self.identical(fromHex('0x0p0'), 0.0)
814 self.identical(fromHex('0x0p1000'), 0.0)
815 self.identical(fromHex('-0x0p1023'), -0.0)
816 self.identical(fromHex('0X0p1024'), 0.0)
817 self.identical(fromHex('-0x0p1025'), -0.0)
818 self.identical(fromHex('0X0p2000'), 0.0)
819 self.identical(fromHex('0x0p123456789123456789'), 0.0)
820 self.identical(fromHex('-0X0p-0'), -0.0)
821 self.identical(fromHex('-0X0p-1000'), -0.0)
822 self.identical(fromHex('0x0p-1023'), 0.0)
823 self.identical(fromHex('-0X0p-1024'), -0.0)
824 self.identical(fromHex('-0x0p-1025'), -0.0)
825 self.identical(fromHex('-0x0p-1072'), -0.0)
826 self.identical(fromHex('0X0p-1073'), 0.0)
827 self.identical(fromHex('-0x0p-1074'), -0.0)
828 self.identical(fromHex('0x0p-1075'), 0.0)
829 self.identical(fromHex('0X0p-1076'), 0.0)
830 self.identical(fromHex('-0X0p-2000'), -0.0)
831 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
832
833 # values that should underflow to 0
834 self.identical(fromHex('0X1p-1075'), 0.0)
835 self.identical(fromHex('-0X1p-1075'), -0.0)
836 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
837 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
838 self.identical(fromHex('-0x1.1p-1075'), -TINY)
839 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
840
841 # check round-half-even is working correctly near 0 ...
842 self.identical(fromHex('0x1p-1076'), 0.0)
843 self.identical(fromHex('0X2p-1076'), 0.0)
844 self.identical(fromHex('0X3p-1076'), TINY)
845 self.identical(fromHex('0x4p-1076'), TINY)
846 self.identical(fromHex('0X5p-1076'), TINY)
847 self.identical(fromHex('0X6p-1076'), 2*TINY)
848 self.identical(fromHex('0x7p-1076'), 2*TINY)
849 self.identical(fromHex('0X8p-1076'), 2*TINY)
850 self.identical(fromHex('0X9p-1076'), 2*TINY)
851 self.identical(fromHex('0xap-1076'), 2*TINY)
852 self.identical(fromHex('0Xbp-1076'), 3*TINY)
853 self.identical(fromHex('0xcp-1076'), 3*TINY)
854 self.identical(fromHex('0Xdp-1076'), 3*TINY)
855 self.identical(fromHex('0Xep-1076'), 4*TINY)
856 self.identical(fromHex('0xfp-1076'), 4*TINY)
857 self.identical(fromHex('0x10p-1076'), 4*TINY)
858 self.identical(fromHex('-0x1p-1076'), -0.0)
859 self.identical(fromHex('-0X2p-1076'), -0.0)
860 self.identical(fromHex('-0x3p-1076'), -TINY)
861 self.identical(fromHex('-0X4p-1076'), -TINY)
862 self.identical(fromHex('-0x5p-1076'), -TINY)
863 self.identical(fromHex('-0x6p-1076'), -2*TINY)
864 self.identical(fromHex('-0X7p-1076'), -2*TINY)
865 self.identical(fromHex('-0X8p-1076'), -2*TINY)
866 self.identical(fromHex('-0X9p-1076'), -2*TINY)
867 self.identical(fromHex('-0Xap-1076'), -2*TINY)
868 self.identical(fromHex('-0xbp-1076'), -3*TINY)
869 self.identical(fromHex('-0xcp-1076'), -3*TINY)
870 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
871 self.identical(fromHex('-0xep-1076'), -4*TINY)
872 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
873 self.identical(fromHex('-0X10p-1076'), -4*TINY)
874
875 # ... and near MIN ...
876 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
877 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
878 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
879 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
880 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
881 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
882 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
883 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
884 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
885 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
886 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
887 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
888 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
889 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
890 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
891 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
892 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
893 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
894 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
895 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
896 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
897 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
898 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
899 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
900 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
901 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
902 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
903 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
904 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
905 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
906 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
907 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
908 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
909 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
910
911 # ... and near 1.0.
912 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
913 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
914 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
915 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
916 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
917 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
918 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
919 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
920 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
921 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
922 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
923 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
924 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
925 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
926 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
927 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
928 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
929 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
930 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
931 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
932 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
933 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
934 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
935 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
936 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
937 1.0)
938 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
939 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
940 1+EPS)
941 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
942 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
943 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
944 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
945 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
946 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
947 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
948 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
949 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
950 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
951 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
952 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
953 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
954 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
955 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
956 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
957 1.0+EPS)
958 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
959 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
960 1.0+2*EPS)
961 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
962 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
963 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
964 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
965 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
966 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
967 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
968 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
969
970 def test_roundtrip(self):
971 def roundtrip(x):
972 return fromHex(toHex(x))
973
974 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
975 self.identical(x, roundtrip(x))
976 self.identical(-x, roundtrip(-x))
977
978 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
979 import random
980 for i in xrange(10000):
981 e = random.randrange(-1200, 1200)
982 m = random.random()
983 s = random.choice([1.0, -1.0])
984 try:
985 x = s*ldexp(m, e)
986 except OverflowError:
987 pass
988 else:
989 self.identical(x, fromHex(toHex(x)))
990
Christian Heimes6f341092008-04-18 23:13:07 +0000991
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000992def test_main():
993 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +0000994 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000995 FormatFunctionsTestCase,
996 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +0000997 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +0000998 ReprTestCase,
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000999 RoundTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001000 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +00001001 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +00001002 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001003
1004if __name__ == '__main__':
1005 test_main()