blob: fd0f410f918ba4de715c7f5f8e8dbbcb9a596ec8 [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 Petersonc9c0f202009-06-30 23:06:06 +0000216 self.assertTrue(f in [f], "'%r' not in []" % f)
217 self.assertTrue(f in (f,), "'%r' not in ()" % f)
218 self.assertTrue(f in {f}, "'%r' not in set()" % f)
219 self.assertTrue(f in {f: None}, "'%r' not in {}" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000220 self.assertEqual([f].count(f), 1, "[].count('%r') != 1" % f)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000221 self.assertTrue(f in floats, "'%r' not in container" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000222
223 for f in floats:
224 # nonidentical containers, same type, same contents
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000225 self.assertTrue([f] == [f], "[%r] != [%r]" % (f, f))
226 self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f))
227 self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f))
228 self.assertTrue({f : None} == {f: None}, "{%r : None} != "
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000229 "{%r : None}" % (f, f))
230
231 # identical containers
232 l, t, s, d = [f], (f,), {f}, {f: None}
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000233 self.assertTrue(l == l, "[%r] not equal to itself" % f)
234 self.assertTrue(t == t, "(%r,) not equal to itself" % f)
235 self.assertTrue(s == s, "{%r} not equal to itself" % f)
236 self.assertTrue(d == d, "{%r : None} not equal to itself" % f)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000237
Mark Dickinson9ab44b52009-12-30 16:22:49 +0000238 def assertEqualAndEqualSign(self, a, b):
239 # fail unless a == b and a and b have the same sign bit;
240 # the only difference from assertEqual is that this test
241 # distingishes -0.0 and 0.0.
242 self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b)))
243
244 @requires_IEEE_754
245 def test_float_pow(self):
246 # test builtin pow and ** operator for IEEE 754 special cases.
247 # Special cases taken from section F.9.4.4 of the C99 specification
248
249 for pow_op in pow, operator.pow:
250 # x**NAN is NAN for any x except 1
251 self.assertTrue(isnan(pow_op(-INF, NAN)))
252 self.assertTrue(isnan(pow_op(-2.0, NAN)))
253 self.assertTrue(isnan(pow_op(-1.0, NAN)))
254 self.assertTrue(isnan(pow_op(-0.5, NAN)))
255 self.assertTrue(isnan(pow_op(-0.0, NAN)))
256 self.assertTrue(isnan(pow_op(0.0, NAN)))
257 self.assertTrue(isnan(pow_op(0.5, NAN)))
258 self.assertTrue(isnan(pow_op(2.0, NAN)))
259 self.assertTrue(isnan(pow_op(INF, NAN)))
260 self.assertTrue(isnan(pow_op(NAN, NAN)))
261
262 # NAN**y is NAN for any y except +-0
263 self.assertTrue(isnan(pow_op(NAN, -INF)))
264 self.assertTrue(isnan(pow_op(NAN, -2.0)))
265 self.assertTrue(isnan(pow_op(NAN, -1.0)))
266 self.assertTrue(isnan(pow_op(NAN, -0.5)))
267 self.assertTrue(isnan(pow_op(NAN, 0.5)))
268 self.assertTrue(isnan(pow_op(NAN, 1.0)))
269 self.assertTrue(isnan(pow_op(NAN, 2.0)))
270 self.assertTrue(isnan(pow_op(NAN, INF)))
271
272 # (+-0)**y raises ZeroDivisionError for y a negative odd integer
273 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0)
274 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0)
275
276 # (+-0)**y raises ZeroDivisionError for y finite and negative
277 # but not an odd integer
278 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0)
279 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5)
280 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0)
281 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5)
282
283 # (+-0)**y is +-0 for y a positive odd integer
284 self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0)
285 self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0)
286
287 # (+-0)**y is 0 for y finite and positive but not an odd integer
288 self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0)
289 self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0)
290 self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0)
291 self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0)
292
293 # (-1)**+-inf is 1
294 self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0)
295 self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0)
296
297 # 1**y is 1 for any y, even if y is an infinity or nan
298 self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0)
299 self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0)
300 self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0)
301 self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0)
302 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
303 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
304 self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0)
305 self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0)
306 self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0)
307 self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0)
308 self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0)
309
310 # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan
311 self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0)
312 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
313 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
314 self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0)
315 self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0)
316 self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0)
317 self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0)
318 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
319 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
320 self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0)
321 self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0)
322 self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0)
323 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
324 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
325 self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0)
326 self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0)
327 self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0)
328 self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0)
329 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
330 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
331 self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0)
332 self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0)
333
334 # x**y defers to complex pow for finite negative x and
335 # non-integral y.
336 self.assertEqual(type(pow_op(-2.0, -0.5)), complex)
337 self.assertEqual(type(pow_op(-2.0, 0.5)), complex)
338 self.assertEqual(type(pow_op(-1.0, -0.5)), complex)
339 self.assertEqual(type(pow_op(-1.0, 0.5)), complex)
340 self.assertEqual(type(pow_op(-0.5, -0.5)), complex)
341 self.assertEqual(type(pow_op(-0.5, 0.5)), complex)
342
343 # x**-INF is INF for abs(x) < 1
344 self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF)
345 self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF)
346 self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF)
347 self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF)
348
349 # x**-INF is 0 for abs(x) > 1
350 self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0)
351 self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0)
352 self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0)
353 self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0)
354
355 # x**INF is 0 for abs(x) < 1
356 self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0)
357 self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0)
358 self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0)
359 self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0)
360
361 # x**INF is INF for abs(x) > 1
362 self.assertEqualAndEqualSign(pow_op(-INF, INF), INF)
363 self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF)
364 self.assertEqualAndEqualSign(pow_op(2.0, INF), INF)
365 self.assertEqualAndEqualSign(pow_op(INF, INF), INF)
366
367 # (-INF)**y is -0.0 for y a negative odd integer
368 self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0)
369
370 # (-INF)**y is 0.0 for y negative but not an odd integer
371 self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0)
372 self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0)
373
374 # (-INF)**y is -INF for y a positive odd integer
375 self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF)
376
377 # (-INF)**y is INF for y positive but not an odd integer
378 self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF)
379 self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF)
380
381 # INF**y is INF for y positive
382 self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF)
383 self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF)
384 self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF)
385
386 # INF**y is 0.0 for y negative
387 self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0)
388 self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0)
389 self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0)
390
391 # basic checks not covered by the special cases above
392 self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25)
393 self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5)
394 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
395 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
396 self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0)
397 self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0)
398 self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0)
399 self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0)
400 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
401 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
402 self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0)
403 self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0)
404 self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25)
405 self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5)
406 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
407 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
408 self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0)
409 self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0)
410
411 # 1 ** large and -1 ** large; some libms apparently
412 # have problems with these
413 self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0)
414 self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0)
415 self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0)
416 self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0)
417
418 # check sign for results that underflow to 0
419 self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0)
420 self.assertEqual(type(pow_op(-2.0, -2000.5)), complex)
421 self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0)
422 self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0)
423 self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0)
424 self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0)
425 self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0)
426 self.assertEqual(type(pow_op(-0.5, 2000.5)), complex)
427 self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0)
428 self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0)
429 self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0)
430 self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0)
431
432 # check we don't raise an exception for subnormal results,
433 # and validate signs. Tests currently disabled, since
434 # they fail on systems where a subnormal result from pow
435 # is flushed to zero (e.g. Debian/ia64.)
436 #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315)
437 #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315)
438 #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315)
439 #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315)
440 #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315)
441 #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315)
442 #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
443 #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
Mark Dickinson4a1f5932008-11-12 23:23:36 +0000444
445
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000446class FormatFunctionsTestCase(unittest.TestCase):
447
448 def setUp(self):
449 self.save_formats = {'double':float.__getformat__('double'),
450 'float':float.__getformat__('float')}
451
452 def tearDown(self):
453 float.__setformat__('double', self.save_formats['double'])
454 float.__setformat__('float', self.save_formats['float'])
455
456 def test_getformat(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000457 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000458 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000459 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000460 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
461 self.assertRaises(ValueError, float.__getformat__, 'chicken')
462 self.assertRaises(TypeError, float.__getformat__, 1)
463
464 def test_setformat(self):
465 for t in 'double', 'float':
466 float.__setformat__(t, 'unknown')
467 if self.save_formats[t] == 'IEEE, big-endian':
468 self.assertRaises(ValueError, float.__setformat__,
469 t, 'IEEE, little-endian')
470 elif self.save_formats[t] == 'IEEE, little-endian':
471 self.assertRaises(ValueError, float.__setformat__,
472 t, 'IEEE, big-endian')
473 else:
474 self.assertRaises(ValueError, float.__setformat__,
475 t, 'IEEE, big-endian')
476 self.assertRaises(ValueError, float.__setformat__,
477 t, 'IEEE, little-endian')
478 self.assertRaises(ValueError, float.__setformat__,
479 t, 'chicken')
480 self.assertRaises(ValueError, float.__setformat__,
481 'chicken', 'unknown')
482
Guido van Rossum2be161d2007-05-15 20:43:51 +0000483BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000484LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000485BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000486LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000487
Guido van Rossum2be161d2007-05-15 20:43:51 +0000488BE_FLOAT_INF = b'\x7f\x80\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000489LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +0000490BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +0000491LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000492
493# on non-IEEE platforms, attempting to unpack a bit pattern
494# representing an infinity or a NaN should raise an exception.
495
496class UnknownFormatTestCase(unittest.TestCase):
497 def setUp(self):
498 self.save_formats = {'double':float.__getformat__('double'),
499 'float':float.__getformat__('float')}
500 float.__setformat__('double', 'unknown')
501 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000502
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000503 def tearDown(self):
504 float.__setformat__('double', self.save_formats['double'])
505 float.__setformat__('float', self.save_formats['float'])
506
507 def test_double_specials_dont_unpack(self):
508 for fmt, data in [('>d', BE_DOUBLE_INF),
509 ('>d', BE_DOUBLE_NAN),
510 ('<d', LE_DOUBLE_INF),
511 ('<d', LE_DOUBLE_NAN)]:
512 self.assertRaises(ValueError, struct.unpack, fmt, data)
513
514 def test_float_specials_dont_unpack(self):
515 for fmt, data in [('>f', BE_FLOAT_INF),
516 ('>f', BE_FLOAT_NAN),
517 ('<f', LE_FLOAT_INF),
518 ('<f', LE_FLOAT_NAN)]:
519 self.assertRaises(ValueError, struct.unpack, fmt, data)
520
521
522# on an IEEE platform, all we guarantee is that bit patterns
523# representing infinities or NaNs do not raise an exception; all else
524# is accident (today).
Guido van Rossum04110fb2007-08-24 16:32:05 +0000525# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000526
527class IEEEFormatTestCase(unittest.TestCase):
528 if float.__getformat__("double").startswith("IEEE"):
529 def test_double_specials_do_unpack(self):
530 for fmt, data in [('>d', BE_DOUBLE_INF),
531 ('>d', BE_DOUBLE_NAN),
532 ('<d', LE_DOUBLE_INF),
533 ('<d', LE_DOUBLE_NAN)]:
534 struct.unpack(fmt, data)
535
536 if float.__getformat__("float").startswith("IEEE"):
537 def test_float_specials_do_unpack(self):
538 for fmt, data in [('>f', BE_FLOAT_INF),
539 ('>f', BE_FLOAT_NAN),
540 ('<f', LE_FLOAT_INF),
541 ('<f', LE_FLOAT_NAN)]:
542 struct.unpack(fmt, data)
543
Guido van Rossum04110fb2007-08-24 16:32:05 +0000544 if float.__getformat__("double").startswith("IEEE"):
545 def test_negative_zero(self):
546 import math
547 def pos_pos():
548 return 0.0, math.atan2(0.0, -1)
549 def pos_neg():
550 return 0.0, math.atan2(-0.0, -1)
551 def neg_pos():
552 return -0.0, math.atan2(0.0, -1)
553 def neg_neg():
554 return -0.0, math.atan2(-0.0, -1)
555 self.assertEquals(pos_pos(), neg_pos())
556 self.assertEquals(pos_neg(), neg_neg())
557
Eric Smith8c663262007-08-25 02:26:07 +0000558class FormatTestCase(unittest.TestCase):
Eric Smith11fe3e02007-08-31 01:33:06 +0000559 def test_format(self):
Eric Smith8c663262007-08-25 02:26:07 +0000560 # these should be rewritten to use both format(x, spec) and
561 # x.__format__(spec)
562
563 self.assertEqual(format(0.0, 'f'), '0.000000')
564
565 # the default is 'g', except for empty format spec
566 self.assertEqual(format(0.0, ''), '0.0')
567 self.assertEqual(format(0.01, ''), '0.01')
568 self.assertEqual(format(0.01, 'g'), '0.01')
569
Eric Smith63376222009-05-05 14:04:18 +0000570 # empty presentation type should format in the same way as str
571 # (issue 5920)
572 x = 100/7.
573 self.assertEqual(format(x, ''), str(x))
574 self.assertEqual(format(x, '-'), str(x))
575 self.assertEqual(format(x, '>'), str(x))
576 self.assertEqual(format(x, '2'), str(x))
Eric Smith8c663262007-08-25 02:26:07 +0000577
578 self.assertEqual(format(1.0, 'f'), '1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000579
580 self.assertEqual(format(-1.0, 'f'), '-1.000000')
Eric Smith8c663262007-08-25 02:26:07 +0000581
582 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
583 self.assertEqual(format(-1.0, ' f'), '-1.000000')
584 self.assertEqual(format( 1.0, '+f'), '+1.000000')
585 self.assertEqual(format(-1.0, '+f'), '-1.000000')
586
587 # % formatting
588 self.assertEqual(format(-1.0, '%'), '-100.000000%')
589
590 # conversion to string should fail
591 self.assertRaises(ValueError, format, 3.0, "s")
592
Eric Smith7b69c6c2008-01-27 21:07:59 +0000593 # other format specifiers shouldn't work on floats,
594 # in particular int specifiers
595 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
596 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
597 if not format_spec in 'eEfFgGn%':
598 self.assertRaises(ValueError, format, 0.0, format_spec)
599 self.assertRaises(ValueError, format, 1.0, format_spec)
600 self.assertRaises(ValueError, format, -1.0, format_spec)
601 self.assertRaises(ValueError, format, 1e100, format_spec)
602 self.assertRaises(ValueError, format, -1e100, format_spec)
603 self.assertRaises(ValueError, format, 1e-100, format_spec)
604 self.assertRaises(ValueError, format, -1e-100, format_spec)
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000605
Eric Smith741191f2009-05-06 13:08:15 +0000606 # issue 3382
607 self.assertEqual(format(NAN, 'f'), 'nan')
608 self.assertEqual(format(NAN, 'F'), 'NAN')
609 self.assertEqual(format(INF, 'f'), 'inf')
610 self.assertEqual(format(INF, 'F'), 'INF')
611
Eric Smith0923d1d2009-04-16 20:16:10 +0000612 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
613 "test requires IEEE 754 doubles")
614 def test_format_testfile(self):
615 for line in open(format_testfile):
616 if line.startswith('--'):
617 continue
618 line = line.strip()
619 if not line:
620 continue
621
622 lhs, rhs = map(str.strip, line.split('->'))
623 fmt, arg = lhs.split()
624 self.assertEqual(fmt % float(arg), rhs)
625 self.assertEqual(fmt % -float(arg), '-' + rhs)
626
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000627 def test_issue5864(self):
628 self.assertEquals(format(123.456, '.4'), '123.5')
629 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
630 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
631
Mark Dickinson7efad9e2009-04-17 20:59:58 +0000632class ReprTestCase(unittest.TestCase):
633 def test_repr(self):
634 floats_file = open(os.path.join(os.path.split(__file__)[0],
635 'floating_points.txt'))
636 for line in floats_file:
637 line = line.strip()
638 if not line or line.startswith('#'):
639 continue
640 v = eval(line)
641 self.assertEqual(v, eval(repr(v)))
642 floats_file.close()
643
Eric Smith0923d1d2009-04-16 20:16:10 +0000644 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
645 "applies only when using short float repr style")
646 def test_short_repr(self):
647 # test short float repr introduced in Python 3.1. One aspect
648 # of this repr is that we get some degree of str -> float ->
649 # str roundtripping. In particular, for any numeric string
650 # containing 15 or fewer significant digits, those exact same
651 # digits (modulo trailing zeros) should appear in the output.
652 # No more repr(0.03) -> "0.029999999999999999"!
653
654 test_strings = [
655 # output always includes *either* a decimal point and at
656 # least one digit after that point, or an exponent.
657 '0.0',
658 '1.0',
659 '0.01',
660 '0.02',
661 '0.03',
662 '0.04',
663 '0.05',
664 '1.23456789',
665 '10.0',
666 '100.0',
667 # values >= 1e16 get an exponent...
668 '1000000000000000.0',
669 '9999999999999990.0',
670 '1e+16',
671 '1e+17',
672 # ... and so do values < 1e-4
673 '0.001',
674 '0.001001',
675 '0.00010000000000001',
676 '0.0001',
677 '9.999999999999e-05',
678 '1e-05',
679 # values designed to provoke failure if the FPU rounding
680 # precision isn't set correctly
681 '8.72293771110361e+25',
682 '7.47005307342313e+26',
683 '2.86438000439698e+28',
684 '8.89142905246179e+28',
685 '3.08578087079232e+35',
686 ]
687
688 for s in test_strings:
689 negs = '-'+s
690 self.assertEqual(s, repr(float(s)))
691 self.assertEqual(negs, repr(float(negs)))
692
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000693class RoundTestCase(unittest.TestCase):
694 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
695 "test requires IEEE 754 doubles")
696 def test_inf_nan(self):
697 self.assertRaises(OverflowError, round, INF)
698 self.assertRaises(OverflowError, round, -INF)
699 self.assertRaises(ValueError, round, NAN)
Mark Dickinson4ca33d12009-11-24 10:59:34 +0000700 self.assertRaises(TypeError, round, INF, 0.0)
701 self.assertRaises(TypeError, round, -INF, 1.0)
702 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
703 self.assertRaises(TypeError, round, -0.0, 1j)
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000704
705 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
706 "test requires IEEE 754 doubles")
707 def test_large_n(self):
708 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
709 self.assertEqual(round(123.456, n), 123.456)
710 self.assertEqual(round(-123.456, n), -123.456)
711 self.assertEqual(round(1e300, n), 1e300)
712 self.assertEqual(round(1e-320, n), 1e-320)
713 self.assertEqual(round(1e150, 300), 1e150)
714 self.assertEqual(round(1e300, 307), 1e300)
715 self.assertEqual(round(-3.1415, 308), -3.1415)
716 self.assertEqual(round(1e150, 309), 1e150)
717 self.assertEqual(round(1.4e-315, 315), 1e-315)
718
719 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
720 "test requires IEEE 754 doubles")
721 def test_small_n(self):
722 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
723 self.assertEqual(round(123.456, n), 0.0)
724 self.assertEqual(round(-123.456, n), -0.0)
725 self.assertEqual(round(1e300, n), 0.0)
726 self.assertEqual(round(1e-320, n), 0.0)
727
728 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
729 "test requires IEEE 754 doubles")
730 def test_overflow(self):
731 self.assertRaises(OverflowError, round, 1.6e308, -308)
732 self.assertRaises(OverflowError, round, -1.7e308, -308)
733
734 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
735 "applies only when using short float repr style")
736 def test_previous_round_bugs(self):
737 # particular cases that have occurred in bug reports
738 self.assertEqual(round(562949953421312.5, 1),
739 562949953421312.5)
740 self.assertEqual(round(56294995342131.5, 3),
741 56294995342131.5)
742 # round-half-even
743 self.assertEqual(round(25.0, -1), 20.0)
744 self.assertEqual(round(35.0, -1), 40.0)
745 self.assertEqual(round(45.0, -1), 40.0)
746 self.assertEqual(round(55.0, -1), 60.0)
747 self.assertEqual(round(65.0, -1), 60.0)
748 self.assertEqual(round(75.0, -1), 80.0)
749 self.assertEqual(round(85.0, -1), 80.0)
750 self.assertEqual(round(95.0, -1), 100.0)
751
752 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
753 "applies only when using short float repr style")
754 def test_matches_float_format(self):
755 # round should give the same results as float formatting
756 for i in range(500):
757 x = i/1000.
758 self.assertEqual(float(format(x, '.0f')), round(x, 0))
759 self.assertEqual(float(format(x, '.1f')), round(x, 1))
760 self.assertEqual(float(format(x, '.2f')), round(x, 2))
761 self.assertEqual(float(format(x, '.3f')), round(x, 3))
762
763 for i in range(5, 5000, 10):
764 x = i/1000.
765 self.assertEqual(float(format(x, '.0f')), round(x, 0))
766 self.assertEqual(float(format(x, '.1f')), round(x, 1))
767 self.assertEqual(float(format(x, '.2f')), round(x, 2))
768 self.assertEqual(float(format(x, '.3f')), round(x, 3))
769
770 for i in range(500):
771 x = random.random()
772 self.assertEqual(float(format(x, '.0f')), round(x, 0))
773 self.assertEqual(float(format(x, '.1f')), round(x, 1))
774 self.assertEqual(float(format(x, '.2f')), round(x, 2))
775 self.assertEqual(float(format(x, '.3f')), round(x, 3))
776
777
Eric Smith8a10ecc2009-12-02 17:58:24 +0000778 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
779 "test requires IEEE 754 doubles")
780 def test_format_specials(self):
781 # Test formatting of nans and infs.
782
783 def test(fmt, value, expected):
784 # Test with both % and format().
785 self.assertEqual(fmt % value, expected, fmt)
786 if not '#' in fmt:
787 # Until issue 7094 is implemented, format() for floats doesn't
788 # support '#' formatting
789 fmt = fmt[1:] # strip off the %
790 self.assertEqual(format(value, fmt), expected, fmt)
791
792 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
793 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
794 pfmt = '%+' + fmt[1:]
795 sfmt = '% ' + fmt[1:]
796 test(fmt, INF, 'inf')
797 test(fmt, -INF, '-inf')
798 test(fmt, NAN, 'nan')
799 test(fmt, -NAN, 'nan')
800 # When asking for a sign, it's always provided. nans are
801 # always positive.
802 test(pfmt, INF, '+inf')
803 test(pfmt, -INF, '-inf')
804 test(pfmt, NAN, '+nan')
805 test(pfmt, -NAN, '+nan')
806 # When using ' ' for a sign code, only infs can be negative.
807 # Others have a space.
808 test(sfmt, INF, ' inf')
809 test(sfmt, -INF, '-inf')
810 test(sfmt, NAN, ' nan')
811 test(sfmt, -NAN, ' nan')
812
Mark Dickinsone6a076d2009-04-18 11:48:33 +0000813
Christian Heimes99170a52007-12-19 02:07:34 +0000814# Beginning with Python 2.6 float has cross platform compatible
Georg Brandl2ee470f2008-07-16 12:55:28 +0000815# ways to create and represent inf and nan
Christian Heimes99170a52007-12-19 02:07:34 +0000816class InfNanTest(unittest.TestCase):
817 def test_inf_from_str(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000818 self.assertTrue(isinf(float("inf")))
819 self.assertTrue(isinf(float("+inf")))
820 self.assertTrue(isinf(float("-inf")))
821 self.assertTrue(isinf(float("infinity")))
822 self.assertTrue(isinf(float("+infinity")))
823 self.assertTrue(isinf(float("-infinity")))
Christian Heimes99170a52007-12-19 02:07:34 +0000824
825 self.assertEqual(repr(float("inf")), "inf")
826 self.assertEqual(repr(float("+inf")), "inf")
827 self.assertEqual(repr(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000828 self.assertEqual(repr(float("infinity")), "inf")
829 self.assertEqual(repr(float("+infinity")), "inf")
830 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000831
832 self.assertEqual(repr(float("INF")), "inf")
833 self.assertEqual(repr(float("+Inf")), "inf")
834 self.assertEqual(repr(float("-iNF")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000835 self.assertEqual(repr(float("Infinity")), "inf")
836 self.assertEqual(repr(float("+iNfInItY")), "inf")
837 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000838
839 self.assertEqual(str(float("inf")), "inf")
840 self.assertEqual(str(float("+inf")), "inf")
841 self.assertEqual(str(float("-inf")), "-inf")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000842 self.assertEqual(str(float("infinity")), "inf")
843 self.assertEqual(str(float("+infinity")), "inf")
844 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes99170a52007-12-19 02:07:34 +0000845
846 self.assertRaises(ValueError, float, "info")
847 self.assertRaises(ValueError, float, "+info")
848 self.assertRaises(ValueError, float, "-info")
849 self.assertRaises(ValueError, float, "in")
850 self.assertRaises(ValueError, float, "+in")
851 self.assertRaises(ValueError, float, "-in")
Georg Brandl2ee470f2008-07-16 12:55:28 +0000852 self.assertRaises(ValueError, float, "infinit")
853 self.assertRaises(ValueError, float, "+Infin")
854 self.assertRaises(ValueError, float, "-INFI")
855 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes99170a52007-12-19 02:07:34 +0000856
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000857 self.assertRaises(ValueError, float, "++Inf")
858 self.assertRaises(ValueError, float, "-+inf")
859 self.assertRaises(ValueError, float, "+-infinity")
860 self.assertRaises(ValueError, float, "--Infinity")
861
Christian Heimes99170a52007-12-19 02:07:34 +0000862 def test_inf_as_str(self):
863 self.assertEqual(repr(1e300 * 1e300), "inf")
864 self.assertEqual(repr(-1e300 * 1e300), "-inf")
865
866 self.assertEqual(str(1e300 * 1e300), "inf")
867 self.assertEqual(str(-1e300 * 1e300), "-inf")
868
869 def test_nan_from_str(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000870 self.assertTrue(isnan(float("nan")))
871 self.assertTrue(isnan(float("+nan")))
872 self.assertTrue(isnan(float("-nan")))
Christian Heimes99170a52007-12-19 02:07:34 +0000873
874 self.assertEqual(repr(float("nan")), "nan")
875 self.assertEqual(repr(float("+nan")), "nan")
876 self.assertEqual(repr(float("-nan")), "nan")
877
878 self.assertEqual(repr(float("NAN")), "nan")
879 self.assertEqual(repr(float("+NAn")), "nan")
880 self.assertEqual(repr(float("-NaN")), "nan")
881
882 self.assertEqual(str(float("nan")), "nan")
883 self.assertEqual(str(float("+nan")), "nan")
884 self.assertEqual(str(float("-nan")), "nan")
885
886 self.assertRaises(ValueError, float, "nana")
887 self.assertRaises(ValueError, float, "+nana")
888 self.assertRaises(ValueError, float, "-nana")
889 self.assertRaises(ValueError, float, "na")
890 self.assertRaises(ValueError, float, "+na")
891 self.assertRaises(ValueError, float, "-na")
892
Mark Dickinsonbd16edd2009-05-20 22:05:25 +0000893 self.assertRaises(ValueError, float, "++nan")
894 self.assertRaises(ValueError, float, "-+NAN")
895 self.assertRaises(ValueError, float, "+-NaN")
896 self.assertRaises(ValueError, float, "--nAn")
897
Christian Heimes99170a52007-12-19 02:07:34 +0000898 def test_nan_as_str(self):
899 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
900 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
901
902 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
903 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes827b35c2007-12-10 22:19:17 +0000904
Christian Heimes53876d92008-04-19 00:31:39 +0000905 def notest_float_nan(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000906 self.assertTrue(NAN.is_nan())
907 self.assertFalse(INF.is_nan())
908 self.assertFalse((0.).is_nan())
Christian Heimes53876d92008-04-19 00:31:39 +0000909
910 def notest_float_inf(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000911 self.assertTrue(INF.is_inf())
912 self.assertFalse(NAN.is_inf())
913 self.assertFalse((0.).is_inf())
Christian Heimes53876d92008-04-19 00:31:39 +0000914
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000915fromHex = float.fromhex
916toHex = float.hex
917class HexFloatTestCase(unittest.TestCase):
918 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
919 MIN = fromHex('0x1p-1022') # min normal
920 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
921 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
922
923 def identical(self, x, y):
924 # check that floats x and y are identical, or that both
925 # are NaNs
926 if isnan(x) or isnan(y):
927 if isnan(x) == isnan(y):
928 return
929 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
930 return
931 self.fail('%r not identical to %r' % (x, y))
932
933 def test_ends(self):
Mark Dickinson38bbc482008-07-16 11:32:23 +0000934 self.identical(self.MIN, ldexp(1.0, -1022))
935 self.identical(self.TINY, ldexp(1.0, -1074))
936 self.identical(self.EPS, ldexp(1.0, -52))
937 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000938
939 def test_invalid_inputs(self):
940 invalid_inputs = [
941 'infi', # misspelt infinities and nans
942 '-Infinit',
943 '++inf',
944 '-+Inf',
945 '--nan',
946 '+-NaN',
947 'snan',
948 'NaNs',
949 'nna',
Mark Dickinsond1ec8b22009-05-11 15:45:15 +0000950 'an',
951 'nf',
952 'nfinity',
953 'inity',
954 'iinity',
Mark Dickinson65fe25e2008-07-16 11:30:51 +0000955 '0xnan',
956 '',
957 ' ',
958 'x1.0p0',
959 '0xX1.0p0',
960 '+ 0x1.0p0', # internal whitespace
961 '- 0x1.0p0',
962 '0 x1.0p0',
963 '0x 1.0p0',
964 '0x1 2.0p0',
965 '+0x1 .0p0',
966 '0x1. 0p0',
967 '-0x1.0 1p0',
968 '-0x1.0 p0',
969 '+0x1.0p +0',
970 '0x1.0p -0',
971 '0x1.0p 0',
972 '+0x1.0p+ 0',
973 '-0x1.0p- 0',
974 '++0x1.0p-0', # double signs
975 '--0x1.0p0',
976 '+-0x1.0p+0',
977 '-+0x1.0p0',
978 '0x1.0p++0',
979 '+0x1.0p+-0',
980 '-0x1.0p-+0',
981 '0x1.0p--0',
982 '0x1.0.p0',
983 '0x.p0', # no hex digits before or after point
984 '0x1,p0', # wrong decimal point character
985 '0x1pa',
986 '0x1p\uff10', # fullwidth Unicode digits
987 '\uff10x1p0',
988 '0x\uff11p0',
989 '0x1.\uff10p0',
990 '0x1p0 \n 0x2p0',
991 '0x1p0\0 0x1p0', # embedded null byte is not end of string
992 ]
993 for x in invalid_inputs:
Mark Dickinson589b7952008-08-21 20:05:56 +0000994 try:
995 result = fromHex(x)
996 except ValueError:
997 pass
998 else:
999 self.fail('Expected float.fromhex(%r) to raise ValueError; '
1000 'got %r instead' % (x, result))
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001001
1002
Mark Dickinsond1ec8b22009-05-11 15:45:15 +00001003 def test_whitespace(self):
1004 value_pairs = [
1005 ('inf', INF),
1006 ('-Infinity', -INF),
1007 ('nan', NAN),
1008 ('1.0', 1.0),
1009 ('-0x.2', -0.125),
1010 ('-0.0', -0.0)
1011 ]
1012 whitespace = [
1013 '',
1014 ' ',
1015 '\t',
1016 '\n',
1017 '\n \t',
1018 '\f',
1019 '\v',
1020 '\r'
1021 ]
1022 for inp, expected in value_pairs:
1023 for lead in whitespace:
1024 for trail in whitespace:
1025 got = fromHex(lead + inp + trail)
1026 self.identical(got, expected)
1027
1028
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001029 def test_from_hex(self):
1030 MIN = self.MIN;
1031 MAX = self.MAX;
1032 TINY = self.TINY;
1033 EPS = self.EPS;
1034
1035 # two spellings of infinity, with optional signs; case-insensitive
1036 self.identical(fromHex('inf'), INF)
1037 self.identical(fromHex('+Inf'), INF)
1038 self.identical(fromHex('-INF'), -INF)
1039 self.identical(fromHex('iNf'), INF)
1040 self.identical(fromHex('Infinity'), INF)
1041 self.identical(fromHex('+INFINITY'), INF)
1042 self.identical(fromHex('-infinity'), -INF)
1043 self.identical(fromHex('-iNFiNitY'), -INF)
1044
1045 # nans with optional sign; case insensitive
1046 self.identical(fromHex('nan'), NAN)
1047 self.identical(fromHex('+NaN'), NAN)
1048 self.identical(fromHex('-NaN'), NAN)
1049 self.identical(fromHex('-nAN'), NAN)
1050
1051 # variations in input format
1052 self.identical(fromHex('1'), 1.0)
1053 self.identical(fromHex('+1'), 1.0)
1054 self.identical(fromHex('1.'), 1.0)
1055 self.identical(fromHex('1.0'), 1.0)
1056 self.identical(fromHex('1.0p0'), 1.0)
1057 self.identical(fromHex('01'), 1.0)
1058 self.identical(fromHex('01.'), 1.0)
1059 self.identical(fromHex('0x1'), 1.0)
1060 self.identical(fromHex('0x1.'), 1.0)
1061 self.identical(fromHex('0x1.0'), 1.0)
1062 self.identical(fromHex('+0x1.0'), 1.0)
1063 self.identical(fromHex('0x1p0'), 1.0)
1064 self.identical(fromHex('0X1p0'), 1.0)
1065 self.identical(fromHex('0X1P0'), 1.0)
1066 self.identical(fromHex('0x1P0'), 1.0)
1067 self.identical(fromHex('0x1.p0'), 1.0)
1068 self.identical(fromHex('0x1.0p0'), 1.0)
1069 self.identical(fromHex('0x.1p4'), 1.0)
1070 self.identical(fromHex('0x.1p04'), 1.0)
1071 self.identical(fromHex('0x.1p004'), 1.0)
1072 self.identical(fromHex('0x1p+0'), 1.0)
1073 self.identical(fromHex('0x1P-0'), 1.0)
1074 self.identical(fromHex('+0x1p0'), 1.0)
1075 self.identical(fromHex('0x01p0'), 1.0)
1076 self.identical(fromHex('0x1p00'), 1.0)
1077 self.identical(fromHex(' 0x1p0 '), 1.0)
1078 self.identical(fromHex('\n 0x1p0'), 1.0)
1079 self.identical(fromHex('0x1p0 \t'), 1.0)
1080 self.identical(fromHex('0xap0'), 10.0)
1081 self.identical(fromHex('0xAp0'), 10.0)
1082 self.identical(fromHex('0xaP0'), 10.0)
1083 self.identical(fromHex('0xAP0'), 10.0)
1084 self.identical(fromHex('0xbep0'), 190.0)
1085 self.identical(fromHex('0xBep0'), 190.0)
1086 self.identical(fromHex('0xbEp0'), 190.0)
1087 self.identical(fromHex('0XBE0P-4'), 190.0)
1088 self.identical(fromHex('0xBEp0'), 190.0)
1089 self.identical(fromHex('0xB.Ep4'), 190.0)
1090 self.identical(fromHex('0x.BEp8'), 190.0)
1091 self.identical(fromHex('0x.0BEp12'), 190.0)
1092
1093 # moving the point around
1094 pi = fromHex('0x1.921fb54442d18p1')
1095 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
1096 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
1097 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
1098 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
1099 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
1100 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
1101 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
1102 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
1103 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
1104 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
1105 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
1106 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
1107 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
1108 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
1109 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
1110 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
1111 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
1112 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
1113 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
1114 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
1115 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
1116 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
1117 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
1118 # ...
1119 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
1120 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
1121 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
1122 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
1123 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
1124 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
1125 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
1126 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
1127 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
1128
1129
1130 # results that should overflow...
1131 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
1132 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
1133 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
1134 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
1135 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
1136 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
1137 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
1138 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
1139 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
1140 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
1141 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
1142 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
1143 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
1144 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
1145 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
1146 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
1147 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
1148 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
1149 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
1150
1151 # ...and those that round to +-max float
1152 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
1153 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
1154 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
1155
1156 # zeros
1157 self.identical(fromHex('0x0p0'), 0.0)
1158 self.identical(fromHex('0x0p1000'), 0.0)
1159 self.identical(fromHex('-0x0p1023'), -0.0)
1160 self.identical(fromHex('0X0p1024'), 0.0)
1161 self.identical(fromHex('-0x0p1025'), -0.0)
1162 self.identical(fromHex('0X0p2000'), 0.0)
1163 self.identical(fromHex('0x0p123456789123456789'), 0.0)
1164 self.identical(fromHex('-0X0p-0'), -0.0)
1165 self.identical(fromHex('-0X0p-1000'), -0.0)
1166 self.identical(fromHex('0x0p-1023'), 0.0)
1167 self.identical(fromHex('-0X0p-1024'), -0.0)
1168 self.identical(fromHex('-0x0p-1025'), -0.0)
1169 self.identical(fromHex('-0x0p-1072'), -0.0)
1170 self.identical(fromHex('0X0p-1073'), 0.0)
1171 self.identical(fromHex('-0x0p-1074'), -0.0)
1172 self.identical(fromHex('0x0p-1075'), 0.0)
1173 self.identical(fromHex('0X0p-1076'), 0.0)
1174 self.identical(fromHex('-0X0p-2000'), -0.0)
1175 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
1176
1177 # values that should underflow to 0
1178 self.identical(fromHex('0X1p-1075'), 0.0)
1179 self.identical(fromHex('-0X1p-1075'), -0.0)
1180 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
1181 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
1182 self.identical(fromHex('-0x1.1p-1075'), -TINY)
1183 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
1184
1185 # check round-half-even is working correctly near 0 ...
1186 self.identical(fromHex('0x1p-1076'), 0.0)
1187 self.identical(fromHex('0X2p-1076'), 0.0)
1188 self.identical(fromHex('0X3p-1076'), TINY)
1189 self.identical(fromHex('0x4p-1076'), TINY)
1190 self.identical(fromHex('0X5p-1076'), TINY)
1191 self.identical(fromHex('0X6p-1076'), 2*TINY)
1192 self.identical(fromHex('0x7p-1076'), 2*TINY)
1193 self.identical(fromHex('0X8p-1076'), 2*TINY)
1194 self.identical(fromHex('0X9p-1076'), 2*TINY)
1195 self.identical(fromHex('0xap-1076'), 2*TINY)
1196 self.identical(fromHex('0Xbp-1076'), 3*TINY)
1197 self.identical(fromHex('0xcp-1076'), 3*TINY)
1198 self.identical(fromHex('0Xdp-1076'), 3*TINY)
1199 self.identical(fromHex('0Xep-1076'), 4*TINY)
1200 self.identical(fromHex('0xfp-1076'), 4*TINY)
1201 self.identical(fromHex('0x10p-1076'), 4*TINY)
1202 self.identical(fromHex('-0x1p-1076'), -0.0)
1203 self.identical(fromHex('-0X2p-1076'), -0.0)
1204 self.identical(fromHex('-0x3p-1076'), -TINY)
1205 self.identical(fromHex('-0X4p-1076'), -TINY)
1206 self.identical(fromHex('-0x5p-1076'), -TINY)
1207 self.identical(fromHex('-0x6p-1076'), -2*TINY)
1208 self.identical(fromHex('-0X7p-1076'), -2*TINY)
1209 self.identical(fromHex('-0X8p-1076'), -2*TINY)
1210 self.identical(fromHex('-0X9p-1076'), -2*TINY)
1211 self.identical(fromHex('-0Xap-1076'), -2*TINY)
1212 self.identical(fromHex('-0xbp-1076'), -3*TINY)
1213 self.identical(fromHex('-0xcp-1076'), -3*TINY)
1214 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
1215 self.identical(fromHex('-0xep-1076'), -4*TINY)
1216 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
1217 self.identical(fromHex('-0X10p-1076'), -4*TINY)
1218
1219 # ... and near MIN ...
1220 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
1221 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
1222 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
1223 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
1224 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
1225 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
1226 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
1227 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
1228 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
1229 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
1230 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
1231 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
1232 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
1233 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
1234 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
1235 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
1236 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
1237 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
1238 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
1239 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
1240 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
1241 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
1242 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
1243 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
1244 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
1245 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
1246 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
1247 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
1248 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
1249 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
1250 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
1251 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
1252 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
1253 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
1254
1255 # ... and near 1.0.
1256 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
1257 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
1258 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
1259 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
1260 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
1261 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
1262 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
1263 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
1264 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
1265 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
1266 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
1267 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
1268 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
1269 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
1270 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
1271 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
1272 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
1273 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
1274 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
1275 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
1276 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
1277 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
1278 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
1279 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
1280 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
1281 1.0)
1282 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
1283 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
1284 1+EPS)
1285 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
1286 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
1287 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
1288 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
1289 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
1290 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
1291 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
1292 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
1293 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
1294 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
1295 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
1296 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
1297 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
1298 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
1299 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
1300 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
1301 1.0+EPS)
1302 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
1303 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
1304 1.0+2*EPS)
1305 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
1306 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
1307 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
1308 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
1309 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
1310 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
1311 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
1312 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
1313
1314 def test_roundtrip(self):
1315 def roundtrip(x):
1316 return fromHex(toHex(x))
1317
1318 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1319 self.identical(x, roundtrip(x))
1320 self.identical(-x, roundtrip(-x))
1321
1322 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1323 import random
1324 for i in range(10000):
1325 e = random.randrange(-1200, 1200)
1326 m = random.random()
1327 s = random.choice([1.0, -1.0])
1328 try:
1329 x = s*ldexp(m, e)
1330 except OverflowError:
1331 pass
1332 else:
1333 self.identical(x, fromHex(toHex(x)))
1334
Mark Dickinson81612e82010-01-12 23:04:19 +00001335class StrtodTestCase(unittest.TestCase):
1336 def check_string(self, s):
1337 expected = strtod(s)
1338 try:
1339 fs = float(s)
1340 except OverflowError:
1341 got = '-inf' if s[0] == '-' else 'inf'
1342 else:
1343 got = fs.hex()
1344 self.assertEqual(expected, got,
1345 "Incorrectly rounded str->float conversion for "
1346 "{}: expected {}, got {}".format(s, expected, got))
1347
1348 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
1349 "applies only when using short float repr style")
1350 def test_bug7632(self):
1351 # check a few particular values that gave incorrectly rounded
1352 # results with previous versions of dtoa.c
1353 test_strings = [
1354 '94393431193180696942841837085033647913224148539854e-358',
1355 '12579816049008305546974391768996369464963024663104e-357',
1356 '17489628565202117263145367596028389348922981857013e-357',
1357 '18487398785991994634182916638542680759613590482273e-357',
1358 '32002864200581033134358724675198044527469366773928e-358',
1359 '73608278998966969345824653500136787876436005957953e-358',
1360 '64774478836417299491718435234611299336288082136054e-358',
1361 '13704940134126574534878641876947980878824688451169e-357',
1362 '46697445774047060960624497964425416610480524760471e-358',
1363 ]
1364 for s in test_strings:
1365 self.check_string(s)
1366
Christian Heimes53876d92008-04-19 00:31:39 +00001367
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001368def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001369 support.run_unittest(
Amaury Forgeot d'Arc7e958d12008-09-06 21:03:22 +00001370 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001371 FormatFunctionsTestCase,
1372 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +00001373 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +00001374 FormatTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001375 ReprTestCase,
Mark Dickinsone6a076d2009-04-18 11:48:33 +00001376 RoundTestCase,
Christian Heimes99170a52007-12-19 02:07:34 +00001377 InfNanTest,
Mark Dickinson65fe25e2008-07-16 11:30:51 +00001378 HexFloatTestCase,
Mark Dickinson81612e82010-01-12 23:04:19 +00001379 StrtodTestCase,
Christian Heimesb76922a2007-12-11 01:06:40 +00001380 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001381
1382if __name__ == '__main__':
1383 test_main()