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