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