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