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