blob: 96024cd2252ad42bf267ae975c4377ed8097e651 [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
Mark Dickinsonbd15a062009-11-18 19:33:35 +00008import random
9import fractions
10import sys
Michael W. Hudsonba283e22005-05-27 15:23:20 +000011
Christian Heimes6f341092008-04-18 23:13:07 +000012INF = float("inf")
13NAN = float("nan")
Christian Heimes0a8143f2007-12-18 23:22:54 +000014
Mark Dickinson99d652e2009-12-30 12:12:23 +000015# decorator for skipping tests on non-IEEE 754 platforms
16requires_IEEE_754 = unittest.skipUnless(
17 float.__getformat__("double").startswith("IEEE"),
18 "test requires IEEE 754 doubles")
19
Mark Dickinson61a0d052009-04-29 21:57:15 +000020#locate file with float format test values
21test_dir = os.path.dirname(__file__) or os.curdir
22format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
23
Benjamin Peterson979395b2008-05-03 21:35:18 +000024class GeneralFloatCases(unittest.TestCase):
25
26 def test_float(self):
27 self.assertEqual(float(3.14), 3.14)
28 self.assertEqual(float(314), 314.0)
29 self.assertEqual(float(314L), 314.0)
30 self.assertEqual(float(" 3.14 "), 3.14)
31 self.assertRaises(ValueError, float, " 0x3.1 ")
32 self.assertRaises(ValueError, float, " -0x3.p-1 ")
33 self.assertRaises(ValueError, float, " +0x3.p-1 ")
34 self.assertRaises(ValueError, float, "++3.14")
35 self.assertRaises(ValueError, float, "+-3.14")
36 self.assertRaises(ValueError, float, "-+3.14")
37 self.assertRaises(ValueError, float, "--3.14")
Mark Dickinson876473b2010-02-12 21:16:38 +000038 # check that we don't accept alternate exponent markers
39 self.assertRaises(ValueError, float, "-1.7d29")
40 self.assertRaises(ValueError, float, "3D-14")
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +000041 if test_support.have_unicode:
Benjamin Peterson979395b2008-05-03 21:35:18 +000042 self.assertEqual(float(unicode(" 3.14 ")), 3.14)
43 self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
Benjamin Peterson979395b2008-05-03 21:35:18 +000044
Mark Dickinson53e9fa42009-10-27 22:09:33 +000045 # extra long strings should no longer be a problem
46 # (in 2.6, long unicode inputs to float raised ValueError)
47 float('.' + '1'*1000)
48 float(unicode('.' + '1'*1000))
49
Benjamin Peterson979395b2008-05-03 21:35:18 +000050 @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
51 def test_float_with_comma(self):
52 # set locale to something that doesn't use '.' for the decimal point
53 # float must not accept the locale specific decimal point but
54 # it still has to accept the normal python syntac
55 import locale
56 if not locale.localeconv()['decimal_point'] == ',':
57 return
58
59 self.assertEqual(float(" 3.14 "), 3.14)
60 self.assertEqual(float("+3.14 "), 3.14)
61 self.assertEqual(float("-3.14 "), -3.14)
62 self.assertEqual(float(".14 "), .14)
63 self.assertEqual(float("3. "), 3.0)
64 self.assertEqual(float("3.e3 "), 3000.0)
65 self.assertEqual(float("3.2e3 "), 3200.0)
66 self.assertEqual(float("2.5e-1 "), 0.25)
67 self.assertEqual(float("5e-1"), 0.5)
68 self.assertRaises(ValueError, float, " 3,14 ")
69 self.assertRaises(ValueError, float, " +3,14 ")
70 self.assertRaises(ValueError, float, " -3,14 ")
71 self.assertRaises(ValueError, float, " 0x3.1 ")
72 self.assertRaises(ValueError, float, " -0x3.p-1 ")
73 self.assertRaises(ValueError, float, " +0x3.p-1 ")
74 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersona853a892008-09-06 23:19:15 +000075 self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
Benjamin Peterson979395b2008-05-03 21:35:18 +000076
77 def test_floatconversion(self):
78 # Make sure that calls to __float__() work properly
79 class Foo0:
80 def __float__(self):
81 return 42.
82
83 class Foo1(object):
84 def __float__(self):
85 return 42.
86
87 class Foo2(float):
88 def __float__(self):
89 return 42.
90
91 class Foo3(float):
92 def __new__(cls, value=0.):
93 return float.__new__(cls, 2*value)
94
95 def __float__(self):
96 return self
97
98 class Foo4(float):
99 def __float__(self):
100 return 42
101
Benjamin Peterson99d36f12009-04-15 21:26:36 +0000102 # Issue 5759: __float__ not called on str subclasses (though it is on
103 # unicode subclasses).
104 class FooStr(str):
105 def __float__(self):
106 return float(str(self)) + 1
107
108 class FooUnicode(unicode):
109 def __float__(self):
110 return float(unicode(self)) + 1
111
Benjamin Peterson979395b2008-05-03 21:35:18 +0000112 self.assertAlmostEqual(float(Foo0()), 42.)
113 self.assertAlmostEqual(float(Foo1()), 42.)
114 self.assertAlmostEqual(float(Foo2()), 42.)
115 self.assertAlmostEqual(float(Foo3(21)), 42.)
116 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson99d36f12009-04-15 21:26:36 +0000117 self.assertAlmostEqual(float(FooUnicode('8')), 9.)
118 self.assertAlmostEqual(float(FooStr('8')), 9.)
Benjamin Peterson979395b2008-05-03 21:35:18 +0000119
120 def test_floatasratio(self):
121 for f, ratio in [
122 (0.875, (7, 8)),
123 (-0.875, (-7, 8)),
124 (0.0, (0, 1)),
125 (11.5, (23, 2)),
126 ]:
127 self.assertEqual(f.as_integer_ratio(), ratio)
128
129 for i in range(10000):
130 f = random.random()
131 f *= 10 ** random.randint(-100, 100)
132 n, d = f.as_integer_ratio()
133 self.assertEqual(float(n).__truediv__(d), f)
134
135 R = fractions.Fraction
136 self.assertEqual(R(0, 1),
137 R(*float(0.0).as_integer_ratio()))
138 self.assertEqual(R(5, 2),
139 R(*float(2.5).as_integer_ratio()))
140 self.assertEqual(R(1, 2),
141 R(*float(0.5).as_integer_ratio()))
142 self.assertEqual(R(4728779608739021, 2251799813685248),
143 R(*float(2.1).as_integer_ratio()))
144 self.assertEqual(R(-4728779608739021, 2251799813685248),
145 R(*float(-2.1).as_integer_ratio()))
146 self.assertEqual(R(-2100, 1),
147 R(*float(-2100.0).as_integer_ratio()))
148
149 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
150 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
151 self.assertRaises(ValueError, float('nan').as_integer_ratio)
152
Mark Dickinson99d652e2009-12-30 12:12:23 +0000153 def assertEqualAndEqualSign(self, a, b):
154 # fail unless a == b and a and b have the same sign bit;
155 # the only difference from assertEqual is that this test
156 # distingishes -0.0 and 0.0.
157 self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b)))
158
159 @requires_IEEE_754
160 def test_float_pow(self):
161 # test builtin pow and ** operator for IEEE 754 special cases.
162 # Special cases taken from section F.9.4.4 of the C99 specification
163
164 for pow_op in pow, operator.pow:
165 # x**NAN is NAN for any x except 1
166 self.assertTrue(isnan(pow_op(-INF, NAN)))
167 self.assertTrue(isnan(pow_op(-2.0, NAN)))
168 self.assertTrue(isnan(pow_op(-1.0, NAN)))
169 self.assertTrue(isnan(pow_op(-0.5, NAN)))
170 self.assertTrue(isnan(pow_op(-0.0, NAN)))
171 self.assertTrue(isnan(pow_op(0.0, NAN)))
172 self.assertTrue(isnan(pow_op(0.5, NAN)))
173 self.assertTrue(isnan(pow_op(2.0, NAN)))
174 self.assertTrue(isnan(pow_op(INF, NAN)))
175 self.assertTrue(isnan(pow_op(NAN, NAN)))
176
177 # NAN**y is NAN for any y except +-0
178 self.assertTrue(isnan(pow_op(NAN, -INF)))
179 self.assertTrue(isnan(pow_op(NAN, -2.0)))
180 self.assertTrue(isnan(pow_op(NAN, -1.0)))
181 self.assertTrue(isnan(pow_op(NAN, -0.5)))
182 self.assertTrue(isnan(pow_op(NAN, 0.5)))
183 self.assertTrue(isnan(pow_op(NAN, 1.0)))
184 self.assertTrue(isnan(pow_op(NAN, 2.0)))
185 self.assertTrue(isnan(pow_op(NAN, INF)))
186
187 # (+-0)**y raises ZeroDivisionError for y a negative odd integer
188 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0)
189 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0)
190
191 # (+-0)**y raises ZeroDivisionError for y finite and negative
192 # but not an odd integer
193 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0)
194 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5)
195 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0)
196 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5)
197
198 # (+-0)**y is +-0 for y a positive odd integer
199 self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0)
200 self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0)
201
202 # (+-0)**y is 0 for y finite and positive but not an odd integer
203 self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0)
204 self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0)
205 self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0)
206 self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0)
207
208 # (-1)**+-inf is 1
209 self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0)
210 self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0)
211
212 # 1**y is 1 for any y, even if y is an infinity or nan
213 self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0)
214 self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0)
215 self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0)
216 self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0)
217 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
218 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
219 self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0)
220 self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0)
221 self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0)
222 self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0)
223 self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0)
224
225 # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan
226 self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0)
227 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
228 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
229 self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0)
230 self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0)
231 self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0)
232 self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0)
233 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
234 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
235 self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0)
236 self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0)
237 self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0)
238 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
239 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
240 self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0)
241 self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0)
242 self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0)
243 self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0)
244 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
245 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
246 self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0)
247 self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0)
248
249 # x**y raises ValueError for finite negative x and non-integral y
250 self.assertRaises(ValueError, pow_op, -2.0, -0.5)
251 self.assertRaises(ValueError, pow_op, -2.0, 0.5)
252 self.assertRaises(ValueError, pow_op, -1.0, -0.5)
253 self.assertRaises(ValueError, pow_op, -1.0, 0.5)
254 self.assertRaises(ValueError, pow_op, -0.5, -0.5)
255 self.assertRaises(ValueError, pow_op, -0.5, 0.5)
256
257 # x**-INF is INF for abs(x) < 1
258 self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF)
259 self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF)
260 self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF)
261 self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF)
262
263 # x**-INF is 0 for abs(x) > 1
264 self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0)
265 self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0)
266 self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0)
267 self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0)
268
269 # x**INF is 0 for abs(x) < 1
270 self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0)
271 self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0)
272 self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0)
273 self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0)
274
275 # x**INF is INF for abs(x) > 1
276 self.assertEqualAndEqualSign(pow_op(-INF, INF), INF)
277 self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF)
278 self.assertEqualAndEqualSign(pow_op(2.0, INF), INF)
279 self.assertEqualAndEqualSign(pow_op(INF, INF), INF)
280
281 # (-INF)**y is -0.0 for y a negative odd integer
282 self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0)
283
284 # (-INF)**y is 0.0 for y negative but not an odd integer
285 self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0)
286 self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0)
287
288 # (-INF)**y is -INF for y a positive odd integer
289 self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF)
290
291 # (-INF)**y is INF for y positive but not an odd integer
292 self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF)
293 self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF)
294
295 # INF**y is INF for y positive
296 self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF)
297 self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF)
298 self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF)
299
300 # INF**y is 0.0 for y negative
301 self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0)
302 self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0)
303 self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0)
304
305 # basic checks not covered by the special cases above
306 self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25)
307 self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5)
308 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
309 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
310 self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0)
311 self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0)
312 self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0)
313 self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0)
314 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
315 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
316 self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0)
317 self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0)
318 self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25)
319 self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5)
320 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
321 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
322 self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0)
323 self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0)
324
325 # 1 ** large and -1 ** large; some libms apparently
326 # have problems with these
327 self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0)
328 self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0)
329 self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0)
330 self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0)
331
332 # check sign for results that underflow to 0
333 self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0)
334 self.assertRaises(ValueError, pow_op, -2.0, -2000.5)
335 self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0)
336 self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0)
337 self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0)
338 self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0)
339 self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0)
340 self.assertRaises(ValueError, pow_op, -0.5, 2000.5)
341 self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0)
342 self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0)
343 self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0)
344 self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0)
345
346 # check we don't raise an exception for subnormal results,
347 # and validate signs. Tests currently disabled, since
348 # they fail on systems where a subnormal result from pow
349 # is flushed to zero (e.g. Debian/ia64.)
350 #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315)
351 #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315)
352 #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315)
353 #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315)
354 #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315)
355 #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315)
356 #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
357 #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
358
359
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000360class FormatFunctionsTestCase(unittest.TestCase):
361
362 def setUp(self):
363 self.save_formats = {'double':float.__getformat__('double'),
364 'float':float.__getformat__('float')}
365
366 def tearDown(self):
367 float.__setformat__('double', self.save_formats['double'])
368 float.__setformat__('float', self.save_formats['float'])
369
370 def test_getformat(self):
Ezio Melottiaa980582010-01-23 23:04:36 +0000371 self.assertIn(float.__getformat__('double'),
372 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
373 self.assertIn(float.__getformat__('float'),
374 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000375 self.assertRaises(ValueError, float.__getformat__, 'chicken')
376 self.assertRaises(TypeError, float.__getformat__, 1)
377
378 def test_setformat(self):
379 for t in 'double', 'float':
380 float.__setformat__(t, 'unknown')
381 if self.save_formats[t] == 'IEEE, big-endian':
382 self.assertRaises(ValueError, float.__setformat__,
383 t, 'IEEE, little-endian')
384 elif self.save_formats[t] == 'IEEE, little-endian':
385 self.assertRaises(ValueError, float.__setformat__,
386 t, 'IEEE, big-endian')
387 else:
388 self.assertRaises(ValueError, float.__setformat__,
389 t, 'IEEE, big-endian')
390 self.assertRaises(ValueError, float.__setformat__,
391 t, 'IEEE, little-endian')
392 self.assertRaises(ValueError, float.__setformat__,
393 t, 'chicken')
394 self.assertRaises(ValueError, float.__setformat__,
395 'chicken', 'unknown')
396
397BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
398LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
399BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
400LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
401
402BE_FLOAT_INF = '\x7f\x80\x00\x00'
403LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
404BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
405LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
406
407# on non-IEEE platforms, attempting to unpack a bit pattern
408# representing an infinity or a NaN should raise an exception.
409
410class UnknownFormatTestCase(unittest.TestCase):
411 def setUp(self):
412 self.save_formats = {'double':float.__getformat__('double'),
413 'float':float.__getformat__('float')}
414 float.__setformat__('double', 'unknown')
415 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000416
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000417 def tearDown(self):
418 float.__setformat__('double', self.save_formats['double'])
419 float.__setformat__('float', self.save_formats['float'])
420
421 def test_double_specials_dont_unpack(self):
422 for fmt, data in [('>d', BE_DOUBLE_INF),
423 ('>d', BE_DOUBLE_NAN),
424 ('<d', LE_DOUBLE_INF),
425 ('<d', LE_DOUBLE_NAN)]:
426 self.assertRaises(ValueError, struct.unpack, fmt, data)
427
428 def test_float_specials_dont_unpack(self):
429 for fmt, data in [('>f', BE_FLOAT_INF),
430 ('>f', BE_FLOAT_NAN),
431 ('<f', LE_FLOAT_INF),
432 ('<f', LE_FLOAT_NAN)]:
433 self.assertRaises(ValueError, struct.unpack, fmt, data)
434
435
436# on an IEEE platform, all we guarantee is that bit patterns
437# representing infinities or NaNs do not raise an exception; all else
438# is accident (today).
Alex Martellid8672aa2007-08-22 21:14:17 +0000439# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000440
441class IEEEFormatTestCase(unittest.TestCase):
442 if float.__getformat__("double").startswith("IEEE"):
443 def test_double_specials_do_unpack(self):
444 for fmt, data in [('>d', BE_DOUBLE_INF),
445 ('>d', BE_DOUBLE_NAN),
446 ('<d', LE_DOUBLE_INF),
447 ('<d', LE_DOUBLE_NAN)]:
448 struct.unpack(fmt, data)
449
450 if float.__getformat__("float").startswith("IEEE"):
451 def test_float_specials_do_unpack(self):
452 for fmt, data in [('>f', BE_FLOAT_INF),
453 ('>f', BE_FLOAT_NAN),
454 ('<f', LE_FLOAT_INF),
455 ('<f', LE_FLOAT_NAN)]:
456 struct.unpack(fmt, data)
457
Alex Martellid8672aa2007-08-22 21:14:17 +0000458 if float.__getformat__("double").startswith("IEEE"):
459 def test_negative_zero(self):
Alex Martellid8672aa2007-08-22 21:14:17 +0000460 def pos_pos():
461 return 0.0, math.atan2(0.0, -1)
462 def pos_neg():
463 return 0.0, math.atan2(-0.0, -1)
464 def neg_pos():
465 return -0.0, math.atan2(0.0, -1)
466 def neg_neg():
467 return -0.0, math.atan2(-0.0, -1)
468 self.assertEquals(pos_pos(), neg_pos())
469 self.assertEquals(pos_neg(), neg_neg())
470
Guido van Rossum3b835492008-01-05 00:59:59 +0000471 if float.__getformat__("double").startswith("IEEE"):
472 def test_underflow_sign(self):
Guido van Rossum3b835492008-01-05 00:59:59 +0000473 # check that -1e-1000 gives -0.0, not 0.0
474 self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
475 self.assertEquals(math.atan2(float('-1e-1000'), -1),
476 math.atan2(-0.0, -1))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000477
Eric Smitha985a3a2009-05-05 18:26:08 +0000478 def test_format(self):
479 # these should be rewritten to use both format(x, spec) and
480 # x.__format__(spec)
481
482 self.assertEqual(format(0.0, 'f'), '0.000000')
483
484 # the default is 'g', except for empty format spec
485 self.assertEqual(format(0.0, ''), '0.0')
486 self.assertEqual(format(0.01, ''), '0.01')
487 self.assertEqual(format(0.01, 'g'), '0.01')
488
489 # empty presentation type should format in the same way as str
490 # (issue 5920)
491 x = 100/7.
492 self.assertEqual(format(x, ''), str(x))
493 self.assertEqual(format(x, '-'), str(x))
494 self.assertEqual(format(x, '>'), str(x))
495 self.assertEqual(format(x, '2'), str(x))
496
497 self.assertEqual(format(1.0, 'f'), '1.000000')
498
499 self.assertEqual(format(-1.0, 'f'), '-1.000000')
500
501 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
502 self.assertEqual(format(-1.0, ' f'), '-1.000000')
503 self.assertEqual(format( 1.0, '+f'), '+1.000000')
504 self.assertEqual(format(-1.0, '+f'), '-1.000000')
505
506 # % formatting
507 self.assertEqual(format(-1.0, '%'), '-100.000000%')
508
509 # conversion to string should fail
510 self.assertRaises(ValueError, format, 3.0, "s")
511
512 # other format specifiers shouldn't work on floats,
513 # in particular int specifiers
514 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
515 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
516 if not format_spec in 'eEfFgGn%':
517 self.assertRaises(ValueError, format, 0.0, format_spec)
518 self.assertRaises(ValueError, format, 1.0, format_spec)
519 self.assertRaises(ValueError, format, -1.0, format_spec)
520 self.assertRaises(ValueError, format, 1e100, format_spec)
521 self.assertRaises(ValueError, format, -1e100, format_spec)
522 self.assertRaises(ValueError, format, 1e-100, format_spec)
523 self.assertRaises(ValueError, format, -1e-100, format_spec)
524
Eric Smithc4ab8332009-11-29 17:40:57 +0000525 # issue 3382: 'f' and 'F' with inf's and nan's
526 self.assertEqual('{0:f}'.format(INF), 'inf')
527 self.assertEqual('{0:F}'.format(INF), 'INF')
528 self.assertEqual('{0:f}'.format(-INF), '-inf')
529 self.assertEqual('{0:F}'.format(-INF), '-INF')
530 self.assertEqual('{0:f}'.format(NAN), 'nan')
531 self.assertEqual('{0:F}'.format(NAN), 'NAN')
532
Mark Dickinson61a0d052009-04-29 21:57:15 +0000533 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
534 "test requires IEEE 754 doubles")
535 def test_format_testfile(self):
536 for line in open(format_testfile):
537 if line.startswith('--'):
538 continue
539 line = line.strip()
540 if not line:
541 continue
542
543 lhs, rhs = map(str.strip, line.split('->'))
544 fmt, arg = lhs.split()
Eric Smithc4ab8332009-11-29 17:40:57 +0000545 arg = float(arg)
546 self.assertEqual(fmt % arg, rhs)
547 if not math.isnan(arg) and copysign(1.0, arg) > 0.0:
548 self.assertEqual(fmt % -arg, '-' + rhs)
Mark Dickinson61a0d052009-04-29 21:57:15 +0000549
Mark Dickinson92fcc9c2009-04-29 20:41:00 +0000550 def test_issue5864(self):
551 self.assertEquals(format(123.456, '.4'), '123.5')
552 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
553 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
554
Christian Heimes284d9272007-12-10 22:28:56 +0000555class ReprTestCase(unittest.TestCase):
556 def test_repr(self):
557 floats_file = open(os.path.join(os.path.split(__file__)[0],
558 'floating_points.txt'))
559 for line in floats_file:
560 line = line.strip()
561 if not line or line.startswith('#'):
562 continue
563 v = eval(line)
564 self.assertEqual(v, eval(repr(v)))
565 floats_file.close()
566
Mark Dickinson3194d142010-01-08 16:53:56 +0000567 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
568 "applies only when using short float repr style")
569 def test_short_repr(self):
570 # test short float repr introduced in Python 3.1. One aspect
571 # of this repr is that we get some degree of str -> float ->
572 # str roundtripping. In particular, for any numeric string
573 # containing 15 or fewer significant digits, those exact same
574 # digits (modulo trailing zeros) should appear in the output.
575 # No more repr(0.03) -> "0.029999999999999999"!
576
577 test_strings = [
578 # output always includes *either* a decimal point and at
579 # least one digit after that point, or an exponent.
580 '0.0',
581 '1.0',
582 '0.01',
583 '0.02',
584 '0.03',
585 '0.04',
586 '0.05',
587 '1.23456789',
588 '10.0',
589 '100.0',
590 # values >= 1e16 get an exponent...
591 '1000000000000000.0',
592 '9999999999999990.0',
593 '1e+16',
594 '1e+17',
595 # ... and so do values < 1e-4
596 '0.001',
597 '0.001001',
598 '0.00010000000000001',
599 '0.0001',
600 '9.999999999999e-05',
601 '1e-05',
602 # values designed to provoke failure if the FPU rounding
603 # precision isn't set correctly
604 '8.72293771110361e+25',
605 '7.47005307342313e+26',
606 '2.86438000439698e+28',
607 '8.89142905246179e+28',
608 '3.08578087079232e+35',
609 ]
610
611 for s in test_strings:
612 negs = '-'+s
613 self.assertEqual(s, repr(float(s)))
614 self.assertEqual(negs, repr(float(negs)))
615
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000616@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
617 "test requires IEEE 754 doubles")
618class RoundTestCase(unittest.TestCase):
619 def test_second_argument_type(self):
620 # any type with an __index__ method should be permitted as
621 # a second argument
622 self.assertAlmostEqual(round(12.34, True), 12.3)
623
624 class MyIndex(object):
625 def __index__(self): return 4
626 self.assertAlmostEqual(round(-0.123456, MyIndex()), -0.1235)
627 # but floats should be illegal
628 self.assertRaises(TypeError, round, 3.14159, 2.0)
629
630 def test_inf_nan(self):
631 # rounding an infinity or nan returns the same number;
632 # (in py3k, rounding an infinity or nan raises an error,
633 # since the result can't be represented as a long).
634 self.assertEqual(round(INF), INF)
635 self.assertEqual(round(-INF), -INF)
636 self.assertTrue(math.isnan(round(NAN)))
637 for n in range(-5, 5):
638 self.assertEqual(round(INF, n), INF)
639 self.assertEqual(round(-INF, n), -INF)
640 self.assertTrue(math.isnan(round(NAN, n)))
641
Mark Dickinsonbce78372009-11-24 10:54:58 +0000642 self.assertRaises(TypeError, round, INF, 0.0)
643 self.assertRaises(TypeError, round, -INF, 1.0)
644 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
645 self.assertRaises(TypeError, round, -0.0, 1j)
646
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000647 def test_large_n(self):
648 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
649 self.assertEqual(round(123.456, n), 123.456)
650 self.assertEqual(round(-123.456, n), -123.456)
651 self.assertEqual(round(1e300, n), 1e300)
652 self.assertEqual(round(1e-320, n), 1e-320)
653 self.assertEqual(round(1e150, 300), 1e150)
654 self.assertEqual(round(1e300, 307), 1e300)
655 self.assertEqual(round(-3.1415, 308), -3.1415)
656 self.assertEqual(round(1e150, 309), 1e150)
657 self.assertEqual(round(1.4e-315, 315), 1e-315)
658
659 def test_small_n(self):
660 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
661 self.assertEqual(round(123.456, n), 0.0)
662 self.assertEqual(round(-123.456, n), -0.0)
663 self.assertEqual(round(1e300, n), 0.0)
664 self.assertEqual(round(1e-320, n), 0.0)
665
666 def test_overflow(self):
667 self.assertRaises(OverflowError, round, 1.6e308, -308)
668 self.assertRaises(OverflowError, round, -1.7e308, -308)
669
670 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
671 "test applies only when using short float repr style")
672 def test_previous_round_bugs(self):
673 # particular cases that have occurred in bug reports
674 self.assertEqual(round(562949953421312.5, 1),
675 562949953421312.5)
676 self.assertEqual(round(56294995342131.5, 3),
677 56294995342131.5)
678
679 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
680 "test applies only when using short float repr style")
681 def test_halfway_cases(self):
682 # Halfway cases need special attention, since the current
683 # implementation has to deal with them specially. Note that
684 # 2.x rounds halfway values up (i.e., away from zero) while
685 # 3.x does round-half-to-even.
686 self.assertAlmostEqual(round(0.125, 2), 0.13)
687 self.assertAlmostEqual(round(0.375, 2), 0.38)
688 self.assertAlmostEqual(round(0.625, 2), 0.63)
689 self.assertAlmostEqual(round(0.875, 2), 0.88)
690 self.assertAlmostEqual(round(-0.125, 2), -0.13)
691 self.assertAlmostEqual(round(-0.375, 2), -0.38)
692 self.assertAlmostEqual(round(-0.625, 2), -0.63)
693 self.assertAlmostEqual(round(-0.875, 2), -0.88)
694
695 self.assertAlmostEqual(round(0.25, 1), 0.3)
696 self.assertAlmostEqual(round(0.75, 1), 0.8)
697 self.assertAlmostEqual(round(-0.25, 1), -0.3)
698 self.assertAlmostEqual(round(-0.75, 1), -0.8)
699
700 self.assertEqual(round(-6.5, 0), -7.0)
701 self.assertEqual(round(-5.5, 0), -6.0)
702 self.assertEqual(round(-1.5, 0), -2.0)
703 self.assertEqual(round(-0.5, 0), -1.0)
704 self.assertEqual(round(0.5, 0), 1.0)
705 self.assertEqual(round(1.5, 0), 2.0)
706 self.assertEqual(round(2.5, 0), 3.0)
707 self.assertEqual(round(3.5, 0), 4.0)
708 self.assertEqual(round(4.5, 0), 5.0)
709 self.assertEqual(round(5.5, 0), 6.0)
710 self.assertEqual(round(6.5, 0), 7.0)
711
712 # same but without an explicit second argument; in 3.x these
713 # will give integers
714 self.assertEqual(round(-6.5), -7.0)
715 self.assertEqual(round(-5.5), -6.0)
716 self.assertEqual(round(-1.5), -2.0)
717 self.assertEqual(round(-0.5), -1.0)
718 self.assertEqual(round(0.5), 1.0)
719 self.assertEqual(round(1.5), 2.0)
720 self.assertEqual(round(2.5), 3.0)
721 self.assertEqual(round(3.5), 4.0)
722 self.assertEqual(round(4.5), 5.0)
723 self.assertEqual(round(5.5), 6.0)
724 self.assertEqual(round(6.5), 7.0)
725
726 self.assertEqual(round(-25.0, -1), -30.0)
727 self.assertEqual(round(-15.0, -1), -20.0)
728 self.assertEqual(round(-5.0, -1), -10.0)
729 self.assertEqual(round(5.0, -1), 10.0)
730 self.assertEqual(round(15.0, -1), 20.0)
731 self.assertEqual(round(25.0, -1), 30.0)
732 self.assertEqual(round(35.0, -1), 40.0)
733 self.assertEqual(round(45.0, -1), 50.0)
734 self.assertEqual(round(55.0, -1), 60.0)
735 self.assertEqual(round(65.0, -1), 70.0)
736 self.assertEqual(round(75.0, -1), 80.0)
737 self.assertEqual(round(85.0, -1), 90.0)
738 self.assertEqual(round(95.0, -1), 100.0)
739 self.assertEqual(round(12325.0, -1), 12330.0)
740
741 self.assertEqual(round(350.0, -2), 400.0)
742 self.assertEqual(round(450.0, -2), 500.0)
743
744 self.assertAlmostEqual(round(0.5e21, -21), 1e21)
745 self.assertAlmostEqual(round(1.5e21, -21), 2e21)
746 self.assertAlmostEqual(round(2.5e21, -21), 3e21)
747 self.assertAlmostEqual(round(5.5e21, -21), 6e21)
748 self.assertAlmostEqual(round(8.5e21, -21), 9e21)
749
750 self.assertAlmostEqual(round(-1.5e22, -22), -2e22)
751 self.assertAlmostEqual(round(-0.5e22, -22), -1e22)
752 self.assertAlmostEqual(round(0.5e22, -22), 1e22)
753 self.assertAlmostEqual(round(1.5e22, -22), 2e22)
754
Eric Smithf2bf0d22009-12-02 17:43:06 +0000755 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
756 "test requires IEEE 754 doubles")
757 def test_format_specials(self):
758 # Test formatting of nans and infs.
759
760 def test(fmt, value, expected):
761 # Test with both % and format().
762 self.assertEqual(fmt % value, expected, fmt)
763 if not '#' in fmt:
764 # Until issue 7094 is implemented, format() for floats doesn't
765 # support '#' formatting
766 fmt = fmt[1:] # strip off the %
767 self.assertEqual(format(value, fmt), expected, fmt)
768
769 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
770 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
771 pfmt = '%+' + fmt[1:]
772 sfmt = '% ' + fmt[1:]
773 test(fmt, INF, 'inf')
774 test(fmt, -INF, '-inf')
775 test(fmt, NAN, 'nan')
776 test(fmt, -NAN, 'nan')
777 # When asking for a sign, it's always provided. nans are
778 # always positive.
779 test(pfmt, INF, '+inf')
780 test(pfmt, -INF, '-inf')
781 test(pfmt, NAN, '+nan')
782 test(pfmt, -NAN, '+nan')
783 # When using ' ' for a sign code, only infs can be negative.
784 # Others have a space.
785 test(sfmt, INF, ' inf')
786 test(sfmt, -INF, '-inf')
787 test(sfmt, NAN, ' nan')
788 test(sfmt, -NAN, ' nan')
789
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000790
Christian Heimes0a8143f2007-12-18 23:22:54 +0000791# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000792# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000793class InfNanTest(unittest.TestCase):
794 def test_inf_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000795 self.assertTrue(isinf(float("inf")))
796 self.assertTrue(isinf(float("+inf")))
797 self.assertTrue(isinf(float("-inf")))
798 self.assertTrue(isinf(float("infinity")))
799 self.assertTrue(isinf(float("+infinity")))
800 self.assertTrue(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000801
802 self.assertEqual(repr(float("inf")), "inf")
803 self.assertEqual(repr(float("+inf")), "inf")
804 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000805 self.assertEqual(repr(float("infinity")), "inf")
806 self.assertEqual(repr(float("+infinity")), "inf")
807 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000808
809 self.assertEqual(repr(float("INF")), "inf")
810 self.assertEqual(repr(float("+Inf")), "inf")
811 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000812 self.assertEqual(repr(float("Infinity")), "inf")
813 self.assertEqual(repr(float("+iNfInItY")), "inf")
814 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000815
816 self.assertEqual(str(float("inf")), "inf")
817 self.assertEqual(str(float("+inf")), "inf")
818 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000819 self.assertEqual(str(float("infinity")), "inf")
820 self.assertEqual(str(float("+infinity")), "inf")
821 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000822
823 self.assertRaises(ValueError, float, "info")
824 self.assertRaises(ValueError, float, "+info")
825 self.assertRaises(ValueError, float, "-info")
826 self.assertRaises(ValueError, float, "in")
827 self.assertRaises(ValueError, float, "+in")
828 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000829 self.assertRaises(ValueError, float, "infinit")
830 self.assertRaises(ValueError, float, "+Infin")
831 self.assertRaises(ValueError, float, "-INFI")
832 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000833
834 def test_inf_as_str(self):
835 self.assertEqual(repr(1e300 * 1e300), "inf")
836 self.assertEqual(repr(-1e300 * 1e300), "-inf")
837
838 self.assertEqual(str(1e300 * 1e300), "inf")
839 self.assertEqual(str(-1e300 * 1e300), "-inf")
840
841 def test_nan_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000842 self.assertTrue(isnan(float("nan")))
843 self.assertTrue(isnan(float("+nan")))
844 self.assertTrue(isnan(float("-nan")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000845
846 self.assertEqual(repr(float("nan")), "nan")
847 self.assertEqual(repr(float("+nan")), "nan")
848 self.assertEqual(repr(float("-nan")), "nan")
849
850 self.assertEqual(repr(float("NAN")), "nan")
851 self.assertEqual(repr(float("+NAn")), "nan")
852 self.assertEqual(repr(float("-NaN")), "nan")
853
854 self.assertEqual(str(float("nan")), "nan")
855 self.assertEqual(str(float("+nan")), "nan")
856 self.assertEqual(str(float("-nan")), "nan")
857
858 self.assertRaises(ValueError, float, "nana")
859 self.assertRaises(ValueError, float, "+nana")
860 self.assertRaises(ValueError, float, "-nana")
861 self.assertRaises(ValueError, float, "na")
862 self.assertRaises(ValueError, float, "+na")
863 self.assertRaises(ValueError, float, "-na")
864
865 def test_nan_as_str(self):
866 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
867 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
868
869 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
870 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000871
Christian Heimes6f341092008-04-18 23:13:07 +0000872 def notest_float_nan(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000873 self.assertTrue(NAN.is_nan())
874 self.assertFalse(INF.is_nan())
875 self.assertFalse((0.).is_nan())
Christian Heimes6f341092008-04-18 23:13:07 +0000876
877 def notest_float_inf(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000878 self.assertTrue(INF.is_inf())
879 self.assertFalse(NAN.is_inf())
880 self.assertFalse((0.).is_inf())
Christian Heimes6f341092008-04-18 23:13:07 +0000881
Mark Dickinson5e0c2742010-04-05 18:07:51 +0000882 def test_hash_inf(self):
883 # the actual values here should be regarded as an
884 # implementation detail, but they need to be
885 # identical to those used in the Decimal module.
886 self.assertEqual(hash(float('inf')), 314159)
887 self.assertEqual(hash(float('-inf')), -271828)
888 self.assertEqual(hash(float('nan')), 0)
889
890
Mark Dickinson7103aa42008-07-15 19:08:33 +0000891fromHex = float.fromhex
892toHex = float.hex
893class HexFloatTestCase(unittest.TestCase):
894 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
895 MIN = fromHex('0x1p-1022') # min normal
896 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
897 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
898
899 def identical(self, x, y):
900 # check that floats x and y are identical, or that both
901 # are NaNs
902 if isnan(x) or isnan(y):
903 if isnan(x) == isnan(y):
904 return
905 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
906 return
907 self.fail('%r not identical to %r' % (x, y))
908
909 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000910 self.identical(self.MIN, ldexp(1.0, -1022))
911 self.identical(self.TINY, ldexp(1.0, -1074))
912 self.identical(self.EPS, ldexp(1.0, -52))
913 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000914
915 def test_invalid_inputs(self):
916 invalid_inputs = [
917 'infi', # misspelt infinities and nans
918 '-Infinit',
919 '++inf',
920 '-+Inf',
921 '--nan',
922 '+-NaN',
923 'snan',
924 'NaNs',
925 'nna',
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000926 'an',
927 'nf',
928 'nfinity',
929 'inity',
930 'iinity',
Mark Dickinson7103aa42008-07-15 19:08:33 +0000931 '0xnan',
932 '',
933 ' ',
934 'x1.0p0',
935 '0xX1.0p0',
936 '+ 0x1.0p0', # internal whitespace
937 '- 0x1.0p0',
938 '0 x1.0p0',
939 '0x 1.0p0',
940 '0x1 2.0p0',
941 '+0x1 .0p0',
942 '0x1. 0p0',
943 '-0x1.0 1p0',
944 '-0x1.0 p0',
945 '+0x1.0p +0',
946 '0x1.0p -0',
947 '0x1.0p 0',
948 '+0x1.0p+ 0',
949 '-0x1.0p- 0',
950 '++0x1.0p-0', # double signs
951 '--0x1.0p0',
952 '+-0x1.0p+0',
953 '-+0x1.0p0',
954 '0x1.0p++0',
955 '+0x1.0p+-0',
956 '-0x1.0p-+0',
957 '0x1.0p--0',
958 '0x1.0.p0',
959 '0x.p0', # no hex digits before or after point
960 '0x1,p0', # wrong decimal point character
961 '0x1pa',
962 u'0x1p\uff10', # fullwidth Unicode digits
963 u'\uff10x1p0',
964 u'0x\uff11p0',
965 u'0x1.\uff10p0',
966 '0x1p0 \n 0x2p0',
967 '0x1p0\0 0x1p0', # embedded null byte is not end of string
968 ]
969 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000970 try:
971 result = fromHex(x)
972 except ValueError:
973 pass
974 else:
975 self.fail('Expected float.fromhex(%r) to raise ValueError; '
976 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000977
978
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000979 def test_whitespace(self):
980 value_pairs = [
981 ('inf', INF),
982 ('-Infinity', -INF),
983 ('nan', NAN),
984 ('1.0', 1.0),
985 ('-0x.2', -0.125),
986 ('-0.0', -0.0)
987 ]
988 whitespace = [
989 '',
990 ' ',
991 '\t',
992 '\n',
993 '\n \t',
994 '\f',
995 '\v',
996 '\r'
997 ]
998 for inp, expected in value_pairs:
999 for lead in whitespace:
1000 for trail in whitespace:
1001 got = fromHex(lead + inp + trail)
1002 self.identical(got, expected)
1003
1004
Mark Dickinson7103aa42008-07-15 19:08:33 +00001005 def test_from_hex(self):
1006 MIN = self.MIN;
1007 MAX = self.MAX;
1008 TINY = self.TINY;
1009 EPS = self.EPS;
1010
1011 # two spellings of infinity, with optional signs; case-insensitive
1012 self.identical(fromHex('inf'), INF)
1013 self.identical(fromHex('+Inf'), INF)
1014 self.identical(fromHex('-INF'), -INF)
1015 self.identical(fromHex('iNf'), INF)
1016 self.identical(fromHex('Infinity'), INF)
1017 self.identical(fromHex('+INFINITY'), INF)
1018 self.identical(fromHex('-infinity'), -INF)
1019 self.identical(fromHex('-iNFiNitY'), -INF)
1020
1021 # nans with optional sign; case insensitive
1022 self.identical(fromHex('nan'), NAN)
1023 self.identical(fromHex('+NaN'), NAN)
1024 self.identical(fromHex('-NaN'), NAN)
1025 self.identical(fromHex('-nAN'), NAN)
1026
1027 # variations in input format
1028 self.identical(fromHex('1'), 1.0)
1029 self.identical(fromHex('+1'), 1.0)
1030 self.identical(fromHex('1.'), 1.0)
1031 self.identical(fromHex('1.0'), 1.0)
1032 self.identical(fromHex('1.0p0'), 1.0)
1033 self.identical(fromHex('01'), 1.0)
1034 self.identical(fromHex('01.'), 1.0)
1035 self.identical(fromHex('0x1'), 1.0)
1036 self.identical(fromHex('0x1.'), 1.0)
1037 self.identical(fromHex('0x1.0'), 1.0)
1038 self.identical(fromHex('+0x1.0'), 1.0)
1039 self.identical(fromHex('0x1p0'), 1.0)
1040 self.identical(fromHex('0X1p0'), 1.0)
1041 self.identical(fromHex('0X1P0'), 1.0)
1042 self.identical(fromHex('0x1P0'), 1.0)
1043 self.identical(fromHex('0x1.p0'), 1.0)
1044 self.identical(fromHex('0x1.0p0'), 1.0)
1045 self.identical(fromHex('0x.1p4'), 1.0)
1046 self.identical(fromHex('0x.1p04'), 1.0)
1047 self.identical(fromHex('0x.1p004'), 1.0)
1048 self.identical(fromHex('0x1p+0'), 1.0)
1049 self.identical(fromHex('0x1P-0'), 1.0)
1050 self.identical(fromHex('+0x1p0'), 1.0)
1051 self.identical(fromHex('0x01p0'), 1.0)
1052 self.identical(fromHex('0x1p00'), 1.0)
1053 self.identical(fromHex(u'0x1p0'), 1.0)
1054 self.identical(fromHex(' 0x1p0 '), 1.0)
1055 self.identical(fromHex('\n 0x1p0'), 1.0)
1056 self.identical(fromHex('0x1p0 \t'), 1.0)
1057 self.identical(fromHex('0xap0'), 10.0)
1058 self.identical(fromHex('0xAp0'), 10.0)
1059 self.identical(fromHex('0xaP0'), 10.0)
1060 self.identical(fromHex('0xAP0'), 10.0)
1061 self.identical(fromHex('0xbep0'), 190.0)
1062 self.identical(fromHex('0xBep0'), 190.0)
1063 self.identical(fromHex('0xbEp0'), 190.0)
1064 self.identical(fromHex('0XBE0P-4'), 190.0)
1065 self.identical(fromHex('0xBEp0'), 190.0)
1066 self.identical(fromHex('0xB.Ep4'), 190.0)
1067 self.identical(fromHex('0x.BEp8'), 190.0)
1068 self.identical(fromHex('0x.0BEp12'), 190.0)
1069
1070 # moving the point around
1071 pi = fromHex('0x1.921fb54442d18p1')
1072 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
1073 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
1074 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
1075 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
1076 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
1077 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
1078 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
1079 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
1080 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
1081 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
1082 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
1083 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
1084 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
1085 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
1086 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
1087 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
1088 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
1089 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
1090 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
1091 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
1092 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
1093 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
1094 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
1095 # ...
1096 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
1097 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
1098 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
1099 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
1100 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
1101 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
1102 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
1103 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
1104 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
1105
1106
1107 # results that should overflow...
1108 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
1109 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
1110 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
1111 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
1112 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
1113 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
1114 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
1115 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
1116 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
1117 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
1118 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
1119 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
1120 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
1121 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
1122 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
1123 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
1124 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
1125 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
1126 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
1127
1128 # ...and those that round to +-max float
1129 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
1130 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
1131 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
1132
1133 # zeros
1134 self.identical(fromHex('0x0p0'), 0.0)
1135 self.identical(fromHex('0x0p1000'), 0.0)
1136 self.identical(fromHex('-0x0p1023'), -0.0)
1137 self.identical(fromHex('0X0p1024'), 0.0)
1138 self.identical(fromHex('-0x0p1025'), -0.0)
1139 self.identical(fromHex('0X0p2000'), 0.0)
1140 self.identical(fromHex('0x0p123456789123456789'), 0.0)
1141 self.identical(fromHex('-0X0p-0'), -0.0)
1142 self.identical(fromHex('-0X0p-1000'), -0.0)
1143 self.identical(fromHex('0x0p-1023'), 0.0)
1144 self.identical(fromHex('-0X0p-1024'), -0.0)
1145 self.identical(fromHex('-0x0p-1025'), -0.0)
1146 self.identical(fromHex('-0x0p-1072'), -0.0)
1147 self.identical(fromHex('0X0p-1073'), 0.0)
1148 self.identical(fromHex('-0x0p-1074'), -0.0)
1149 self.identical(fromHex('0x0p-1075'), 0.0)
1150 self.identical(fromHex('0X0p-1076'), 0.0)
1151 self.identical(fromHex('-0X0p-2000'), -0.0)
1152 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
1153
1154 # values that should underflow to 0
1155 self.identical(fromHex('0X1p-1075'), 0.0)
1156 self.identical(fromHex('-0X1p-1075'), -0.0)
1157 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
1158 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
1159 self.identical(fromHex('-0x1.1p-1075'), -TINY)
1160 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
1161
1162 # check round-half-even is working correctly near 0 ...
1163 self.identical(fromHex('0x1p-1076'), 0.0)
1164 self.identical(fromHex('0X2p-1076'), 0.0)
1165 self.identical(fromHex('0X3p-1076'), TINY)
1166 self.identical(fromHex('0x4p-1076'), TINY)
1167 self.identical(fromHex('0X5p-1076'), TINY)
1168 self.identical(fromHex('0X6p-1076'), 2*TINY)
1169 self.identical(fromHex('0x7p-1076'), 2*TINY)
1170 self.identical(fromHex('0X8p-1076'), 2*TINY)
1171 self.identical(fromHex('0X9p-1076'), 2*TINY)
1172 self.identical(fromHex('0xap-1076'), 2*TINY)
1173 self.identical(fromHex('0Xbp-1076'), 3*TINY)
1174 self.identical(fromHex('0xcp-1076'), 3*TINY)
1175 self.identical(fromHex('0Xdp-1076'), 3*TINY)
1176 self.identical(fromHex('0Xep-1076'), 4*TINY)
1177 self.identical(fromHex('0xfp-1076'), 4*TINY)
1178 self.identical(fromHex('0x10p-1076'), 4*TINY)
1179 self.identical(fromHex('-0x1p-1076'), -0.0)
1180 self.identical(fromHex('-0X2p-1076'), -0.0)
1181 self.identical(fromHex('-0x3p-1076'), -TINY)
1182 self.identical(fromHex('-0X4p-1076'), -TINY)
1183 self.identical(fromHex('-0x5p-1076'), -TINY)
1184 self.identical(fromHex('-0x6p-1076'), -2*TINY)
1185 self.identical(fromHex('-0X7p-1076'), -2*TINY)
1186 self.identical(fromHex('-0X8p-1076'), -2*TINY)
1187 self.identical(fromHex('-0X9p-1076'), -2*TINY)
1188 self.identical(fromHex('-0Xap-1076'), -2*TINY)
1189 self.identical(fromHex('-0xbp-1076'), -3*TINY)
1190 self.identical(fromHex('-0xcp-1076'), -3*TINY)
1191 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
1192 self.identical(fromHex('-0xep-1076'), -4*TINY)
1193 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
1194 self.identical(fromHex('-0X10p-1076'), -4*TINY)
1195
1196 # ... and near MIN ...
1197 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
1198 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
1199 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
1200 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
1201 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
1202 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
1203 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
1204 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
1205 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
1206 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
1207 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
1208 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
1209 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
1210 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
1211 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
1212 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
1213 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
1214 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
1215 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
1216 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
1217 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
1218 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
1219 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
1220 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
1221 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
1222 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
1223 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
1224 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
1225 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
1226 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
1227 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
1228 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
1229 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
1230 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
1231
1232 # ... and near 1.0.
1233 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
1234 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
1235 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
1236 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
1237 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
1238 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
1239 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
1240 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
1241 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
1242 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
1243 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
1244 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
1245 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
1246 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
1247 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
1248 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
1249 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
1250 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
1251 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
1252 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
1253 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
1254 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
1255 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
1256 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
1257 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
1258 1.0)
1259 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
1260 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
1261 1+EPS)
1262 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
1263 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
1264 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
1265 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
1266 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
1267 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
1268 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
1269 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
1270 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
1271 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
1272 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
1273 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
1274 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
1275 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
1276 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
1277 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
1278 1.0+EPS)
1279 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
1280 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
1281 1.0+2*EPS)
1282 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
1283 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
1284 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
1285 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
1286 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
1287 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
1288 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
1289 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
1290
1291 def test_roundtrip(self):
1292 def roundtrip(x):
1293 return fromHex(toHex(x))
1294
1295 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1296 self.identical(x, roundtrip(x))
1297 self.identical(-x, roundtrip(-x))
1298
1299 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1300 import random
1301 for i in xrange(10000):
1302 e = random.randrange(-1200, 1200)
1303 m = random.random()
1304 s = random.choice([1.0, -1.0])
1305 try:
1306 x = s*ldexp(m, e)
1307 except OverflowError:
1308 pass
1309 else:
1310 self.identical(x, fromHex(toHex(x)))
1311
Christian Heimes6f341092008-04-18 23:13:07 +00001312
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001313def test_main():
1314 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +00001315 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001316 FormatFunctionsTestCase,
1317 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +00001318 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001319 ReprTestCase,
Mark Dickinsonbd15a062009-11-18 19:33:35 +00001320 RoundTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001321 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +00001322 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +00001323 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001324
1325if __name__ == '__main__':
1326 test_main()