blob: db397ce0ad34917c7a9b548b3f156230a935ead5 [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes827b35c2007-12-10 22:19:17 +00003import os
Eric Smith0923d1d2009-04-16 20:16:10 +00004import sys
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Christian Heimes53876d92008-04-19 00:31:39 +00006import math
Mark Dickinson65fe25e2008-07-16 11:30:51 +00007from math import isinf, isnan, copysign, ldexp
Christian Heimes53876d92008-04-19 00:31:39 +00008import operator
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +00009import random, fractions
Mark Dickinson81612e82010-01-12 23:04:19 +000010import re
Michael W. Hudsonba283e22005-05-27 15:23:20 +000011
Christian Heimes53876d92008-04-19 00:31:39 +000012INF = float("inf")
13NAN = float("nan")
Christian Heimes99170a52007-12-19 02:07:34 +000014
Mark Dickinson9ab44b52009-12-30 16:22:49 +000015# decorator for skipping tests on non-IEEE 754 platforms
16requires_IEEE_754 = unittest.skipUnless(
17 float.__getformat__("double").startswith("IEEE"),
18 "test requires IEEE 754 doubles")
19
Eric Smith0923d1d2009-04-16 20:16:10 +000020#locate file with float format test values
21test_dir = os.path.dirname(__file__) or os.curdir
22format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
23
Mark Dickinson81612e82010-01-12 23:04:19 +000024finite_decimal_parser = re.compile(r""" # A numeric string consists of:
25 (?P<sign>[-+])? # an optional sign, followed by
26 (?=\d|\.\d) # a number with at least one digit
27 (?P<int>\d*) # having a (possibly empty) integer part
28 (?:\.(?P<frac>\d*))? # followed by an optional fractional part
29 (?:E(?P<exp>[-+]?\d+))? # and an optional exponent
30 \Z
31""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match
32
33# Pure Python version of correctly rounded string->float conversion.
34# Avoids any use of floating-point by returning the result as a hex string.
35def strtod(s, mant_dig=53, min_exp = -1021, max_exp = 1024):
36 """Convert a finite decimal string to a hex string representing an
37 IEEE 754 binary64 float. Return 'inf' or '-inf' on overflow.
38 This function makes no use of floating-point arithmetic at any
39 stage."""
40
41 # parse string into a pair of integers 'a' and 'b' such that
42 # abs(decimal value) = a/b, and a boolean 'negative'.
43 m = finite_decimal_parser(s)
44 if m is None:
45 raise ValueError('invalid numeric string')
46 fraction = m.group('frac') or ''
47 intpart = int(m.group('int') + fraction)
48 exp = int(m.group('exp') or '0') - len(fraction)
49 negative = m.group('sign') == '-'
50 a, b = intpart*10**max(exp, 0), 10**max(0, -exp)
51
52 # quick return for zeros
53 if not a:
54 return '-0x0.0p+0' if negative else '0x0.0p+0'
55
56 # compute exponent e for result; may be one too small in the case
57 # that the rounded value of a/b lies in a different binade from a/b
58 d = a.bit_length() - b.bit_length()
59 d += (a >> d if d >= 0 else a << -d) >= b
60 e = max(d, min_exp) - mant_dig
61
62 # approximate a/b by number of the form q * 2**e; adjust e if necessary
63 a, b = a << max(-e, 0), b << max(e, 0)
64 q, r = divmod(a, b)
65 if 2*r > b or 2*r == b and q & 1:
66 q += 1
67 if q.bit_length() == mant_dig+1:
68 q //= 2
69 e += 1
70
71 # double check that (q, e) has the right form
72 assert q.bit_length() <= mant_dig and e >= min_exp - mant_dig
73 assert q.bit_length() == mant_dig or e == min_exp - mant_dig
74
75 # check for overflow and underflow
76 if e + q.bit_length() > max_exp:
77 return '-inf' if negative else 'inf'
78 if not q:
79 return '-0x0.0p+0' if negative else '0x0.0p+0'
80
81 # for hex representation, shift so # bits after point is a multiple of 4
82 hexdigs = 1 + (mant_dig-2)//4
83 shift = 3 - (mant_dig-2)%4
84 q, e = q << shift, e - shift
85 return '{}0x{:x}.{:0{}x}p{:+d}'.format(
86 '-' if negative else '',
87 q // 16**hexdigs,
88 q % 16**hexdigs,
89 hexdigs,
90 e + 4*hexdigs)
91
Christian Heimes81ee3ef2008-05-04 22:42:01 +000092class GeneralFloatCases(unittest.TestCase):
93
94 def test_float(self):
95 self.assertEqual(float(3.14), 3.14)
96 self.assertEqual(float(314), 314.0)
97 self.assertEqual(float(" 3.14 "), 3.14)
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +000098 self.assertEqual(float(b" 3.14 "), 3.14)
Christian Heimes81ee3ef2008-05-04 22:42:01 +000099 self.assertRaises(ValueError, float, " 0x3.1 ")
100 self.assertRaises(ValueError, float, " -0x3.p-1 ")
101 self.assertRaises(ValueError, float, " +0x3.p-1 ")
102 self.assertRaises(ValueError, float, "++3.14")
103 self.assertRaises(ValueError, float, "+-3.14")
104 self.assertRaises(ValueError, float, "-+3.14")
105 self.assertRaises(ValueError, float, "--3.14")
Eric Smith0923d1d2009-04-16 20:16:10 +0000106 self.assertRaises(ValueError, float, ".nan")
107 self.assertRaises(ValueError, float, "+.inf")
108 self.assertRaises(ValueError, float, ".")
109 self.assertRaises(ValueError, float, "-.")
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +0000110 self.assertEqual(float(b" \u0663.\u0661\u0664 ".decode('raw-unicode-escape')), 3.14)
Mark Dickinsona9023be2009-10-27 22:12:20 +0000111 # extra long strings should not be a problem
112 float(b'.' + b'1'*1000)
113 float('.' + '1'*1000)
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000114
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000115 @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000116 def test_float_with_comma(self):
117 # set locale to something that doesn't use '.' for the decimal point
118 # float must not accept the locale specific decimal point but
119 # it still has to accept the normal python syntac
120 import locale
121 if not locale.localeconv()['decimal_point'] == ',':
122 return
123
124 self.assertEqual(float(" 3.14 "), 3.14)
125 self.assertEqual(float("+3.14 "), 3.14)
126 self.assertEqual(float("-3.14 "), -3.14)
127 self.assertEqual(float(".14 "), .14)
128 self.assertEqual(float("3. "), 3.0)
129 self.assertEqual(float("3.e3 "), 3000.0)
130 self.assertEqual(float("3.2e3 "), 3200.0)
131 self.assertEqual(float("2.5e-1 "), 0.25)
132 self.assertEqual(float("5e-1"), 0.5)
133 self.assertRaises(ValueError, float, " 3,14 ")
134 self.assertRaises(ValueError, float, " +3,14 ")
135 self.assertRaises(ValueError, float, " -3,14 ")
136 self.assertRaises(ValueError, float, " 0x3.1 ")
137 self.assertRaises(ValueError, float, " -0x3.p-1 ")
138 self.assertRaises(ValueError, float, " +0x3.p-1 ")
139 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersond43029b2008-09-06 23:33:21 +0000140 self.assertEqual(support.fcmp(float(" .25e-1 "), .025), 0)
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000141
142 def test_floatconversion(self):
143 # Make sure that calls to __float__() work properly
144 class Foo0:
145 def __float__(self):
146 return 42.
147
148 class Foo1(object):
149 def __float__(self):
150 return 42.
151
152 class Foo2(float):
153 def __float__(self):
154 return 42.
155
156 class Foo3(float):
157 def __new__(cls, value=0.):
158 return float.__new__(cls, 2*value)
159
160 def __float__(self):
161 return self
162
163 class Foo4(float):
164 def __float__(self):
165 return 42
166
Benjamin Peterson2808d3c2009-04-15 21:34:27 +0000167 # Issue 5759: __float__ not called on str subclasses (though it is on
168 # unicode subclasses).
169 class FooStr(str):
170 def __float__(self):
171 return float(str(self)) + 1
172
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000173 self.assertAlmostEqual(float(Foo0()), 42.)
174 self.assertAlmostEqual(float(Foo1()), 42.)
175 self.assertAlmostEqual(float(Foo2()), 42.)
176 self.assertAlmostEqual(float(Foo3(21)), 42.)
177 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson2808d3c2009-04-15 21:34:27 +0000178 self.assertAlmostEqual(float(FooStr('8')), 9.)
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000179
180 def test_floatasratio(self):
181 for f, ratio in [
182 (0.875, (7, 8)),
183 (-0.875, (-7, 8)),
184 (0.0, (0, 1)),
185 (11.5, (23, 2)),
186 ]:
187 self.assertEqual(f.as_integer_ratio(), ratio)
188
189 for i in range(10000):
190 f = random.random()
191 f *= 10 ** random.randint(-100, 100)
192 n, d = f.as_integer_ratio()
193 self.assertEqual(float(n).__truediv__(d), f)
194
195 R = fractions.Fraction
196 self.assertEqual(R(0, 1),
197 R(*float(0.0).as_integer_ratio()))
198 self.assertEqual(R(5, 2),
199 R(*float(2.5).as_integer_ratio()))
200 self.assertEqual(R(1, 2),
201 R(*float(0.5).as_integer_ratio()))
202 self.assertEqual(R(4728779608739021, 2251799813685248),
203 R(*float(2.1).as_integer_ratio()))
204 self.assertEqual(R(-4728779608739021, 2251799813685248),
205 R(*float(-2.1).as_integer_ratio()))
206 self.assertEqual(R(-2100, 1),
207 R(*float(-2100.0).as_integer_ratio()))
208
209 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
210 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
211 self.assertRaises(ValueError, float('nan').as_integer_ratio)
212
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000213 def test_float_containment(self):
214 floats = (INF, -INF, 0.0, 1.0, NAN)
215 for f in floats:
Benjamin Peterson577473f2010-01-19 00:09:57 +0000216 self.assertIn(f, [f])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000217 self.assertTrue(f in [f], "'%r' not in []" % f)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000218 self.assertIn(f, (f,))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000219 self.assertTrue(f in (f,), "'%r' not in ()" % f)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000220 self.assertIn(f, {f})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000221 self.assertTrue(f in {f}, "'%r' not in set()" % f)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000222 self.assertIn(f, {f: None})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000223 self.assertTrue(f in {f: None}, "'%r' not in {}" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000224 self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000225 self.assertIn(f, floats)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000226 self.assertTrue(f in floats, "'%r' not in container" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000227
228 for f in floats:
229 # nonidentical containers, same type, same contents
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000230 self.assertTrue([f] == [f], "[%r] != [%r]" % (f, f))
231 self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f))
232 self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f))
233 self.assertTrue({f : None} == {f: None}, "{%r : None} != "
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000234 "{%r : None}" % (f, f))
235
236 # identical containers
237 l, t, s, d = [f], (f,), {f}, {f: None}
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000238 self.assertTrue(l == l, "[%r] not equal to itself" % f)
239 self.assertTrue(t == t, "(%r,) not equal to itself" % f)
240 self.assertTrue(s == s, "{%r} not equal to itself" % f)
241 self.assertTrue(d == d, "{%r : None} not equal to itself" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000242
Mark Dickinson9ab44b52009-12-30 16:22:49 +0000243 def assertEqualAndEqualSign(self, a, b):
244 # fail unless a == b and a and b have the same sign bit;
245 # the only difference from assertEqual is that this test
246 # distingishes -0.0 and 0.0.
247 self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b)))
248
249 @requires_IEEE_754
250 def test_float_pow(self):
251 # test builtin pow and ** operator for IEEE 754 special cases.
252 # Special cases taken from section F.9.4.4 of the C99 specification
253
254 for pow_op in pow, operator.pow:
255 # x**NAN is NAN for any x except 1
256 self.assertTrue(isnan(pow_op(-INF, NAN)))
257 self.assertTrue(isnan(pow_op(-2.0, NAN)))
258 self.assertTrue(isnan(pow_op(-1.0, NAN)))
259 self.assertTrue(isnan(pow_op(-0.5, NAN)))
260 self.assertTrue(isnan(pow_op(-0.0, NAN)))
261 self.assertTrue(isnan(pow_op(0.0, NAN)))
262 self.assertTrue(isnan(pow_op(0.5, NAN)))
263 self.assertTrue(isnan(pow_op(2.0, NAN)))
264 self.assertTrue(isnan(pow_op(INF, NAN)))
265 self.assertTrue(isnan(pow_op(NAN, NAN)))
266
267 # NAN**y is NAN for any y except +-0
268 self.assertTrue(isnan(pow_op(NAN, -INF)))
269 self.assertTrue(isnan(pow_op(NAN, -2.0)))
270 self.assertTrue(isnan(pow_op(NAN, -1.0)))
271 self.assertTrue(isnan(pow_op(NAN, -0.5)))
272 self.assertTrue(isnan(pow_op(NAN, 0.5)))
273 self.assertTrue(isnan(pow_op(NAN, 1.0)))
274 self.assertTrue(isnan(pow_op(NAN, 2.0)))
275 self.assertTrue(isnan(pow_op(NAN, INF)))
276
277 # (+-0)**y raises ZeroDivisionError for y a negative odd integer
278 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0)
279 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0)
280
281 # (+-0)**y raises ZeroDivisionError for y finite and negative
282 # but not an odd integer
283 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0)
284 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5)
285 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0)
286 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5)
287
288 # (+-0)**y is +-0 for y a positive odd integer
289 self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0)
290 self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0)
291
292 # (+-0)**y is 0 for y finite and positive but not an odd integer
293 self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0)
294 self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0)
295 self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0)
296 self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0)
297
298 # (-1)**+-inf is 1
299 self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0)
300 self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0)
301
302 # 1**y is 1 for any y, even if y is an infinity or nan
303 self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0)
304 self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0)
305 self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0)
306 self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0)
307 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
308 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
309 self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0)
310 self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0)
311 self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0)
312 self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0)
313 self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0)
314
315 # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan
316 self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0)
317 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
318 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
319 self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0)
320 self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0)
321 self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0)
322 self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0)
323 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
324 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
325 self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0)
326 self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0)
327 self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0)
328 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
329 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
330 self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0)
331 self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0)
332 self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0)
333 self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0)
334 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
335 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
336 self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0)
337 self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0)
338
339 # x**y defers to complex pow for finite negative x and
340 # non-integral y.
341 self.assertEqual(type(pow_op(-2.0, -0.5)), complex)
342 self.assertEqual(type(pow_op(-2.0, 0.5)), complex)
343 self.assertEqual(type(pow_op(-1.0, -0.5)), complex)
344 self.assertEqual(type(pow_op(-1.0, 0.5)), complex)
345 self.assertEqual(type(pow_op(-0.5, -0.5)), complex)
346 self.assertEqual(type(pow_op(-0.5, 0.5)), complex)
347
348 # x**-INF is INF for abs(x) < 1
349 self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF)
350 self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF)
351 self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF)
352 self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF)
353
354 # x**-INF is 0 for abs(x) > 1
355 self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0)
356 self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0)
357 self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0)
358 self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0)
359
360 # x**INF is 0 for abs(x) < 1
361 self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0)
362 self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0)
363 self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0)
364 self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0)
365
366 # x**INF is INF for abs(x) > 1
367 self.assertEqualAndEqualSign(pow_op(-INF, INF), INF)
368 self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF)
369 self.assertEqualAndEqualSign(pow_op(2.0, INF), INF)
370 self.assertEqualAndEqualSign(pow_op(INF, INF), INF)
371
372 # (-INF)**y is -0.0 for y a negative odd integer
373 self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0)
374
375 # (-INF)**y is 0.0 for y negative but not an odd integer
376 self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0)
377 self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0)
378
379 # (-INF)**y is -INF for y a positive odd integer
380 self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF)
381
382 # (-INF)**y is INF for y positive but not an odd integer
383 self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF)
384 self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF)
385
386 # INF**y is INF for y positive
387 self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF)
388 self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF)
389 self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF)
390
391 # INF**y is 0.0 for y negative
392 self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0)
393 self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0)
394 self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0)
395
396 # basic checks not covered by the special cases above
397 self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25)
398 self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5)
399 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
400 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
401 self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0)
402 self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0)
403 self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0)
404 self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0)
405 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
406 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
407 self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0)
408 self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0)
409 self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25)
410 self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5)
411 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
412 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
413 self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0)
414 self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0)
415
416 # 1 ** large and -1 ** large; some libms apparently
417 # have problems with these
418 self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0)
419 self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0)
420 self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0)
421 self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0)
422
423 # check sign for results that underflow to 0
424 self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0)
425 self.assertEqual(type(pow_op(-2.0, -2000.5)), complex)
426 self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0)
427 self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0)
428 self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0)
429 self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0)
430 self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0)
431 self.assertEqual(type(pow_op(-0.5, 2000.5)), complex)
432 self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0)
433 self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0)
434 self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0)
435 self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0)
436
437 # check we don't raise an exception for subnormal results,
438 # and validate signs. Tests currently disabled, since
439 # they fail on systems where a subnormal result from pow
440 # is flushed to zero (e.g. Debian/ia64.)
441 #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315)
442 #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315)
443 #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315)
444 #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315)
445 #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315)
446 #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315)
447 #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
448 #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000449
450
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000451class FormatFunctionsTestCase(unittest.TestCase):
452
453 def setUp(self):
454 self.save_formats = {'double':float.__getformat__('double'),
455 'float':float.__getformat__('float')}
456
457 def tearDown(self):
458 float.__setformat__('double', self.save_formats['double'])
459 float.__setformat__('float', self.save_formats['float'])
460
461 def test_getformat(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000462 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000463 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000464 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000465 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
466 self.assertRaises(ValueError, float.__getformat__, 'chicken')
467 self.assertRaises(TypeError, float.__getformat__, 1)
468
469 def test_setformat(self):
470 for t in 'double', 'float':
471 float.__setformat__(t, 'unknown')
472 if self.save_formats[t] == 'IEEE, big-endian':
473 self.assertRaises(ValueError, float.__setformat__,
474 t, 'IEEE, little-endian')
475 elif self.save_formats[t] == 'IEEE, little-endian':
476 self.assertRaises(ValueError, float.__setformat__,
477 t, 'IEEE, big-endian')
478 else:
479 self.assertRaises(ValueError, float.__setformat__,
480 t, 'IEEE, big-endian')
481 self.assertRaises(ValueError, float.__setformat__,
482 t, 'IEEE, little-endian')
483 self.assertRaises(ValueError, float.__setformat__,
484 t, 'chicken')
485 self.assertRaises(ValueError, float.__setformat__,
486 'chicken', 'unknown')
487
Guido van Rossum2be161d2007-05-15 20:43:51 +0000488BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000489LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000490BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000491LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000492
Guido van Rossum2be161d2007-05-15 20:43:51 +0000493BE_FLOAT_INF = b'\x7f\x80\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000494LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000495BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000496LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000497
498# on non-IEEE platforms, attempting to unpack a bit pattern
499# representing an infinity or a NaN should raise an exception.
500
501class UnknownFormatTestCase(unittest.TestCase):
502 def setUp(self):
503 self.save_formats = {'double':float.__getformat__('double'),
504 'float':float.__getformat__('float')}
505 float.__setformat__('double', 'unknown')
506 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000507
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000508 def tearDown(self):
509 float.__setformat__('double', self.save_formats['double'])
510 float.__setformat__('float', self.save_formats['float'])
511
512 def test_double_specials_dont_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 self.assertRaises(ValueError, struct.unpack, fmt, data)
518
519 def test_float_specials_dont_unpack(self):
520 for fmt, data in [('>f', BE_FLOAT_INF),
521 ('>f', BE_FLOAT_NAN),
522 ('<f', LE_FLOAT_INF),
523 ('<f', LE_FLOAT_NAN)]:
524 self.assertRaises(ValueError, struct.unpack, fmt, data)
525
526
527# on an IEEE platform, all we guarantee is that bit patterns
528# representing infinities or NaNs do not raise an exception; all else
529# is accident (today).
Guido van Rossum04110fb2007-08-24 16:32:05 +0000530# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000531
532class IEEEFormatTestCase(unittest.TestCase):
533 if float.__getformat__("double").startswith("IEEE"):
534 def test_double_specials_do_unpack(self):
535 for fmt, data in [('>d', BE_DOUBLE_INF),
536 ('>d', BE_DOUBLE_NAN),
537 ('<d', LE_DOUBLE_INF),
538 ('<d', LE_DOUBLE_NAN)]:
539 struct.unpack(fmt, data)
540
541 if float.__getformat__("float").startswith("IEEE"):
542 def test_float_specials_do_unpack(self):
543 for fmt, data in [('>f', BE_FLOAT_INF),
544 ('>f', BE_FLOAT_NAN),
545 ('<f', LE_FLOAT_INF),
546 ('<f', LE_FLOAT_NAN)]:
547 struct.unpack(fmt, data)
548
Guido van Rossum04110fb2007-08-24 16:32:05 +0000549 if float.__getformat__("double").startswith("IEEE"):
550 def test_negative_zero(self):
551 import math
552 def pos_pos():
553 return 0.0, math.atan2(0.0, -1)
554 def pos_neg():
555 return 0.0, math.atan2(-0.0, -1)
556 def neg_pos():
557 return -0.0, math.atan2(0.0, -1)
558 def neg_neg():
559 return -0.0, math.atan2(-0.0, -1)
560 self.assertEquals(pos_pos(), neg_pos())
561 self.assertEquals(pos_neg(), neg_neg())
562
Eric Smith8c663262007-08-25 02:26:07 +0000563class FormatTestCase(unittest.TestCase):
Eric Smith11fe3e02007-08-31 01:33:06 +0000564 def test_format(self):
Eric Smith8c663262007-08-25 02:26:07 +0000565 # these should be rewritten to use both format(x, spec) and
566 # x.__format__(spec)
567
568 self.assertEqual(format(0.0, 'f'), '0.000000')
569
570 # the default is 'g', except for empty format spec
571 self.assertEqual(format(0.0, ''), '0.0')
572 self.assertEqual(format(0.01, ''), '0.01')
573 self.assertEqual(format(0.01, 'g'), '0.01')
574
Eric Smith63376222009-05-05 14:04:18 +0000575 # empty presentation type should format in the same way as str
576 # (issue 5920)
577 x = 100/7.
578 self.assertEqual(format(x, ''), str(x))
579 self.assertEqual(format(x, '-'), str(x))
580 self.assertEqual(format(x, '>'), str(x))
581 self.assertEqual(format(x, '2'), str(x))
Eric Smith8c663262007-08-25 02:26:07 +0000582
583 self.assertEqual(format(1.0, 'f'), '1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000584
585 self.assertEqual(format(-1.0, 'f'), '-1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000586
587 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
588 self.assertEqual(format(-1.0, ' f'), '-1.000000')
589 self.assertEqual(format( 1.0, '+f'), '+1.000000')
590 self.assertEqual(format(-1.0, '+f'), '-1.000000')
591
592 # % formatting
593 self.assertEqual(format(-1.0, '%'), '-100.000000%')
594
595 # conversion to string should fail
596 self.assertRaises(ValueError, format, 3.0, "s")
597
Eric Smith7b69c6c2008-01-27 21:07:59 +0000598 # other format specifiers shouldn't work on floats,
599 # in particular int specifiers
600 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
601 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
602 if not format_spec in 'eEfFgGn%':
603 self.assertRaises(ValueError, format, 0.0, format_spec)
604 self.assertRaises(ValueError, format, 1.0, format_spec)
605 self.assertRaises(ValueError, format, -1.0, format_spec)
606 self.assertRaises(ValueError, format, 1e100, format_spec)
607 self.assertRaises(ValueError, format, -1e100, format_spec)
608 self.assertRaises(ValueError, format, 1e-100, format_spec)
609 self.assertRaises(ValueError, format, -1e-100, format_spec)
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000610
Eric Smith741191f2009-05-06 13:08:15 +0000611 # issue 3382
612 self.assertEqual(format(NAN, 'f'), 'nan')
613 self.assertEqual(format(NAN, 'F'), 'NAN')
614 self.assertEqual(format(INF, 'f'), 'inf')
615 self.assertEqual(format(INF, 'F'), 'INF')
616
Eric Smith0923d1d2009-04-16 20:16:10 +0000617 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
618 "test requires IEEE 754 doubles")
619 def test_format_testfile(self):
620 for line in open(format_testfile):
621 if line.startswith('--'):
622 continue
623 line = line.strip()
624 if not line:
625 continue
626
627 lhs, rhs = map(str.strip, line.split('->'))
628 fmt, arg = lhs.split()
629 self.assertEqual(fmt % float(arg), rhs)
630 self.assertEqual(fmt % -float(arg), '-' + rhs)
631
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000632 def test_issue5864(self):
633 self.assertEquals(format(123.456, '.4'), '123.5')
634 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
635 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
636
Mark Dickinson7efad9e2009-04-17 20:59:58 +0000637class ReprTestCase(unittest.TestCase):
638 def test_repr(self):
639 floats_file = open(os.path.join(os.path.split(__file__)[0],
640 'floating_points.txt'))
641 for line in floats_file:
642 line = line.strip()
643 if not line or line.startswith('#'):
644 continue
645 v = eval(line)
646 self.assertEqual(v, eval(repr(v)))
647 floats_file.close()
648
Eric Smith0923d1d2009-04-16 20:16:10 +0000649 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
650 "applies only when using short float repr style")
651 def test_short_repr(self):
652 # test short float repr introduced in Python 3.1. One aspect
653 # of this repr is that we get some degree of str -> float ->
654 # str roundtripping. In particular, for any numeric string
655 # containing 15 or fewer significant digits, those exact same
656 # digits (modulo trailing zeros) should appear in the output.
657 # No more repr(0.03) -> "0.029999999999999999"!
658
659 test_strings = [
660 # output always includes *either* a decimal point and at
661 # least one digit after that point, or an exponent.
662 '0.0',
663 '1.0',
664 '0.01',
665 '0.02',
666 '0.03',
667 '0.04',
668 '0.05',
669 '1.23456789',
670 '10.0',
671 '100.0',
672 # values >= 1e16 get an exponent...
673 '1000000000000000.0',
674 '9999999999999990.0',
675 '1e+16',
676 '1e+17',
677 # ... and so do values < 1e-4
678 '0.001',
679 '0.001001',
680 '0.00010000000000001',
681 '0.0001',
682 '9.999999999999e-05',
683 '1e-05',
684 # values designed to provoke failure if the FPU rounding
685 # precision isn't set correctly
686 '8.72293771110361e+25',
687 '7.47005307342313e+26',
688 '2.86438000439698e+28',
689 '8.89142905246179e+28',
690 '3.08578087079232e+35',
691 ]
692
693 for s in test_strings:
694 negs = '-'+s
695 self.assertEqual(s, repr(float(s)))
696 self.assertEqual(negs, repr(float(negs)))
697
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000698class RoundTestCase(unittest.TestCase):
699 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
700 "test requires IEEE 754 doubles")
701 def test_inf_nan(self):
702 self.assertRaises(OverflowError, round, INF)
703 self.assertRaises(OverflowError, round, -INF)
704 self.assertRaises(ValueError, round, NAN)
Mark Dickinson4ca33d12009-11-24 10:59:34 +0000705 self.assertRaises(TypeError, round, INF, 0.0)
706 self.assertRaises(TypeError, round, -INF, 1.0)
707 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
708 self.assertRaises(TypeError, round, -0.0, 1j)
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000709
710 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
711 "test requires IEEE 754 doubles")
712 def test_large_n(self):
713 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
714 self.assertEqual(round(123.456, n), 123.456)
715 self.assertEqual(round(-123.456, n), -123.456)
716 self.assertEqual(round(1e300, n), 1e300)
717 self.assertEqual(round(1e-320, n), 1e-320)
718 self.assertEqual(round(1e150, 300), 1e150)
719 self.assertEqual(round(1e300, 307), 1e300)
720 self.assertEqual(round(-3.1415, 308), -3.1415)
721 self.assertEqual(round(1e150, 309), 1e150)
722 self.assertEqual(round(1.4e-315, 315), 1e-315)
723
724 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
725 "test requires IEEE 754 doubles")
726 def test_small_n(self):
727 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
728 self.assertEqual(round(123.456, n), 0.0)
729 self.assertEqual(round(-123.456, n), -0.0)
730 self.assertEqual(round(1e300, n), 0.0)
731 self.assertEqual(round(1e-320, n), 0.0)
732
733 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
734 "test requires IEEE 754 doubles")
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 "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 # round-half-even
748 self.assertEqual(round(25.0, -1), 20.0)
749 self.assertEqual(round(35.0, -1), 40.0)
750 self.assertEqual(round(45.0, -1), 40.0)
751 self.assertEqual(round(55.0, -1), 60.0)
752 self.assertEqual(round(65.0, -1), 60.0)
753 self.assertEqual(round(75.0, -1), 80.0)
754 self.assertEqual(round(85.0, -1), 80.0)
755 self.assertEqual(round(95.0, -1), 100.0)
756
757 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
758 "applies only when using short float repr style")
759 def test_matches_float_format(self):
760 # round should give the same results as float formatting
761 for i in range(500):
762 x = i/1000.
763 self.assertEqual(float(format(x, '.0f')), round(x, 0))
764 self.assertEqual(float(format(x, '.1f')), round(x, 1))
765 self.assertEqual(float(format(x, '.2f')), round(x, 2))
766 self.assertEqual(float(format(x, '.3f')), round(x, 3))
767
768 for i in range(5, 5000, 10):
769 x = i/1000.
770 self.assertEqual(float(format(x, '.0f')), round(x, 0))
771 self.assertEqual(float(format(x, '.1f')), round(x, 1))
772 self.assertEqual(float(format(x, '.2f')), round(x, 2))
773 self.assertEqual(float(format(x, '.3f')), round(x, 3))
774
775 for i in range(500):
776 x = random.random()
777 self.assertEqual(float(format(x, '.0f')), round(x, 0))
778 self.assertEqual(float(format(x, '.1f')), round(x, 1))
779 self.assertEqual(float(format(x, '.2f')), round(x, 2))
780 self.assertEqual(float(format(x, '.3f')), round(x, 3))
781
782
Eric Smith8a10ecc2009-12-02 17:58:24 +0000783 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
784 "test requires IEEE 754 doubles")
785 def test_format_specials(self):
786 # Test formatting of nans and infs.
787
788 def test(fmt, value, expected):
789 # Test with both % and format().
790 self.assertEqual(fmt % value, expected, fmt)
791 if not '#' in fmt:
792 # Until issue 7094 is implemented, format() for floats doesn't
793 # support '#' formatting
794 fmt = fmt[1:] # strip off the %
795 self.assertEqual(format(value, fmt), expected, fmt)
796
797 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
798 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
799 pfmt = '%+' + fmt[1:]
800 sfmt = '% ' + fmt[1:]
801 test(fmt, INF, 'inf')
802 test(fmt, -INF, '-inf')
803 test(fmt, NAN, 'nan')
804 test(fmt, -NAN, 'nan')
805 # When asking for a sign, it's always provided. nans are
806 # always positive.
807 test(pfmt, INF, '+inf')
808 test(pfmt, -INF, '-inf')
809 test(pfmt, NAN, '+nan')
810 test(pfmt, -NAN, '+nan')
811 # When using ' ' for a sign code, only infs can be negative.
812 # Others have a space.
813 test(sfmt, INF, ' inf')
814 test(sfmt, -INF, '-inf')
815 test(sfmt, NAN, ' nan')
816 test(sfmt, -NAN, ' nan')
817
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000818
Christian Heimes99170a52007-12-19 02:07:34 +0000819# Beginning with Python 2.6 float has cross platform compatible
Georg Brandl2ee470f2008-07-16 12:55:28 +0000820# ways to create and represent inf and nan
Christian Heimes99170a52007-12-19 02:07:34 +0000821class InfNanTest(unittest.TestCase):
822 def test_inf_from_str(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000823 self.assertTrue(isinf(float("inf")))
824 self.assertTrue(isinf(float("+inf")))
825 self.assertTrue(isinf(float("-inf")))
826 self.assertTrue(isinf(float("infinity")))
827 self.assertTrue(isinf(float("+infinity")))
828 self.assertTrue(isinf(float("-infinity")))
Christian Heimes99170a52007-12-19 02:07:34 +0000829
830 self.assertEqual(repr(float("inf")), "inf")
831 self.assertEqual(repr(float("+inf")), "inf")
832 self.assertEqual(repr(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000833 self.assertEqual(repr(float("infinity")), "inf")
834 self.assertEqual(repr(float("+infinity")), "inf")
835 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000836
837 self.assertEqual(repr(float("INF")), "inf")
838 self.assertEqual(repr(float("+Inf")), "inf")
839 self.assertEqual(repr(float("-iNF")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000840 self.assertEqual(repr(float("Infinity")), "inf")
841 self.assertEqual(repr(float("+iNfInItY")), "inf")
842 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000843
844 self.assertEqual(str(float("inf")), "inf")
845 self.assertEqual(str(float("+inf")), "inf")
846 self.assertEqual(str(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000847 self.assertEqual(str(float("infinity")), "inf")
848 self.assertEqual(str(float("+infinity")), "inf")
849 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000850
851 self.assertRaises(ValueError, float, "info")
852 self.assertRaises(ValueError, float, "+info")
853 self.assertRaises(ValueError, float, "-info")
854 self.assertRaises(ValueError, float, "in")
855 self.assertRaises(ValueError, float, "+in")
856 self.assertRaises(ValueError, float, "-in")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000857 self.assertRaises(ValueError, float, "infinit")
858 self.assertRaises(ValueError, float, "+Infin")
859 self.assertRaises(ValueError, float, "-INFI")
860 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes99170a52007-12-19 02:07:34 +0000861
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000862 self.assertRaises(ValueError, float, "++Inf")
863 self.assertRaises(ValueError, float, "-+inf")
864 self.assertRaises(ValueError, float, "+-infinity")
865 self.assertRaises(ValueError, float, "--Infinity")
866
Christian Heimes99170a52007-12-19 02:07:34 +0000867 def test_inf_as_str(self):
868 self.assertEqual(repr(1e300 * 1e300), "inf")
869 self.assertEqual(repr(-1e300 * 1e300), "-inf")
870
871 self.assertEqual(str(1e300 * 1e300), "inf")
872 self.assertEqual(str(-1e300 * 1e300), "-inf")
873
874 def test_nan_from_str(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000875 self.assertTrue(isnan(float("nan")))
876 self.assertTrue(isnan(float("+nan")))
877 self.assertTrue(isnan(float("-nan")))
Christian Heimes99170a52007-12-19 02:07:34 +0000878
879 self.assertEqual(repr(float("nan")), "nan")
880 self.assertEqual(repr(float("+nan")), "nan")
881 self.assertEqual(repr(float("-nan")), "nan")
882
883 self.assertEqual(repr(float("NAN")), "nan")
884 self.assertEqual(repr(float("+NAn")), "nan")
885 self.assertEqual(repr(float("-NaN")), "nan")
886
887 self.assertEqual(str(float("nan")), "nan")
888 self.assertEqual(str(float("+nan")), "nan")
889 self.assertEqual(str(float("-nan")), "nan")
890
891 self.assertRaises(ValueError, float, "nana")
892 self.assertRaises(ValueError, float, "+nana")
893 self.assertRaises(ValueError, float, "-nana")
894 self.assertRaises(ValueError, float, "na")
895 self.assertRaises(ValueError, float, "+na")
896 self.assertRaises(ValueError, float, "-na")
897
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000898 self.assertRaises(ValueError, float, "++nan")
899 self.assertRaises(ValueError, float, "-+NAN")
900 self.assertRaises(ValueError, float, "+-NaN")
901 self.assertRaises(ValueError, float, "--nAn")
902
Christian Heimes99170a52007-12-19 02:07:34 +0000903 def test_nan_as_str(self):
904 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
905 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
906
907 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
908 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000909
Christian Heimes53876d92008-04-19 00:31:39 +0000910 def notest_float_nan(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000911 self.assertTrue(NAN.is_nan())
912 self.assertFalse(INF.is_nan())
913 self.assertFalse((0.).is_nan())
Christian Heimes53876d92008-04-19 00:31:39 +0000914
915 def notest_float_inf(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000916 self.assertTrue(INF.is_inf())
917 self.assertFalse(NAN.is_inf())
918 self.assertFalse((0.).is_inf())
Christian Heimes53876d92008-04-19 00:31:39 +0000919
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000920fromHex = float.fromhex
921toHex = float.hex
922class HexFloatTestCase(unittest.TestCase):
923 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
924 MIN = fromHex('0x1p-1022') # min normal
925 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
926 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
927
928 def identical(self, x, y):
929 # check that floats x and y are identical, or that both
930 # are NaNs
931 if isnan(x) or isnan(y):
932 if isnan(x) == isnan(y):
933 return
934 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
935 return
936 self.fail('%r not identical to %r' % (x, y))
937
938 def test_ends(self):
Mark Dickinson38bbc482008-07-16 11:32:23 +0000939 self.identical(self.MIN, ldexp(1.0, -1022))
940 self.identical(self.TINY, ldexp(1.0, -1074))
941 self.identical(self.EPS, ldexp(1.0, -52))
942 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000943
944 def test_invalid_inputs(self):
945 invalid_inputs = [
946 'infi', # misspelt infinities and nans
947 '-Infinit',
948 '++inf',
949 '-+Inf',
950 '--nan',
951 '+-NaN',
952 'snan',
953 'NaNs',
954 'nna',
Mark Dickinsond1ec8b22009-05-11 15:45:15 +0000955 'an',
956 'nf',
957 'nfinity',
958 'inity',
959 'iinity',
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000960 '0xnan',
961 '',
962 ' ',
963 'x1.0p0',
964 '0xX1.0p0',
965 '+ 0x1.0p0', # internal whitespace
966 '- 0x1.0p0',
967 '0 x1.0p0',
968 '0x 1.0p0',
969 '0x1 2.0p0',
970 '+0x1 .0p0',
971 '0x1. 0p0',
972 '-0x1.0 1p0',
973 '-0x1.0 p0',
974 '+0x1.0p +0',
975 '0x1.0p -0',
976 '0x1.0p 0',
977 '+0x1.0p+ 0',
978 '-0x1.0p- 0',
979 '++0x1.0p-0', # double signs
980 '--0x1.0p0',
981 '+-0x1.0p+0',
982 '-+0x1.0p0',
983 '0x1.0p++0',
984 '+0x1.0p+-0',
985 '-0x1.0p-+0',
986 '0x1.0p--0',
987 '0x1.0.p0',
988 '0x.p0', # no hex digits before or after point
989 '0x1,p0', # wrong decimal point character
990 '0x1pa',
991 '0x1p\uff10', # fullwidth Unicode digits
992 '\uff10x1p0',
993 '0x\uff11p0',
994 '0x1.\uff10p0',
995 '0x1p0 \n 0x2p0',
996 '0x1p0\0 0x1p0', # embedded null byte is not end of string
997 ]
998 for x in invalid_inputs:
Mark Dickinson589b7952008-08-21 20:05:56 +0000999 try:
1000 result = fromHex(x)
1001 except ValueError:
1002 pass
1003 else:
1004 self.fail('Expected float.fromhex(%r) to raise ValueError; '
1005 'got %r instead' % (x, result))
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001006
1007
Mark Dickinsond1ec8b22009-05-11 15:45:15 +00001008 def test_whitespace(self):
1009 value_pairs = [
1010 ('inf', INF),
1011 ('-Infinity', -INF),
1012 ('nan', NAN),
1013 ('1.0', 1.0),
1014 ('-0x.2', -0.125),
1015 ('-0.0', -0.0)
1016 ]
1017 whitespace = [
1018 '',
1019 ' ',
1020 '\t',
1021 '\n',
1022 '\n \t',
1023 '\f',
1024 '\v',
1025 '\r'
1026 ]
1027 for inp, expected in value_pairs:
1028 for lead in whitespace:
1029 for trail in whitespace:
1030 got = fromHex(lead + inp + trail)
1031 self.identical(got, expected)
1032
1033
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001034 def test_from_hex(self):
1035 MIN = self.MIN;
1036 MAX = self.MAX;
1037 TINY = self.TINY;
1038 EPS = self.EPS;
1039
1040 # two spellings of infinity, with optional signs; case-insensitive
1041 self.identical(fromHex('inf'), INF)
1042 self.identical(fromHex('+Inf'), INF)
1043 self.identical(fromHex('-INF'), -INF)
1044 self.identical(fromHex('iNf'), INF)
1045 self.identical(fromHex('Infinity'), INF)
1046 self.identical(fromHex('+INFINITY'), INF)
1047 self.identical(fromHex('-infinity'), -INF)
1048 self.identical(fromHex('-iNFiNitY'), -INF)
1049
1050 # nans with optional sign; case insensitive
1051 self.identical(fromHex('nan'), NAN)
1052 self.identical(fromHex('+NaN'), NAN)
1053 self.identical(fromHex('-NaN'), NAN)
1054 self.identical(fromHex('-nAN'), NAN)
1055
1056 # variations in input format
1057 self.identical(fromHex('1'), 1.0)
1058 self.identical(fromHex('+1'), 1.0)
1059 self.identical(fromHex('1.'), 1.0)
1060 self.identical(fromHex('1.0'), 1.0)
1061 self.identical(fromHex('1.0p0'), 1.0)
1062 self.identical(fromHex('01'), 1.0)
1063 self.identical(fromHex('01.'), 1.0)
1064 self.identical(fromHex('0x1'), 1.0)
1065 self.identical(fromHex('0x1.'), 1.0)
1066 self.identical(fromHex('0x1.0'), 1.0)
1067 self.identical(fromHex('+0x1.0'), 1.0)
1068 self.identical(fromHex('0x1p0'), 1.0)
1069 self.identical(fromHex('0X1p0'), 1.0)
1070 self.identical(fromHex('0X1P0'), 1.0)
1071 self.identical(fromHex('0x1P0'), 1.0)
1072 self.identical(fromHex('0x1.p0'), 1.0)
1073 self.identical(fromHex('0x1.0p0'), 1.0)
1074 self.identical(fromHex('0x.1p4'), 1.0)
1075 self.identical(fromHex('0x.1p04'), 1.0)
1076 self.identical(fromHex('0x.1p004'), 1.0)
1077 self.identical(fromHex('0x1p+0'), 1.0)
1078 self.identical(fromHex('0x1P-0'), 1.0)
1079 self.identical(fromHex('+0x1p0'), 1.0)
1080 self.identical(fromHex('0x01p0'), 1.0)
1081 self.identical(fromHex('0x1p00'), 1.0)
1082 self.identical(fromHex(' 0x1p0 '), 1.0)
1083 self.identical(fromHex('\n 0x1p0'), 1.0)
1084 self.identical(fromHex('0x1p0 \t'), 1.0)
1085 self.identical(fromHex('0xap0'), 10.0)
1086 self.identical(fromHex('0xAp0'), 10.0)
1087 self.identical(fromHex('0xaP0'), 10.0)
1088 self.identical(fromHex('0xAP0'), 10.0)
1089 self.identical(fromHex('0xbep0'), 190.0)
1090 self.identical(fromHex('0xBep0'), 190.0)
1091 self.identical(fromHex('0xbEp0'), 190.0)
1092 self.identical(fromHex('0XBE0P-4'), 190.0)
1093 self.identical(fromHex('0xBEp0'), 190.0)
1094 self.identical(fromHex('0xB.Ep4'), 190.0)
1095 self.identical(fromHex('0x.BEp8'), 190.0)
1096 self.identical(fromHex('0x.0BEp12'), 190.0)
1097
1098 # moving the point around
1099 pi = fromHex('0x1.921fb54442d18p1')
1100 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
1101 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
1102 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
1103 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
1104 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
1105 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
1106 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
1107 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
1108 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
1109 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
1110 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
1111 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
1112 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
1113 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
1114 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
1115 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
1116 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
1117 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
1118 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
1119 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
1120 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
1121 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
1122 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
1123 # ...
1124 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
1125 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
1126 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
1127 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
1128 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
1129 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
1130 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
1131 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
1132 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
1133
1134
1135 # results that should overflow...
1136 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
1137 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
1138 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
1139 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
1140 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
1141 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
1142 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
1143 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
1144 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
1145 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
1146 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
1147 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
1148 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
1149 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
1150 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
1151 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
1152 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
1153 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
1154 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
1155
1156 # ...and those that round to +-max float
1157 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
1158 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
1159 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
1160
1161 # zeros
1162 self.identical(fromHex('0x0p0'), 0.0)
1163 self.identical(fromHex('0x0p1000'), 0.0)
1164 self.identical(fromHex('-0x0p1023'), -0.0)
1165 self.identical(fromHex('0X0p1024'), 0.0)
1166 self.identical(fromHex('-0x0p1025'), -0.0)
1167 self.identical(fromHex('0X0p2000'), 0.0)
1168 self.identical(fromHex('0x0p123456789123456789'), 0.0)
1169 self.identical(fromHex('-0X0p-0'), -0.0)
1170 self.identical(fromHex('-0X0p-1000'), -0.0)
1171 self.identical(fromHex('0x0p-1023'), 0.0)
1172 self.identical(fromHex('-0X0p-1024'), -0.0)
1173 self.identical(fromHex('-0x0p-1025'), -0.0)
1174 self.identical(fromHex('-0x0p-1072'), -0.0)
1175 self.identical(fromHex('0X0p-1073'), 0.0)
1176 self.identical(fromHex('-0x0p-1074'), -0.0)
1177 self.identical(fromHex('0x0p-1075'), 0.0)
1178 self.identical(fromHex('0X0p-1076'), 0.0)
1179 self.identical(fromHex('-0X0p-2000'), -0.0)
1180 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
1181
1182 # values that should underflow to 0
1183 self.identical(fromHex('0X1p-1075'), 0.0)
1184 self.identical(fromHex('-0X1p-1075'), -0.0)
1185 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
1186 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
1187 self.identical(fromHex('-0x1.1p-1075'), -TINY)
1188 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
1189
1190 # check round-half-even is working correctly near 0 ...
1191 self.identical(fromHex('0x1p-1076'), 0.0)
1192 self.identical(fromHex('0X2p-1076'), 0.0)
1193 self.identical(fromHex('0X3p-1076'), TINY)
1194 self.identical(fromHex('0x4p-1076'), TINY)
1195 self.identical(fromHex('0X5p-1076'), TINY)
1196 self.identical(fromHex('0X6p-1076'), 2*TINY)
1197 self.identical(fromHex('0x7p-1076'), 2*TINY)
1198 self.identical(fromHex('0X8p-1076'), 2*TINY)
1199 self.identical(fromHex('0X9p-1076'), 2*TINY)
1200 self.identical(fromHex('0xap-1076'), 2*TINY)
1201 self.identical(fromHex('0Xbp-1076'), 3*TINY)
1202 self.identical(fromHex('0xcp-1076'), 3*TINY)
1203 self.identical(fromHex('0Xdp-1076'), 3*TINY)
1204 self.identical(fromHex('0Xep-1076'), 4*TINY)
1205 self.identical(fromHex('0xfp-1076'), 4*TINY)
1206 self.identical(fromHex('0x10p-1076'), 4*TINY)
1207 self.identical(fromHex('-0x1p-1076'), -0.0)
1208 self.identical(fromHex('-0X2p-1076'), -0.0)
1209 self.identical(fromHex('-0x3p-1076'), -TINY)
1210 self.identical(fromHex('-0X4p-1076'), -TINY)
1211 self.identical(fromHex('-0x5p-1076'), -TINY)
1212 self.identical(fromHex('-0x6p-1076'), -2*TINY)
1213 self.identical(fromHex('-0X7p-1076'), -2*TINY)
1214 self.identical(fromHex('-0X8p-1076'), -2*TINY)
1215 self.identical(fromHex('-0X9p-1076'), -2*TINY)
1216 self.identical(fromHex('-0Xap-1076'), -2*TINY)
1217 self.identical(fromHex('-0xbp-1076'), -3*TINY)
1218 self.identical(fromHex('-0xcp-1076'), -3*TINY)
1219 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
1220 self.identical(fromHex('-0xep-1076'), -4*TINY)
1221 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
1222 self.identical(fromHex('-0X10p-1076'), -4*TINY)
1223
1224 # ... and near MIN ...
1225 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
1226 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
1227 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
1228 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
1229 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
1230 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
1231 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
1232 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
1233 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
1234 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
1235 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
1236 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
1237 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
1238 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
1239 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
1240 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
1241 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
1242 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
1243 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
1244 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
1245 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
1246 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
1247 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
1248 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
1249 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
1250 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
1251 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
1252 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
1253 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
1254 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
1255 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
1256 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
1257 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
1258 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
1259
1260 # ... and near 1.0.
1261 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
1262 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
1263 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
1264 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
1265 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
1266 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
1267 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
1268 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
1269 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
1270 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
1271 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
1272 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
1273 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
1274 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
1275 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
1276 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
1277 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
1278 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
1279 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
1280 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
1281 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
1282 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
1283 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
1284 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
1285 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
1286 1.0)
1287 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
1288 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
1289 1+EPS)
1290 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
1291 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
1292 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
1293 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
1294 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
1295 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
1296 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
1297 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
1298 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
1299 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
1300 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
1301 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
1302 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
1303 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
1304 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
1305 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
1306 1.0+EPS)
1307 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
1308 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
1309 1.0+2*EPS)
1310 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
1311 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
1312 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
1313 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
1314 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
1315 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
1316 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
1317 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
1318
1319 def test_roundtrip(self):
1320 def roundtrip(x):
1321 return fromHex(toHex(x))
1322
1323 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1324 self.identical(x, roundtrip(x))
1325 self.identical(-x, roundtrip(-x))
1326
1327 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1328 import random
1329 for i in range(10000):
1330 e = random.randrange(-1200, 1200)
1331 m = random.random()
1332 s = random.choice([1.0, -1.0])
1333 try:
1334 x = s*ldexp(m, e)
1335 except OverflowError:
1336 pass
1337 else:
1338 self.identical(x, fromHex(toHex(x)))
1339
Mark Dickinson81612e82010-01-12 23:04:19 +00001340class StrtodTestCase(unittest.TestCase):
1341 def check_string(self, s):
1342 expected = strtod(s)
1343 try:
1344 fs = float(s)
1345 except OverflowError:
1346 got = '-inf' if s[0] == '-' else 'inf'
1347 else:
1348 got = fs.hex()
1349 self.assertEqual(expected, got,
1350 "Incorrectly rounded str->float conversion for "
1351 "{}: expected {}, got {}".format(s, expected, got))
1352
1353 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
1354 "applies only when using short float repr style")
1355 def test_bug7632(self):
1356 # check a few particular values that gave incorrectly rounded
1357 # results with previous versions of dtoa.c
1358 test_strings = [
1359 '94393431193180696942841837085033647913224148539854e-358',
1360 '12579816049008305546974391768996369464963024663104e-357',
1361 '17489628565202117263145367596028389348922981857013e-357',
1362 '18487398785991994634182916638542680759613590482273e-357',
1363 '32002864200581033134358724675198044527469366773928e-358',
1364 '73608278998966969345824653500136787876436005957953e-358',
1365 '64774478836417299491718435234611299336288082136054e-358',
1366 '13704940134126574534878641876947980878824688451169e-357',
1367 '46697445774047060960624497964425416610480524760471e-358',
1368 ]
1369 for s in test_strings:
1370 self.check_string(s)
1371
Christian Heimes53876d92008-04-19 00:31:39 +00001372
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001373def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001374 support.run_unittest(
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +00001375 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001376 FormatFunctionsTestCase,
1377 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +00001378 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +00001379 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001380 ReprTestCase,
Mark Dickinsone6a076d2009-04-18 11:48:33 +00001381 RoundTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001382 InfNanTest,
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001383 HexFloatTestCase,
Mark Dickinson81612e82010-01-12 23:04:19 +00001384 StrtodTestCase,
Christian Heimesb76922a2007-12-11 01:06:40 +00001385 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001386
1387if __name__ == '__main__':
1388 test_main()