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