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