blob: 7de53206af5b5420f735b3bad289b3b2347e87e9 [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
287# ways to create and representate inf and nan
288class 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")))
293
294 self.assertEqual(repr(float("inf")), "inf")
295 self.assertEqual(repr(float("+inf")), "inf")
296 self.assertEqual(repr(float("-inf")), "-inf")
297
298 self.assertEqual(repr(float("INF")), "inf")
299 self.assertEqual(repr(float("+Inf")), "inf")
300 self.assertEqual(repr(float("-iNF")), "-inf")
301
302 self.assertEqual(str(float("inf")), "inf")
303 self.assertEqual(str(float("+inf")), "inf")
304 self.assertEqual(str(float("-inf")), "-inf")
305
306 self.assertRaises(ValueError, float, "info")
307 self.assertRaises(ValueError, float, "+info")
308 self.assertRaises(ValueError, float, "-info")
309 self.assertRaises(ValueError, float, "in")
310 self.assertRaises(ValueError, float, "+in")
311 self.assertRaises(ValueError, float, "-in")
312
313 def test_inf_as_str(self):
314 self.assertEqual(repr(1e300 * 1e300), "inf")
315 self.assertEqual(repr(-1e300 * 1e300), "-inf")
316
317 self.assertEqual(str(1e300 * 1e300), "inf")
318 self.assertEqual(str(-1e300 * 1e300), "-inf")
319
320 def test_nan_from_str(self):
321 self.assert_(isnan(float("nan")))
322 self.assert_(isnan(float("+nan")))
323 self.assert_(isnan(float("-nan")))
324
325 self.assertEqual(repr(float("nan")), "nan")
326 self.assertEqual(repr(float("+nan")), "nan")
327 self.assertEqual(repr(float("-nan")), "nan")
328
329 self.assertEqual(repr(float("NAN")), "nan")
330 self.assertEqual(repr(float("+NAn")), "nan")
331 self.assertEqual(repr(float("-NaN")), "nan")
332
333 self.assertEqual(str(float("nan")), "nan")
334 self.assertEqual(str(float("+nan")), "nan")
335 self.assertEqual(str(float("-nan")), "nan")
336
337 self.assertRaises(ValueError, float, "nana")
338 self.assertRaises(ValueError, float, "+nana")
339 self.assertRaises(ValueError, float, "-nana")
340 self.assertRaises(ValueError, float, "na")
341 self.assertRaises(ValueError, float, "+na")
342 self.assertRaises(ValueError, float, "-na")
343
344 def test_nan_as_str(self):
345 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
346 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
347
348 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
349 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000350
Christian Heimes53876d92008-04-19 00:31:39 +0000351 def notest_float_nan(self):
352 self.assert_(NAN.is_nan())
353 self.failIf(INF.is_nan())
354 self.failIf((0.).is_nan())
355
356 def notest_float_inf(self):
357 self.assert_(INF.is_inf())
358 self.failIf(NAN.is_inf())
359 self.failIf((0.).is_inf())
360
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000361fromHex = float.fromhex
362toHex = float.hex
363class HexFloatTestCase(unittest.TestCase):
364 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
365 MIN = fromHex('0x1p-1022') # min normal
366 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
367 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
368
369 def identical(self, x, y):
370 # check that floats x and y are identical, or that both
371 # are NaNs
372 if isnan(x) or isnan(y):
373 if isnan(x) == isnan(y):
374 return
375 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
376 return
377 self.fail('%r not identical to %r' % (x, y))
378
379 def test_ends(self):
Mark Dickinson38bbc482008-07-16 11:32:23 +0000380 self.identical(self.MIN, ldexp(1.0, -1022))
381 self.identical(self.TINY, ldexp(1.0, -1074))
382 self.identical(self.EPS, ldexp(1.0, -52))
383 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000384
385 def test_invalid_inputs(self):
386 invalid_inputs = [
387 'infi', # misspelt infinities and nans
388 '-Infinit',
389 '++inf',
390 '-+Inf',
391 '--nan',
392 '+-NaN',
393 'snan',
394 'NaNs',
395 'nna',
396 '0xnan',
397 '',
398 ' ',
399 'x1.0p0',
400 '0xX1.0p0',
401 '+ 0x1.0p0', # internal whitespace
402 '- 0x1.0p0',
403 '0 x1.0p0',
404 '0x 1.0p0',
405 '0x1 2.0p0',
406 '+0x1 .0p0',
407 '0x1. 0p0',
408 '-0x1.0 1p0',
409 '-0x1.0 p0',
410 '+0x1.0p +0',
411 '0x1.0p -0',
412 '0x1.0p 0',
413 '+0x1.0p+ 0',
414 '-0x1.0p- 0',
415 '++0x1.0p-0', # double signs
416 '--0x1.0p0',
417 '+-0x1.0p+0',
418 '-+0x1.0p0',
419 '0x1.0p++0',
420 '+0x1.0p+-0',
421 '-0x1.0p-+0',
422 '0x1.0p--0',
423 '0x1.0.p0',
424 '0x.p0', # no hex digits before or after point
425 '0x1,p0', # wrong decimal point character
426 '0x1pa',
427 '0x1p\uff10', # fullwidth Unicode digits
428 '\uff10x1p0',
429 '0x\uff11p0',
430 '0x1.\uff10p0',
431 '0x1p0 \n 0x2p0',
432 '0x1p0\0 0x1p0', # embedded null byte is not end of string
433 ]
434 for x in invalid_inputs:
435 self.assertRaises(ValueError, fromHex, x)
436
437
438 def test_from_hex(self):
439 MIN = self.MIN;
440 MAX = self.MAX;
441 TINY = self.TINY;
442 EPS = self.EPS;
443
444 # two spellings of infinity, with optional signs; case-insensitive
445 self.identical(fromHex('inf'), INF)
446 self.identical(fromHex('+Inf'), INF)
447 self.identical(fromHex('-INF'), -INF)
448 self.identical(fromHex('iNf'), INF)
449 self.identical(fromHex('Infinity'), INF)
450 self.identical(fromHex('+INFINITY'), INF)
451 self.identical(fromHex('-infinity'), -INF)
452 self.identical(fromHex('-iNFiNitY'), -INF)
453
454 # nans with optional sign; case insensitive
455 self.identical(fromHex('nan'), NAN)
456 self.identical(fromHex('+NaN'), NAN)
457 self.identical(fromHex('-NaN'), NAN)
458 self.identical(fromHex('-nAN'), NAN)
459
460 # variations in input format
461 self.identical(fromHex('1'), 1.0)
462 self.identical(fromHex('+1'), 1.0)
463 self.identical(fromHex('1.'), 1.0)
464 self.identical(fromHex('1.0'), 1.0)
465 self.identical(fromHex('1.0p0'), 1.0)
466 self.identical(fromHex('01'), 1.0)
467 self.identical(fromHex('01.'), 1.0)
468 self.identical(fromHex('0x1'), 1.0)
469 self.identical(fromHex('0x1.'), 1.0)
470 self.identical(fromHex('0x1.0'), 1.0)
471 self.identical(fromHex('+0x1.0'), 1.0)
472 self.identical(fromHex('0x1p0'), 1.0)
473 self.identical(fromHex('0X1p0'), 1.0)
474 self.identical(fromHex('0X1P0'), 1.0)
475 self.identical(fromHex('0x1P0'), 1.0)
476 self.identical(fromHex('0x1.p0'), 1.0)
477 self.identical(fromHex('0x1.0p0'), 1.0)
478 self.identical(fromHex('0x.1p4'), 1.0)
479 self.identical(fromHex('0x.1p04'), 1.0)
480 self.identical(fromHex('0x.1p004'), 1.0)
481 self.identical(fromHex('0x1p+0'), 1.0)
482 self.identical(fromHex('0x1P-0'), 1.0)
483 self.identical(fromHex('+0x1p0'), 1.0)
484 self.identical(fromHex('0x01p0'), 1.0)
485 self.identical(fromHex('0x1p00'), 1.0)
486 self.identical(fromHex(' 0x1p0 '), 1.0)
487 self.identical(fromHex('\n 0x1p0'), 1.0)
488 self.identical(fromHex('0x1p0 \t'), 1.0)
489 self.identical(fromHex('0xap0'), 10.0)
490 self.identical(fromHex('0xAp0'), 10.0)
491 self.identical(fromHex('0xaP0'), 10.0)
492 self.identical(fromHex('0xAP0'), 10.0)
493 self.identical(fromHex('0xbep0'), 190.0)
494 self.identical(fromHex('0xBep0'), 190.0)
495 self.identical(fromHex('0xbEp0'), 190.0)
496 self.identical(fromHex('0XBE0P-4'), 190.0)
497 self.identical(fromHex('0xBEp0'), 190.0)
498 self.identical(fromHex('0xB.Ep4'), 190.0)
499 self.identical(fromHex('0x.BEp8'), 190.0)
500 self.identical(fromHex('0x.0BEp12'), 190.0)
501
502 # moving the point around
503 pi = fromHex('0x1.921fb54442d18p1')
504 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
505 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
506 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
507 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
508 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
509 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
510 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
511 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
512 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
513 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
514 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
515 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
516 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
517 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
518 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
519 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
520 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
521 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
522 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
523 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
524 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
525 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
526 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
527 # ...
528 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
529 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
530 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
531 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
532 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
533 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
534 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
535 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
536 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
537
538
539 # results that should overflow...
540 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
541 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
542 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
543 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
544 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
545 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
546 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
547 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
548 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
549 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
550 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
551 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
552 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
553 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
554 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
555 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
556 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
557 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
558 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
559
560 # ...and those that round to +-max float
561 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
562 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
563 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
564
565 # zeros
566 self.identical(fromHex('0x0p0'), 0.0)
567 self.identical(fromHex('0x0p1000'), 0.0)
568 self.identical(fromHex('-0x0p1023'), -0.0)
569 self.identical(fromHex('0X0p1024'), 0.0)
570 self.identical(fromHex('-0x0p1025'), -0.0)
571 self.identical(fromHex('0X0p2000'), 0.0)
572 self.identical(fromHex('0x0p123456789123456789'), 0.0)
573 self.identical(fromHex('-0X0p-0'), -0.0)
574 self.identical(fromHex('-0X0p-1000'), -0.0)
575 self.identical(fromHex('0x0p-1023'), 0.0)
576 self.identical(fromHex('-0X0p-1024'), -0.0)
577 self.identical(fromHex('-0x0p-1025'), -0.0)
578 self.identical(fromHex('-0x0p-1072'), -0.0)
579 self.identical(fromHex('0X0p-1073'), 0.0)
580 self.identical(fromHex('-0x0p-1074'), -0.0)
581 self.identical(fromHex('0x0p-1075'), 0.0)
582 self.identical(fromHex('0X0p-1076'), 0.0)
583 self.identical(fromHex('-0X0p-2000'), -0.0)
584 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
585
586 # values that should underflow to 0
587 self.identical(fromHex('0X1p-1075'), 0.0)
588 self.identical(fromHex('-0X1p-1075'), -0.0)
589 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
590 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
591 self.identical(fromHex('-0x1.1p-1075'), -TINY)
592 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
593
594 # check round-half-even is working correctly near 0 ...
595 self.identical(fromHex('0x1p-1076'), 0.0)
596 self.identical(fromHex('0X2p-1076'), 0.0)
597 self.identical(fromHex('0X3p-1076'), TINY)
598 self.identical(fromHex('0x4p-1076'), TINY)
599 self.identical(fromHex('0X5p-1076'), TINY)
600 self.identical(fromHex('0X6p-1076'), 2*TINY)
601 self.identical(fromHex('0x7p-1076'), 2*TINY)
602 self.identical(fromHex('0X8p-1076'), 2*TINY)
603 self.identical(fromHex('0X9p-1076'), 2*TINY)
604 self.identical(fromHex('0xap-1076'), 2*TINY)
605 self.identical(fromHex('0Xbp-1076'), 3*TINY)
606 self.identical(fromHex('0xcp-1076'), 3*TINY)
607 self.identical(fromHex('0Xdp-1076'), 3*TINY)
608 self.identical(fromHex('0Xep-1076'), 4*TINY)
609 self.identical(fromHex('0xfp-1076'), 4*TINY)
610 self.identical(fromHex('0x10p-1076'), 4*TINY)
611 self.identical(fromHex('-0x1p-1076'), -0.0)
612 self.identical(fromHex('-0X2p-1076'), -0.0)
613 self.identical(fromHex('-0x3p-1076'), -TINY)
614 self.identical(fromHex('-0X4p-1076'), -TINY)
615 self.identical(fromHex('-0x5p-1076'), -TINY)
616 self.identical(fromHex('-0x6p-1076'), -2*TINY)
617 self.identical(fromHex('-0X7p-1076'), -2*TINY)
618 self.identical(fromHex('-0X8p-1076'), -2*TINY)
619 self.identical(fromHex('-0X9p-1076'), -2*TINY)
620 self.identical(fromHex('-0Xap-1076'), -2*TINY)
621 self.identical(fromHex('-0xbp-1076'), -3*TINY)
622 self.identical(fromHex('-0xcp-1076'), -3*TINY)
623 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
624 self.identical(fromHex('-0xep-1076'), -4*TINY)
625 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
626 self.identical(fromHex('-0X10p-1076'), -4*TINY)
627
628 # ... and near MIN ...
629 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
630 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
631 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
632 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
633 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
634 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
635 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
636 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
637 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
638 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
639 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
640 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
641 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
642 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
643 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
644 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
645 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
646 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
647 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
648 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
649 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
650 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
651 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
652 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
653 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
654 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
655 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
656 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
657 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
658 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
659 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
660 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
661 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
662 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
663
664 # ... and near 1.0.
665 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
666 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
667 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
668 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
669 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
670 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
671 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
672 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
673 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
674 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
675 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
676 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
677 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
678 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
679 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
680 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
681 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
682 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
683 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
684 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
685 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
686 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
687 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
688 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
689 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
690 1.0)
691 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
692 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
693 1+EPS)
694 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
695 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
696 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
697 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
698 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
699 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
700 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
701 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
702 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
703 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
704 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
705 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
706 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
707 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
708 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
709 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
710 1.0+EPS)
711 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
712 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
713 1.0+2*EPS)
714 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
715 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
716 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
717 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
718 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
719 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
720 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
721 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
722
723 def test_roundtrip(self):
724 def roundtrip(x):
725 return fromHex(toHex(x))
726
727 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
728 self.identical(x, roundtrip(x))
729 self.identical(-x, roundtrip(-x))
730
731 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
732 import random
733 for i in range(10000):
734 e = random.randrange(-1200, 1200)
735 m = random.random()
736 s = random.choice([1.0, -1.0])
737 try:
738 x = s*ldexp(m, e)
739 except OverflowError:
740 pass
741 else:
742 self.identical(x, fromHex(toHex(x)))
743
Christian Heimes53876d92008-04-19 00:31:39 +0000744
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000745def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000746 support.run_unittest(
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000747 FormatFunctionsTestCase,
748 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +0000749 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +0000750 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +0000751 ReprTestCase,
752 InfNanTest,
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000753 HexFloatTestCase,
Christian Heimesb76922a2007-12-11 01:06:40 +0000754 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000755
756if __name__ == '__main__':
757 test_main()