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