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