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