blob: 971c14f441d66773986fc11aa6ca6fcba74b06e5 [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
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +00008import random, fractions
Michael W. Hudsonba283e22005-05-27 15:23:20 +00009
Christian Heimes6f341092008-04-18 23:13:07 +000010INF = float("inf")
11NAN = float("nan")
Christian Heimes0a8143f2007-12-18 23:22:54 +000012
Mark Dickinson61a0d052009-04-29 21:57:15 +000013#locate file with float format test values
14test_dir = os.path.dirname(__file__) or os.curdir
15format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
16
Benjamin Peterson979395b2008-05-03 21:35:18 +000017class GeneralFloatCases(unittest.TestCase):
18
19 def test_float(self):
20 self.assertEqual(float(3.14), 3.14)
21 self.assertEqual(float(314), 314.0)
22 self.assertEqual(float(314L), 314.0)
23 self.assertEqual(float(" 3.14 "), 3.14)
24 self.assertRaises(ValueError, float, " 0x3.1 ")
25 self.assertRaises(ValueError, float, " -0x3.p-1 ")
26 self.assertRaises(ValueError, float, " +0x3.p-1 ")
27 self.assertRaises(ValueError, float, "++3.14")
28 self.assertRaises(ValueError, float, "+-3.14")
29 self.assertRaises(ValueError, float, "-+3.14")
30 self.assertRaises(ValueError, float, "--3.14")
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +000031 if test_support.have_unicode:
Benjamin Peterson979395b2008-05-03 21:35:18 +000032 self.assertEqual(float(unicode(" 3.14 ")), 3.14)
33 self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
34 # Implementation limitation in PyFloat_FromString()
35 self.assertRaises(ValueError, float, unicode("1"*10000))
36
37 @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
38 def test_float_with_comma(self):
39 # set locale to something that doesn't use '.' for the decimal point
40 # float must not accept the locale specific decimal point but
41 # it still has to accept the normal python syntac
42 import locale
43 if not locale.localeconv()['decimal_point'] == ',':
44 return
45
46 self.assertEqual(float(" 3.14 "), 3.14)
47 self.assertEqual(float("+3.14 "), 3.14)
48 self.assertEqual(float("-3.14 "), -3.14)
49 self.assertEqual(float(".14 "), .14)
50 self.assertEqual(float("3. "), 3.0)
51 self.assertEqual(float("3.e3 "), 3000.0)
52 self.assertEqual(float("3.2e3 "), 3200.0)
53 self.assertEqual(float("2.5e-1 "), 0.25)
54 self.assertEqual(float("5e-1"), 0.5)
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, " 0x3.1 ")
59 self.assertRaises(ValueError, float, " -0x3.p-1 ")
60 self.assertRaises(ValueError, float, " +0x3.p-1 ")
61 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersona853a892008-09-06 23:19:15 +000062 self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
Benjamin Peterson979395b2008-05-03 21:35:18 +000063
64 def test_floatconversion(self):
65 # Make sure that calls to __float__() work properly
66 class Foo0:
67 def __float__(self):
68 return 42.
69
70 class Foo1(object):
71 def __float__(self):
72 return 42.
73
74 class Foo2(float):
75 def __float__(self):
76 return 42.
77
78 class Foo3(float):
79 def __new__(cls, value=0.):
80 return float.__new__(cls, 2*value)
81
82 def __float__(self):
83 return self
84
85 class Foo4(float):
86 def __float__(self):
87 return 42
88
Benjamin Peterson99d36f12009-04-15 21:26:36 +000089 # Issue 5759: __float__ not called on str subclasses (though it is on
90 # unicode subclasses).
91 class FooStr(str):
92 def __float__(self):
93 return float(str(self)) + 1
94
95 class FooUnicode(unicode):
96 def __float__(self):
97 return float(unicode(self)) + 1
98
Benjamin Peterson979395b2008-05-03 21:35:18 +000099 self.assertAlmostEqual(float(Foo0()), 42.)
100 self.assertAlmostEqual(float(Foo1()), 42.)
101 self.assertAlmostEqual(float(Foo2()), 42.)
102 self.assertAlmostEqual(float(Foo3(21)), 42.)
103 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson99d36f12009-04-15 21:26:36 +0000104 self.assertAlmostEqual(float(FooUnicode('8')), 9.)
105 self.assertAlmostEqual(float(FooStr('8')), 9.)
Benjamin Peterson979395b2008-05-03 21:35:18 +0000106
107 def test_floatasratio(self):
108 for f, ratio in [
109 (0.875, (7, 8)),
110 (-0.875, (-7, 8)),
111 (0.0, (0, 1)),
112 (11.5, (23, 2)),
113 ]:
114 self.assertEqual(f.as_integer_ratio(), ratio)
115
116 for i in range(10000):
117 f = random.random()
118 f *= 10 ** random.randint(-100, 100)
119 n, d = f.as_integer_ratio()
120 self.assertEqual(float(n).__truediv__(d), f)
121
122 R = fractions.Fraction
123 self.assertEqual(R(0, 1),
124 R(*float(0.0).as_integer_ratio()))
125 self.assertEqual(R(5, 2),
126 R(*float(2.5).as_integer_ratio()))
127 self.assertEqual(R(1, 2),
128 R(*float(0.5).as_integer_ratio()))
129 self.assertEqual(R(4728779608739021, 2251799813685248),
130 R(*float(2.1).as_integer_ratio()))
131 self.assertEqual(R(-4728779608739021, 2251799813685248),
132 R(*float(-2.1).as_integer_ratio()))
133 self.assertEqual(R(-2100, 1),
134 R(*float(-2100.0).as_integer_ratio()))
135
136 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
137 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
138 self.assertRaises(ValueError, float('nan').as_integer_ratio)
139
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000140class FormatFunctionsTestCase(unittest.TestCase):
141
142 def setUp(self):
143 self.save_formats = {'double':float.__getformat__('double'),
144 'float':float.__getformat__('float')}
145
146 def tearDown(self):
147 float.__setformat__('double', self.save_formats['double'])
148 float.__setformat__('float', self.save_formats['float'])
149
150 def test_getformat(self):
151 self.assert_(float.__getformat__('double') in
152 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
153 self.assert_(float.__getformat__('float') in
154 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
155 self.assertRaises(ValueError, float.__getformat__, 'chicken')
156 self.assertRaises(TypeError, float.__getformat__, 1)
157
158 def test_setformat(self):
159 for t in 'double', 'float':
160 float.__setformat__(t, 'unknown')
161 if self.save_formats[t] == 'IEEE, big-endian':
162 self.assertRaises(ValueError, float.__setformat__,
163 t, 'IEEE, little-endian')
164 elif self.save_formats[t] == 'IEEE, little-endian':
165 self.assertRaises(ValueError, float.__setformat__,
166 t, 'IEEE, big-endian')
167 else:
168 self.assertRaises(ValueError, float.__setformat__,
169 t, 'IEEE, big-endian')
170 self.assertRaises(ValueError, float.__setformat__,
171 t, 'IEEE, little-endian')
172 self.assertRaises(ValueError, float.__setformat__,
173 t, 'chicken')
174 self.assertRaises(ValueError, float.__setformat__,
175 'chicken', 'unknown')
176
177BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
178LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
179BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
180LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
181
182BE_FLOAT_INF = '\x7f\x80\x00\x00'
183LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
184BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
185LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
186
187# on non-IEEE platforms, attempting to unpack a bit pattern
188# representing an infinity or a NaN should raise an exception.
189
190class UnknownFormatTestCase(unittest.TestCase):
191 def setUp(self):
192 self.save_formats = {'double':float.__getformat__('double'),
193 'float':float.__getformat__('float')}
194 float.__setformat__('double', 'unknown')
195 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000196
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000197 def tearDown(self):
198 float.__setformat__('double', self.save_formats['double'])
199 float.__setformat__('float', self.save_formats['float'])
200
201 def test_double_specials_dont_unpack(self):
202 for fmt, data in [('>d', BE_DOUBLE_INF),
203 ('>d', BE_DOUBLE_NAN),
204 ('<d', LE_DOUBLE_INF),
205 ('<d', LE_DOUBLE_NAN)]:
206 self.assertRaises(ValueError, struct.unpack, fmt, data)
207
208 def test_float_specials_dont_unpack(self):
209 for fmt, data in [('>f', BE_FLOAT_INF),
210 ('>f', BE_FLOAT_NAN),
211 ('<f', LE_FLOAT_INF),
212 ('<f', LE_FLOAT_NAN)]:
213 self.assertRaises(ValueError, struct.unpack, fmt, data)
214
215
216# on an IEEE platform, all we guarantee is that bit patterns
217# representing infinities or NaNs do not raise an exception; all else
218# is accident (today).
Alex Martellid8672aa2007-08-22 21:14:17 +0000219# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000220
221class IEEEFormatTestCase(unittest.TestCase):
222 if float.__getformat__("double").startswith("IEEE"):
223 def test_double_specials_do_unpack(self):
224 for fmt, data in [('>d', BE_DOUBLE_INF),
225 ('>d', BE_DOUBLE_NAN),
226 ('<d', LE_DOUBLE_INF),
227 ('<d', LE_DOUBLE_NAN)]:
228 struct.unpack(fmt, data)
229
230 if float.__getformat__("float").startswith("IEEE"):
231 def test_float_specials_do_unpack(self):
232 for fmt, data in [('>f', BE_FLOAT_INF),
233 ('>f', BE_FLOAT_NAN),
234 ('<f', LE_FLOAT_INF),
235 ('<f', LE_FLOAT_NAN)]:
236 struct.unpack(fmt, data)
237
Alex Martellid8672aa2007-08-22 21:14:17 +0000238 if float.__getformat__("double").startswith("IEEE"):
239 def test_negative_zero(self):
240 import math
241 def pos_pos():
242 return 0.0, math.atan2(0.0, -1)
243 def pos_neg():
244 return 0.0, math.atan2(-0.0, -1)
245 def neg_pos():
246 return -0.0, math.atan2(0.0, -1)
247 def neg_neg():
248 return -0.0, math.atan2(-0.0, -1)
249 self.assertEquals(pos_pos(), neg_pos())
250 self.assertEquals(pos_neg(), neg_neg())
251
Guido van Rossum3b835492008-01-05 00:59:59 +0000252 if float.__getformat__("double").startswith("IEEE"):
253 def test_underflow_sign(self):
254 import math
255 # check that -1e-1000 gives -0.0, not 0.0
256 self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
257 self.assertEquals(math.atan2(float('-1e-1000'), -1),
258 math.atan2(-0.0, -1))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000259
Mark Dickinson61a0d052009-04-29 21:57:15 +0000260 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
261 "test requires IEEE 754 doubles")
262 def test_format_testfile(self):
263 for line in open(format_testfile):
264 if line.startswith('--'):
265 continue
266 line = line.strip()
267 if not line:
268 continue
269
270 lhs, rhs = map(str.strip, line.split('->'))
271 fmt, arg = lhs.split()
272 self.assertEqual(fmt % float(arg), rhs)
273 self.assertEqual(fmt % -float(arg), '-' + rhs)
274
Mark Dickinson92fcc9c2009-04-29 20:41:00 +0000275 def test_issue5864(self):
276 self.assertEquals(format(123.456, '.4'), '123.5')
277 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
278 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
279
Christian Heimes284d9272007-12-10 22:28:56 +0000280class ReprTestCase(unittest.TestCase):
281 def test_repr(self):
282 floats_file = open(os.path.join(os.path.split(__file__)[0],
283 'floating_points.txt'))
284 for line in floats_file:
285 line = line.strip()
286 if not line or line.startswith('#'):
287 continue
288 v = eval(line)
289 self.assertEqual(v, eval(repr(v)))
290 floats_file.close()
291
Christian Heimes0a8143f2007-12-18 23:22:54 +0000292# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000293# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000294class InfNanTest(unittest.TestCase):
295 def test_inf_from_str(self):
296 self.assert_(isinf(float("inf")))
297 self.assert_(isinf(float("+inf")))
298 self.assert_(isinf(float("-inf")))
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000299 self.assert_(isinf(float("infinity")))
300 self.assert_(isinf(float("+infinity")))
301 self.assert_(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000302
303 self.assertEqual(repr(float("inf")), "inf")
304 self.assertEqual(repr(float("+inf")), "inf")
305 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000306 self.assertEqual(repr(float("infinity")), "inf")
307 self.assertEqual(repr(float("+infinity")), "inf")
308 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000309
310 self.assertEqual(repr(float("INF")), "inf")
311 self.assertEqual(repr(float("+Inf")), "inf")
312 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000313 self.assertEqual(repr(float("Infinity")), "inf")
314 self.assertEqual(repr(float("+iNfInItY")), "inf")
315 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000316
317 self.assertEqual(str(float("inf")), "inf")
318 self.assertEqual(str(float("+inf")), "inf")
319 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000320 self.assertEqual(str(float("infinity")), "inf")
321 self.assertEqual(str(float("+infinity")), "inf")
322 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000323
324 self.assertRaises(ValueError, float, "info")
325 self.assertRaises(ValueError, float, "+info")
326 self.assertRaises(ValueError, float, "-info")
327 self.assertRaises(ValueError, float, "in")
328 self.assertRaises(ValueError, float, "+in")
329 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000330 self.assertRaises(ValueError, float, "infinit")
331 self.assertRaises(ValueError, float, "+Infin")
332 self.assertRaises(ValueError, float, "-INFI")
333 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000334
335 def test_inf_as_str(self):
336 self.assertEqual(repr(1e300 * 1e300), "inf")
337 self.assertEqual(repr(-1e300 * 1e300), "-inf")
338
339 self.assertEqual(str(1e300 * 1e300), "inf")
340 self.assertEqual(str(-1e300 * 1e300), "-inf")
341
342 def test_nan_from_str(self):
343 self.assert_(isnan(float("nan")))
344 self.assert_(isnan(float("+nan")))
345 self.assert_(isnan(float("-nan")))
346
347 self.assertEqual(repr(float("nan")), "nan")
348 self.assertEqual(repr(float("+nan")), "nan")
349 self.assertEqual(repr(float("-nan")), "nan")
350
351 self.assertEqual(repr(float("NAN")), "nan")
352 self.assertEqual(repr(float("+NAn")), "nan")
353 self.assertEqual(repr(float("-NaN")), "nan")
354
355 self.assertEqual(str(float("nan")), "nan")
356 self.assertEqual(str(float("+nan")), "nan")
357 self.assertEqual(str(float("-nan")), "nan")
358
359 self.assertRaises(ValueError, float, "nana")
360 self.assertRaises(ValueError, float, "+nana")
361 self.assertRaises(ValueError, float, "-nana")
362 self.assertRaises(ValueError, float, "na")
363 self.assertRaises(ValueError, float, "+na")
364 self.assertRaises(ValueError, float, "-na")
365
366 def test_nan_as_str(self):
367 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
368 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
369
370 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
371 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000372
Christian Heimes6f341092008-04-18 23:13:07 +0000373 def notest_float_nan(self):
374 self.assert_(NAN.is_nan())
375 self.failIf(INF.is_nan())
376 self.failIf((0.).is_nan())
377
378 def notest_float_inf(self):
379 self.assert_(INF.is_inf())
380 self.failIf(NAN.is_inf())
381 self.failIf((0.).is_inf())
382
Mark Dickinson7103aa42008-07-15 19:08:33 +0000383fromHex = float.fromhex
384toHex = float.hex
385class HexFloatTestCase(unittest.TestCase):
386 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
387 MIN = fromHex('0x1p-1022') # min normal
388 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
389 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
390
391 def identical(self, x, y):
392 # check that floats x and y are identical, or that both
393 # are NaNs
394 if isnan(x) or isnan(y):
395 if isnan(x) == isnan(y):
396 return
397 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
398 return
399 self.fail('%r not identical to %r' % (x, y))
400
401 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000402 self.identical(self.MIN, ldexp(1.0, -1022))
403 self.identical(self.TINY, ldexp(1.0, -1074))
404 self.identical(self.EPS, ldexp(1.0, -52))
405 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000406
407 def test_invalid_inputs(self):
408 invalid_inputs = [
409 'infi', # misspelt infinities and nans
410 '-Infinit',
411 '++inf',
412 '-+Inf',
413 '--nan',
414 '+-NaN',
415 'snan',
416 'NaNs',
417 'nna',
418 '0xnan',
419 '',
420 ' ',
421 'x1.0p0',
422 '0xX1.0p0',
423 '+ 0x1.0p0', # internal whitespace
424 '- 0x1.0p0',
425 '0 x1.0p0',
426 '0x 1.0p0',
427 '0x1 2.0p0',
428 '+0x1 .0p0',
429 '0x1. 0p0',
430 '-0x1.0 1p0',
431 '-0x1.0 p0',
432 '+0x1.0p +0',
433 '0x1.0p -0',
434 '0x1.0p 0',
435 '+0x1.0p+ 0',
436 '-0x1.0p- 0',
437 '++0x1.0p-0', # double signs
438 '--0x1.0p0',
439 '+-0x1.0p+0',
440 '-+0x1.0p0',
441 '0x1.0p++0',
442 '+0x1.0p+-0',
443 '-0x1.0p-+0',
444 '0x1.0p--0',
445 '0x1.0.p0',
446 '0x.p0', # no hex digits before or after point
447 '0x1,p0', # wrong decimal point character
448 '0x1pa',
449 u'0x1p\uff10', # fullwidth Unicode digits
450 u'\uff10x1p0',
451 u'0x\uff11p0',
452 u'0x1.\uff10p0',
453 '0x1p0 \n 0x2p0',
454 '0x1p0\0 0x1p0', # embedded null byte is not end of string
455 ]
456 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000457 try:
458 result = fromHex(x)
459 except ValueError:
460 pass
461 else:
462 self.fail('Expected float.fromhex(%r) to raise ValueError; '
463 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000464
465
466 def test_from_hex(self):
467 MIN = self.MIN;
468 MAX = self.MAX;
469 TINY = self.TINY;
470 EPS = self.EPS;
471
472 # two spellings of infinity, with optional signs; case-insensitive
473 self.identical(fromHex('inf'), INF)
474 self.identical(fromHex('+Inf'), INF)
475 self.identical(fromHex('-INF'), -INF)
476 self.identical(fromHex('iNf'), INF)
477 self.identical(fromHex('Infinity'), INF)
478 self.identical(fromHex('+INFINITY'), INF)
479 self.identical(fromHex('-infinity'), -INF)
480 self.identical(fromHex('-iNFiNitY'), -INF)
481
482 # nans with optional sign; case insensitive
483 self.identical(fromHex('nan'), NAN)
484 self.identical(fromHex('+NaN'), NAN)
485 self.identical(fromHex('-NaN'), NAN)
486 self.identical(fromHex('-nAN'), NAN)
487
488 # variations in input format
489 self.identical(fromHex('1'), 1.0)
490 self.identical(fromHex('+1'), 1.0)
491 self.identical(fromHex('1.'), 1.0)
492 self.identical(fromHex('1.0'), 1.0)
493 self.identical(fromHex('1.0p0'), 1.0)
494 self.identical(fromHex('01'), 1.0)
495 self.identical(fromHex('01.'), 1.0)
496 self.identical(fromHex('0x1'), 1.0)
497 self.identical(fromHex('0x1.'), 1.0)
498 self.identical(fromHex('0x1.0'), 1.0)
499 self.identical(fromHex('+0x1.0'), 1.0)
500 self.identical(fromHex('0x1p0'), 1.0)
501 self.identical(fromHex('0X1p0'), 1.0)
502 self.identical(fromHex('0X1P0'), 1.0)
503 self.identical(fromHex('0x1P0'), 1.0)
504 self.identical(fromHex('0x1.p0'), 1.0)
505 self.identical(fromHex('0x1.0p0'), 1.0)
506 self.identical(fromHex('0x.1p4'), 1.0)
507 self.identical(fromHex('0x.1p04'), 1.0)
508 self.identical(fromHex('0x.1p004'), 1.0)
509 self.identical(fromHex('0x1p+0'), 1.0)
510 self.identical(fromHex('0x1P-0'), 1.0)
511 self.identical(fromHex('+0x1p0'), 1.0)
512 self.identical(fromHex('0x01p0'), 1.0)
513 self.identical(fromHex('0x1p00'), 1.0)
514 self.identical(fromHex(u'0x1p0'), 1.0)
515 self.identical(fromHex(' 0x1p0 '), 1.0)
516 self.identical(fromHex('\n 0x1p0'), 1.0)
517 self.identical(fromHex('0x1p0 \t'), 1.0)
518 self.identical(fromHex('0xap0'), 10.0)
519 self.identical(fromHex('0xAp0'), 10.0)
520 self.identical(fromHex('0xaP0'), 10.0)
521 self.identical(fromHex('0xAP0'), 10.0)
522 self.identical(fromHex('0xbep0'), 190.0)
523 self.identical(fromHex('0xBep0'), 190.0)
524 self.identical(fromHex('0xbEp0'), 190.0)
525 self.identical(fromHex('0XBE0P-4'), 190.0)
526 self.identical(fromHex('0xBEp0'), 190.0)
527 self.identical(fromHex('0xB.Ep4'), 190.0)
528 self.identical(fromHex('0x.BEp8'), 190.0)
529 self.identical(fromHex('0x.0BEp12'), 190.0)
530
531 # moving the point around
532 pi = fromHex('0x1.921fb54442d18p1')
533 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
534 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
535 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
536 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
537 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
538 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
539 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
540 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
541 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
542 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
543 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
544 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
545 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
546 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
547 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
548 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
549 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
550 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
551 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
552 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
553 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
554 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
555 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
556 # ...
557 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
558 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
559 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
560 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
561 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
562 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
563 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
564 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
565 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
566
567
568 # results that should overflow...
569 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
570 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
571 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
572 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
573 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
574 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
575 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
576 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
577 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
578 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
579 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
580 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
581 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
582 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
583 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
584 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
585 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
586 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
587 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
588
589 # ...and those that round to +-max float
590 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
591 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
592 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
593
594 # zeros
595 self.identical(fromHex('0x0p0'), 0.0)
596 self.identical(fromHex('0x0p1000'), 0.0)
597 self.identical(fromHex('-0x0p1023'), -0.0)
598 self.identical(fromHex('0X0p1024'), 0.0)
599 self.identical(fromHex('-0x0p1025'), -0.0)
600 self.identical(fromHex('0X0p2000'), 0.0)
601 self.identical(fromHex('0x0p123456789123456789'), 0.0)
602 self.identical(fromHex('-0X0p-0'), -0.0)
603 self.identical(fromHex('-0X0p-1000'), -0.0)
604 self.identical(fromHex('0x0p-1023'), 0.0)
605 self.identical(fromHex('-0X0p-1024'), -0.0)
606 self.identical(fromHex('-0x0p-1025'), -0.0)
607 self.identical(fromHex('-0x0p-1072'), -0.0)
608 self.identical(fromHex('0X0p-1073'), 0.0)
609 self.identical(fromHex('-0x0p-1074'), -0.0)
610 self.identical(fromHex('0x0p-1075'), 0.0)
611 self.identical(fromHex('0X0p-1076'), 0.0)
612 self.identical(fromHex('-0X0p-2000'), -0.0)
613 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
614
615 # values that should underflow to 0
616 self.identical(fromHex('0X1p-1075'), 0.0)
617 self.identical(fromHex('-0X1p-1075'), -0.0)
618 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
619 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
620 self.identical(fromHex('-0x1.1p-1075'), -TINY)
621 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
622
623 # check round-half-even is working correctly near 0 ...
624 self.identical(fromHex('0x1p-1076'), 0.0)
625 self.identical(fromHex('0X2p-1076'), 0.0)
626 self.identical(fromHex('0X3p-1076'), TINY)
627 self.identical(fromHex('0x4p-1076'), TINY)
628 self.identical(fromHex('0X5p-1076'), TINY)
629 self.identical(fromHex('0X6p-1076'), 2*TINY)
630 self.identical(fromHex('0x7p-1076'), 2*TINY)
631 self.identical(fromHex('0X8p-1076'), 2*TINY)
632 self.identical(fromHex('0X9p-1076'), 2*TINY)
633 self.identical(fromHex('0xap-1076'), 2*TINY)
634 self.identical(fromHex('0Xbp-1076'), 3*TINY)
635 self.identical(fromHex('0xcp-1076'), 3*TINY)
636 self.identical(fromHex('0Xdp-1076'), 3*TINY)
637 self.identical(fromHex('0Xep-1076'), 4*TINY)
638 self.identical(fromHex('0xfp-1076'), 4*TINY)
639 self.identical(fromHex('0x10p-1076'), 4*TINY)
640 self.identical(fromHex('-0x1p-1076'), -0.0)
641 self.identical(fromHex('-0X2p-1076'), -0.0)
642 self.identical(fromHex('-0x3p-1076'), -TINY)
643 self.identical(fromHex('-0X4p-1076'), -TINY)
644 self.identical(fromHex('-0x5p-1076'), -TINY)
645 self.identical(fromHex('-0x6p-1076'), -2*TINY)
646 self.identical(fromHex('-0X7p-1076'), -2*TINY)
647 self.identical(fromHex('-0X8p-1076'), -2*TINY)
648 self.identical(fromHex('-0X9p-1076'), -2*TINY)
649 self.identical(fromHex('-0Xap-1076'), -2*TINY)
650 self.identical(fromHex('-0xbp-1076'), -3*TINY)
651 self.identical(fromHex('-0xcp-1076'), -3*TINY)
652 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
653 self.identical(fromHex('-0xep-1076'), -4*TINY)
654 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
655 self.identical(fromHex('-0X10p-1076'), -4*TINY)
656
657 # ... and near MIN ...
658 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
659 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
660 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
661 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
662 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
663 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
664 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
665 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
666 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
667 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
668 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
669 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
670 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
671 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
672 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
673 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
674 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
675 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
676 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
677 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
678 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
679 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
680 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
681 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
682 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
683 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
684 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
685 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
686 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
687 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
688 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
689 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
690 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
691 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
692
693 # ... and near 1.0.
694 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
695 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
696 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
697 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
698 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
699 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
700 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
701 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
702 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
703 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
704 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
705 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
706 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
707 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
708 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
709 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
710 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
711 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
712 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
713 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
714 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
715 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
716 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
717 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
718 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
719 1.0)
720 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
721 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
722 1+EPS)
723 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
724 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
725 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
726 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
727 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
728 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
729 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
730 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
731 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
732 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
733 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
734 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
735 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
736 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
737 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
738 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
739 1.0+EPS)
740 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
741 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
742 1.0+2*EPS)
743 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
744 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
745 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
746 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
747 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
748 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
749 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
750 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
751
752 def test_roundtrip(self):
753 def roundtrip(x):
754 return fromHex(toHex(x))
755
756 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
757 self.identical(x, roundtrip(x))
758 self.identical(-x, roundtrip(-x))
759
760 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
761 import random
762 for i in xrange(10000):
763 e = random.randrange(-1200, 1200)
764 m = random.random()
765 s = random.choice([1.0, -1.0])
766 try:
767 x = s*ldexp(m, e)
768 except OverflowError:
769 pass
770 else:
771 self.identical(x, fromHex(toHex(x)))
772
Christian Heimes6f341092008-04-18 23:13:07 +0000773
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000774def test_main():
775 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +0000776 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000777 FormatFunctionsTestCase,
778 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +0000779 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +0000780 ReprTestCase,
781 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +0000782 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +0000783 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000784
785if __name__ == '__main__':
786 test_main()