blob: ddaf7bd09044b9fc68a195fa18f77a0a8b56fc2b [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes284d9272007-12-10 22:28:56 +00003import os
Michael W. Hudsonba283e22005-05-27 15:23:20 +00004from test import test_support
Christian Heimes6f341092008-04-18 23:13:07 +00005import math
Mark Dickinson7103aa42008-07-15 19:08:33 +00006from math import isinf, isnan, copysign, ldexp
Christian Heimes6f341092008-04-18 23:13:07 +00007import operator
Mark Dickinsonbd15a062009-11-18 19:33:35 +00008import random
9import fractions
10import sys
Michael W. Hudsonba283e22005-05-27 15:23:20 +000011
Christian Heimes6f341092008-04-18 23:13:07 +000012INF = float("inf")
13NAN = float("nan")
Christian Heimes0a8143f2007-12-18 23:22:54 +000014
Mark Dickinson99d652e2009-12-30 12:12:23 +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
Mark Dickinson61a0d052009-04-29 21:57:15 +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
Benjamin Peterson979395b2008-05-03 21:35:18 +000024class GeneralFloatCases(unittest.TestCase):
25
26 def test_float(self):
27 self.assertEqual(float(3.14), 3.14)
28 self.assertEqual(float(314), 314.0)
29 self.assertEqual(float(314L), 314.0)
30 self.assertEqual(float(" 3.14 "), 3.14)
31 self.assertRaises(ValueError, float, " 0x3.1 ")
32 self.assertRaises(ValueError, float, " -0x3.p-1 ")
33 self.assertRaises(ValueError, float, " +0x3.p-1 ")
34 self.assertRaises(ValueError, float, "++3.14")
35 self.assertRaises(ValueError, float, "+-3.14")
36 self.assertRaises(ValueError, float, "-+3.14")
37 self.assertRaises(ValueError, float, "--3.14")
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +000038 if test_support.have_unicode:
Benjamin Peterson979395b2008-05-03 21:35:18 +000039 self.assertEqual(float(unicode(" 3.14 ")), 3.14)
40 self.assertEqual(float(unicode(" \u0663.\u0661\u0664 ",'raw-unicode-escape')), 3.14)
Benjamin Peterson979395b2008-05-03 21:35:18 +000041
Mark Dickinson53e9fa42009-10-27 22:09:33 +000042 # extra long strings should no longer be a problem
43 # (in 2.6, long unicode inputs to float raised ValueError)
44 float('.' + '1'*1000)
45 float(unicode('.' + '1'*1000))
46
Benjamin Peterson979395b2008-05-03 21:35:18 +000047 @test_support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE')
48 def test_float_with_comma(self):
49 # set locale to something that doesn't use '.' for the decimal point
50 # float must not accept the locale specific decimal point but
51 # it still has to accept the normal python syntac
52 import locale
53 if not locale.localeconv()['decimal_point'] == ',':
54 return
55
56 self.assertEqual(float(" 3.14 "), 3.14)
57 self.assertEqual(float("+3.14 "), 3.14)
58 self.assertEqual(float("-3.14 "), -3.14)
59 self.assertEqual(float(".14 "), .14)
60 self.assertEqual(float("3. "), 3.0)
61 self.assertEqual(float("3.e3 "), 3000.0)
62 self.assertEqual(float("3.2e3 "), 3200.0)
63 self.assertEqual(float("2.5e-1 "), 0.25)
64 self.assertEqual(float("5e-1"), 0.5)
65 self.assertRaises(ValueError, float, " 3,14 ")
66 self.assertRaises(ValueError, float, " +3,14 ")
67 self.assertRaises(ValueError, float, " -3,14 ")
68 self.assertRaises(ValueError, float, " 0x3.1 ")
69 self.assertRaises(ValueError, float, " -0x3.p-1 ")
70 self.assertRaises(ValueError, float, " +0x3.p-1 ")
71 self.assertEqual(float(" 25.e-1 "), 2.5)
Benjamin Petersona853a892008-09-06 23:19:15 +000072 self.assertEqual(test_support.fcmp(float(" .25e-1 "), .025), 0)
Benjamin Peterson979395b2008-05-03 21:35:18 +000073
74 def test_floatconversion(self):
75 # Make sure that calls to __float__() work properly
76 class Foo0:
77 def __float__(self):
78 return 42.
79
80 class Foo1(object):
81 def __float__(self):
82 return 42.
83
84 class Foo2(float):
85 def __float__(self):
86 return 42.
87
88 class Foo3(float):
89 def __new__(cls, value=0.):
90 return float.__new__(cls, 2*value)
91
92 def __float__(self):
93 return self
94
95 class Foo4(float):
96 def __float__(self):
97 return 42
98
Benjamin Peterson99d36f12009-04-15 21:26:36 +000099 # Issue 5759: __float__ not called on str subclasses (though it is on
100 # unicode subclasses).
101 class FooStr(str):
102 def __float__(self):
103 return float(str(self)) + 1
104
105 class FooUnicode(unicode):
106 def __float__(self):
107 return float(unicode(self)) + 1
108
Benjamin Peterson979395b2008-05-03 21:35:18 +0000109 self.assertAlmostEqual(float(Foo0()), 42.)
110 self.assertAlmostEqual(float(Foo1()), 42.)
111 self.assertAlmostEqual(float(Foo2()), 42.)
112 self.assertAlmostEqual(float(Foo3(21)), 42.)
113 self.assertRaises(TypeError, float, Foo4(42))
Benjamin Peterson99d36f12009-04-15 21:26:36 +0000114 self.assertAlmostEqual(float(FooUnicode('8')), 9.)
115 self.assertAlmostEqual(float(FooStr('8')), 9.)
Benjamin Peterson979395b2008-05-03 21:35:18 +0000116
117 def test_floatasratio(self):
118 for f, ratio in [
119 (0.875, (7, 8)),
120 (-0.875, (-7, 8)),
121 (0.0, (0, 1)),
122 (11.5, (23, 2)),
123 ]:
124 self.assertEqual(f.as_integer_ratio(), ratio)
125
126 for i in range(10000):
127 f = random.random()
128 f *= 10 ** random.randint(-100, 100)
129 n, d = f.as_integer_ratio()
130 self.assertEqual(float(n).__truediv__(d), f)
131
132 R = fractions.Fraction
133 self.assertEqual(R(0, 1),
134 R(*float(0.0).as_integer_ratio()))
135 self.assertEqual(R(5, 2),
136 R(*float(2.5).as_integer_ratio()))
137 self.assertEqual(R(1, 2),
138 R(*float(0.5).as_integer_ratio()))
139 self.assertEqual(R(4728779608739021, 2251799813685248),
140 R(*float(2.1).as_integer_ratio()))
141 self.assertEqual(R(-4728779608739021, 2251799813685248),
142 R(*float(-2.1).as_integer_ratio()))
143 self.assertEqual(R(-2100, 1),
144 R(*float(-2100.0).as_integer_ratio()))
145
146 self.assertRaises(OverflowError, float('inf').as_integer_ratio)
147 self.assertRaises(OverflowError, float('-inf').as_integer_ratio)
148 self.assertRaises(ValueError, float('nan').as_integer_ratio)
149
Mark Dickinson99d652e2009-12-30 12:12:23 +0000150 def assertEqualAndEqualSign(self, a, b):
151 # fail unless a == b and a and b have the same sign bit;
152 # the only difference from assertEqual is that this test
153 # distingishes -0.0 and 0.0.
154 self.assertEqual((a, copysign(1.0, a)), (b, copysign(1.0, b)))
155
156 @requires_IEEE_754
157 def test_float_pow(self):
158 # test builtin pow and ** operator for IEEE 754 special cases.
159 # Special cases taken from section F.9.4.4 of the C99 specification
160
161 for pow_op in pow, operator.pow:
162 # x**NAN is NAN for any x except 1
163 self.assertTrue(isnan(pow_op(-INF, NAN)))
164 self.assertTrue(isnan(pow_op(-2.0, NAN)))
165 self.assertTrue(isnan(pow_op(-1.0, NAN)))
166 self.assertTrue(isnan(pow_op(-0.5, NAN)))
167 self.assertTrue(isnan(pow_op(-0.0, NAN)))
168 self.assertTrue(isnan(pow_op(0.0, NAN)))
169 self.assertTrue(isnan(pow_op(0.5, NAN)))
170 self.assertTrue(isnan(pow_op(2.0, NAN)))
171 self.assertTrue(isnan(pow_op(INF, NAN)))
172 self.assertTrue(isnan(pow_op(NAN, NAN)))
173
174 # NAN**y is NAN for any y except +-0
175 self.assertTrue(isnan(pow_op(NAN, -INF)))
176 self.assertTrue(isnan(pow_op(NAN, -2.0)))
177 self.assertTrue(isnan(pow_op(NAN, -1.0)))
178 self.assertTrue(isnan(pow_op(NAN, -0.5)))
179 self.assertTrue(isnan(pow_op(NAN, 0.5)))
180 self.assertTrue(isnan(pow_op(NAN, 1.0)))
181 self.assertTrue(isnan(pow_op(NAN, 2.0)))
182 self.assertTrue(isnan(pow_op(NAN, INF)))
183
184 # (+-0)**y raises ZeroDivisionError for y a negative odd integer
185 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -1.0)
186 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -1.0)
187
188 # (+-0)**y raises ZeroDivisionError for y finite and negative
189 # but not an odd integer
190 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -2.0)
191 self.assertRaises(ZeroDivisionError, pow_op, -0.0, -0.5)
192 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -2.0)
193 self.assertRaises(ZeroDivisionError, pow_op, 0.0, -0.5)
194
195 # (+-0)**y is +-0 for y a positive odd integer
196 self.assertEqualAndEqualSign(pow_op(-0.0, 1.0), -0.0)
197 self.assertEqualAndEqualSign(pow_op(0.0, 1.0), 0.0)
198
199 # (+-0)**y is 0 for y finite and positive but not an odd integer
200 self.assertEqualAndEqualSign(pow_op(-0.0, 0.5), 0.0)
201 self.assertEqualAndEqualSign(pow_op(-0.0, 2.0), 0.0)
202 self.assertEqualAndEqualSign(pow_op(0.0, 0.5), 0.0)
203 self.assertEqualAndEqualSign(pow_op(0.0, 2.0), 0.0)
204
205 # (-1)**+-inf is 1
206 self.assertEqualAndEqualSign(pow_op(-1.0, -INF), 1.0)
207 self.assertEqualAndEqualSign(pow_op(-1.0, INF), 1.0)
208
209 # 1**y is 1 for any y, even if y is an infinity or nan
210 self.assertEqualAndEqualSign(pow_op(1.0, -INF), 1.0)
211 self.assertEqualAndEqualSign(pow_op(1.0, -2.0), 1.0)
212 self.assertEqualAndEqualSign(pow_op(1.0, -1.0), 1.0)
213 self.assertEqualAndEqualSign(pow_op(1.0, -0.5), 1.0)
214 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
215 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
216 self.assertEqualAndEqualSign(pow_op(1.0, 0.5), 1.0)
217 self.assertEqualAndEqualSign(pow_op(1.0, 1.0), 1.0)
218 self.assertEqualAndEqualSign(pow_op(1.0, 2.0), 1.0)
219 self.assertEqualAndEqualSign(pow_op(1.0, INF), 1.0)
220 self.assertEqualAndEqualSign(pow_op(1.0, NAN), 1.0)
221
222 # x**+-0 is 1 for any x, even if x is a zero, infinity, or nan
223 self.assertEqualAndEqualSign(pow_op(-INF, 0.0), 1.0)
224 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
225 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
226 self.assertEqualAndEqualSign(pow_op(-0.5, 0.0), 1.0)
227 self.assertEqualAndEqualSign(pow_op(-0.0, 0.0), 1.0)
228 self.assertEqualAndEqualSign(pow_op(0.0, 0.0), 1.0)
229 self.assertEqualAndEqualSign(pow_op(0.5, 0.0), 1.0)
230 self.assertEqualAndEqualSign(pow_op(1.0, 0.0), 1.0)
231 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
232 self.assertEqualAndEqualSign(pow_op(INF, 0.0), 1.0)
233 self.assertEqualAndEqualSign(pow_op(NAN, 0.0), 1.0)
234 self.assertEqualAndEqualSign(pow_op(-INF, -0.0), 1.0)
235 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
236 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
237 self.assertEqualAndEqualSign(pow_op(-0.5, -0.0), 1.0)
238 self.assertEqualAndEqualSign(pow_op(-0.0, -0.0), 1.0)
239 self.assertEqualAndEqualSign(pow_op(0.0, -0.0), 1.0)
240 self.assertEqualAndEqualSign(pow_op(0.5, -0.0), 1.0)
241 self.assertEqualAndEqualSign(pow_op(1.0, -0.0), 1.0)
242 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
243 self.assertEqualAndEqualSign(pow_op(INF, -0.0), 1.0)
244 self.assertEqualAndEqualSign(pow_op(NAN, -0.0), 1.0)
245
246 # x**y raises ValueError for finite negative x and non-integral y
247 self.assertRaises(ValueError, pow_op, -2.0, -0.5)
248 self.assertRaises(ValueError, pow_op, -2.0, 0.5)
249 self.assertRaises(ValueError, pow_op, -1.0, -0.5)
250 self.assertRaises(ValueError, pow_op, -1.0, 0.5)
251 self.assertRaises(ValueError, pow_op, -0.5, -0.5)
252 self.assertRaises(ValueError, pow_op, -0.5, 0.5)
253
254 # x**-INF is INF for abs(x) < 1
255 self.assertEqualAndEqualSign(pow_op(-0.5, -INF), INF)
256 self.assertEqualAndEqualSign(pow_op(-0.0, -INF), INF)
257 self.assertEqualAndEqualSign(pow_op(0.0, -INF), INF)
258 self.assertEqualAndEqualSign(pow_op(0.5, -INF), INF)
259
260 # x**-INF is 0 for abs(x) > 1
261 self.assertEqualAndEqualSign(pow_op(-INF, -INF), 0.0)
262 self.assertEqualAndEqualSign(pow_op(-2.0, -INF), 0.0)
263 self.assertEqualAndEqualSign(pow_op(2.0, -INF), 0.0)
264 self.assertEqualAndEqualSign(pow_op(INF, -INF), 0.0)
265
266 # x**INF is 0 for abs(x) < 1
267 self.assertEqualAndEqualSign(pow_op(-0.5, INF), 0.0)
268 self.assertEqualAndEqualSign(pow_op(-0.0, INF), 0.0)
269 self.assertEqualAndEqualSign(pow_op(0.0, INF), 0.0)
270 self.assertEqualAndEqualSign(pow_op(0.5, INF), 0.0)
271
272 # x**INF is INF for abs(x) > 1
273 self.assertEqualAndEqualSign(pow_op(-INF, INF), INF)
274 self.assertEqualAndEqualSign(pow_op(-2.0, INF), INF)
275 self.assertEqualAndEqualSign(pow_op(2.0, INF), INF)
276 self.assertEqualAndEqualSign(pow_op(INF, INF), INF)
277
278 # (-INF)**y is -0.0 for y a negative odd integer
279 self.assertEqualAndEqualSign(pow_op(-INF, -1.0), -0.0)
280
281 # (-INF)**y is 0.0 for y negative but not an odd integer
282 self.assertEqualAndEqualSign(pow_op(-INF, -0.5), 0.0)
283 self.assertEqualAndEqualSign(pow_op(-INF, -2.0), 0.0)
284
285 # (-INF)**y is -INF for y a positive odd integer
286 self.assertEqualAndEqualSign(pow_op(-INF, 1.0), -INF)
287
288 # (-INF)**y is INF for y positive but not an odd integer
289 self.assertEqualAndEqualSign(pow_op(-INF, 0.5), INF)
290 self.assertEqualAndEqualSign(pow_op(-INF, 2.0), INF)
291
292 # INF**y is INF for y positive
293 self.assertEqualAndEqualSign(pow_op(INF, 0.5), INF)
294 self.assertEqualAndEqualSign(pow_op(INF, 1.0), INF)
295 self.assertEqualAndEqualSign(pow_op(INF, 2.0), INF)
296
297 # INF**y is 0.0 for y negative
298 self.assertEqualAndEqualSign(pow_op(INF, -2.0), 0.0)
299 self.assertEqualAndEqualSign(pow_op(INF, -1.0), 0.0)
300 self.assertEqualAndEqualSign(pow_op(INF, -0.5), 0.0)
301
302 # basic checks not covered by the special cases above
303 self.assertEqualAndEqualSign(pow_op(-2.0, -2.0), 0.25)
304 self.assertEqualAndEqualSign(pow_op(-2.0, -1.0), -0.5)
305 self.assertEqualAndEqualSign(pow_op(-2.0, -0.0), 1.0)
306 self.assertEqualAndEqualSign(pow_op(-2.0, 0.0), 1.0)
307 self.assertEqualAndEqualSign(pow_op(-2.0, 1.0), -2.0)
308 self.assertEqualAndEqualSign(pow_op(-2.0, 2.0), 4.0)
309 self.assertEqualAndEqualSign(pow_op(-1.0, -2.0), 1.0)
310 self.assertEqualAndEqualSign(pow_op(-1.0, -1.0), -1.0)
311 self.assertEqualAndEqualSign(pow_op(-1.0, -0.0), 1.0)
312 self.assertEqualAndEqualSign(pow_op(-1.0, 0.0), 1.0)
313 self.assertEqualAndEqualSign(pow_op(-1.0, 1.0), -1.0)
314 self.assertEqualAndEqualSign(pow_op(-1.0, 2.0), 1.0)
315 self.assertEqualAndEqualSign(pow_op(2.0, -2.0), 0.25)
316 self.assertEqualAndEqualSign(pow_op(2.0, -1.0), 0.5)
317 self.assertEqualAndEqualSign(pow_op(2.0, -0.0), 1.0)
318 self.assertEqualAndEqualSign(pow_op(2.0, 0.0), 1.0)
319 self.assertEqualAndEqualSign(pow_op(2.0, 1.0), 2.0)
320 self.assertEqualAndEqualSign(pow_op(2.0, 2.0), 4.0)
321
322 # 1 ** large and -1 ** large; some libms apparently
323 # have problems with these
324 self.assertEqualAndEqualSign(pow_op(1.0, -1e100), 1.0)
325 self.assertEqualAndEqualSign(pow_op(1.0, 1e100), 1.0)
326 self.assertEqualAndEqualSign(pow_op(-1.0, -1e100), 1.0)
327 self.assertEqualAndEqualSign(pow_op(-1.0, 1e100), 1.0)
328
329 # check sign for results that underflow to 0
330 self.assertEqualAndEqualSign(pow_op(-2.0, -2000.0), 0.0)
331 self.assertRaises(ValueError, pow_op, -2.0, -2000.5)
332 self.assertEqualAndEqualSign(pow_op(-2.0, -2001.0), -0.0)
333 self.assertEqualAndEqualSign(pow_op(2.0, -2000.0), 0.0)
334 self.assertEqualAndEqualSign(pow_op(2.0, -2000.5), 0.0)
335 self.assertEqualAndEqualSign(pow_op(2.0, -2001.0), 0.0)
336 self.assertEqualAndEqualSign(pow_op(-0.5, 2000.0), 0.0)
337 self.assertRaises(ValueError, pow_op, -0.5, 2000.5)
338 self.assertEqualAndEqualSign(pow_op(-0.5, 2001.0), -0.0)
339 self.assertEqualAndEqualSign(pow_op(0.5, 2000.0), 0.0)
340 self.assertEqualAndEqualSign(pow_op(0.5, 2000.5), 0.0)
341 self.assertEqualAndEqualSign(pow_op(0.5, 2001.0), 0.0)
342
343 # check we don't raise an exception for subnormal results,
344 # and validate signs. Tests currently disabled, since
345 # they fail on systems where a subnormal result from pow
346 # is flushed to zero (e.g. Debian/ia64.)
347 #self.assertTrue(0.0 < pow_op(0.5, 1048) < 1e-315)
348 #self.assertTrue(0.0 < pow_op(-0.5, 1048) < 1e-315)
349 #self.assertTrue(0.0 < pow_op(0.5, 1047) < 1e-315)
350 #self.assertTrue(0.0 > pow_op(-0.5, 1047) > -1e-315)
351 #self.assertTrue(0.0 < pow_op(2.0, -1048) < 1e-315)
352 #self.assertTrue(0.0 < pow_op(-2.0, -1048) < 1e-315)
353 #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
354 #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
355
356
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000357class FormatFunctionsTestCase(unittest.TestCase):
358
359 def setUp(self):
360 self.save_formats = {'double':float.__getformat__('double'),
361 'float':float.__getformat__('float')}
362
363 def tearDown(self):
364 float.__setformat__('double', self.save_formats['double'])
365 float.__setformat__('float', self.save_formats['float'])
366
367 def test_getformat(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000368 self.assertTrue(float.__getformat__('double') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000369 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000370 self.assertTrue(float.__getformat__('float') in
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000371 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
372 self.assertRaises(ValueError, float.__getformat__, 'chicken')
373 self.assertRaises(TypeError, float.__getformat__, 1)
374
375 def test_setformat(self):
376 for t in 'double', 'float':
377 float.__setformat__(t, 'unknown')
378 if self.save_formats[t] == 'IEEE, big-endian':
379 self.assertRaises(ValueError, float.__setformat__,
380 t, 'IEEE, little-endian')
381 elif self.save_formats[t] == 'IEEE, little-endian':
382 self.assertRaises(ValueError, float.__setformat__,
383 t, 'IEEE, big-endian')
384 else:
385 self.assertRaises(ValueError, float.__setformat__,
386 t, 'IEEE, big-endian')
387 self.assertRaises(ValueError, float.__setformat__,
388 t, 'IEEE, little-endian')
389 self.assertRaises(ValueError, float.__setformat__,
390 t, 'chicken')
391 self.assertRaises(ValueError, float.__setformat__,
392 'chicken', 'unknown')
393
394BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
395LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
396BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
397LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
398
399BE_FLOAT_INF = '\x7f\x80\x00\x00'
400LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
401BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
402LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
403
404# on non-IEEE platforms, attempting to unpack a bit pattern
405# representing an infinity or a NaN should raise an exception.
406
407class UnknownFormatTestCase(unittest.TestCase):
408 def setUp(self):
409 self.save_formats = {'double':float.__getformat__('double'),
410 'float':float.__getformat__('float')}
411 float.__setformat__('double', 'unknown')
412 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +0000413
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000414 def tearDown(self):
415 float.__setformat__('double', self.save_formats['double'])
416 float.__setformat__('float', self.save_formats['float'])
417
418 def test_double_specials_dont_unpack(self):
419 for fmt, data in [('>d', BE_DOUBLE_INF),
420 ('>d', BE_DOUBLE_NAN),
421 ('<d', LE_DOUBLE_INF),
422 ('<d', LE_DOUBLE_NAN)]:
423 self.assertRaises(ValueError, struct.unpack, fmt, data)
424
425 def test_float_specials_dont_unpack(self):
426 for fmt, data in [('>f', BE_FLOAT_INF),
427 ('>f', BE_FLOAT_NAN),
428 ('<f', LE_FLOAT_INF),
429 ('<f', LE_FLOAT_NAN)]:
430 self.assertRaises(ValueError, struct.unpack, fmt, data)
431
432
433# on an IEEE platform, all we guarantee is that bit patterns
434# representing infinities or NaNs do not raise an exception; all else
435# is accident (today).
Alex Martellid8672aa2007-08-22 21:14:17 +0000436# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000437
438class IEEEFormatTestCase(unittest.TestCase):
439 if float.__getformat__("double").startswith("IEEE"):
440 def test_double_specials_do_unpack(self):
441 for fmt, data in [('>d', BE_DOUBLE_INF),
442 ('>d', BE_DOUBLE_NAN),
443 ('<d', LE_DOUBLE_INF),
444 ('<d', LE_DOUBLE_NAN)]:
445 struct.unpack(fmt, data)
446
447 if float.__getformat__("float").startswith("IEEE"):
448 def test_float_specials_do_unpack(self):
449 for fmt, data in [('>f', BE_FLOAT_INF),
450 ('>f', BE_FLOAT_NAN),
451 ('<f', LE_FLOAT_INF),
452 ('<f', LE_FLOAT_NAN)]:
453 struct.unpack(fmt, data)
454
Alex Martellid8672aa2007-08-22 21:14:17 +0000455 if float.__getformat__("double").startswith("IEEE"):
456 def test_negative_zero(self):
457 import math
458 def pos_pos():
459 return 0.0, math.atan2(0.0, -1)
460 def pos_neg():
461 return 0.0, math.atan2(-0.0, -1)
462 def neg_pos():
463 return -0.0, math.atan2(0.0, -1)
464 def neg_neg():
465 return -0.0, math.atan2(-0.0, -1)
466 self.assertEquals(pos_pos(), neg_pos())
467 self.assertEquals(pos_neg(), neg_neg())
468
Guido van Rossum3b835492008-01-05 00:59:59 +0000469 if float.__getformat__("double").startswith("IEEE"):
470 def test_underflow_sign(self):
471 import math
472 # check that -1e-1000 gives -0.0, not 0.0
473 self.assertEquals(math.atan2(-1e-1000, -1), math.atan2(-0.0, -1))
474 self.assertEquals(math.atan2(float('-1e-1000'), -1),
475 math.atan2(-0.0, -1))
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000476
Eric Smitha985a3a2009-05-05 18:26:08 +0000477 def test_format(self):
478 # these should be rewritten to use both format(x, spec) and
479 # x.__format__(spec)
480
481 self.assertEqual(format(0.0, 'f'), '0.000000')
482
483 # the default is 'g', except for empty format spec
484 self.assertEqual(format(0.0, ''), '0.0')
485 self.assertEqual(format(0.01, ''), '0.01')
486 self.assertEqual(format(0.01, 'g'), '0.01')
487
488 # empty presentation type should format in the same way as str
489 # (issue 5920)
490 x = 100/7.
491 self.assertEqual(format(x, ''), str(x))
492 self.assertEqual(format(x, '-'), str(x))
493 self.assertEqual(format(x, '>'), str(x))
494 self.assertEqual(format(x, '2'), str(x))
495
496 self.assertEqual(format(1.0, 'f'), '1.000000')
497
498 self.assertEqual(format(-1.0, 'f'), '-1.000000')
499
500 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
501 self.assertEqual(format(-1.0, ' f'), '-1.000000')
502 self.assertEqual(format( 1.0, '+f'), '+1.000000')
503 self.assertEqual(format(-1.0, '+f'), '-1.000000')
504
505 # % formatting
506 self.assertEqual(format(-1.0, '%'), '-100.000000%')
507
508 # conversion to string should fail
509 self.assertRaises(ValueError, format, 3.0, "s")
510
511 # other format specifiers shouldn't work on floats,
512 # in particular int specifiers
513 for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] +
514 [chr(x) for x in range(ord('A'), ord('Z')+1)]):
515 if not format_spec in 'eEfFgGn%':
516 self.assertRaises(ValueError, format, 0.0, format_spec)
517 self.assertRaises(ValueError, format, 1.0, format_spec)
518 self.assertRaises(ValueError, format, -1.0, format_spec)
519 self.assertRaises(ValueError, format, 1e100, format_spec)
520 self.assertRaises(ValueError, format, -1e100, format_spec)
521 self.assertRaises(ValueError, format, 1e-100, format_spec)
522 self.assertRaises(ValueError, format, -1e-100, format_spec)
523
Eric Smithc4ab8332009-11-29 17:40:57 +0000524 # issue 3382: 'f' and 'F' with inf's and nan's
525 self.assertEqual('{0:f}'.format(INF), 'inf')
526 self.assertEqual('{0:F}'.format(INF), 'INF')
527 self.assertEqual('{0:f}'.format(-INF), '-inf')
528 self.assertEqual('{0:F}'.format(-INF), '-INF')
529 self.assertEqual('{0:f}'.format(NAN), 'nan')
530 self.assertEqual('{0:F}'.format(NAN), 'NAN')
531
Mark Dickinson61a0d052009-04-29 21:57:15 +0000532 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
533 "test requires IEEE 754 doubles")
534 def test_format_testfile(self):
535 for line in open(format_testfile):
536 if line.startswith('--'):
537 continue
538 line = line.strip()
539 if not line:
540 continue
541
542 lhs, rhs = map(str.strip, line.split('->'))
543 fmt, arg = lhs.split()
Eric Smithc4ab8332009-11-29 17:40:57 +0000544 arg = float(arg)
545 self.assertEqual(fmt % arg, rhs)
546 if not math.isnan(arg) and copysign(1.0, arg) > 0.0:
547 self.assertEqual(fmt % -arg, '-' + rhs)
Mark Dickinson61a0d052009-04-29 21:57:15 +0000548
Mark Dickinson92fcc9c2009-04-29 20:41:00 +0000549 def test_issue5864(self):
550 self.assertEquals(format(123.456, '.4'), '123.5')
551 self.assertEquals(format(1234.56, '.4'), '1.235e+03')
552 self.assertEquals(format(12345.6, '.4'), '1.235e+04')
553
Christian Heimes284d9272007-12-10 22:28:56 +0000554class ReprTestCase(unittest.TestCase):
555 def test_repr(self):
556 floats_file = open(os.path.join(os.path.split(__file__)[0],
557 'floating_points.txt'))
558 for line in floats_file:
559 line = line.strip()
560 if not line or line.startswith('#'):
561 continue
562 v = eval(line)
563 self.assertEqual(v, eval(repr(v)))
564 floats_file.close()
565
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000566@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
567 "test requires IEEE 754 doubles")
568class RoundTestCase(unittest.TestCase):
569 def test_second_argument_type(self):
570 # any type with an __index__ method should be permitted as
571 # a second argument
572 self.assertAlmostEqual(round(12.34, True), 12.3)
573
574 class MyIndex(object):
575 def __index__(self): return 4
576 self.assertAlmostEqual(round(-0.123456, MyIndex()), -0.1235)
577 # but floats should be illegal
578 self.assertRaises(TypeError, round, 3.14159, 2.0)
579
580 def test_inf_nan(self):
581 # rounding an infinity or nan returns the same number;
582 # (in py3k, rounding an infinity or nan raises an error,
583 # since the result can't be represented as a long).
584 self.assertEqual(round(INF), INF)
585 self.assertEqual(round(-INF), -INF)
586 self.assertTrue(math.isnan(round(NAN)))
587 for n in range(-5, 5):
588 self.assertEqual(round(INF, n), INF)
589 self.assertEqual(round(-INF, n), -INF)
590 self.assertTrue(math.isnan(round(NAN, n)))
591
Mark Dickinsonbce78372009-11-24 10:54:58 +0000592 self.assertRaises(TypeError, round, INF, 0.0)
593 self.assertRaises(TypeError, round, -INF, 1.0)
594 self.assertRaises(TypeError, round, NAN, "ceci n'est pas un integer")
595 self.assertRaises(TypeError, round, -0.0, 1j)
596
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000597 def test_large_n(self):
598 for n in [324, 325, 400, 2**31-1, 2**31, 2**32, 2**100]:
599 self.assertEqual(round(123.456, n), 123.456)
600 self.assertEqual(round(-123.456, n), -123.456)
601 self.assertEqual(round(1e300, n), 1e300)
602 self.assertEqual(round(1e-320, n), 1e-320)
603 self.assertEqual(round(1e150, 300), 1e150)
604 self.assertEqual(round(1e300, 307), 1e300)
605 self.assertEqual(round(-3.1415, 308), -3.1415)
606 self.assertEqual(round(1e150, 309), 1e150)
607 self.assertEqual(round(1.4e-315, 315), 1e-315)
608
609 def test_small_n(self):
610 for n in [-308, -309, -400, 1-2**31, -2**31, -2**31-1, -2**100]:
611 self.assertEqual(round(123.456, n), 0.0)
612 self.assertEqual(round(-123.456, n), -0.0)
613 self.assertEqual(round(1e300, n), 0.0)
614 self.assertEqual(round(1e-320, n), 0.0)
615
616 def test_overflow(self):
617 self.assertRaises(OverflowError, round, 1.6e308, -308)
618 self.assertRaises(OverflowError, round, -1.7e308, -308)
619
620 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
621 "test applies only when using short float repr style")
622 def test_previous_round_bugs(self):
623 # particular cases that have occurred in bug reports
624 self.assertEqual(round(562949953421312.5, 1),
625 562949953421312.5)
626 self.assertEqual(round(56294995342131.5, 3),
627 56294995342131.5)
628
629 @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short',
630 "test applies only when using short float repr style")
631 def test_halfway_cases(self):
632 # Halfway cases need special attention, since the current
633 # implementation has to deal with them specially. Note that
634 # 2.x rounds halfway values up (i.e., away from zero) while
635 # 3.x does round-half-to-even.
636 self.assertAlmostEqual(round(0.125, 2), 0.13)
637 self.assertAlmostEqual(round(0.375, 2), 0.38)
638 self.assertAlmostEqual(round(0.625, 2), 0.63)
639 self.assertAlmostEqual(round(0.875, 2), 0.88)
640 self.assertAlmostEqual(round(-0.125, 2), -0.13)
641 self.assertAlmostEqual(round(-0.375, 2), -0.38)
642 self.assertAlmostEqual(round(-0.625, 2), -0.63)
643 self.assertAlmostEqual(round(-0.875, 2), -0.88)
644
645 self.assertAlmostEqual(round(0.25, 1), 0.3)
646 self.assertAlmostEqual(round(0.75, 1), 0.8)
647 self.assertAlmostEqual(round(-0.25, 1), -0.3)
648 self.assertAlmostEqual(round(-0.75, 1), -0.8)
649
650 self.assertEqual(round(-6.5, 0), -7.0)
651 self.assertEqual(round(-5.5, 0), -6.0)
652 self.assertEqual(round(-1.5, 0), -2.0)
653 self.assertEqual(round(-0.5, 0), -1.0)
654 self.assertEqual(round(0.5, 0), 1.0)
655 self.assertEqual(round(1.5, 0), 2.0)
656 self.assertEqual(round(2.5, 0), 3.0)
657 self.assertEqual(round(3.5, 0), 4.0)
658 self.assertEqual(round(4.5, 0), 5.0)
659 self.assertEqual(round(5.5, 0), 6.0)
660 self.assertEqual(round(6.5, 0), 7.0)
661
662 # same but without an explicit second argument; in 3.x these
663 # will give integers
664 self.assertEqual(round(-6.5), -7.0)
665 self.assertEqual(round(-5.5), -6.0)
666 self.assertEqual(round(-1.5), -2.0)
667 self.assertEqual(round(-0.5), -1.0)
668 self.assertEqual(round(0.5), 1.0)
669 self.assertEqual(round(1.5), 2.0)
670 self.assertEqual(round(2.5), 3.0)
671 self.assertEqual(round(3.5), 4.0)
672 self.assertEqual(round(4.5), 5.0)
673 self.assertEqual(round(5.5), 6.0)
674 self.assertEqual(round(6.5), 7.0)
675
676 self.assertEqual(round(-25.0, -1), -30.0)
677 self.assertEqual(round(-15.0, -1), -20.0)
678 self.assertEqual(round(-5.0, -1), -10.0)
679 self.assertEqual(round(5.0, -1), 10.0)
680 self.assertEqual(round(15.0, -1), 20.0)
681 self.assertEqual(round(25.0, -1), 30.0)
682 self.assertEqual(round(35.0, -1), 40.0)
683 self.assertEqual(round(45.0, -1), 50.0)
684 self.assertEqual(round(55.0, -1), 60.0)
685 self.assertEqual(round(65.0, -1), 70.0)
686 self.assertEqual(round(75.0, -1), 80.0)
687 self.assertEqual(round(85.0, -1), 90.0)
688 self.assertEqual(round(95.0, -1), 100.0)
689 self.assertEqual(round(12325.0, -1), 12330.0)
690
691 self.assertEqual(round(350.0, -2), 400.0)
692 self.assertEqual(round(450.0, -2), 500.0)
693
694 self.assertAlmostEqual(round(0.5e21, -21), 1e21)
695 self.assertAlmostEqual(round(1.5e21, -21), 2e21)
696 self.assertAlmostEqual(round(2.5e21, -21), 3e21)
697 self.assertAlmostEqual(round(5.5e21, -21), 6e21)
698 self.assertAlmostEqual(round(8.5e21, -21), 9e21)
699
700 self.assertAlmostEqual(round(-1.5e22, -22), -2e22)
701 self.assertAlmostEqual(round(-0.5e22, -22), -1e22)
702 self.assertAlmostEqual(round(0.5e22, -22), 1e22)
703 self.assertAlmostEqual(round(1.5e22, -22), 2e22)
704
Eric Smithf2bf0d22009-12-02 17:43:06 +0000705 @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
706 "test requires IEEE 754 doubles")
707 def test_format_specials(self):
708 # Test formatting of nans and infs.
709
710 def test(fmt, value, expected):
711 # Test with both % and format().
712 self.assertEqual(fmt % value, expected, fmt)
713 if not '#' in fmt:
714 # Until issue 7094 is implemented, format() for floats doesn't
715 # support '#' formatting
716 fmt = fmt[1:] # strip off the %
717 self.assertEqual(format(value, fmt), expected, fmt)
718
719 for fmt in ['%e', '%f', '%g', '%.0e', '%.6f', '%.20g',
720 '%#e', '%#f', '%#g', '%#.20e', '%#.15f', '%#.3g']:
721 pfmt = '%+' + fmt[1:]
722 sfmt = '% ' + fmt[1:]
723 test(fmt, INF, 'inf')
724 test(fmt, -INF, '-inf')
725 test(fmt, NAN, 'nan')
726 test(fmt, -NAN, 'nan')
727 # When asking for a sign, it's always provided. nans are
728 # always positive.
729 test(pfmt, INF, '+inf')
730 test(pfmt, -INF, '-inf')
731 test(pfmt, NAN, '+nan')
732 test(pfmt, -NAN, '+nan')
733 # When using ' ' for a sign code, only infs can be negative.
734 # Others have a space.
735 test(sfmt, INF, ' inf')
736 test(sfmt, -INF, '-inf')
737 test(sfmt, NAN, ' nan')
738 test(sfmt, -NAN, ' nan')
739
Mark Dickinsonbd15a062009-11-18 19:33:35 +0000740
Christian Heimes0a8143f2007-12-18 23:22:54 +0000741# Beginning with Python 2.6 float has cross platform compatible
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000742# ways to create and represent inf and nan
Christian Heimes0a8143f2007-12-18 23:22:54 +0000743class InfNanTest(unittest.TestCase):
744 def test_inf_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000745 self.assertTrue(isinf(float("inf")))
746 self.assertTrue(isinf(float("+inf")))
747 self.assertTrue(isinf(float("-inf")))
748 self.assertTrue(isinf(float("infinity")))
749 self.assertTrue(isinf(float("+infinity")))
750 self.assertTrue(isinf(float("-infinity")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000751
752 self.assertEqual(repr(float("inf")), "inf")
753 self.assertEqual(repr(float("+inf")), "inf")
754 self.assertEqual(repr(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000755 self.assertEqual(repr(float("infinity")), "inf")
756 self.assertEqual(repr(float("+infinity")), "inf")
757 self.assertEqual(repr(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000758
759 self.assertEqual(repr(float("INF")), "inf")
760 self.assertEqual(repr(float("+Inf")), "inf")
761 self.assertEqual(repr(float("-iNF")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000762 self.assertEqual(repr(float("Infinity")), "inf")
763 self.assertEqual(repr(float("+iNfInItY")), "inf")
764 self.assertEqual(repr(float("-INFINITY")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000765
766 self.assertEqual(str(float("inf")), "inf")
767 self.assertEqual(str(float("+inf")), "inf")
768 self.assertEqual(str(float("-inf")), "-inf")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000769 self.assertEqual(str(float("infinity")), "inf")
770 self.assertEqual(str(float("+infinity")), "inf")
771 self.assertEqual(str(float("-infinity")), "-inf")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000772
773 self.assertRaises(ValueError, float, "info")
774 self.assertRaises(ValueError, float, "+info")
775 self.assertRaises(ValueError, float, "-info")
776 self.assertRaises(ValueError, float, "in")
777 self.assertRaises(ValueError, float, "+in")
778 self.assertRaises(ValueError, float, "-in")
Mark Dickinsonbf9f4d82008-07-05 11:33:52 +0000779 self.assertRaises(ValueError, float, "infinit")
780 self.assertRaises(ValueError, float, "+Infin")
781 self.assertRaises(ValueError, float, "-INFI")
782 self.assertRaises(ValueError, float, "infinitys")
Christian Heimes0a8143f2007-12-18 23:22:54 +0000783
784 def test_inf_as_str(self):
785 self.assertEqual(repr(1e300 * 1e300), "inf")
786 self.assertEqual(repr(-1e300 * 1e300), "-inf")
787
788 self.assertEqual(str(1e300 * 1e300), "inf")
789 self.assertEqual(str(-1e300 * 1e300), "-inf")
790
791 def test_nan_from_str(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000792 self.assertTrue(isnan(float("nan")))
793 self.assertTrue(isnan(float("+nan")))
794 self.assertTrue(isnan(float("-nan")))
Christian Heimes0a8143f2007-12-18 23:22:54 +0000795
796 self.assertEqual(repr(float("nan")), "nan")
797 self.assertEqual(repr(float("+nan")), "nan")
798 self.assertEqual(repr(float("-nan")), "nan")
799
800 self.assertEqual(repr(float("NAN")), "nan")
801 self.assertEqual(repr(float("+NAn")), "nan")
802 self.assertEqual(repr(float("-NaN")), "nan")
803
804 self.assertEqual(str(float("nan")), "nan")
805 self.assertEqual(str(float("+nan")), "nan")
806 self.assertEqual(str(float("-nan")), "nan")
807
808 self.assertRaises(ValueError, float, "nana")
809 self.assertRaises(ValueError, float, "+nana")
810 self.assertRaises(ValueError, float, "-nana")
811 self.assertRaises(ValueError, float, "na")
812 self.assertRaises(ValueError, float, "+na")
813 self.assertRaises(ValueError, float, "-na")
814
815 def test_nan_as_str(self):
816 self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
817 self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
818
819 self.assertEqual(str(1e300 * 1e300 * 0), "nan")
820 self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
Christian Heimes284d9272007-12-10 22:28:56 +0000821
Christian Heimes6f341092008-04-18 23:13:07 +0000822 def notest_float_nan(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000823 self.assertTrue(NAN.is_nan())
824 self.assertFalse(INF.is_nan())
825 self.assertFalse((0.).is_nan())
Christian Heimes6f341092008-04-18 23:13:07 +0000826
827 def notest_float_inf(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000828 self.assertTrue(INF.is_inf())
829 self.assertFalse(NAN.is_inf())
830 self.assertFalse((0.).is_inf())
Christian Heimes6f341092008-04-18 23:13:07 +0000831
Mark Dickinson7103aa42008-07-15 19:08:33 +0000832fromHex = float.fromhex
833toHex = float.hex
834class HexFloatTestCase(unittest.TestCase):
835 MAX = fromHex('0x.fffffffffffff8p+1024') # max normal
836 MIN = fromHex('0x1p-1022') # min normal
837 TINY = fromHex('0x0.0000000000001p-1022') # min subnormal
838 EPS = fromHex('0x0.0000000000001p0') # diff between 1.0 and next float up
839
840 def identical(self, x, y):
841 # check that floats x and y are identical, or that both
842 # are NaNs
843 if isnan(x) or isnan(y):
844 if isnan(x) == isnan(y):
845 return
846 elif x == y and (x != 0.0 or copysign(1.0, x) == copysign(1.0, y)):
847 return
848 self.fail('%r not identical to %r' % (x, y))
849
850 def test_ends(self):
Mark Dickinson62764562008-07-15 21:55:23 +0000851 self.identical(self.MIN, ldexp(1.0, -1022))
852 self.identical(self.TINY, ldexp(1.0, -1074))
853 self.identical(self.EPS, ldexp(1.0, -52))
854 self.identical(self.MAX, 2.*(ldexp(1.0, 1023) - ldexp(1.0, 970)))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000855
856 def test_invalid_inputs(self):
857 invalid_inputs = [
858 'infi', # misspelt infinities and nans
859 '-Infinit',
860 '++inf',
861 '-+Inf',
862 '--nan',
863 '+-NaN',
864 'snan',
865 'NaNs',
866 'nna',
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000867 'an',
868 'nf',
869 'nfinity',
870 'inity',
871 'iinity',
Mark Dickinson7103aa42008-07-15 19:08:33 +0000872 '0xnan',
873 '',
874 ' ',
875 'x1.0p0',
876 '0xX1.0p0',
877 '+ 0x1.0p0', # internal whitespace
878 '- 0x1.0p0',
879 '0 x1.0p0',
880 '0x 1.0p0',
881 '0x1 2.0p0',
882 '+0x1 .0p0',
883 '0x1. 0p0',
884 '-0x1.0 1p0',
885 '-0x1.0 p0',
886 '+0x1.0p +0',
887 '0x1.0p -0',
888 '0x1.0p 0',
889 '+0x1.0p+ 0',
890 '-0x1.0p- 0',
891 '++0x1.0p-0', # double signs
892 '--0x1.0p0',
893 '+-0x1.0p+0',
894 '-+0x1.0p0',
895 '0x1.0p++0',
896 '+0x1.0p+-0',
897 '-0x1.0p-+0',
898 '0x1.0p--0',
899 '0x1.0.p0',
900 '0x.p0', # no hex digits before or after point
901 '0x1,p0', # wrong decimal point character
902 '0x1pa',
903 u'0x1p\uff10', # fullwidth Unicode digits
904 u'\uff10x1p0',
905 u'0x\uff11p0',
906 u'0x1.\uff10p0',
907 '0x1p0 \n 0x2p0',
908 '0x1p0\0 0x1p0', # embedded null byte is not end of string
909 ]
910 for x in invalid_inputs:
Mark Dickinson892429b2008-08-21 20:02:24 +0000911 try:
912 result = fromHex(x)
913 except ValueError:
914 pass
915 else:
916 self.fail('Expected float.fromhex(%r) to raise ValueError; '
917 'got %r instead' % (x, result))
Mark Dickinson7103aa42008-07-15 19:08:33 +0000918
919
Mark Dickinsonb1d45852009-05-11 15:33:08 +0000920 def test_whitespace(self):
921 value_pairs = [
922 ('inf', INF),
923 ('-Infinity', -INF),
924 ('nan', NAN),
925 ('1.0', 1.0),
926 ('-0x.2', -0.125),
927 ('-0.0', -0.0)
928 ]
929 whitespace = [
930 '',
931 ' ',
932 '\t',
933 '\n',
934 '\n \t',
935 '\f',
936 '\v',
937 '\r'
938 ]
939 for inp, expected in value_pairs:
940 for lead in whitespace:
941 for trail in whitespace:
942 got = fromHex(lead + inp + trail)
943 self.identical(got, expected)
944
945
Mark Dickinson7103aa42008-07-15 19:08:33 +0000946 def test_from_hex(self):
947 MIN = self.MIN;
948 MAX = self.MAX;
949 TINY = self.TINY;
950 EPS = self.EPS;
951
952 # two spellings of infinity, with optional signs; case-insensitive
953 self.identical(fromHex('inf'), INF)
954 self.identical(fromHex('+Inf'), INF)
955 self.identical(fromHex('-INF'), -INF)
956 self.identical(fromHex('iNf'), INF)
957 self.identical(fromHex('Infinity'), INF)
958 self.identical(fromHex('+INFINITY'), INF)
959 self.identical(fromHex('-infinity'), -INF)
960 self.identical(fromHex('-iNFiNitY'), -INF)
961
962 # nans with optional sign; case insensitive
963 self.identical(fromHex('nan'), NAN)
964 self.identical(fromHex('+NaN'), NAN)
965 self.identical(fromHex('-NaN'), NAN)
966 self.identical(fromHex('-nAN'), NAN)
967
968 # variations in input format
969 self.identical(fromHex('1'), 1.0)
970 self.identical(fromHex('+1'), 1.0)
971 self.identical(fromHex('1.'), 1.0)
972 self.identical(fromHex('1.0'), 1.0)
973 self.identical(fromHex('1.0p0'), 1.0)
974 self.identical(fromHex('01'), 1.0)
975 self.identical(fromHex('01.'), 1.0)
976 self.identical(fromHex('0x1'), 1.0)
977 self.identical(fromHex('0x1.'), 1.0)
978 self.identical(fromHex('0x1.0'), 1.0)
979 self.identical(fromHex('+0x1.0'), 1.0)
980 self.identical(fromHex('0x1p0'), 1.0)
981 self.identical(fromHex('0X1p0'), 1.0)
982 self.identical(fromHex('0X1P0'), 1.0)
983 self.identical(fromHex('0x1P0'), 1.0)
984 self.identical(fromHex('0x1.p0'), 1.0)
985 self.identical(fromHex('0x1.0p0'), 1.0)
986 self.identical(fromHex('0x.1p4'), 1.0)
987 self.identical(fromHex('0x.1p04'), 1.0)
988 self.identical(fromHex('0x.1p004'), 1.0)
989 self.identical(fromHex('0x1p+0'), 1.0)
990 self.identical(fromHex('0x1P-0'), 1.0)
991 self.identical(fromHex('+0x1p0'), 1.0)
992 self.identical(fromHex('0x01p0'), 1.0)
993 self.identical(fromHex('0x1p00'), 1.0)
994 self.identical(fromHex(u'0x1p0'), 1.0)
995 self.identical(fromHex(' 0x1p0 '), 1.0)
996 self.identical(fromHex('\n 0x1p0'), 1.0)
997 self.identical(fromHex('0x1p0 \t'), 1.0)
998 self.identical(fromHex('0xap0'), 10.0)
999 self.identical(fromHex('0xAp0'), 10.0)
1000 self.identical(fromHex('0xaP0'), 10.0)
1001 self.identical(fromHex('0xAP0'), 10.0)
1002 self.identical(fromHex('0xbep0'), 190.0)
1003 self.identical(fromHex('0xBep0'), 190.0)
1004 self.identical(fromHex('0xbEp0'), 190.0)
1005 self.identical(fromHex('0XBE0P-4'), 190.0)
1006 self.identical(fromHex('0xBEp0'), 190.0)
1007 self.identical(fromHex('0xB.Ep4'), 190.0)
1008 self.identical(fromHex('0x.BEp8'), 190.0)
1009 self.identical(fromHex('0x.0BEp12'), 190.0)
1010
1011 # moving the point around
1012 pi = fromHex('0x1.921fb54442d18p1')
1013 self.identical(fromHex('0x.006487ed5110b46p11'), pi)
1014 self.identical(fromHex('0x.00c90fdaa22168cp10'), pi)
1015 self.identical(fromHex('0x.01921fb54442d18p9'), pi)
1016 self.identical(fromHex('0x.03243f6a8885a3p8'), pi)
1017 self.identical(fromHex('0x.06487ed5110b46p7'), pi)
1018 self.identical(fromHex('0x.0c90fdaa22168cp6'), pi)
1019 self.identical(fromHex('0x.1921fb54442d18p5'), pi)
1020 self.identical(fromHex('0x.3243f6a8885a3p4'), pi)
1021 self.identical(fromHex('0x.6487ed5110b46p3'), pi)
1022 self.identical(fromHex('0x.c90fdaa22168cp2'), pi)
1023 self.identical(fromHex('0x1.921fb54442d18p1'), pi)
1024 self.identical(fromHex('0x3.243f6a8885a3p0'), pi)
1025 self.identical(fromHex('0x6.487ed5110b46p-1'), pi)
1026 self.identical(fromHex('0xc.90fdaa22168cp-2'), pi)
1027 self.identical(fromHex('0x19.21fb54442d18p-3'), pi)
1028 self.identical(fromHex('0x32.43f6a8885a3p-4'), pi)
1029 self.identical(fromHex('0x64.87ed5110b46p-5'), pi)
1030 self.identical(fromHex('0xc9.0fdaa22168cp-6'), pi)
1031 self.identical(fromHex('0x192.1fb54442d18p-7'), pi)
1032 self.identical(fromHex('0x324.3f6a8885a3p-8'), pi)
1033 self.identical(fromHex('0x648.7ed5110b46p-9'), pi)
1034 self.identical(fromHex('0xc90.fdaa22168cp-10'), pi)
1035 self.identical(fromHex('0x1921.fb54442d18p-11'), pi)
1036 # ...
1037 self.identical(fromHex('0x1921fb54442d1.8p-47'), pi)
1038 self.identical(fromHex('0x3243f6a8885a3p-48'), pi)
1039 self.identical(fromHex('0x6487ed5110b46p-49'), pi)
1040 self.identical(fromHex('0xc90fdaa22168cp-50'), pi)
1041 self.identical(fromHex('0x1921fb54442d18p-51'), pi)
1042 self.identical(fromHex('0x3243f6a8885a30p-52'), pi)
1043 self.identical(fromHex('0x6487ed5110b460p-53'), pi)
1044 self.identical(fromHex('0xc90fdaa22168c0p-54'), pi)
1045 self.identical(fromHex('0x1921fb54442d180p-55'), pi)
1046
1047
1048 # results that should overflow...
1049 self.assertRaises(OverflowError, fromHex, '-0x1p1024')
1050 self.assertRaises(OverflowError, fromHex, '0x1p+1025')
1051 self.assertRaises(OverflowError, fromHex, '+0X1p1030')
1052 self.assertRaises(OverflowError, fromHex, '-0x1p+1100')
1053 self.assertRaises(OverflowError, fromHex, '0X1p123456789123456789')
1054 self.assertRaises(OverflowError, fromHex, '+0X.8p+1025')
1055 self.assertRaises(OverflowError, fromHex, '+0x0.8p1025')
1056 self.assertRaises(OverflowError, fromHex, '-0x0.4p1026')
1057 self.assertRaises(OverflowError, fromHex, '0X2p+1023')
1058 self.assertRaises(OverflowError, fromHex, '0x2.p1023')
1059 self.assertRaises(OverflowError, fromHex, '-0x2.0p+1023')
1060 self.assertRaises(OverflowError, fromHex, '+0X4p+1022')
1061 self.assertRaises(OverflowError, fromHex, '0x1.ffffffffffffffp+1023')
1062 self.assertRaises(OverflowError, fromHex, '-0X1.fffffffffffff9p1023')
1063 self.assertRaises(OverflowError, fromHex, '0X1.fffffffffffff8p1023')
1064 self.assertRaises(OverflowError, fromHex, '+0x3.fffffffffffffp1022')
1065 self.assertRaises(OverflowError, fromHex, '0x3fffffffffffffp+970')
1066 self.assertRaises(OverflowError, fromHex, '0x10000000000000000p960')
1067 self.assertRaises(OverflowError, fromHex, '-0Xffffffffffffffffp960')
1068
1069 # ...and those that round to +-max float
1070 self.identical(fromHex('+0x1.fffffffffffffp+1023'), MAX)
1071 self.identical(fromHex('-0X1.fffffffffffff7p1023'), -MAX)
1072 self.identical(fromHex('0X1.fffffffffffff7fffffffffffffp1023'), MAX)
1073
1074 # zeros
1075 self.identical(fromHex('0x0p0'), 0.0)
1076 self.identical(fromHex('0x0p1000'), 0.0)
1077 self.identical(fromHex('-0x0p1023'), -0.0)
1078 self.identical(fromHex('0X0p1024'), 0.0)
1079 self.identical(fromHex('-0x0p1025'), -0.0)
1080 self.identical(fromHex('0X0p2000'), 0.0)
1081 self.identical(fromHex('0x0p123456789123456789'), 0.0)
1082 self.identical(fromHex('-0X0p-0'), -0.0)
1083 self.identical(fromHex('-0X0p-1000'), -0.0)
1084 self.identical(fromHex('0x0p-1023'), 0.0)
1085 self.identical(fromHex('-0X0p-1024'), -0.0)
1086 self.identical(fromHex('-0x0p-1025'), -0.0)
1087 self.identical(fromHex('-0x0p-1072'), -0.0)
1088 self.identical(fromHex('0X0p-1073'), 0.0)
1089 self.identical(fromHex('-0x0p-1074'), -0.0)
1090 self.identical(fromHex('0x0p-1075'), 0.0)
1091 self.identical(fromHex('0X0p-1076'), 0.0)
1092 self.identical(fromHex('-0X0p-2000'), -0.0)
1093 self.identical(fromHex('-0x0p-123456789123456789'), -0.0)
1094
1095 # values that should underflow to 0
1096 self.identical(fromHex('0X1p-1075'), 0.0)
1097 self.identical(fromHex('-0X1p-1075'), -0.0)
1098 self.identical(fromHex('-0x1p-123456789123456789'), -0.0)
1099 self.identical(fromHex('0x1.00000000000000001p-1075'), TINY)
1100 self.identical(fromHex('-0x1.1p-1075'), -TINY)
1101 self.identical(fromHex('0x1.fffffffffffffffffp-1075'), TINY)
1102
1103 # check round-half-even is working correctly near 0 ...
1104 self.identical(fromHex('0x1p-1076'), 0.0)
1105 self.identical(fromHex('0X2p-1076'), 0.0)
1106 self.identical(fromHex('0X3p-1076'), TINY)
1107 self.identical(fromHex('0x4p-1076'), TINY)
1108 self.identical(fromHex('0X5p-1076'), TINY)
1109 self.identical(fromHex('0X6p-1076'), 2*TINY)
1110 self.identical(fromHex('0x7p-1076'), 2*TINY)
1111 self.identical(fromHex('0X8p-1076'), 2*TINY)
1112 self.identical(fromHex('0X9p-1076'), 2*TINY)
1113 self.identical(fromHex('0xap-1076'), 2*TINY)
1114 self.identical(fromHex('0Xbp-1076'), 3*TINY)
1115 self.identical(fromHex('0xcp-1076'), 3*TINY)
1116 self.identical(fromHex('0Xdp-1076'), 3*TINY)
1117 self.identical(fromHex('0Xep-1076'), 4*TINY)
1118 self.identical(fromHex('0xfp-1076'), 4*TINY)
1119 self.identical(fromHex('0x10p-1076'), 4*TINY)
1120 self.identical(fromHex('-0x1p-1076'), -0.0)
1121 self.identical(fromHex('-0X2p-1076'), -0.0)
1122 self.identical(fromHex('-0x3p-1076'), -TINY)
1123 self.identical(fromHex('-0X4p-1076'), -TINY)
1124 self.identical(fromHex('-0x5p-1076'), -TINY)
1125 self.identical(fromHex('-0x6p-1076'), -2*TINY)
1126 self.identical(fromHex('-0X7p-1076'), -2*TINY)
1127 self.identical(fromHex('-0X8p-1076'), -2*TINY)
1128 self.identical(fromHex('-0X9p-1076'), -2*TINY)
1129 self.identical(fromHex('-0Xap-1076'), -2*TINY)
1130 self.identical(fromHex('-0xbp-1076'), -3*TINY)
1131 self.identical(fromHex('-0xcp-1076'), -3*TINY)
1132 self.identical(fromHex('-0Xdp-1076'), -3*TINY)
1133 self.identical(fromHex('-0xep-1076'), -4*TINY)
1134 self.identical(fromHex('-0Xfp-1076'), -4*TINY)
1135 self.identical(fromHex('-0X10p-1076'), -4*TINY)
1136
1137 # ... and near MIN ...
1138 self.identical(fromHex('0x0.ffffffffffffd6p-1022'), MIN-3*TINY)
1139 self.identical(fromHex('0x0.ffffffffffffd8p-1022'), MIN-2*TINY)
1140 self.identical(fromHex('0x0.ffffffffffffdap-1022'), MIN-2*TINY)
1141 self.identical(fromHex('0x0.ffffffffffffdcp-1022'), MIN-2*TINY)
1142 self.identical(fromHex('0x0.ffffffffffffdep-1022'), MIN-2*TINY)
1143 self.identical(fromHex('0x0.ffffffffffffe0p-1022'), MIN-2*TINY)
1144 self.identical(fromHex('0x0.ffffffffffffe2p-1022'), MIN-2*TINY)
1145 self.identical(fromHex('0x0.ffffffffffffe4p-1022'), MIN-2*TINY)
1146 self.identical(fromHex('0x0.ffffffffffffe6p-1022'), MIN-2*TINY)
1147 self.identical(fromHex('0x0.ffffffffffffe8p-1022'), MIN-2*TINY)
1148 self.identical(fromHex('0x0.ffffffffffffeap-1022'), MIN-TINY)
1149 self.identical(fromHex('0x0.ffffffffffffecp-1022'), MIN-TINY)
1150 self.identical(fromHex('0x0.ffffffffffffeep-1022'), MIN-TINY)
1151 self.identical(fromHex('0x0.fffffffffffff0p-1022'), MIN-TINY)
1152 self.identical(fromHex('0x0.fffffffffffff2p-1022'), MIN-TINY)
1153 self.identical(fromHex('0x0.fffffffffffff4p-1022'), MIN-TINY)
1154 self.identical(fromHex('0x0.fffffffffffff6p-1022'), MIN-TINY)
1155 self.identical(fromHex('0x0.fffffffffffff8p-1022'), MIN)
1156 self.identical(fromHex('0x0.fffffffffffffap-1022'), MIN)
1157 self.identical(fromHex('0x0.fffffffffffffcp-1022'), MIN)
1158 self.identical(fromHex('0x0.fffffffffffffep-1022'), MIN)
1159 self.identical(fromHex('0x1.00000000000000p-1022'), MIN)
1160 self.identical(fromHex('0x1.00000000000002p-1022'), MIN)
1161 self.identical(fromHex('0x1.00000000000004p-1022'), MIN)
1162 self.identical(fromHex('0x1.00000000000006p-1022'), MIN)
1163 self.identical(fromHex('0x1.00000000000008p-1022'), MIN)
1164 self.identical(fromHex('0x1.0000000000000ap-1022'), MIN+TINY)
1165 self.identical(fromHex('0x1.0000000000000cp-1022'), MIN+TINY)
1166 self.identical(fromHex('0x1.0000000000000ep-1022'), MIN+TINY)
1167 self.identical(fromHex('0x1.00000000000010p-1022'), MIN+TINY)
1168 self.identical(fromHex('0x1.00000000000012p-1022'), MIN+TINY)
1169 self.identical(fromHex('0x1.00000000000014p-1022'), MIN+TINY)
1170 self.identical(fromHex('0x1.00000000000016p-1022'), MIN+TINY)
1171 self.identical(fromHex('0x1.00000000000018p-1022'), MIN+2*TINY)
1172
1173 # ... and near 1.0.
1174 self.identical(fromHex('0x0.fffffffffffff0p0'), 1.0-EPS)
1175 self.identical(fromHex('0x0.fffffffffffff1p0'), 1.0-EPS)
1176 self.identical(fromHex('0X0.fffffffffffff2p0'), 1.0-EPS)
1177 self.identical(fromHex('0x0.fffffffffffff3p0'), 1.0-EPS)
1178 self.identical(fromHex('0X0.fffffffffffff4p0'), 1.0-EPS)
1179 self.identical(fromHex('0X0.fffffffffffff5p0'), 1.0-EPS/2)
1180 self.identical(fromHex('0X0.fffffffffffff6p0'), 1.0-EPS/2)
1181 self.identical(fromHex('0x0.fffffffffffff7p0'), 1.0-EPS/2)
1182 self.identical(fromHex('0x0.fffffffffffff8p0'), 1.0-EPS/2)
1183 self.identical(fromHex('0X0.fffffffffffff9p0'), 1.0-EPS/2)
1184 self.identical(fromHex('0X0.fffffffffffffap0'), 1.0-EPS/2)
1185 self.identical(fromHex('0x0.fffffffffffffbp0'), 1.0-EPS/2)
1186 self.identical(fromHex('0X0.fffffffffffffcp0'), 1.0)
1187 self.identical(fromHex('0x0.fffffffffffffdp0'), 1.0)
1188 self.identical(fromHex('0X0.fffffffffffffep0'), 1.0)
1189 self.identical(fromHex('0x0.ffffffffffffffp0'), 1.0)
1190 self.identical(fromHex('0X1.00000000000000p0'), 1.0)
1191 self.identical(fromHex('0X1.00000000000001p0'), 1.0)
1192 self.identical(fromHex('0x1.00000000000002p0'), 1.0)
1193 self.identical(fromHex('0X1.00000000000003p0'), 1.0)
1194 self.identical(fromHex('0x1.00000000000004p0'), 1.0)
1195 self.identical(fromHex('0X1.00000000000005p0'), 1.0)
1196 self.identical(fromHex('0X1.00000000000006p0'), 1.0)
1197 self.identical(fromHex('0X1.00000000000007p0'), 1.0)
1198 self.identical(fromHex('0x1.00000000000007ffffffffffffffffffffp0'),
1199 1.0)
1200 self.identical(fromHex('0x1.00000000000008p0'), 1.0)
1201 self.identical(fromHex('0x1.00000000000008000000000000000001p0'),
1202 1+EPS)
1203 self.identical(fromHex('0X1.00000000000009p0'), 1.0+EPS)
1204 self.identical(fromHex('0x1.0000000000000ap0'), 1.0+EPS)
1205 self.identical(fromHex('0x1.0000000000000bp0'), 1.0+EPS)
1206 self.identical(fromHex('0X1.0000000000000cp0'), 1.0+EPS)
1207 self.identical(fromHex('0x1.0000000000000dp0'), 1.0+EPS)
1208 self.identical(fromHex('0x1.0000000000000ep0'), 1.0+EPS)
1209 self.identical(fromHex('0X1.0000000000000fp0'), 1.0+EPS)
1210 self.identical(fromHex('0x1.00000000000010p0'), 1.0+EPS)
1211 self.identical(fromHex('0X1.00000000000011p0'), 1.0+EPS)
1212 self.identical(fromHex('0x1.00000000000012p0'), 1.0+EPS)
1213 self.identical(fromHex('0X1.00000000000013p0'), 1.0+EPS)
1214 self.identical(fromHex('0X1.00000000000014p0'), 1.0+EPS)
1215 self.identical(fromHex('0x1.00000000000015p0'), 1.0+EPS)
1216 self.identical(fromHex('0x1.00000000000016p0'), 1.0+EPS)
1217 self.identical(fromHex('0X1.00000000000017p0'), 1.0+EPS)
1218 self.identical(fromHex('0x1.00000000000017ffffffffffffffffffffp0'),
1219 1.0+EPS)
1220 self.identical(fromHex('0x1.00000000000018p0'), 1.0+2*EPS)
1221 self.identical(fromHex('0X1.00000000000018000000000000000001p0'),
1222 1.0+2*EPS)
1223 self.identical(fromHex('0x1.00000000000019p0'), 1.0+2*EPS)
1224 self.identical(fromHex('0X1.0000000000001ap0'), 1.0+2*EPS)
1225 self.identical(fromHex('0X1.0000000000001bp0'), 1.0+2*EPS)
1226 self.identical(fromHex('0x1.0000000000001cp0'), 1.0+2*EPS)
1227 self.identical(fromHex('0x1.0000000000001dp0'), 1.0+2*EPS)
1228 self.identical(fromHex('0x1.0000000000001ep0'), 1.0+2*EPS)
1229 self.identical(fromHex('0X1.0000000000001fp0'), 1.0+2*EPS)
1230 self.identical(fromHex('0x1.00000000000020p0'), 1.0+2*EPS)
1231
1232 def test_roundtrip(self):
1233 def roundtrip(x):
1234 return fromHex(toHex(x))
1235
1236 for x in [NAN, INF, self.MAX, self.MIN, self.MIN-self.TINY, self.TINY, 0.0]:
1237 self.identical(x, roundtrip(x))
1238 self.identical(-x, roundtrip(-x))
1239
1240 # fromHex(toHex(x)) should exactly recover x, for any non-NaN float x.
1241 import random
1242 for i in xrange(10000):
1243 e = random.randrange(-1200, 1200)
1244 m = random.random()
1245 s = random.choice([1.0, -1.0])
1246 try:
1247 x = s*ldexp(m, e)
1248 except OverflowError:
1249 pass
1250 else:
1251 self.identical(x, fromHex(toHex(x)))
1252
Christian Heimes6f341092008-04-18 23:13:07 +00001253
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001254def test_main():
1255 test_support.run_unittest(
Amaury Forgeot d'Arcfeb8cad2008-09-06 20:53:51 +00001256 GeneralFloatCases,
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001257 FormatFunctionsTestCase,
1258 UnknownFormatTestCase,
Christian Heimes284d9272007-12-10 22:28:56 +00001259 IEEEFormatTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001260 ReprTestCase,
Mark Dickinsonbd15a062009-11-18 19:33:35 +00001261 RoundTestCase,
Christian Heimes0a8143f2007-12-18 23:22:54 +00001262 InfNanTest,
Mark Dickinson7103aa42008-07-15 19:08:33 +00001263 HexFloatTestCase,
Christian Heimesf15c66e2007-12-11 00:54:34 +00001264 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001265
1266if __name__ == '__main__':
1267 test_main()