python (3.12.0)
1 # Python test set -- math module
2 # XXXX Should not do tests around zero only
3
4 from test.support import verbose, requires_IEEE_754
5 from test import support
6 import unittest
7 import fractions
8 import itertools
9 import decimal
10 import math
11 import os
12 import platform
13 import random
14 import struct
15 import sys
16
17
18 eps = 1E-05
19 NAN = float('nan')
20 INF = float('inf')
21 NINF = float('-inf')
22 FLOAT_MAX = sys.float_info.max
23 FLOAT_MIN = sys.float_info.min
24
25 # detect evidence of double-rounding: fsum is not always correctly
26 # rounded on machines that suffer from double rounding.
27 x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer
28 HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
29
30 # locate file with test values
31 if __name__ == '__main__':
32 file = sys.argv[0]
33 else:
34 file = __file__
35 test_dir = os.path.dirname(file) or os.curdir
36 math_testcases = os.path.join(test_dir, 'math_testcases.txt')
37 test_file = os.path.join(test_dir, 'cmath_testcases.txt')
38
39
40 def to_ulps(x):
41 """Convert a non-NaN float x to an integer, in such a way that
42 adjacent floats are converted to adjacent integers. Then
43 abs(ulps(x) - ulps(y)) gives the difference in ulps between two
44 floats.
45
46 The results from this function will only make sense on platforms
47 where native doubles are represented in IEEE 754 binary64 format.
48
49 Note: 0.0 and -0.0 are converted to 0 and -1, respectively.
50 """
51 n = struct.unpack('<q', struct.pack('<d', x))[0]
52 if n < 0:
53 n = ~(n+2**63)
54 return n
55
56
57 # Here's a pure Python version of the math.factorial algorithm, for
58 # documentation and comparison purposes.
59 #
60 # Formula:
61 #
62 # factorial(n) = factorial_odd_part(n) << (n - count_set_bits(n))
63 #
64 # where
65 #
66 # factorial_odd_part(n) = product_{i >= 0} product_{0 < j <= n >> i; j odd} j
67 #
68 # The outer product above is an infinite product, but once i >= n.bit_length,
69 # (n >> i) < 1 and the corresponding term of the product is empty. So only the
70 # finitely many terms for 0 <= i < n.bit_length() contribute anything.
71 #
72 # We iterate downwards from i == n.bit_length() - 1 to i == 0. The inner
73 # product in the formula above starts at 1 for i == n.bit_length(); for each i
74 # < n.bit_length() we get the inner product for i from that for i + 1 by
75 # multiplying by all j in {n >> i+1 < j <= n >> i; j odd}. In Python terms,
76 # this set is range((n >> i+1) + 1 | 1, (n >> i) + 1 | 1, 2).
77
78 def count_set_bits(n):
79 """Number of '1' bits in binary expansion of a nonnnegative integer."""
80 return 1 + count_set_bits(n & n - 1) if n else 0
81
82 def partial_product(start, stop):
83 """Product of integers in range(start, stop, 2), computed recursively.
84 start and stop should both be odd, with start <= stop.
85
86 """
87 numfactors = (stop - start) >> 1
88 if not numfactors:
89 return 1
90 elif numfactors == 1:
91 return start
92 else:
93 mid = (start + numfactors) | 1
94 return partial_product(start, mid) * partial_product(mid, stop)
95
96 def py_factorial(n):
97 """Factorial of nonnegative integer n, via "Binary Split Factorial Formula"
98 described at http://www.luschny.de/math/factorial/binarysplitfact.html
99
100 """
101 inner = outer = 1
102 for i in reversed(range(n.bit_length())):
103 inner *= partial_product((n >> i + 1) + 1 | 1, (n >> i) + 1 | 1)
104 outer *= inner
105 return outer << (n - count_set_bits(n))
106
107 def ulp_abs_check(expected, got, ulp_tol, abs_tol):
108 """Given finite floats `expected` and `got`, check that they're
109 approximately equal to within the given number of ulps or the
110 given absolute tolerance, whichever is bigger.
111
112 Returns None on success and an error message on failure.
113 """
114 ulp_error = abs(to_ulps(expected) - to_ulps(got))
115 abs_error = abs(expected - got)
116
117 # Succeed if either abs_error <= abs_tol or ulp_error <= ulp_tol.
118 if abs_error <= abs_tol or ulp_error <= ulp_tol:
119 return None
120 else:
121 fmt = ("error = {:.3g} ({:d} ulps); "
122 "permitted error = {:.3g} or {:d} ulps")
123 return fmt.format(abs_error, ulp_error, abs_tol, ulp_tol)
124
125 def parse_mtestfile(fname):
126 """Parse a file with test values
127
128 -- starts a comment
129 blank lines, or lines containing only a comment, are ignored
130 other lines are expected to have the form
131 id fn arg -> expected [flag]*
132
133 """
134 with open(fname, encoding="utf-8") as fp:
135 for line in fp:
136 # strip comments, and skip blank lines
137 if '--' in line:
138 line = line[:line.index('--')]
139 if not line.strip():
140 continue
141
142 lhs, rhs = line.split('->')
143 id, fn, arg = lhs.split()
144 rhs_pieces = rhs.split()
145 exp = rhs_pieces[0]
146 flags = rhs_pieces[1:]
147
148 yield (id, fn, float(arg), float(exp), flags)
149
150
151 def parse_testfile(fname):
152 """Parse a file with test values
153
154 Empty lines or lines starting with -- are ignored
155 yields id, fn, arg_real, arg_imag, exp_real, exp_imag
156 """
157 with open(fname, encoding="utf-8") as fp:
158 for line in fp:
159 # skip comment lines and blank lines
160 if line.startswith('--') or not line.strip():
161 continue
162
163 lhs, rhs = line.split('->')
164 id, fn, arg_real, arg_imag = lhs.split()
165 rhs_pieces = rhs.split()
166 exp_real, exp_imag = rhs_pieces[0], rhs_pieces[1]
167 flags = rhs_pieces[2:]
168
169 yield (id, fn,
170 float(arg_real), float(arg_imag),
171 float(exp_real), float(exp_imag),
172 flags)
173
174
175 def result_check(expected, got, ulp_tol=5, abs_tol=0.0):
176 # Common logic of MathTests.(ftest, test_testcases, test_mtestcases)
177 """Compare arguments expected and got, as floats, if either
178 is a float, using a tolerance expressed in multiples of
179 ulp(expected) or absolutely (if given and greater).
180
181 As a convenience, when neither argument is a float, and for
182 non-finite floats, exact equality is demanded. Also, nan==nan
183 as far as this function is concerned.
184
185 Returns None on success and an error message on failure.
186 """
187
188 # Check exactly equal (applies also to strings representing exceptions)
189 if got == expected:
190 return None
191
192 failure = "not equal"
193
194 # Turn mixed float and int comparison (e.g. floor()) to all-float
195 if isinstance(expected, float) and isinstance(got, int):
196 got = float(got)
197 elif isinstance(got, float) and isinstance(expected, int):
198 expected = float(expected)
199
200 if isinstance(expected, float) and isinstance(got, float):
201 if math.isnan(expected) and math.isnan(got):
202 # Pass, since both nan
203 failure = None
204 elif math.isinf(expected) or math.isinf(got):
205 # We already know they're not equal, drop through to failure
206 pass
207 else:
208 # Both are finite floats (now). Are they close enough?
209 failure = ulp_abs_check(expected, got, ulp_tol, abs_tol)
210
211 # arguments are not equal, and if numeric, are too far apart
212 if failure is not None:
213 fail_fmt = "expected {!r}, got {!r}"
214 fail_msg = fail_fmt.format(expected, got)
215 fail_msg += ' ({})'.format(failure)
216 return fail_msg
217 else:
218 return None
219
220 class ESC[4;38;5;81mFloatLike:
221 def __init__(self, value):
222 self.value = value
223
224 def __float__(self):
225 return self.value
226
227 class ESC[4;38;5;81mIntSubclass(ESC[4;38;5;149mint):
228 pass
229
230 # Class providing an __index__ method.
231 class ESC[4;38;5;81mMyIndexable(ESC[4;38;5;149mobject):
232 def __init__(self, value):
233 self.value = value
234
235 def __index__(self):
236 return self.value
237
238 class ESC[4;38;5;81mMathTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
239
240 def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
241 """Compare arguments expected and got, as floats, if either
242 is a float, using a tolerance expressed in multiples of
243 ulp(expected) or absolutely, whichever is greater.
244
245 As a convenience, when neither argument is a float, and for
246 non-finite floats, exact equality is demanded. Also, nan==nan
247 in this function.
248 """
249 failure = result_check(expected, got, ulp_tol, abs_tol)
250 if failure is not None:
251 self.fail("{}: {}".format(name, failure))
252
253 def testConstants(self):
254 # Ref: Abramowitz & Stegun (Dover, 1965)
255 self.ftest('pi', math.pi, 3.141592653589793238462643)
256 self.ftest('e', math.e, 2.718281828459045235360287)
257 self.assertEqual(math.tau, 2*math.pi)
258
259 def testAcos(self):
260 self.assertRaises(TypeError, math.acos)
261 self.ftest('acos(-1)', math.acos(-1), math.pi)
262 self.ftest('acos(0)', math.acos(0), math.pi/2)
263 self.ftest('acos(1)', math.acos(1), 0)
264 self.assertRaises(ValueError, math.acos, INF)
265 self.assertRaises(ValueError, math.acos, NINF)
266 self.assertRaises(ValueError, math.acos, 1 + eps)
267 self.assertRaises(ValueError, math.acos, -1 - eps)
268 self.assertTrue(math.isnan(math.acos(NAN)))
269
270 def testAcosh(self):
271 self.assertRaises(TypeError, math.acosh)
272 self.ftest('acosh(1)', math.acosh(1), 0)
273 self.ftest('acosh(2)', math.acosh(2), 1.3169578969248168)
274 self.assertRaises(ValueError, math.acosh, 0)
275 self.assertRaises(ValueError, math.acosh, -1)
276 self.assertEqual(math.acosh(INF), INF)
277 self.assertRaises(ValueError, math.acosh, NINF)
278 self.assertTrue(math.isnan(math.acosh(NAN)))
279
280 def testAsin(self):
281 self.assertRaises(TypeError, math.asin)
282 self.ftest('asin(-1)', math.asin(-1), -math.pi/2)
283 self.ftest('asin(0)', math.asin(0), 0)
284 self.ftest('asin(1)', math.asin(1), math.pi/2)
285 self.assertRaises(ValueError, math.asin, INF)
286 self.assertRaises(ValueError, math.asin, NINF)
287 self.assertRaises(ValueError, math.asin, 1 + eps)
288 self.assertRaises(ValueError, math.asin, -1 - eps)
289 self.assertTrue(math.isnan(math.asin(NAN)))
290
291 def testAsinh(self):
292 self.assertRaises(TypeError, math.asinh)
293 self.ftest('asinh(0)', math.asinh(0), 0)
294 self.ftest('asinh(1)', math.asinh(1), 0.88137358701954305)
295 self.ftest('asinh(-1)', math.asinh(-1), -0.88137358701954305)
296 self.assertEqual(math.asinh(INF), INF)
297 self.assertEqual(math.asinh(NINF), NINF)
298 self.assertTrue(math.isnan(math.asinh(NAN)))
299
300 def testAtan(self):
301 self.assertRaises(TypeError, math.atan)
302 self.ftest('atan(-1)', math.atan(-1), -math.pi/4)
303 self.ftest('atan(0)', math.atan(0), 0)
304 self.ftest('atan(1)', math.atan(1), math.pi/4)
305 self.ftest('atan(inf)', math.atan(INF), math.pi/2)
306 self.ftest('atan(-inf)', math.atan(NINF), -math.pi/2)
307 self.assertTrue(math.isnan(math.atan(NAN)))
308
309 def testAtanh(self):
310 self.assertRaises(TypeError, math.atan)
311 self.ftest('atanh(0)', math.atanh(0), 0)
312 self.ftest('atanh(0.5)', math.atanh(0.5), 0.54930614433405489)
313 self.ftest('atanh(-0.5)', math.atanh(-0.5), -0.54930614433405489)
314 self.assertRaises(ValueError, math.atanh, 1)
315 self.assertRaises(ValueError, math.atanh, -1)
316 self.assertRaises(ValueError, math.atanh, INF)
317 self.assertRaises(ValueError, math.atanh, NINF)
318 self.assertTrue(math.isnan(math.atanh(NAN)))
319
320 def testAtan2(self):
321 self.assertRaises(TypeError, math.atan2)
322 self.ftest('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
323 self.ftest('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4)
324 self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
325 self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
326 self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
327
328 # math.atan2(0, x)
329 self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
330 self.ftest('atan2(0., -2.3)', math.atan2(0., -2.3), math.pi)
331 self.ftest('atan2(0., -0.)', math.atan2(0., -0.), math.pi)
332 self.assertEqual(math.atan2(0., 0.), 0.)
333 self.assertEqual(math.atan2(0., 2.3), 0.)
334 self.assertEqual(math.atan2(0., INF), 0.)
335 self.assertTrue(math.isnan(math.atan2(0., NAN)))
336 # math.atan2(-0, x)
337 self.ftest('atan2(-0., -inf)', math.atan2(-0., NINF), -math.pi)
338 self.ftest('atan2(-0., -2.3)', math.atan2(-0., -2.3), -math.pi)
339 self.ftest('atan2(-0., -0.)', math.atan2(-0., -0.), -math.pi)
340 self.assertEqual(math.atan2(-0., 0.), -0.)
341 self.assertEqual(math.atan2(-0., 2.3), -0.)
342 self.assertEqual(math.atan2(-0., INF), -0.)
343 self.assertTrue(math.isnan(math.atan2(-0., NAN)))
344 # math.atan2(INF, x)
345 self.ftest('atan2(inf, -inf)', math.atan2(INF, NINF), math.pi*3/4)
346 self.ftest('atan2(inf, -2.3)', math.atan2(INF, -2.3), math.pi/2)
347 self.ftest('atan2(inf, -0.)', math.atan2(INF, -0.0), math.pi/2)
348 self.ftest('atan2(inf, 0.)', math.atan2(INF, 0.0), math.pi/2)
349 self.ftest('atan2(inf, 2.3)', math.atan2(INF, 2.3), math.pi/2)
350 self.ftest('atan2(inf, inf)', math.atan2(INF, INF), math.pi/4)
351 self.assertTrue(math.isnan(math.atan2(INF, NAN)))
352 # math.atan2(NINF, x)
353 self.ftest('atan2(-inf, -inf)', math.atan2(NINF, NINF), -math.pi*3/4)
354 self.ftest('atan2(-inf, -2.3)', math.atan2(NINF, -2.3), -math.pi/2)
355 self.ftest('atan2(-inf, -0.)', math.atan2(NINF, -0.0), -math.pi/2)
356 self.ftest('atan2(-inf, 0.)', math.atan2(NINF, 0.0), -math.pi/2)
357 self.ftest('atan2(-inf, 2.3)', math.atan2(NINF, 2.3), -math.pi/2)
358 self.ftest('atan2(-inf, inf)', math.atan2(NINF, INF), -math.pi/4)
359 self.assertTrue(math.isnan(math.atan2(NINF, NAN)))
360 # math.atan2(+finite, x)
361 self.ftest('atan2(2.3, -inf)', math.atan2(2.3, NINF), math.pi)
362 self.ftest('atan2(2.3, -0.)', math.atan2(2.3, -0.), math.pi/2)
363 self.ftest('atan2(2.3, 0.)', math.atan2(2.3, 0.), math.pi/2)
364 self.assertEqual(math.atan2(2.3, INF), 0.)
365 self.assertTrue(math.isnan(math.atan2(2.3, NAN)))
366 # math.atan2(-finite, x)
367 self.ftest('atan2(-2.3, -inf)', math.atan2(-2.3, NINF), -math.pi)
368 self.ftest('atan2(-2.3, -0.)', math.atan2(-2.3, -0.), -math.pi/2)
369 self.ftest('atan2(-2.3, 0.)', math.atan2(-2.3, 0.), -math.pi/2)
370 self.assertEqual(math.atan2(-2.3, INF), -0.)
371 self.assertTrue(math.isnan(math.atan2(-2.3, NAN)))
372 # math.atan2(NAN, x)
373 self.assertTrue(math.isnan(math.atan2(NAN, NINF)))
374 self.assertTrue(math.isnan(math.atan2(NAN, -2.3)))
375 self.assertTrue(math.isnan(math.atan2(NAN, -0.)))
376 self.assertTrue(math.isnan(math.atan2(NAN, 0.)))
377 self.assertTrue(math.isnan(math.atan2(NAN, 2.3)))
378 self.assertTrue(math.isnan(math.atan2(NAN, INF)))
379 self.assertTrue(math.isnan(math.atan2(NAN, NAN)))
380
381 def testCbrt(self):
382 self.assertRaises(TypeError, math.cbrt)
383 self.ftest('cbrt(0)', math.cbrt(0), 0)
384 self.ftest('cbrt(1)', math.cbrt(1), 1)
385 self.ftest('cbrt(8)', math.cbrt(8), 2)
386 self.ftest('cbrt(0.0)', math.cbrt(0.0), 0.0)
387 self.ftest('cbrt(-0.0)', math.cbrt(-0.0), -0.0)
388 self.ftest('cbrt(1.2)', math.cbrt(1.2), 1.062658569182611)
389 self.ftest('cbrt(-2.6)', math.cbrt(-2.6), -1.375068867074141)
390 self.ftest('cbrt(27)', math.cbrt(27), 3)
391 self.ftest('cbrt(-1)', math.cbrt(-1), -1)
392 self.ftest('cbrt(-27)', math.cbrt(-27), -3)
393 self.assertEqual(math.cbrt(INF), INF)
394 self.assertEqual(math.cbrt(NINF), NINF)
395 self.assertTrue(math.isnan(math.cbrt(NAN)))
396
397 def testCeil(self):
398 self.assertRaises(TypeError, math.ceil)
399 self.assertEqual(int, type(math.ceil(0.5)))
400 self.assertEqual(math.ceil(0.5), 1)
401 self.assertEqual(math.ceil(1.0), 1)
402 self.assertEqual(math.ceil(1.5), 2)
403 self.assertEqual(math.ceil(-0.5), 0)
404 self.assertEqual(math.ceil(-1.0), -1)
405 self.assertEqual(math.ceil(-1.5), -1)
406 self.assertEqual(math.ceil(0.0), 0)
407 self.assertEqual(math.ceil(-0.0), 0)
408 #self.assertEqual(math.ceil(INF), INF)
409 #self.assertEqual(math.ceil(NINF), NINF)
410 #self.assertTrue(math.isnan(math.ceil(NAN)))
411
412 class ESC[4;38;5;81mTestCeil:
413 def __ceil__(self):
414 return 42
415 class ESC[4;38;5;81mFloatCeil(ESC[4;38;5;149mfloat):
416 def __ceil__(self):
417 return 42
418 class ESC[4;38;5;81mTestNoCeil:
419 pass
420 self.assertEqual(math.ceil(TestCeil()), 42)
421 self.assertEqual(math.ceil(FloatCeil()), 42)
422 self.assertEqual(math.ceil(FloatLike(42.5)), 43)
423 self.assertRaises(TypeError, math.ceil, TestNoCeil())
424
425 t = TestNoCeil()
426 t.__ceil__ = lambda *args: args
427 self.assertRaises(TypeError, math.ceil, t)
428 self.assertRaises(TypeError, math.ceil, t, 0)
429
430 @requires_IEEE_754
431 def testCopysign(self):
432 self.assertEqual(math.copysign(1, 42), 1.0)
433 self.assertEqual(math.copysign(0., 42), 0.0)
434 self.assertEqual(math.copysign(1., -42), -1.0)
435 self.assertEqual(math.copysign(3, 0.), 3.0)
436 self.assertEqual(math.copysign(4., -0.), -4.0)
437
438 self.assertRaises(TypeError, math.copysign)
439 # copysign should let us distinguish signs of zeros
440 self.assertEqual(math.copysign(1., 0.), 1.)
441 self.assertEqual(math.copysign(1., -0.), -1.)
442 self.assertEqual(math.copysign(INF, 0.), INF)
443 self.assertEqual(math.copysign(INF, -0.), NINF)
444 self.assertEqual(math.copysign(NINF, 0.), INF)
445 self.assertEqual(math.copysign(NINF, -0.), NINF)
446 # and of infinities
447 self.assertEqual(math.copysign(1., INF), 1.)
448 self.assertEqual(math.copysign(1., NINF), -1.)
449 self.assertEqual(math.copysign(INF, INF), INF)
450 self.assertEqual(math.copysign(INF, NINF), NINF)
451 self.assertEqual(math.copysign(NINF, INF), INF)
452 self.assertEqual(math.copysign(NINF, NINF), NINF)
453 self.assertTrue(math.isnan(math.copysign(NAN, 1.)))
454 self.assertTrue(math.isnan(math.copysign(NAN, INF)))
455 self.assertTrue(math.isnan(math.copysign(NAN, NINF)))
456 self.assertTrue(math.isnan(math.copysign(NAN, NAN)))
457 # copysign(INF, NAN) may be INF or it may be NINF, since
458 # we don't know whether the sign bit of NAN is set on any
459 # given platform.
460 self.assertTrue(math.isinf(math.copysign(INF, NAN)))
461 # similarly, copysign(2., NAN) could be 2. or -2.
462 self.assertEqual(abs(math.copysign(2., NAN)), 2.)
463
464 def testCos(self):
465 self.assertRaises(TypeError, math.cos)
466 self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0, abs_tol=math.ulp(1))
467 self.ftest('cos(0)', math.cos(0), 1)
468 self.ftest('cos(pi/2)', math.cos(math.pi/2), 0, abs_tol=math.ulp(1))
469 self.ftest('cos(pi)', math.cos(math.pi), -1)
470 try:
471 self.assertTrue(math.isnan(math.cos(INF)))
472 self.assertTrue(math.isnan(math.cos(NINF)))
473 except ValueError:
474 self.assertRaises(ValueError, math.cos, INF)
475 self.assertRaises(ValueError, math.cos, NINF)
476 self.assertTrue(math.isnan(math.cos(NAN)))
477
478 @unittest.skipIf(sys.platform == 'win32' and platform.machine() in ('ARM', 'ARM64'),
479 "Windows UCRT is off by 2 ULP this test requires accuracy within 1 ULP")
480 def testCosh(self):
481 self.assertRaises(TypeError, math.cosh)
482 self.ftest('cosh(0)', math.cosh(0), 1)
483 self.ftest('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert
484 self.assertEqual(math.cosh(INF), INF)
485 self.assertEqual(math.cosh(NINF), INF)
486 self.assertTrue(math.isnan(math.cosh(NAN)))
487
488 def testDegrees(self):
489 self.assertRaises(TypeError, math.degrees)
490 self.ftest('degrees(pi)', math.degrees(math.pi), 180.0)
491 self.ftest('degrees(pi/2)', math.degrees(math.pi/2), 90.0)
492 self.ftest('degrees(-pi/4)', math.degrees(-math.pi/4), -45.0)
493 self.ftest('degrees(0)', math.degrees(0), 0)
494
495 def testExp(self):
496 self.assertRaises(TypeError, math.exp)
497 self.ftest('exp(-1)', math.exp(-1), 1/math.e)
498 self.ftest('exp(0)', math.exp(0), 1)
499 self.ftest('exp(1)', math.exp(1), math.e)
500 self.assertEqual(math.exp(INF), INF)
501 self.assertEqual(math.exp(NINF), 0.)
502 self.assertTrue(math.isnan(math.exp(NAN)))
503 self.assertRaises(OverflowError, math.exp, 1000000)
504
505 def testExp2(self):
506 self.assertRaises(TypeError, math.exp2)
507 self.ftest('exp2(-1)', math.exp2(-1), 0.5)
508 self.ftest('exp2(0)', math.exp2(0), 1)
509 self.ftest('exp2(1)', math.exp2(1), 2)
510 self.ftest('exp2(2.3)', math.exp2(2.3), 4.924577653379665)
511 self.assertEqual(math.exp2(INF), INF)
512 self.assertEqual(math.exp2(NINF), 0.)
513 self.assertTrue(math.isnan(math.exp2(NAN)))
514 self.assertRaises(OverflowError, math.exp2, 1000000)
515
516 def testFabs(self):
517 self.assertRaises(TypeError, math.fabs)
518 self.ftest('fabs(-1)', math.fabs(-1), 1)
519 self.ftest('fabs(0)', math.fabs(0), 0)
520 self.ftest('fabs(1)', math.fabs(1), 1)
521
522 def testFactorial(self):
523 self.assertEqual(math.factorial(0), 1)
524 total = 1
525 for i in range(1, 1000):
526 total *= i
527 self.assertEqual(math.factorial(i), total)
528 self.assertEqual(math.factorial(i), py_factorial(i))
529 self.assertRaises(ValueError, math.factorial, -1)
530 self.assertRaises(ValueError, math.factorial, -10**100)
531
532 def testFactorialNonIntegers(self):
533 self.assertRaises(TypeError, math.factorial, 5.0)
534 self.assertRaises(TypeError, math.factorial, 5.2)
535 self.assertRaises(TypeError, math.factorial, -1.0)
536 self.assertRaises(TypeError, math.factorial, -1e100)
537 self.assertRaises(TypeError, math.factorial, decimal.Decimal('5'))
538 self.assertRaises(TypeError, math.factorial, decimal.Decimal('5.2'))
539 self.assertRaises(TypeError, math.factorial, "5")
540
541 # Other implementations may place different upper bounds.
542 @support.cpython_only
543 def testFactorialHugeInputs(self):
544 # Currently raises OverflowError for inputs that are too large
545 # to fit into a C long.
546 self.assertRaises(OverflowError, math.factorial, 10**100)
547 self.assertRaises(TypeError, math.factorial, 1e100)
548
549 def testFloor(self):
550 self.assertRaises(TypeError, math.floor)
551 self.assertEqual(int, type(math.floor(0.5)))
552 self.assertEqual(math.floor(0.5), 0)
553 self.assertEqual(math.floor(1.0), 1)
554 self.assertEqual(math.floor(1.5), 1)
555 self.assertEqual(math.floor(-0.5), -1)
556 self.assertEqual(math.floor(-1.0), -1)
557 self.assertEqual(math.floor(-1.5), -2)
558 #self.assertEqual(math.ceil(INF), INF)
559 #self.assertEqual(math.ceil(NINF), NINF)
560 #self.assertTrue(math.isnan(math.floor(NAN)))
561
562 class ESC[4;38;5;81mTestFloor:
563 def __floor__(self):
564 return 42
565 class ESC[4;38;5;81mFloatFloor(ESC[4;38;5;149mfloat):
566 def __floor__(self):
567 return 42
568 class ESC[4;38;5;81mTestNoFloor:
569 pass
570 self.assertEqual(math.floor(TestFloor()), 42)
571 self.assertEqual(math.floor(FloatFloor()), 42)
572 self.assertEqual(math.floor(FloatLike(41.9)), 41)
573 self.assertRaises(TypeError, math.floor, TestNoFloor())
574
575 t = TestNoFloor()
576 t.__floor__ = lambda *args: args
577 self.assertRaises(TypeError, math.floor, t)
578 self.assertRaises(TypeError, math.floor, t, 0)
579
580 def testFmod(self):
581 self.assertRaises(TypeError, math.fmod)
582 self.ftest('fmod(10, 1)', math.fmod(10, 1), 0.0)
583 self.ftest('fmod(10, 0.5)', math.fmod(10, 0.5), 0.0)
584 self.ftest('fmod(10, 1.5)', math.fmod(10, 1.5), 1.0)
585 self.ftest('fmod(-10, 1)', math.fmod(-10, 1), -0.0)
586 self.ftest('fmod(-10, 0.5)', math.fmod(-10, 0.5), -0.0)
587 self.ftest('fmod(-10, 1.5)', math.fmod(-10, 1.5), -1.0)
588 self.assertTrue(math.isnan(math.fmod(NAN, 1.)))
589 self.assertTrue(math.isnan(math.fmod(1., NAN)))
590 self.assertTrue(math.isnan(math.fmod(NAN, NAN)))
591 self.assertRaises(ValueError, math.fmod, 1., 0.)
592 self.assertRaises(ValueError, math.fmod, INF, 1.)
593 self.assertRaises(ValueError, math.fmod, NINF, 1.)
594 self.assertRaises(ValueError, math.fmod, INF, 0.)
595 self.assertEqual(math.fmod(3.0, INF), 3.0)
596 self.assertEqual(math.fmod(-3.0, INF), -3.0)
597 self.assertEqual(math.fmod(3.0, NINF), 3.0)
598 self.assertEqual(math.fmod(-3.0, NINF), -3.0)
599 self.assertEqual(math.fmod(0.0, 3.0), 0.0)
600 self.assertEqual(math.fmod(0.0, NINF), 0.0)
601
602 def testFrexp(self):
603 self.assertRaises(TypeError, math.frexp)
604
605 def testfrexp(name, result, expected):
606 (mant, exp), (emant, eexp) = result, expected
607 if abs(mant-emant) > eps or exp != eexp:
608 self.fail('%s returned %r, expected %r'%\
609 (name, result, expected))
610
611 testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1))
612 testfrexp('frexp(0)', math.frexp(0), (0, 0))
613 testfrexp('frexp(1)', math.frexp(1), (0.5, 1))
614 testfrexp('frexp(2)', math.frexp(2), (0.5, 2))
615
616 self.assertEqual(math.frexp(INF)[0], INF)
617 self.assertEqual(math.frexp(NINF)[0], NINF)
618 self.assertTrue(math.isnan(math.frexp(NAN)[0]))
619
620 @requires_IEEE_754
621 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
622 "fsum is not exact on machines with double rounding")
623 def testFsum(self):
624 # math.fsum relies on exact rounding for correct operation.
625 # There's a known problem with IA32 floating-point that causes
626 # inexact rounding in some situations, and will cause the
627 # math.fsum tests below to fail; see issue #2937. On non IEEE
628 # 754 platforms, and on IEEE 754 platforms that exhibit the
629 # problem described in issue #2937, we simply skip the whole
630 # test.
631
632 # Python version of math.fsum, for comparison. Uses a
633 # different algorithm based on frexp, ldexp and integer
634 # arithmetic.
635 from sys import float_info
636 mant_dig = float_info.mant_dig
637 etiny = float_info.min_exp - mant_dig
638
639 def msum(iterable):
640 """Full precision summation. Compute sum(iterable) without any
641 intermediate accumulation of error. Based on the 'lsum' function
642 at http://code.activestate.com/recipes/393090/
643
644 """
645 tmant, texp = 0, 0
646 for x in iterable:
647 mant, exp = math.frexp(x)
648 mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
649 if texp > exp:
650 tmant <<= texp-exp
651 texp = exp
652 else:
653 mant <<= exp-texp
654 tmant += mant
655 # Round tmant * 2**texp to a float. The original recipe
656 # used float(str(tmant)) * 2.0**texp for this, but that's
657 # a little unsafe because str -> float conversion can't be
658 # relied upon to do correct rounding on all platforms.
659 tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
660 if tail > 0:
661 h = 1 << (tail-1)
662 tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
663 texp += tail
664 return math.ldexp(tmant, texp)
665
666 test_values = [
667 ([], 0.0),
668 ([0.0], 0.0),
669 ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
670 ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
671 ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
672 ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
673 ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
674 ([1./n for n in range(1, 1001)],
675 float.fromhex('0x1.df11f45f4e61ap+2')),
676 ([(-1.)**n/n for n in range(1, 1001)],
677 float.fromhex('-0x1.62a2af1bd3624p-1')),
678 ([1e16, 1., 1e-16], 10000000000000002.0),
679 ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
680 # exercise code for resizing partials array
681 ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
682 [-2.**1022],
683 float.fromhex('0x1.5555555555555p+970')),
684 ]
685
686 # Telescoping sum, with exact differences (due to Sterbenz)
687 terms = [1.7**i for i in range(1001)]
688 test_values.append((
689 [terms[i+1] - terms[i] for i in range(1000)] + [-terms[1000]],
690 -terms[0]
691 ))
692
693 for i, (vals, expected) in enumerate(test_values):
694 try:
695 actual = math.fsum(vals)
696 except OverflowError:
697 self.fail("test %d failed: got OverflowError, expected %r "
698 "for math.fsum(%.100r)" % (i, expected, vals))
699 except ValueError:
700 self.fail("test %d failed: got ValueError, expected %r "
701 "for math.fsum(%.100r)" % (i, expected, vals))
702 self.assertEqual(actual, expected)
703
704 from random import random, gauss, shuffle
705 for j in range(1000):
706 vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
707 s = 0
708 for i in range(200):
709 v = gauss(0, random()) ** 7 - s
710 s += v
711 vals.append(v)
712 shuffle(vals)
713
714 s = msum(vals)
715 self.assertEqual(msum(vals), math.fsum(vals))
716
717 def testGcd(self):
718 gcd = math.gcd
719 self.assertEqual(gcd(0, 0), 0)
720 self.assertEqual(gcd(1, 0), 1)
721 self.assertEqual(gcd(-1, 0), 1)
722 self.assertEqual(gcd(0, 1), 1)
723 self.assertEqual(gcd(0, -1), 1)
724 self.assertEqual(gcd(7, 1), 1)
725 self.assertEqual(gcd(7, -1), 1)
726 self.assertEqual(gcd(-23, 15), 1)
727 self.assertEqual(gcd(120, 84), 12)
728 self.assertEqual(gcd(84, -120), 12)
729 self.assertEqual(gcd(1216342683557601535506311712,
730 436522681849110124616458784), 32)
731
732 x = 434610456570399902378880679233098819019853229470286994367836600566
733 y = 1064502245825115327754847244914921553977
734 for c in (652560,
735 576559230871654959816130551884856912003141446781646602790216406874):
736 a = x * c
737 b = y * c
738 self.assertEqual(gcd(a, b), c)
739 self.assertEqual(gcd(b, a), c)
740 self.assertEqual(gcd(-a, b), c)
741 self.assertEqual(gcd(b, -a), c)
742 self.assertEqual(gcd(a, -b), c)
743 self.assertEqual(gcd(-b, a), c)
744 self.assertEqual(gcd(-a, -b), c)
745 self.assertEqual(gcd(-b, -a), c)
746
747 self.assertEqual(gcd(), 0)
748 self.assertEqual(gcd(120), 120)
749 self.assertEqual(gcd(-120), 120)
750 self.assertEqual(gcd(120, 84, 102), 6)
751 self.assertEqual(gcd(120, 1, 84), 1)
752
753 self.assertRaises(TypeError, gcd, 120.0)
754 self.assertRaises(TypeError, gcd, 120.0, 84)
755 self.assertRaises(TypeError, gcd, 120, 84.0)
756 self.assertRaises(TypeError, gcd, 120, 1, 84.0)
757 self.assertEqual(gcd(MyIndexable(120), MyIndexable(84)), 12)
758
759 def testHypot(self):
760 from decimal import Decimal
761 from fractions import Fraction
762
763 hypot = math.hypot
764
765 # Test different numbers of arguments (from zero to five)
766 # against a straightforward pure python implementation
767 args = math.e, math.pi, math.sqrt(2.0), math.gamma(3.5), math.sin(2.1)
768 for i in range(len(args)+1):
769 self.assertAlmostEqual(
770 hypot(*args[:i]),
771 math.sqrt(sum(s**2 for s in args[:i]))
772 )
773
774 # Test allowable types (those with __float__)
775 self.assertEqual(hypot(12.0, 5.0), 13.0)
776 self.assertEqual(hypot(12, 5), 13)
777 self.assertEqual(hypot(Decimal(12), Decimal(5)), 13)
778 self.assertEqual(hypot(Fraction(12, 32), Fraction(5, 32)), Fraction(13, 32))
779 self.assertEqual(hypot(bool(1), bool(0), bool(1), bool(1)), math.sqrt(3))
780
781 # Test corner cases
782 self.assertEqual(hypot(0.0, 0.0), 0.0) # Max input is zero
783 self.assertEqual(hypot(-10.5), 10.5) # Negative input
784 self.assertEqual(hypot(), 0.0) # Negative input
785 self.assertEqual(1.0,
786 math.copysign(1.0, hypot(-0.0)) # Convert negative zero to positive zero
787 )
788 self.assertEqual( # Handling of moving max to the end
789 hypot(1.5, 1.5, 0.5),
790 hypot(1.5, 0.5, 1.5),
791 )
792
793 # Test handling of bad arguments
794 with self.assertRaises(TypeError): # Reject keyword args
795 hypot(x=1)
796 with self.assertRaises(TypeError): # Reject values without __float__
797 hypot(1.1, 'string', 2.2)
798 int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5)
799 with self.assertRaises((ValueError, OverflowError)):
800 hypot(1, int_too_big_for_float)
801
802 # Any infinity gives positive infinity.
803 self.assertEqual(hypot(INF), INF)
804 self.assertEqual(hypot(0, INF), INF)
805 self.assertEqual(hypot(10, INF), INF)
806 self.assertEqual(hypot(-10, INF), INF)
807 self.assertEqual(hypot(NAN, INF), INF)
808 self.assertEqual(hypot(INF, NAN), INF)
809 self.assertEqual(hypot(NINF, NAN), INF)
810 self.assertEqual(hypot(NAN, NINF), INF)
811 self.assertEqual(hypot(-INF, INF), INF)
812 self.assertEqual(hypot(-INF, -INF), INF)
813 self.assertEqual(hypot(10, -INF), INF)
814
815 # If no infinity, any NaN gives a NaN.
816 self.assertTrue(math.isnan(hypot(NAN)))
817 self.assertTrue(math.isnan(hypot(0, NAN)))
818 self.assertTrue(math.isnan(hypot(NAN, 10)))
819 self.assertTrue(math.isnan(hypot(10, NAN)))
820 self.assertTrue(math.isnan(hypot(NAN, NAN)))
821 self.assertTrue(math.isnan(hypot(NAN)))
822
823 # Verify scaling for extremely large values
824 fourthmax = FLOAT_MAX / 4.0
825 for n in range(32):
826 self.assertTrue(math.isclose(hypot(*([fourthmax]*n)),
827 fourthmax * math.sqrt(n)))
828
829 # Verify scaling for extremely small values
830 for exp in range(32):
831 scale = FLOAT_MIN / 2.0 ** exp
832 self.assertEqual(math.hypot(4*scale, 3*scale), 5*scale)
833
834 @requires_IEEE_754
835 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
836 "hypot() loses accuracy on machines with double rounding")
837 def testHypotAccuracy(self):
838 # Verify improved accuracy in cases that were known to be inaccurate.
839 #
840 # The new algorithm's accuracy depends on IEEE 754 arithmetic
841 # guarantees, on having the usual ROUND HALF EVEN rounding mode, on
842 # the system not having double rounding due to extended precision,
843 # and on the compiler maintaining the specified order of operations.
844 #
845 # This test is known to succeed on most of our builds. If it fails
846 # some build, we either need to add another skipIf if the cause is
847 # identifiable; otherwise, we can remove this test entirely.
848
849 hypot = math.hypot
850 Decimal = decimal.Decimal
851 high_precision = decimal.Context(prec=500)
852
853 for hx, hy in [
854 # Cases with a 1 ulp error in Python 3.7 compiled with Clang
855 ('0x1.10e89518dca48p+29', '0x1.1970f7565b7efp+30'),
856 ('0x1.10106eb4b44a2p+29', '0x1.ef0596cdc97f8p+29'),
857 ('0x1.459c058e20bb7p+30', '0x1.993ca009b9178p+29'),
858 ('0x1.378371ae67c0cp+30', '0x1.fbe6619854b4cp+29'),
859 ('0x1.f4cd0574fb97ap+29', '0x1.50fe31669340ep+30'),
860 ('0x1.494b2cdd3d446p+29', '0x1.212a5367b4c7cp+29'),
861 ('0x1.f84e649f1e46dp+29', '0x1.1fa56bef8eec4p+30'),
862 ('0x1.2e817edd3d6fap+30', '0x1.eb0814f1e9602p+29'),
863 ('0x1.0d3a6e3d04245p+29', '0x1.32a62fea52352p+30'),
864 ('0x1.888e19611bfc5p+29', '0x1.52b8e70b24353p+29'),
865
866 # Cases with 2 ulp error in Python 3.8
867 ('0x1.538816d48a13fp+29', '0x1.7967c5ca43e16p+29'),
868 ('0x1.57b47b7234530p+29', '0x1.74e2c7040e772p+29'),
869 ('0x1.821b685e9b168p+30', '0x1.677dc1c1e3dc6p+29'),
870 ('0x1.9e8247f67097bp+29', '0x1.24bd2dc4f4baep+29'),
871 ('0x1.b73b59e0cb5f9p+29', '0x1.da899ab784a97p+28'),
872 ('0x1.94a8d2842a7cfp+30', '0x1.326a51d4d8d8ap+30'),
873 ('0x1.e930b9cd99035p+29', '0x1.5a1030e18dff9p+30'),
874 ('0x1.1592bbb0e4690p+29', '0x1.a9c337b33fb9ap+29'),
875 ('0x1.1243a50751fd4p+29', '0x1.a5a10175622d9p+29'),
876 ('0x1.57a8596e74722p+30', '0x1.42d1af9d04da9p+30'),
877
878 # Cases with 1 ulp error in version fff3c28052e6b0
879 ('0x1.ee7dbd9565899p+29', '0x1.7ab4d6fc6e4b4p+29'),
880 ('0x1.5c6bfbec5c4dcp+30', '0x1.02511184b4970p+30'),
881 ('0x1.59dcebba995cap+30', '0x1.50ca7e7c38854p+29'),
882 ('0x1.768cdd94cf5aap+29', '0x1.9cfdc5571d38ep+29'),
883 ('0x1.dcf137d60262ep+29', '0x1.1101621990b3ep+30'),
884 ('0x1.3a2d006e288b0p+30', '0x1.e9a240914326cp+29'),
885 ('0x1.62a32f7f53c61p+29', '0x1.47eb6cd72684fp+29'),
886 ('0x1.d3bcb60748ef2p+29', '0x1.3f13c4056312cp+30'),
887 ('0x1.282bdb82f17f3p+30', '0x1.640ba4c4eed3ap+30'),
888 ('0x1.89d8c423ea0c6p+29', '0x1.d35dcfe902bc3p+29'),
889 ]:
890 x = float.fromhex(hx)
891 y = float.fromhex(hy)
892 with self.subTest(hx=hx, hy=hy, x=x, y=y):
893 with decimal.localcontext(high_precision):
894 z = float((Decimal(x)**2 + Decimal(y)**2).sqrt())
895 self.assertEqual(hypot(x, y), z)
896
897 def testDist(self):
898 from decimal import Decimal as D
899 from fractions import Fraction as F
900
901 dist = math.dist
902 sqrt = math.sqrt
903
904 # Simple exact cases
905 self.assertEqual(dist((1.0, 2.0, 3.0), (4.0, 2.0, -1.0)), 5.0)
906 self.assertEqual(dist((1, 2, 3), (4, 2, -1)), 5.0)
907
908 # Test different numbers of arguments (from zero to nine)
909 # against a straightforward pure python implementation
910 for i in range(9):
911 for j in range(5):
912 p = tuple(random.uniform(-5, 5) for k in range(i))
913 q = tuple(random.uniform(-5, 5) for k in range(i))
914 self.assertAlmostEqual(
915 dist(p, q),
916 sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))
917 )
918
919 # Test non-tuple inputs
920 self.assertEqual(dist([1.0, 2.0, 3.0], [4.0, 2.0, -1.0]), 5.0)
921 self.assertEqual(dist(iter([1.0, 2.0, 3.0]), iter([4.0, 2.0, -1.0])), 5.0)
922
923 # Test allowable types (those with __float__)
924 self.assertEqual(dist((14.0, 1.0), (2.0, -4.0)), 13.0)
925 self.assertEqual(dist((14, 1), (2, -4)), 13)
926 self.assertEqual(dist((D(14), D(1)), (D(2), D(-4))), D(13))
927 self.assertEqual(dist((F(14, 32), F(1, 32)), (F(2, 32), F(-4, 32))),
928 F(13, 32))
929 self.assertEqual(dist((True, True, False, True, False),
930 (True, False, True, True, False)),
931 sqrt(2.0))
932
933 # Test corner cases
934 self.assertEqual(dist((13.25, 12.5, -3.25),
935 (13.25, 12.5, -3.25)),
936 0.0) # Distance with self is zero
937 self.assertEqual(dist((), ()), 0.0) # Zero-dimensional case
938 self.assertEqual(1.0, # Convert negative zero to positive zero
939 math.copysign(1.0, dist((-0.0,), (0.0,)))
940 )
941 self.assertEqual(1.0, # Convert negative zero to positive zero
942 math.copysign(1.0, dist((0.0,), (-0.0,)))
943 )
944 self.assertEqual( # Handling of moving max to the end
945 dist((1.5, 1.5, 0.5), (0, 0, 0)),
946 dist((1.5, 0.5, 1.5), (0, 0, 0))
947 )
948
949 # Verify tuple subclasses are allowed
950 class ESC[4;38;5;81mT(ESC[4;38;5;149mtuple):
951 pass
952 self.assertEqual(dist(T((1, 2, 3)), ((4, 2, -1))), 5.0)
953
954 # Test handling of bad arguments
955 with self.assertRaises(TypeError): # Reject keyword args
956 dist(p=(1, 2, 3), q=(4, 5, 6))
957 with self.assertRaises(TypeError): # Too few args
958 dist((1, 2, 3))
959 with self.assertRaises(TypeError): # Too many args
960 dist((1, 2, 3), (4, 5, 6), (7, 8, 9))
961 with self.assertRaises(TypeError): # Scalars not allowed
962 dist(1, 2)
963 with self.assertRaises(TypeError): # Reject values without __float__
964 dist((1.1, 'string', 2.2), (1, 2, 3))
965 with self.assertRaises(ValueError): # Check dimension agree
966 dist((1, 2, 3, 4), (5, 6, 7))
967 with self.assertRaises(ValueError): # Check dimension agree
968 dist((1, 2, 3), (4, 5, 6, 7))
969 with self.assertRaises(TypeError): # Rejects invalid types
970 dist("abc", "xyz")
971 int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5)
972 with self.assertRaises((ValueError, OverflowError)):
973 dist((1, int_too_big_for_float), (2, 3))
974 with self.assertRaises((ValueError, OverflowError)):
975 dist((2, 3), (1, int_too_big_for_float))
976
977 # Verify that the one dimensional case is equivalent to abs()
978 for i in range(20):
979 p, q = random.random(), random.random()
980 self.assertEqual(dist((p,), (q,)), abs(p - q))
981
982 # Test special values
983 values = [NINF, -10.5, -0.0, 0.0, 10.5, INF, NAN]
984 for p in itertools.product(values, repeat=3):
985 for q in itertools.product(values, repeat=3):
986 diffs = [px - qx for px, qx in zip(p, q)]
987 if any(map(math.isinf, diffs)):
988 # Any infinite difference gives positive infinity.
989 self.assertEqual(dist(p, q), INF)
990 elif any(map(math.isnan, diffs)):
991 # If no infinity, any NaN gives a NaN.
992 self.assertTrue(math.isnan(dist(p, q)))
993
994 # Verify scaling for extremely large values
995 fourthmax = FLOAT_MAX / 4.0
996 for n in range(32):
997 p = (fourthmax,) * n
998 q = (0.0,) * n
999 self.assertTrue(math.isclose(dist(p, q), fourthmax * math.sqrt(n)))
1000 self.assertTrue(math.isclose(dist(q, p), fourthmax * math.sqrt(n)))
1001
1002 # Verify scaling for extremely small values
1003 for exp in range(32):
1004 scale = FLOAT_MIN / 2.0 ** exp
1005 p = (4*scale, 3*scale)
1006 q = (0.0, 0.0)
1007 self.assertEqual(math.dist(p, q), 5*scale)
1008 self.assertEqual(math.dist(q, p), 5*scale)
1009
1010 def test_math_dist_leak(self):
1011 # gh-98897: Check for error handling does not leak memory
1012 with self.assertRaises(ValueError):
1013 math.dist([1, 2], [3, 4, 5])
1014
1015 def testIsqrt(self):
1016 # Test a variety of inputs, large and small.
1017 test_values = (
1018 list(range(1000))
1019 + list(range(10**6 - 1000, 10**6 + 1000))
1020 + [2**e + i for e in range(60, 200) for i in range(-40, 40)]
1021 + [3**9999, 10**5001]
1022 )
1023
1024 for value in test_values:
1025 with self.subTest(value=value):
1026 s = math.isqrt(value)
1027 self.assertIs(type(s), int)
1028 self.assertLessEqual(s*s, value)
1029 self.assertLess(value, (s+1)*(s+1))
1030
1031 # Negative values
1032 with self.assertRaises(ValueError):
1033 math.isqrt(-1)
1034
1035 # Integer-like things
1036 s = math.isqrt(True)
1037 self.assertIs(type(s), int)
1038 self.assertEqual(s, 1)
1039
1040 s = math.isqrt(False)
1041 self.assertIs(type(s), int)
1042 self.assertEqual(s, 0)
1043
1044 class ESC[4;38;5;81mIntegerLike(ESC[4;38;5;149mobject):
1045 def __init__(self, value):
1046 self.value = value
1047
1048 def __index__(self):
1049 return self.value
1050
1051 s = math.isqrt(IntegerLike(1729))
1052 self.assertIs(type(s), int)
1053 self.assertEqual(s, 41)
1054
1055 with self.assertRaises(ValueError):
1056 math.isqrt(IntegerLike(-3))
1057
1058 # Non-integer-like things
1059 bad_values = [
1060 3.5, "a string", decimal.Decimal("3.5"), 3.5j,
1061 100.0, -4.0,
1062 ]
1063 for value in bad_values:
1064 with self.subTest(value=value):
1065 with self.assertRaises(TypeError):
1066 math.isqrt(value)
1067
1068 def test_lcm(self):
1069 lcm = math.lcm
1070 self.assertEqual(lcm(0, 0), 0)
1071 self.assertEqual(lcm(1, 0), 0)
1072 self.assertEqual(lcm(-1, 0), 0)
1073 self.assertEqual(lcm(0, 1), 0)
1074 self.assertEqual(lcm(0, -1), 0)
1075 self.assertEqual(lcm(7, 1), 7)
1076 self.assertEqual(lcm(7, -1), 7)
1077 self.assertEqual(lcm(-23, 15), 345)
1078 self.assertEqual(lcm(120, 84), 840)
1079 self.assertEqual(lcm(84, -120), 840)
1080 self.assertEqual(lcm(1216342683557601535506311712,
1081 436522681849110124616458784),
1082 16592536571065866494401400422922201534178938447014944)
1083
1084 x = 43461045657039990237
1085 y = 10645022458251153277
1086 for c in (652560,
1087 57655923087165495981):
1088 a = x * c
1089 b = y * c
1090 d = x * y * c
1091 self.assertEqual(lcm(a, b), d)
1092 self.assertEqual(lcm(b, a), d)
1093 self.assertEqual(lcm(-a, b), d)
1094 self.assertEqual(lcm(b, -a), d)
1095 self.assertEqual(lcm(a, -b), d)
1096 self.assertEqual(lcm(-b, a), d)
1097 self.assertEqual(lcm(-a, -b), d)
1098 self.assertEqual(lcm(-b, -a), d)
1099
1100 self.assertEqual(lcm(), 1)
1101 self.assertEqual(lcm(120), 120)
1102 self.assertEqual(lcm(-120), 120)
1103 self.assertEqual(lcm(120, 84, 102), 14280)
1104 self.assertEqual(lcm(120, 0, 84), 0)
1105
1106 self.assertRaises(TypeError, lcm, 120.0)
1107 self.assertRaises(TypeError, lcm, 120.0, 84)
1108 self.assertRaises(TypeError, lcm, 120, 84.0)
1109 self.assertRaises(TypeError, lcm, 120, 0, 84.0)
1110 self.assertEqual(lcm(MyIndexable(120), MyIndexable(84)), 840)
1111
1112 def testLdexp(self):
1113 self.assertRaises(TypeError, math.ldexp)
1114 self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
1115 self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
1116 self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
1117 self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2)
1118 self.assertRaises(OverflowError, math.ldexp, 1., 1000000)
1119 self.assertRaises(OverflowError, math.ldexp, -1., 1000000)
1120 self.assertEqual(math.ldexp(1., -1000000), 0.)
1121 self.assertEqual(math.ldexp(-1., -1000000), -0.)
1122 self.assertEqual(math.ldexp(INF, 30), INF)
1123 self.assertEqual(math.ldexp(NINF, -213), NINF)
1124 self.assertTrue(math.isnan(math.ldexp(NAN, 0)))
1125
1126 # large second argument
1127 for n in [10**5, 10**10, 10**20, 10**40]:
1128 self.assertEqual(math.ldexp(INF, -n), INF)
1129 self.assertEqual(math.ldexp(NINF, -n), NINF)
1130 self.assertEqual(math.ldexp(1., -n), 0.)
1131 self.assertEqual(math.ldexp(-1., -n), -0.)
1132 self.assertEqual(math.ldexp(0., -n), 0.)
1133 self.assertEqual(math.ldexp(-0., -n), -0.)
1134 self.assertTrue(math.isnan(math.ldexp(NAN, -n)))
1135
1136 self.assertRaises(OverflowError, math.ldexp, 1., n)
1137 self.assertRaises(OverflowError, math.ldexp, -1., n)
1138 self.assertEqual(math.ldexp(0., n), 0.)
1139 self.assertEqual(math.ldexp(-0., n), -0.)
1140 self.assertEqual(math.ldexp(INF, n), INF)
1141 self.assertEqual(math.ldexp(NINF, n), NINF)
1142 self.assertTrue(math.isnan(math.ldexp(NAN, n)))
1143
1144 def testLog(self):
1145 self.assertRaises(TypeError, math.log)
1146 self.ftest('log(1/e)', math.log(1/math.e), -1)
1147 self.ftest('log(1)', math.log(1), 0)
1148 self.ftest('log(e)', math.log(math.e), 1)
1149 self.ftest('log(32,2)', math.log(32,2), 5)
1150 self.ftest('log(10**40, 10)', math.log(10**40, 10), 40)
1151 self.ftest('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
1152 self.ftest('log(10**1000)', math.log(10**1000),
1153 2302.5850929940457)
1154 self.assertRaises(ValueError, math.log, -1.5)
1155 self.assertRaises(ValueError, math.log, -10**1000)
1156 self.assertRaises(ValueError, math.log, NINF)
1157 self.assertEqual(math.log(INF), INF)
1158 self.assertTrue(math.isnan(math.log(NAN)))
1159
1160 def testLog1p(self):
1161 self.assertRaises(TypeError, math.log1p)
1162 for n in [2, 2**90, 2**300]:
1163 self.assertAlmostEqual(math.log1p(n), math.log1p(float(n)))
1164 self.assertRaises(ValueError, math.log1p, -1)
1165 self.assertEqual(math.log1p(INF), INF)
1166
1167 @requires_IEEE_754
1168 def testLog2(self):
1169 self.assertRaises(TypeError, math.log2)
1170
1171 # Check some integer values
1172 self.assertEqual(math.log2(1), 0.0)
1173 self.assertEqual(math.log2(2), 1.0)
1174 self.assertEqual(math.log2(4), 2.0)
1175
1176 # Large integer values
1177 self.assertEqual(math.log2(2**1023), 1023.0)
1178 self.assertEqual(math.log2(2**1024), 1024.0)
1179 self.assertEqual(math.log2(2**2000), 2000.0)
1180
1181 self.assertRaises(ValueError, math.log2, -1.5)
1182 self.assertRaises(ValueError, math.log2, NINF)
1183 self.assertTrue(math.isnan(math.log2(NAN)))
1184
1185 @requires_IEEE_754
1186 # log2() is not accurate enough on Mac OS X Tiger (10.4)
1187 @support.requires_mac_ver(10, 5)
1188 def testLog2Exact(self):
1189 # Check that we get exact equality for log2 of powers of 2.
1190 actual = [math.log2(math.ldexp(1.0, n)) for n in range(-1074, 1024)]
1191 expected = [float(n) for n in range(-1074, 1024)]
1192 self.assertEqual(actual, expected)
1193
1194 def testLog10(self):
1195 self.assertRaises(TypeError, math.log10)
1196 self.ftest('log10(0.1)', math.log10(0.1), -1)
1197 self.ftest('log10(1)', math.log10(1), 0)
1198 self.ftest('log10(10)', math.log10(10), 1)
1199 self.ftest('log10(10**1000)', math.log10(10**1000), 1000.0)
1200 self.assertRaises(ValueError, math.log10, -1.5)
1201 self.assertRaises(ValueError, math.log10, -10**1000)
1202 self.assertRaises(ValueError, math.log10, NINF)
1203 self.assertEqual(math.log(INF), INF)
1204 self.assertTrue(math.isnan(math.log10(NAN)))
1205
1206 def testSumProd(self):
1207 sumprod = math.sumprod
1208 Decimal = decimal.Decimal
1209 Fraction = fractions.Fraction
1210
1211 # Core functionality
1212 self.assertEqual(sumprod(iter([10, 20, 30]), (1, 2, 3)), 140)
1213 self.assertEqual(sumprod([1.5, 2.5], [3.5, 4.5]), 16.5)
1214 self.assertEqual(sumprod([], []), 0)
1215
1216 # Type preservation and coercion
1217 for v in [
1218 (10, 20, 30),
1219 (1.5, -2.5),
1220 (Fraction(3, 5), Fraction(4, 5)),
1221 (Decimal(3.5), Decimal(4.5)),
1222 (2.5, 10), # float/int
1223 (2.5, Fraction(3, 5)), # float/fraction
1224 (25, Fraction(3, 5)), # int/fraction
1225 (25, Decimal(4.5)), # int/decimal
1226 ]:
1227 for p, q in [(v, v), (v, v[::-1])]:
1228 with self.subTest(p=p, q=q):
1229 expected = sum(p_i * q_i for p_i, q_i in zip(p, q, strict=True))
1230 actual = sumprod(p, q)
1231 self.assertEqual(expected, actual)
1232 self.assertEqual(type(expected), type(actual))
1233
1234 # Bad arguments
1235 self.assertRaises(TypeError, sumprod) # No args
1236 self.assertRaises(TypeError, sumprod, []) # One arg
1237 self.assertRaises(TypeError, sumprod, [], [], []) # Three args
1238 self.assertRaises(TypeError, sumprod, None, [10]) # Non-iterable
1239 self.assertRaises(TypeError, sumprod, [10], None) # Non-iterable
1240
1241 # Uneven lengths
1242 self.assertRaises(ValueError, sumprod, [10, 20], [30])
1243 self.assertRaises(ValueError, sumprod, [10], [20, 30])
1244
1245 # Error in iterator
1246 def raise_after(n):
1247 for i in range(n):
1248 yield i
1249 raise RuntimeError
1250 with self.assertRaises(RuntimeError):
1251 sumprod(range(10), raise_after(5))
1252 with self.assertRaises(RuntimeError):
1253 sumprod(raise_after(5), range(10))
1254
1255 # Error in multiplication
1256 class ESC[4;38;5;81mBadMultiply:
1257 def __mul__(self, other):
1258 raise RuntimeError
1259 def __rmul__(self, other):
1260 raise RuntimeError
1261 with self.assertRaises(RuntimeError):
1262 sumprod([10, BadMultiply(), 30], [1, 2, 3])
1263 with self.assertRaises(RuntimeError):
1264 sumprod([1, 2, 3], [10, BadMultiply(), 30])
1265
1266 # Error in addition
1267 with self.assertRaises(TypeError):
1268 sumprod(['abc', 3], [5, 10])
1269 with self.assertRaises(TypeError):
1270 sumprod([5, 10], ['abc', 3])
1271
1272 # Special values should give the same as the pure python recipe
1273 self.assertEqual(sumprod([10.1, math.inf], [20.2, 30.3]), math.inf)
1274 self.assertEqual(sumprod([10.1, math.inf], [math.inf, 30.3]), math.inf)
1275 self.assertEqual(sumprod([10.1, math.inf], [math.inf, math.inf]), math.inf)
1276 self.assertEqual(sumprod([10.1, -math.inf], [20.2, 30.3]), -math.inf)
1277 self.assertTrue(math.isnan(sumprod([10.1, math.inf], [-math.inf, math.inf])))
1278 self.assertTrue(math.isnan(sumprod([10.1, math.nan], [20.2, 30.3])))
1279 self.assertTrue(math.isnan(sumprod([10.1, math.inf], [math.nan, 30.3])))
1280 self.assertTrue(math.isnan(sumprod([10.1, math.inf], [20.3, math.nan])))
1281
1282 # Error cases that arose during development
1283 args = ((-5, -5, 10), (1.5, 4611686018427387904, 2305843009213693952))
1284 self.assertEqual(sumprod(*args), 0.0)
1285
1286
1287 @requires_IEEE_754
1288 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
1289 "sumprod() accuracy not guaranteed on machines with double rounding")
1290 @support.cpython_only # Other implementations may choose a different algorithm
1291 def test_sumprod_accuracy(self):
1292 sumprod = math.sumprod
1293 self.assertEqual(sumprod([0.1] * 10, [1]*10), 1.0)
1294 self.assertEqual(sumprod([0.1] * 20, [True, False] * 10), 1.0)
1295 self.assertEqual(sumprod([1.0, 10E100, 1.0, -10E100], [1.0]*4), 2.0)
1296
1297 @support.requires_resource('cpu')
1298 def test_sumprod_stress(self):
1299 sumprod = math.sumprod
1300 product = itertools.product
1301 Decimal = decimal.Decimal
1302 Fraction = fractions.Fraction
1303
1304 class ESC[4;38;5;81mInt(ESC[4;38;5;149mint):
1305 def __add__(self, other):
1306 return Int(int(self) + int(other))
1307 def __mul__(self, other):
1308 return Int(int(self) * int(other))
1309 __radd__ = __add__
1310 __rmul__ = __mul__
1311 def __repr__(self):
1312 return f'Int({int(self)})'
1313
1314 class ESC[4;38;5;81mFlt(ESC[4;38;5;149mfloat):
1315 def __add__(self, other):
1316 return Int(int(self) + int(other))
1317 def __mul__(self, other):
1318 return Int(int(self) * int(other))
1319 __radd__ = __add__
1320 __rmul__ = __mul__
1321 def __repr__(self):
1322 return f'Flt({int(self)})'
1323
1324 def baseline_sumprod(p, q):
1325 """This defines the target behavior including expections and special values.
1326 However, it is subject to rounding errors, so float inputs should be exactly
1327 representable with only a few bits.
1328 """
1329 total = 0
1330 for p_i, q_i in zip(p, q, strict=True):
1331 total += p_i * q_i
1332 return total
1333
1334 def run(func, *args):
1335 "Make comparing functions easier. Returns error status, type, and result."
1336 try:
1337 result = func(*args)
1338 except (AssertionError, NameError):
1339 raise
1340 except Exception as e:
1341 return type(e), None, 'None'
1342 return None, type(result), repr(result)
1343
1344 pools = [
1345 (-5, 10, -2**20, 2**31, 2**40, 2**61, 2**62, 2**80, 1.5, Int(7)),
1346 (5.25, -3.5, 4.75, 11.25, 400.5, 0.046875, 0.25, -1.0, -0.078125),
1347 (-19.0*2**500, 11*2**1000, -3*2**1500, 17*2*333,
1348 5.25, -3.25, -3.0*2**(-333), 3, 2**513),
1349 (3.75, 2.5, -1.5, float('inf'), -float('inf'), float('NaN'), 14,
1350 9, 3+4j, Flt(13), 0.0),
1351 (13.25, -4.25, Decimal('10.5'), Decimal('-2.25'), Fraction(13, 8),
1352 Fraction(-11, 16), 4.75 + 0.125j, 97, -41, Int(3)),
1353 (Decimal('6.125'), Decimal('12.375'), Decimal('-2.75'), Decimal(0),
1354 Decimal('Inf'), -Decimal('Inf'), Decimal('NaN'), 12, 13.5),
1355 (-2.0 ** -1000, 11*2**1000, 3, 7, -37*2**32, -2*2**-537, -2*2**-538,
1356 2*2**-513),
1357 (-7 * 2.0 ** -510, 5 * 2.0 ** -520, 17, -19.0, -6.25),
1358 (11.25, -3.75, -0.625, 23.375, True, False, 7, Int(5)),
1359 ]
1360
1361 for pool in pools:
1362 for size in range(4):
1363 for args1 in product(pool, repeat=size):
1364 for args2 in product(pool, repeat=size):
1365 args = (args1, args2)
1366 self.assertEqual(
1367 run(baseline_sumprod, *args),
1368 run(sumprod, *args),
1369 args,
1370 )
1371
1372 @requires_IEEE_754
1373 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
1374 "sumprod() accuracy not guaranteed on machines with double rounding")
1375 @support.cpython_only # Other implementations may choose a different algorithm
1376 @support.requires_resource('cpu')
1377 def test_sumprod_extended_precision_accuracy(self):
1378 import operator
1379 from fractions import Fraction
1380 from itertools import starmap
1381 from collections import namedtuple
1382 from math import log2, exp2, fabs
1383 from random import choices, uniform, shuffle
1384 from statistics import median
1385
1386 DotExample = namedtuple('DotExample', ('x', 'y', 'target_sumprod', 'condition'))
1387
1388 def DotExact(x, y):
1389 vec1 = map(Fraction, x)
1390 vec2 = map(Fraction, y)
1391 return sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))
1392
1393 def Condition(x, y):
1394 return 2.0 * DotExact(map(abs, x), map(abs, y)) / abs(DotExact(x, y))
1395
1396 def linspace(lo, hi, n):
1397 width = (hi - lo) / (n - 1)
1398 return [lo + width * i for i in range(n)]
1399
1400 def GenDot(n, c):
1401 """ Algorithm 6.1 (GenDot) works as follows. The condition number (5.7) of
1402 the dot product xT y is proportional to the degree of cancellation. In
1403 order to achieve a prescribed cancellation, we generate the first half of
1404 the vectors x and y randomly within a large exponent range. This range is
1405 chosen according to the anticipated condition number. The second half of x
1406 and y is then constructed choosing xi randomly with decreasing exponent,
1407 and calculating yi such that some cancellation occurs. Finally, we permute
1408 the vectors x, y randomly and calculate the achieved condition number.
1409 """
1410
1411 assert n >= 6
1412 n2 = n // 2
1413 x = [0.0] * n
1414 y = [0.0] * n
1415 b = log2(c)
1416
1417 # First half with exponents from 0 to |_b/2_| and random ints in between
1418 e = choices(range(int(b/2)), k=n2)
1419 e[0] = int(b / 2) + 1
1420 e[-1] = 0.0
1421
1422 x[:n2] = [uniform(-1.0, 1.0) * exp2(p) for p in e]
1423 y[:n2] = [uniform(-1.0, 1.0) * exp2(p) for p in e]
1424
1425 # Second half
1426 e = list(map(round, linspace(b/2, 0.0 , n-n2)))
1427 for i in range(n2, n):
1428 x[i] = uniform(-1.0, 1.0) * exp2(e[i - n2])
1429 y[i] = (uniform(-1.0, 1.0) * exp2(e[i - n2]) - DotExact(x, y)) / x[i]
1430
1431 # Shuffle
1432 pairs = list(zip(x, y))
1433 shuffle(pairs)
1434 x, y = zip(*pairs)
1435
1436 return DotExample(x, y, DotExact(x, y), Condition(x, y))
1437
1438 def RelativeError(res, ex):
1439 x, y, target_sumprod, condition = ex
1440 n = DotExact(list(x) + [-res], list(y) + [1])
1441 return fabs(n / target_sumprod)
1442
1443 def Trial(dotfunc, c, n):
1444 ex = GenDot(10, c)
1445 res = dotfunc(ex.x, ex.y)
1446 return RelativeError(res, ex)
1447
1448 times = 1000 # Number of trials
1449 n = 20 # Length of vectors
1450 c = 1e30 # Target condition number
1451
1452 # If the following test fails, it means that the C math library
1453 # implementation of fma() is not compliant with the C99 standard
1454 # and is inaccurate. To solve this problem, make a new build
1455 # with the symbol UNRELIABLE_FMA defined. That will enable a
1456 # slower but accurate code path that avoids the fma() call.
1457 relative_err = median(Trial(math.sumprod, c, n) for i in range(times))
1458 self.assertLess(relative_err, 1e-16)
1459
1460 def testModf(self):
1461 self.assertRaises(TypeError, math.modf)
1462
1463 def testmodf(name, result, expected):
1464 (v1, v2), (e1, e2) = result, expected
1465 if abs(v1-e1) > eps or abs(v2-e2):
1466 self.fail('%s returned %r, expected %r'%\
1467 (name, result, expected))
1468
1469 testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0))
1470 testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0))
1471
1472 self.assertEqual(math.modf(INF), (0.0, INF))
1473 self.assertEqual(math.modf(NINF), (-0.0, NINF))
1474
1475 modf_nan = math.modf(NAN)
1476 self.assertTrue(math.isnan(modf_nan[0]))
1477 self.assertTrue(math.isnan(modf_nan[1]))
1478
1479 def testPow(self):
1480 self.assertRaises(TypeError, math.pow)
1481 self.ftest('pow(0,1)', math.pow(0,1), 0)
1482 self.ftest('pow(1,0)', math.pow(1,0), 1)
1483 self.ftest('pow(2,1)', math.pow(2,1), 2)
1484 self.ftest('pow(2,-1)', math.pow(2,-1), 0.5)
1485 self.assertEqual(math.pow(INF, 1), INF)
1486 self.assertEqual(math.pow(NINF, 1), NINF)
1487 self.assertEqual((math.pow(1, INF)), 1.)
1488 self.assertEqual((math.pow(1, NINF)), 1.)
1489 self.assertTrue(math.isnan(math.pow(NAN, 1)))
1490 self.assertTrue(math.isnan(math.pow(2, NAN)))
1491 self.assertTrue(math.isnan(math.pow(0, NAN)))
1492 self.assertEqual(math.pow(1, NAN), 1)
1493
1494 # pow(0., x)
1495 self.assertEqual(math.pow(0., INF), 0.)
1496 self.assertEqual(math.pow(0., 3.), 0.)
1497 self.assertEqual(math.pow(0., 2.3), 0.)
1498 self.assertEqual(math.pow(0., 2.), 0.)
1499 self.assertEqual(math.pow(0., 0.), 1.)
1500 self.assertEqual(math.pow(0., -0.), 1.)
1501 self.assertRaises(ValueError, math.pow, 0., -2.)
1502 self.assertRaises(ValueError, math.pow, 0., -2.3)
1503 self.assertRaises(ValueError, math.pow, 0., -3.)
1504 self.assertEqual(math.pow(0., NINF), INF)
1505 self.assertTrue(math.isnan(math.pow(0., NAN)))
1506
1507 # pow(INF, x)
1508 self.assertEqual(math.pow(INF, INF), INF)
1509 self.assertEqual(math.pow(INF, 3.), INF)
1510 self.assertEqual(math.pow(INF, 2.3), INF)
1511 self.assertEqual(math.pow(INF, 2.), INF)
1512 self.assertEqual(math.pow(INF, 0.), 1.)
1513 self.assertEqual(math.pow(INF, -0.), 1.)
1514 self.assertEqual(math.pow(INF, -2.), 0.)
1515 self.assertEqual(math.pow(INF, -2.3), 0.)
1516 self.assertEqual(math.pow(INF, -3.), 0.)
1517 self.assertEqual(math.pow(INF, NINF), 0.)
1518 self.assertTrue(math.isnan(math.pow(INF, NAN)))
1519
1520 # pow(-0., x)
1521 self.assertEqual(math.pow(-0., INF), 0.)
1522 self.assertEqual(math.pow(-0., 3.), -0.)
1523 self.assertEqual(math.pow(-0., 2.3), 0.)
1524 self.assertEqual(math.pow(-0., 2.), 0.)
1525 self.assertEqual(math.pow(-0., 0.), 1.)
1526 self.assertEqual(math.pow(-0., -0.), 1.)
1527 self.assertRaises(ValueError, math.pow, -0., -2.)
1528 self.assertRaises(ValueError, math.pow, -0., -2.3)
1529 self.assertRaises(ValueError, math.pow, -0., -3.)
1530 self.assertEqual(math.pow(-0., NINF), INF)
1531 self.assertTrue(math.isnan(math.pow(-0., NAN)))
1532
1533 # pow(NINF, x)
1534 self.assertEqual(math.pow(NINF, INF), INF)
1535 self.assertEqual(math.pow(NINF, 3.), NINF)
1536 self.assertEqual(math.pow(NINF, 2.3), INF)
1537 self.assertEqual(math.pow(NINF, 2.), INF)
1538 self.assertEqual(math.pow(NINF, 0.), 1.)
1539 self.assertEqual(math.pow(NINF, -0.), 1.)
1540 self.assertEqual(math.pow(NINF, -2.), 0.)
1541 self.assertEqual(math.pow(NINF, -2.3), 0.)
1542 self.assertEqual(math.pow(NINF, -3.), -0.)
1543 self.assertEqual(math.pow(NINF, NINF), 0.)
1544 self.assertTrue(math.isnan(math.pow(NINF, NAN)))
1545
1546 # pow(-1, x)
1547 self.assertEqual(math.pow(-1., INF), 1.)
1548 self.assertEqual(math.pow(-1., 3.), -1.)
1549 self.assertRaises(ValueError, math.pow, -1., 2.3)
1550 self.assertEqual(math.pow(-1., 2.), 1.)
1551 self.assertEqual(math.pow(-1., 0.), 1.)
1552 self.assertEqual(math.pow(-1., -0.), 1.)
1553 self.assertEqual(math.pow(-1., -2.), 1.)
1554 self.assertRaises(ValueError, math.pow, -1., -2.3)
1555 self.assertEqual(math.pow(-1., -3.), -1.)
1556 self.assertEqual(math.pow(-1., NINF), 1.)
1557 self.assertTrue(math.isnan(math.pow(-1., NAN)))
1558
1559 # pow(1, x)
1560 self.assertEqual(math.pow(1., INF), 1.)
1561 self.assertEqual(math.pow(1., 3.), 1.)
1562 self.assertEqual(math.pow(1., 2.3), 1.)
1563 self.assertEqual(math.pow(1., 2.), 1.)
1564 self.assertEqual(math.pow(1., 0.), 1.)
1565 self.assertEqual(math.pow(1., -0.), 1.)
1566 self.assertEqual(math.pow(1., -2.), 1.)
1567 self.assertEqual(math.pow(1., -2.3), 1.)
1568 self.assertEqual(math.pow(1., -3.), 1.)
1569 self.assertEqual(math.pow(1., NINF), 1.)
1570 self.assertEqual(math.pow(1., NAN), 1.)
1571
1572 # pow(x, 0) should be 1 for any x
1573 self.assertEqual(math.pow(2.3, 0.), 1.)
1574 self.assertEqual(math.pow(-2.3, 0.), 1.)
1575 self.assertEqual(math.pow(NAN, 0.), 1.)
1576 self.assertEqual(math.pow(2.3, -0.), 1.)
1577 self.assertEqual(math.pow(-2.3, -0.), 1.)
1578 self.assertEqual(math.pow(NAN, -0.), 1.)
1579
1580 # pow(x, y) is invalid if x is negative and y is not integral
1581 self.assertRaises(ValueError, math.pow, -1., 2.3)
1582 self.assertRaises(ValueError, math.pow, -15., -3.1)
1583
1584 # pow(x, NINF)
1585 self.assertEqual(math.pow(1.9, NINF), 0.)
1586 self.assertEqual(math.pow(1.1, NINF), 0.)
1587 self.assertEqual(math.pow(0.9, NINF), INF)
1588 self.assertEqual(math.pow(0.1, NINF), INF)
1589 self.assertEqual(math.pow(-0.1, NINF), INF)
1590 self.assertEqual(math.pow(-0.9, NINF), INF)
1591 self.assertEqual(math.pow(-1.1, NINF), 0.)
1592 self.assertEqual(math.pow(-1.9, NINF), 0.)
1593
1594 # pow(x, INF)
1595 self.assertEqual(math.pow(1.9, INF), INF)
1596 self.assertEqual(math.pow(1.1, INF), INF)
1597 self.assertEqual(math.pow(0.9, INF), 0.)
1598 self.assertEqual(math.pow(0.1, INF), 0.)
1599 self.assertEqual(math.pow(-0.1, INF), 0.)
1600 self.assertEqual(math.pow(-0.9, INF), 0.)
1601 self.assertEqual(math.pow(-1.1, INF), INF)
1602 self.assertEqual(math.pow(-1.9, INF), INF)
1603
1604 # pow(x, y) should work for x negative, y an integer
1605 self.ftest('(-2.)**3.', math.pow(-2.0, 3.0), -8.0)
1606 self.ftest('(-2.)**2.', math.pow(-2.0, 2.0), 4.0)
1607 self.ftest('(-2.)**1.', math.pow(-2.0, 1.0), -2.0)
1608 self.ftest('(-2.)**0.', math.pow(-2.0, 0.0), 1.0)
1609 self.ftest('(-2.)**-0.', math.pow(-2.0, -0.0), 1.0)
1610 self.ftest('(-2.)**-1.', math.pow(-2.0, -1.0), -0.5)
1611 self.ftest('(-2.)**-2.', math.pow(-2.0, -2.0), 0.25)
1612 self.ftest('(-2.)**-3.', math.pow(-2.0, -3.0), -0.125)
1613 self.assertRaises(ValueError, math.pow, -2.0, -0.5)
1614 self.assertRaises(ValueError, math.pow, -2.0, 0.5)
1615
1616 # the following tests have been commented out since they don't
1617 # really belong here: the implementation of ** for floats is
1618 # independent of the implementation of math.pow
1619 #self.assertEqual(1**NAN, 1)
1620 #self.assertEqual(1**INF, 1)
1621 #self.assertEqual(1**NINF, 1)
1622 #self.assertEqual(1**0, 1)
1623 #self.assertEqual(1.**NAN, 1)
1624 #self.assertEqual(1.**INF, 1)
1625 #self.assertEqual(1.**NINF, 1)
1626 #self.assertEqual(1.**0, 1)
1627
1628 def testRadians(self):
1629 self.assertRaises(TypeError, math.radians)
1630 self.ftest('radians(180)', math.radians(180), math.pi)
1631 self.ftest('radians(90)', math.radians(90), math.pi/2)
1632 self.ftest('radians(-45)', math.radians(-45), -math.pi/4)
1633 self.ftest('radians(0)', math.radians(0), 0)
1634
1635 @requires_IEEE_754
1636 def testRemainder(self):
1637 from fractions import Fraction
1638
1639 def validate_spec(x, y, r):
1640 """
1641 Check that r matches remainder(x, y) according to the IEEE 754
1642 specification. Assumes that x, y and r are finite and y is nonzero.
1643 """
1644 fx, fy, fr = Fraction(x), Fraction(y), Fraction(r)
1645 # r should not exceed y/2 in absolute value
1646 self.assertLessEqual(abs(fr), abs(fy/2))
1647 # x - r should be an exact integer multiple of y
1648 n = (fx - fr) / fy
1649 self.assertEqual(n, int(n))
1650 if abs(fr) == abs(fy/2):
1651 # If |r| == |y/2|, n should be even.
1652 self.assertEqual(n/2, int(n/2))
1653
1654 # triples (x, y, remainder(x, y)) in hexadecimal form.
1655 testcases = [
1656 # Remainders modulo 1, showing the ties-to-even behaviour.
1657 '-4.0 1 -0.0',
1658 '-3.8 1 0.8',
1659 '-3.0 1 -0.0',
1660 '-2.8 1 -0.8',
1661 '-2.0 1 -0.0',
1662 '-1.8 1 0.8',
1663 '-1.0 1 -0.0',
1664 '-0.8 1 -0.8',
1665 '-0.0 1 -0.0',
1666 ' 0.0 1 0.0',
1667 ' 0.8 1 0.8',
1668 ' 1.0 1 0.0',
1669 ' 1.8 1 -0.8',
1670 ' 2.0 1 0.0',
1671 ' 2.8 1 0.8',
1672 ' 3.0 1 0.0',
1673 ' 3.8 1 -0.8',
1674 ' 4.0 1 0.0',
1675
1676 # Reductions modulo 2*pi
1677 '0x0.0p+0 0x1.921fb54442d18p+2 0x0.0p+0',
1678 '0x1.921fb54442d18p+0 0x1.921fb54442d18p+2 0x1.921fb54442d18p+0',
1679 '0x1.921fb54442d17p+1 0x1.921fb54442d18p+2 0x1.921fb54442d17p+1',
1680 '0x1.921fb54442d18p+1 0x1.921fb54442d18p+2 0x1.921fb54442d18p+1',
1681 '0x1.921fb54442d19p+1 0x1.921fb54442d18p+2 -0x1.921fb54442d17p+1',
1682 '0x1.921fb54442d17p+2 0x1.921fb54442d18p+2 -0x0.0000000000001p+2',
1683 '0x1.921fb54442d18p+2 0x1.921fb54442d18p+2 0x0p0',
1684 '0x1.921fb54442d19p+2 0x1.921fb54442d18p+2 0x0.0000000000001p+2',
1685 '0x1.2d97c7f3321d1p+3 0x1.921fb54442d18p+2 0x1.921fb54442d14p+1',
1686 '0x1.2d97c7f3321d2p+3 0x1.921fb54442d18p+2 -0x1.921fb54442d18p+1',
1687 '0x1.2d97c7f3321d3p+3 0x1.921fb54442d18p+2 -0x1.921fb54442d14p+1',
1688 '0x1.921fb54442d17p+3 0x1.921fb54442d18p+2 -0x0.0000000000001p+3',
1689 '0x1.921fb54442d18p+3 0x1.921fb54442d18p+2 0x0p0',
1690 '0x1.921fb54442d19p+3 0x1.921fb54442d18p+2 0x0.0000000000001p+3',
1691 '0x1.f6a7a2955385dp+3 0x1.921fb54442d18p+2 0x1.921fb54442d14p+1',
1692 '0x1.f6a7a2955385ep+3 0x1.921fb54442d18p+2 0x1.921fb54442d18p+1',
1693 '0x1.f6a7a2955385fp+3 0x1.921fb54442d18p+2 -0x1.921fb54442d14p+1',
1694 '0x1.1475cc9eedf00p+5 0x1.921fb54442d18p+2 0x1.921fb54442d10p+1',
1695 '0x1.1475cc9eedf01p+5 0x1.921fb54442d18p+2 -0x1.921fb54442d10p+1',
1696
1697 # Symmetry with respect to signs.
1698 ' 1 0.c 0.4',
1699 '-1 0.c -0.4',
1700 ' 1 -0.c 0.4',
1701 '-1 -0.c -0.4',
1702 ' 1.4 0.c -0.4',
1703 '-1.4 0.c 0.4',
1704 ' 1.4 -0.c -0.4',
1705 '-1.4 -0.c 0.4',
1706
1707 # Huge modulus, to check that the underlying algorithm doesn't
1708 # rely on 2.0 * modulus being representable.
1709 '0x1.dp+1023 0x1.4p+1023 0x0.9p+1023',
1710 '0x1.ep+1023 0x1.4p+1023 -0x0.ap+1023',
1711 '0x1.fp+1023 0x1.4p+1023 -0x0.9p+1023',
1712 ]
1713
1714 for case in testcases:
1715 with self.subTest(case=case):
1716 x_hex, y_hex, expected_hex = case.split()
1717 x = float.fromhex(x_hex)
1718 y = float.fromhex(y_hex)
1719 expected = float.fromhex(expected_hex)
1720 validate_spec(x, y, expected)
1721 actual = math.remainder(x, y)
1722 # Cheap way of checking that the floats are
1723 # as identical as we need them to be.
1724 self.assertEqual(actual.hex(), expected.hex())
1725
1726 # Test tiny subnormal modulus: there's potential for
1727 # getting the implementation wrong here (for example,
1728 # by assuming that modulus/2 is exactly representable).
1729 tiny = float.fromhex('1p-1074') # min +ve subnormal
1730 for n in range(-25, 25):
1731 if n == 0:
1732 continue
1733 y = n * tiny
1734 for m in range(100):
1735 x = m * tiny
1736 actual = math.remainder(x, y)
1737 validate_spec(x, y, actual)
1738 actual = math.remainder(-x, y)
1739 validate_spec(-x, y, actual)
1740
1741 # Special values.
1742 # NaNs should propagate as usual.
1743 for value in [NAN, 0.0, -0.0, 2.0, -2.3, NINF, INF]:
1744 self.assertIsNaN(math.remainder(NAN, value))
1745 self.assertIsNaN(math.remainder(value, NAN))
1746
1747 # remainder(x, inf) is x, for non-nan non-infinite x.
1748 for value in [-2.3, -0.0, 0.0, 2.3]:
1749 self.assertEqual(math.remainder(value, INF), value)
1750 self.assertEqual(math.remainder(value, NINF), value)
1751
1752 # remainder(x, 0) and remainder(infinity, x) for non-NaN x are invalid
1753 # operations according to IEEE 754-2008 7.2(f), and should raise.
1754 for value in [NINF, -2.3, -0.0, 0.0, 2.3, INF]:
1755 with self.assertRaises(ValueError):
1756 math.remainder(INF, value)
1757 with self.assertRaises(ValueError):
1758 math.remainder(NINF, value)
1759 with self.assertRaises(ValueError):
1760 math.remainder(value, 0.0)
1761 with self.assertRaises(ValueError):
1762 math.remainder(value, -0.0)
1763
1764 def testSin(self):
1765 self.assertRaises(TypeError, math.sin)
1766 self.ftest('sin(0)', math.sin(0), 0)
1767 self.ftest('sin(pi/2)', math.sin(math.pi/2), 1)
1768 self.ftest('sin(-pi/2)', math.sin(-math.pi/2), -1)
1769 try:
1770 self.assertTrue(math.isnan(math.sin(INF)))
1771 self.assertTrue(math.isnan(math.sin(NINF)))
1772 except ValueError:
1773 self.assertRaises(ValueError, math.sin, INF)
1774 self.assertRaises(ValueError, math.sin, NINF)
1775 self.assertTrue(math.isnan(math.sin(NAN)))
1776
1777 def testSinh(self):
1778 self.assertRaises(TypeError, math.sinh)
1779 self.ftest('sinh(0)', math.sinh(0), 0)
1780 self.ftest('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
1781 self.ftest('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
1782 self.assertEqual(math.sinh(INF), INF)
1783 self.assertEqual(math.sinh(NINF), NINF)
1784 self.assertTrue(math.isnan(math.sinh(NAN)))
1785
1786 def testSqrt(self):
1787 self.assertRaises(TypeError, math.sqrt)
1788 self.ftest('sqrt(0)', math.sqrt(0), 0)
1789 self.ftest('sqrt(0)', math.sqrt(0.0), 0.0)
1790 self.ftest('sqrt(2.5)', math.sqrt(2.5), 1.5811388300841898)
1791 self.ftest('sqrt(0.25)', math.sqrt(0.25), 0.5)
1792 self.ftest('sqrt(25.25)', math.sqrt(25.25), 5.024937810560445)
1793 self.ftest('sqrt(1)', math.sqrt(1), 1)
1794 self.ftest('sqrt(4)', math.sqrt(4), 2)
1795 self.assertEqual(math.sqrt(INF), INF)
1796 self.assertRaises(ValueError, math.sqrt, -1)
1797 self.assertRaises(ValueError, math.sqrt, NINF)
1798 self.assertTrue(math.isnan(math.sqrt(NAN)))
1799
1800 def testTan(self):
1801 self.assertRaises(TypeError, math.tan)
1802 self.ftest('tan(0)', math.tan(0), 0)
1803 self.ftest('tan(pi/4)', math.tan(math.pi/4), 1)
1804 self.ftest('tan(-pi/4)', math.tan(-math.pi/4), -1)
1805 try:
1806 self.assertTrue(math.isnan(math.tan(INF)))
1807 self.assertTrue(math.isnan(math.tan(NINF)))
1808 except:
1809 self.assertRaises(ValueError, math.tan, INF)
1810 self.assertRaises(ValueError, math.tan, NINF)
1811 self.assertTrue(math.isnan(math.tan(NAN)))
1812
1813 def testTanh(self):
1814 self.assertRaises(TypeError, math.tanh)
1815 self.ftest('tanh(0)', math.tanh(0), 0)
1816 self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0,
1817 abs_tol=math.ulp(1))
1818 self.ftest('tanh(inf)', math.tanh(INF), 1)
1819 self.ftest('tanh(-inf)', math.tanh(NINF), -1)
1820 self.assertTrue(math.isnan(math.tanh(NAN)))
1821
1822 @requires_IEEE_754
1823 def testTanhSign(self):
1824 # check that tanh(-0.) == -0. on IEEE 754 systems
1825 self.assertEqual(math.tanh(-0.), -0.)
1826 self.assertEqual(math.copysign(1., math.tanh(-0.)),
1827 math.copysign(1., -0.))
1828
1829 def test_trunc(self):
1830 self.assertEqual(math.trunc(1), 1)
1831 self.assertEqual(math.trunc(-1), -1)
1832 self.assertEqual(type(math.trunc(1)), int)
1833 self.assertEqual(type(math.trunc(1.5)), int)
1834 self.assertEqual(math.trunc(1.5), 1)
1835 self.assertEqual(math.trunc(-1.5), -1)
1836 self.assertEqual(math.trunc(1.999999), 1)
1837 self.assertEqual(math.trunc(-1.999999), -1)
1838 self.assertEqual(math.trunc(-0.999999), -0)
1839 self.assertEqual(math.trunc(-100.999), -100)
1840
1841 class ESC[4;38;5;81mTestTrunc:
1842 def __trunc__(self):
1843 return 23
1844 class ESC[4;38;5;81mFloatTrunc(ESC[4;38;5;149mfloat):
1845 def __trunc__(self):
1846 return 23
1847 class ESC[4;38;5;81mTestNoTrunc:
1848 pass
1849
1850 self.assertEqual(math.trunc(TestTrunc()), 23)
1851 self.assertEqual(math.trunc(FloatTrunc()), 23)
1852
1853 self.assertRaises(TypeError, math.trunc)
1854 self.assertRaises(TypeError, math.trunc, 1, 2)
1855 self.assertRaises(TypeError, math.trunc, FloatLike(23.5))
1856 self.assertRaises(TypeError, math.trunc, TestNoTrunc())
1857
1858 def testIsfinite(self):
1859 self.assertTrue(math.isfinite(0.0))
1860 self.assertTrue(math.isfinite(-0.0))
1861 self.assertTrue(math.isfinite(1.0))
1862 self.assertTrue(math.isfinite(-1.0))
1863 self.assertFalse(math.isfinite(float("nan")))
1864 self.assertFalse(math.isfinite(float("inf")))
1865 self.assertFalse(math.isfinite(float("-inf")))
1866
1867 def testIsnan(self):
1868 self.assertTrue(math.isnan(float("nan")))
1869 self.assertTrue(math.isnan(float("-nan")))
1870 self.assertTrue(math.isnan(float("inf") * 0.))
1871 self.assertFalse(math.isnan(float("inf")))
1872 self.assertFalse(math.isnan(0.))
1873 self.assertFalse(math.isnan(1.))
1874
1875 def testIsinf(self):
1876 self.assertTrue(math.isinf(float("inf")))
1877 self.assertTrue(math.isinf(float("-inf")))
1878 self.assertTrue(math.isinf(1E400))
1879 self.assertTrue(math.isinf(-1E400))
1880 self.assertFalse(math.isinf(float("nan")))
1881 self.assertFalse(math.isinf(0.))
1882 self.assertFalse(math.isinf(1.))
1883
1884 def test_nan_constant(self):
1885 # `math.nan` must be a quiet NaN with positive sign bit
1886 self.assertTrue(math.isnan(math.nan))
1887 self.assertEqual(math.copysign(1., math.nan), 1.)
1888
1889 def test_inf_constant(self):
1890 self.assertTrue(math.isinf(math.inf))
1891 self.assertGreater(math.inf, 0.0)
1892 self.assertEqual(math.inf, float("inf"))
1893 self.assertEqual(-math.inf, float("-inf"))
1894
1895 # RED_FLAG 16-Oct-2000 Tim
1896 # While 2.0 is more consistent about exceptions than previous releases, it
1897 # still fails this part of the test on some platforms. For now, we only
1898 # *run* test_exceptions() in verbose mode, so that this isn't normally
1899 # tested.
1900 @unittest.skipUnless(verbose, 'requires verbose mode')
1901 def test_exceptions(self):
1902 try:
1903 x = math.exp(-1000000000)
1904 except:
1905 # mathmodule.c is failing to weed out underflows from libm, or
1906 # we've got an fp format with huge dynamic range
1907 self.fail("underflowing exp() should not have raised "
1908 "an exception")
1909 if x != 0:
1910 self.fail("underflowing exp() should have returned 0")
1911
1912 # If this fails, probably using a strict IEEE-754 conforming libm, and x
1913 # is +Inf afterwards. But Python wants overflows detected by default.
1914 try:
1915 x = math.exp(1000000000)
1916 except OverflowError:
1917 pass
1918 else:
1919 self.fail("overflowing exp() didn't trigger OverflowError")
1920
1921 # If this fails, it could be a puzzle. One odd possibility is that
1922 # mathmodule.c's macros are getting confused while comparing
1923 # Inf (HUGE_VAL) to a NaN, and artificially setting errno to ERANGE
1924 # as a result (and so raising OverflowError instead).
1925 try:
1926 x = math.sqrt(-1.0)
1927 except ValueError:
1928 pass
1929 else:
1930 self.fail("sqrt(-1) didn't raise ValueError")
1931
1932 @requires_IEEE_754
1933 def test_testfile(self):
1934 # Some tests need to be skipped on ancient OS X versions.
1935 # See issue #27953.
1936 SKIP_ON_TIGER = {'tan0064'}
1937
1938 osx_version = None
1939 if sys.platform == 'darwin':
1940 version_txt = platform.mac_ver()[0]
1941 try:
1942 osx_version = tuple(map(int, version_txt.split('.')))
1943 except ValueError:
1944 pass
1945
1946 fail_fmt = "{}: {}({!r}): {}"
1947
1948 failures = []
1949 for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file):
1950 # Skip if either the input or result is complex
1951 if ai != 0.0 or ei != 0.0:
1952 continue
1953 if fn in ['rect', 'polar']:
1954 # no real versions of rect, polar
1955 continue
1956 # Skip certain tests on OS X 10.4.
1957 if osx_version is not None and osx_version < (10, 5):
1958 if id in SKIP_ON_TIGER:
1959 continue
1960
1961 func = getattr(math, fn)
1962
1963 if 'invalid' in flags or 'divide-by-zero' in flags:
1964 er = 'ValueError'
1965 elif 'overflow' in flags:
1966 er = 'OverflowError'
1967
1968 try:
1969 result = func(ar)
1970 except ValueError:
1971 result = 'ValueError'
1972 except OverflowError:
1973 result = 'OverflowError'
1974
1975 # Default tolerances
1976 ulp_tol, abs_tol = 5, 0.0
1977
1978 failure = result_check(er, result, ulp_tol, abs_tol)
1979 if failure is None:
1980 continue
1981
1982 msg = fail_fmt.format(id, fn, ar, failure)
1983 failures.append(msg)
1984
1985 if failures:
1986 self.fail('Failures in test_testfile:\n ' +
1987 '\n '.join(failures))
1988
1989 @requires_IEEE_754
1990 def test_mtestfile(self):
1991 fail_fmt = "{}: {}({!r}): {}"
1992
1993 failures = []
1994 for id, fn, arg, expected, flags in parse_mtestfile(math_testcases):
1995 func = getattr(math, fn)
1996
1997 if 'invalid' in flags or 'divide-by-zero' in flags:
1998 expected = 'ValueError'
1999 elif 'overflow' in flags:
2000 expected = 'OverflowError'
2001
2002 try:
2003 got = func(arg)
2004 except ValueError:
2005 got = 'ValueError'
2006 except OverflowError:
2007 got = 'OverflowError'
2008
2009 # Default tolerances
2010 ulp_tol, abs_tol = 5, 0.0
2011
2012 # Exceptions to the defaults
2013 if fn == 'gamma':
2014 # Experimental results on one platform gave
2015 # an accuracy of <= 10 ulps across the entire float
2016 # domain. We weaken that to require 20 ulp accuracy.
2017 ulp_tol = 20
2018
2019 elif fn == 'lgamma':
2020 # we use a weaker accuracy test for lgamma;
2021 # lgamma only achieves an absolute error of
2022 # a few multiples of the machine accuracy, in
2023 # general.
2024 abs_tol = 1e-15
2025
2026 elif fn == 'erfc' and arg >= 0.0:
2027 # erfc has less-than-ideal accuracy for large
2028 # arguments (x ~ 25 or so), mainly due to the
2029 # error involved in computing exp(-x*x).
2030 #
2031 # Observed between CPython and mpmath at 25 dp:
2032 # x < 0 : err <= 2 ulp
2033 # 0 <= x < 1 : err <= 10 ulp
2034 # 1 <= x < 10 : err <= 100 ulp
2035 # 10 <= x < 20 : err <= 300 ulp
2036 # 20 <= x : < 600 ulp
2037 #
2038 if arg < 1.0:
2039 ulp_tol = 10
2040 elif arg < 10.0:
2041 ulp_tol = 100
2042 else:
2043 ulp_tol = 1000
2044
2045 failure = result_check(expected, got, ulp_tol, abs_tol)
2046 if failure is None:
2047 continue
2048
2049 msg = fail_fmt.format(id, fn, arg, failure)
2050 failures.append(msg)
2051
2052 if failures:
2053 self.fail('Failures in test_mtestfile:\n ' +
2054 '\n '.join(failures))
2055
2056 def test_prod(self):
2057 prod = math.prod
2058 self.assertEqual(prod([]), 1)
2059 self.assertEqual(prod([], start=5), 5)
2060 self.assertEqual(prod(list(range(2,8))), 5040)
2061 self.assertEqual(prod(iter(list(range(2,8)))), 5040)
2062 self.assertEqual(prod(range(1, 10), start=10), 3628800)
2063
2064 self.assertEqual(prod([1, 2, 3, 4, 5]), 120)
2065 self.assertEqual(prod([1.0, 2.0, 3.0, 4.0, 5.0]), 120.0)
2066 self.assertEqual(prod([1, 2, 3, 4.0, 5.0]), 120.0)
2067 self.assertEqual(prod([1.0, 2.0, 3.0, 4, 5]), 120.0)
2068
2069 # Test overflow in fast-path for integers
2070 self.assertEqual(prod([1, 1, 2**32, 1, 1]), 2**32)
2071 # Test overflow in fast-path for floats
2072 self.assertEqual(prod([1.0, 1.0, 2**32, 1, 1]), float(2**32))
2073
2074 self.assertRaises(TypeError, prod)
2075 self.assertRaises(TypeError, prod, 42)
2076 self.assertRaises(TypeError, prod, ['a', 'b', 'c'])
2077 self.assertRaises(TypeError, prod, ['a', 'b', 'c'], start='')
2078 self.assertRaises(TypeError, prod, [b'a', b'c'], start=b'')
2079 values = [bytearray(b'a'), bytearray(b'b')]
2080 self.assertRaises(TypeError, prod, values, start=bytearray(b''))
2081 self.assertRaises(TypeError, prod, [[1], [2], [3]])
2082 self.assertRaises(TypeError, prod, [{2:3}])
2083 self.assertRaises(TypeError, prod, [{2:3}]*2, start={2:3})
2084 self.assertRaises(TypeError, prod, [[1], [2], [3]], start=[])
2085
2086 # Some odd cases
2087 self.assertEqual(prod([2, 3], start='ab'), 'abababababab')
2088 self.assertEqual(prod([2, 3], start=[1, 2]), [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2])
2089 self.assertEqual(prod([], start={2: 3}), {2:3})
2090
2091 with self.assertRaises(TypeError):
2092 prod([10, 20], 1) # start is a keyword-only argument
2093
2094 self.assertEqual(prod([0, 1, 2, 3]), 0)
2095 self.assertEqual(prod([1, 0, 2, 3]), 0)
2096 self.assertEqual(prod([1, 2, 3, 0]), 0)
2097
2098 def _naive_prod(iterable, start=1):
2099 for elem in iterable:
2100 start *= elem
2101 return start
2102
2103 # Big integers
2104
2105 iterable = range(1, 10000)
2106 self.assertEqual(prod(iterable), _naive_prod(iterable))
2107 iterable = range(-10000, -1)
2108 self.assertEqual(prod(iterable), _naive_prod(iterable))
2109 iterable = range(-1000, 1000)
2110 self.assertEqual(prod(iterable), 0)
2111
2112 # Big floats
2113
2114 iterable = [float(x) for x in range(1, 1000)]
2115 self.assertEqual(prod(iterable), _naive_prod(iterable))
2116 iterable = [float(x) for x in range(-1000, -1)]
2117 self.assertEqual(prod(iterable), _naive_prod(iterable))
2118 iterable = [float(x) for x in range(-1000, 1000)]
2119 self.assertIsNaN(prod(iterable))
2120
2121 # Float tests
2122
2123 self.assertIsNaN(prod([1, 2, 3, float("nan"), 2, 3]))
2124 self.assertIsNaN(prod([1, 0, float("nan"), 2, 3]))
2125 self.assertIsNaN(prod([1, float("nan"), 0, 3]))
2126 self.assertIsNaN(prod([1, float("inf"), float("nan"),3]))
2127 self.assertIsNaN(prod([1, float("-inf"), float("nan"),3]))
2128 self.assertIsNaN(prod([1, float("nan"), float("inf"),3]))
2129 self.assertIsNaN(prod([1, float("nan"), float("-inf"),3]))
2130
2131 self.assertEqual(prod([1, 2, 3, float('inf'),-3,4]), float('-inf'))
2132 self.assertEqual(prod([1, 2, 3, float('-inf'),-3,4]), float('inf'))
2133
2134 self.assertIsNaN(prod([1,2,0,float('inf'), -3, 4]))
2135 self.assertIsNaN(prod([1,2,0,float('-inf'), -3, 4]))
2136 self.assertIsNaN(prod([1, 2, 3, float('inf'), -3, 0, 3]))
2137 self.assertIsNaN(prod([1, 2, 3, float('-inf'), -3, 0, 2]))
2138
2139 # Type preservation
2140
2141 self.assertEqual(type(prod([1, 2, 3, 4, 5, 6])), int)
2142 self.assertEqual(type(prod([1, 2.0, 3, 4, 5, 6])), float)
2143 self.assertEqual(type(prod(range(1, 10000))), int)
2144 self.assertEqual(type(prod(range(1, 10000), start=1.0)), float)
2145 self.assertEqual(type(prod([1, decimal.Decimal(2.0), 3, 4, 5, 6])),
2146 decimal.Decimal)
2147
2148 def testPerm(self):
2149 perm = math.perm
2150 factorial = math.factorial
2151 # Test if factorial definition is satisfied
2152 for n in range(500):
2153 for k in (range(n + 1) if n < 100 else range(30) if n < 200 else range(10)):
2154 self.assertEqual(perm(n, k),
2155 factorial(n) // factorial(n - k))
2156
2157 # Test for Pascal's identity
2158 for n in range(1, 100):
2159 for k in range(1, n):
2160 self.assertEqual(perm(n, k), perm(n - 1, k - 1) * k + perm(n - 1, k))
2161
2162 # Test corner cases
2163 for n in range(1, 100):
2164 self.assertEqual(perm(n, 0), 1)
2165 self.assertEqual(perm(n, 1), n)
2166 self.assertEqual(perm(n, n), factorial(n))
2167
2168 # Test one argument form
2169 for n in range(20):
2170 self.assertEqual(perm(n), factorial(n))
2171 self.assertEqual(perm(n, None), factorial(n))
2172
2173 # Raises TypeError if any argument is non-integer or argument count is
2174 # not 1 or 2
2175 self.assertRaises(TypeError, perm, 10, 1.0)
2176 self.assertRaises(TypeError, perm, 10, decimal.Decimal(1.0))
2177 self.assertRaises(TypeError, perm, 10, "1")
2178 self.assertRaises(TypeError, perm, 10.0, 1)
2179 self.assertRaises(TypeError, perm, decimal.Decimal(10.0), 1)
2180 self.assertRaises(TypeError, perm, "10", 1)
2181
2182 self.assertRaises(TypeError, perm)
2183 self.assertRaises(TypeError, perm, 10, 1, 3)
2184 self.assertRaises(TypeError, perm)
2185
2186 # Raises Value error if not k or n are negative numbers
2187 self.assertRaises(ValueError, perm, -1, 1)
2188 self.assertRaises(ValueError, perm, -2**1000, 1)
2189 self.assertRaises(ValueError, perm, 1, -1)
2190 self.assertRaises(ValueError, perm, 1, -2**1000)
2191
2192 # Returns zero if k is greater than n
2193 self.assertEqual(perm(1, 2), 0)
2194 self.assertEqual(perm(1, 2**1000), 0)
2195
2196 n = 2**1000
2197 self.assertEqual(perm(n, 0), 1)
2198 self.assertEqual(perm(n, 1), n)
2199 self.assertEqual(perm(n, 2), n * (n-1))
2200 if support.check_impl_detail(cpython=True):
2201 self.assertRaises(OverflowError, perm, n, n)
2202
2203 for n, k in (True, True), (True, False), (False, False):
2204 self.assertEqual(perm(n, k), 1)
2205 self.assertIs(type(perm(n, k)), int)
2206 self.assertEqual(perm(IntSubclass(5), IntSubclass(2)), 20)
2207 self.assertEqual(perm(MyIndexable(5), MyIndexable(2)), 20)
2208 for k in range(3):
2209 self.assertIs(type(perm(IntSubclass(5), IntSubclass(k))), int)
2210 self.assertIs(type(perm(MyIndexable(5), MyIndexable(k))), int)
2211
2212 def testComb(self):
2213 comb = math.comb
2214 factorial = math.factorial
2215 # Test if factorial definition is satisfied
2216 for n in range(500):
2217 for k in (range(n + 1) if n < 100 else range(30) if n < 200 else range(10)):
2218 self.assertEqual(comb(n, k), factorial(n)
2219 // (factorial(k) * factorial(n - k)))
2220
2221 # Test for Pascal's identity
2222 for n in range(1, 100):
2223 for k in range(1, n):
2224 self.assertEqual(comb(n, k), comb(n - 1, k - 1) + comb(n - 1, k))
2225
2226 # Test corner cases
2227 for n in range(100):
2228 self.assertEqual(comb(n, 0), 1)
2229 self.assertEqual(comb(n, n), 1)
2230
2231 for n in range(1, 100):
2232 self.assertEqual(comb(n, 1), n)
2233 self.assertEqual(comb(n, n - 1), n)
2234
2235 # Test Symmetry
2236 for n in range(100):
2237 for k in range(n // 2):
2238 self.assertEqual(comb(n, k), comb(n, n - k))
2239
2240 # Raises TypeError if any argument is non-integer or argument count is
2241 # not 2
2242 self.assertRaises(TypeError, comb, 10, 1.0)
2243 self.assertRaises(TypeError, comb, 10, decimal.Decimal(1.0))
2244 self.assertRaises(TypeError, comb, 10, "1")
2245 self.assertRaises(TypeError, comb, 10.0, 1)
2246 self.assertRaises(TypeError, comb, decimal.Decimal(10.0), 1)
2247 self.assertRaises(TypeError, comb, "10", 1)
2248
2249 self.assertRaises(TypeError, comb, 10)
2250 self.assertRaises(TypeError, comb, 10, 1, 3)
2251 self.assertRaises(TypeError, comb)
2252
2253 # Raises Value error if not k or n are negative numbers
2254 self.assertRaises(ValueError, comb, -1, 1)
2255 self.assertRaises(ValueError, comb, -2**1000, 1)
2256 self.assertRaises(ValueError, comb, 1, -1)
2257 self.assertRaises(ValueError, comb, 1, -2**1000)
2258
2259 # Returns zero if k is greater than n
2260 self.assertEqual(comb(1, 2), 0)
2261 self.assertEqual(comb(1, 2**1000), 0)
2262
2263 n = 2**1000
2264 self.assertEqual(comb(n, 0), 1)
2265 self.assertEqual(comb(n, 1), n)
2266 self.assertEqual(comb(n, 2), n * (n-1) // 2)
2267 self.assertEqual(comb(n, n), 1)
2268 self.assertEqual(comb(n, n-1), n)
2269 self.assertEqual(comb(n, n-2), n * (n-1) // 2)
2270 if support.check_impl_detail(cpython=True):
2271 self.assertRaises(OverflowError, comb, n, n//2)
2272
2273 for n, k in (True, True), (True, False), (False, False):
2274 self.assertEqual(comb(n, k), 1)
2275 self.assertIs(type(comb(n, k)), int)
2276 self.assertEqual(comb(IntSubclass(5), IntSubclass(2)), 10)
2277 self.assertEqual(comb(MyIndexable(5), MyIndexable(2)), 10)
2278 for k in range(3):
2279 self.assertIs(type(comb(IntSubclass(5), IntSubclass(k))), int)
2280 self.assertIs(type(comb(MyIndexable(5), MyIndexable(k))), int)
2281
2282 @requires_IEEE_754
2283 def test_nextafter(self):
2284 # around 2^52 and 2^63
2285 self.assertEqual(math.nextafter(4503599627370496.0, -INF),
2286 4503599627370495.5)
2287 self.assertEqual(math.nextafter(4503599627370496.0, INF),
2288 4503599627370497.0)
2289 self.assertEqual(math.nextafter(9223372036854775808.0, 0.0),
2290 9223372036854774784.0)
2291 self.assertEqual(math.nextafter(-9223372036854775808.0, 0.0),
2292 -9223372036854774784.0)
2293
2294 # around 1.0
2295 self.assertEqual(math.nextafter(1.0, -INF),
2296 float.fromhex('0x1.fffffffffffffp-1'))
2297 self.assertEqual(math.nextafter(1.0, INF),
2298 float.fromhex('0x1.0000000000001p+0'))
2299 self.assertEqual(math.nextafter(1.0, -INF, steps=1),
2300 float.fromhex('0x1.fffffffffffffp-1'))
2301 self.assertEqual(math.nextafter(1.0, INF, steps=1),
2302 float.fromhex('0x1.0000000000001p+0'))
2303 self.assertEqual(math.nextafter(1.0, -INF, steps=3),
2304 float.fromhex('0x1.ffffffffffffdp-1'))
2305 self.assertEqual(math.nextafter(1.0, INF, steps=3),
2306 float.fromhex('0x1.0000000000003p+0'))
2307
2308 # x == y: y is returned
2309 for steps in range(1, 5):
2310 self.assertEqual(math.nextafter(2.0, 2.0, steps=steps), 2.0)
2311 self.assertEqualSign(math.nextafter(-0.0, +0.0, steps=steps), +0.0)
2312 self.assertEqualSign(math.nextafter(+0.0, -0.0, steps=steps), -0.0)
2313
2314 # around 0.0
2315 smallest_subnormal = sys.float_info.min * sys.float_info.epsilon
2316 self.assertEqual(math.nextafter(+0.0, INF), smallest_subnormal)
2317 self.assertEqual(math.nextafter(-0.0, INF), smallest_subnormal)
2318 self.assertEqual(math.nextafter(+0.0, -INF), -smallest_subnormal)
2319 self.assertEqual(math.nextafter(-0.0, -INF), -smallest_subnormal)
2320 self.assertEqualSign(math.nextafter(smallest_subnormal, +0.0), +0.0)
2321 self.assertEqualSign(math.nextafter(-smallest_subnormal, +0.0), -0.0)
2322 self.assertEqualSign(math.nextafter(smallest_subnormal, -0.0), +0.0)
2323 self.assertEqualSign(math.nextafter(-smallest_subnormal, -0.0), -0.0)
2324
2325 # around infinity
2326 largest_normal = sys.float_info.max
2327 self.assertEqual(math.nextafter(INF, 0.0), largest_normal)
2328 self.assertEqual(math.nextafter(-INF, 0.0), -largest_normal)
2329 self.assertEqual(math.nextafter(largest_normal, INF), INF)
2330 self.assertEqual(math.nextafter(-largest_normal, -INF), -INF)
2331
2332 # NaN
2333 self.assertIsNaN(math.nextafter(NAN, 1.0))
2334 self.assertIsNaN(math.nextafter(1.0, NAN))
2335 self.assertIsNaN(math.nextafter(NAN, NAN))
2336
2337 self.assertEqual(1.0, math.nextafter(1.0, INF, steps=0))
2338 with self.assertRaises(ValueError):
2339 math.nextafter(1.0, INF, steps=-1)
2340
2341
2342 @requires_IEEE_754
2343 def test_ulp(self):
2344 self.assertEqual(math.ulp(1.0), sys.float_info.epsilon)
2345 # use int ** int rather than float ** int to not rely on pow() accuracy
2346 self.assertEqual(math.ulp(2 ** 52), 1.0)
2347 self.assertEqual(math.ulp(2 ** 53), 2.0)
2348 self.assertEqual(math.ulp(2 ** 64), 4096.0)
2349
2350 # min and max
2351 self.assertEqual(math.ulp(0.0),
2352 sys.float_info.min * sys.float_info.epsilon)
2353 self.assertEqual(math.ulp(FLOAT_MAX),
2354 FLOAT_MAX - math.nextafter(FLOAT_MAX, -INF))
2355
2356 # special cases
2357 self.assertEqual(math.ulp(INF), INF)
2358 self.assertIsNaN(math.ulp(math.nan))
2359
2360 # negative number: ulp(-x) == ulp(x)
2361 for x in (0.0, 1.0, 2 ** 52, 2 ** 64, INF):
2362 with self.subTest(x=x):
2363 self.assertEqual(math.ulp(-x), math.ulp(x))
2364
2365 def test_issue39871(self):
2366 # A SystemError should not be raised if the first arg to atan2(),
2367 # copysign(), or remainder() cannot be converted to a float.
2368 class ESC[4;38;5;81mF:
2369 def __float__(self):
2370 self.converted = True
2371 1/0
2372 for func in math.atan2, math.copysign, math.remainder:
2373 y = F()
2374 with self.assertRaises(TypeError):
2375 func("not a number", y)
2376
2377 # There should not have been any attempt to convert the second
2378 # argument to a float.
2379 self.assertFalse(getattr(y, "converted", False))
2380
2381 # Custom assertions.
2382
2383 def assertIsNaN(self, value):
2384 if not math.isnan(value):
2385 self.fail("Expected a NaN, got {!r}.".format(value))
2386
2387 def assertEqualSign(self, x, y):
2388 """Similar to assertEqual(), but compare also the sign with copysign().
2389
2390 Function useful to compare signed zeros.
2391 """
2392 self.assertEqual(x, y)
2393 self.assertEqual(math.copysign(1.0, x), math.copysign(1.0, y))
2394
2395
2396 class ESC[4;38;5;81mIsCloseTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
2397 isclose = math.isclose # subclasses should override this
2398
2399 def assertIsClose(self, a, b, *args, **kwargs):
2400 self.assertTrue(self.isclose(a, b, *args, **kwargs),
2401 msg="%s and %s should be close!" % (a, b))
2402
2403 def assertIsNotClose(self, a, b, *args, **kwargs):
2404 self.assertFalse(self.isclose(a, b, *args, **kwargs),
2405 msg="%s and %s should not be close!" % (a, b))
2406
2407 def assertAllClose(self, examples, *args, **kwargs):
2408 for a, b in examples:
2409 self.assertIsClose(a, b, *args, **kwargs)
2410
2411 def assertAllNotClose(self, examples, *args, **kwargs):
2412 for a, b in examples:
2413 self.assertIsNotClose(a, b, *args, **kwargs)
2414
2415 def test_negative_tolerances(self):
2416 # ValueError should be raised if either tolerance is less than zero
2417 with self.assertRaises(ValueError):
2418 self.assertIsClose(1, 1, rel_tol=-1e-100)
2419 with self.assertRaises(ValueError):
2420 self.assertIsClose(1, 1, rel_tol=1e-100, abs_tol=-1e10)
2421
2422 def test_identical(self):
2423 # identical values must test as close
2424 identical_examples = [(2.0, 2.0),
2425 (0.1e200, 0.1e200),
2426 (1.123e-300, 1.123e-300),
2427 (12345, 12345.0),
2428 (0.0, -0.0),
2429 (345678, 345678)]
2430 self.assertAllClose(identical_examples, rel_tol=0.0, abs_tol=0.0)
2431
2432 def test_eight_decimal_places(self):
2433 # examples that are close to 1e-8, but not 1e-9
2434 eight_decimal_places_examples = [(1e8, 1e8 + 1),
2435 (-1e-8, -1.000000009e-8),
2436 (1.12345678, 1.12345679)]
2437 self.assertAllClose(eight_decimal_places_examples, rel_tol=1e-8)
2438 self.assertAllNotClose(eight_decimal_places_examples, rel_tol=1e-9)
2439
2440 def test_near_zero(self):
2441 # values close to zero
2442 near_zero_examples = [(1e-9, 0.0),
2443 (-1e-9, 0.0),
2444 (-1e-150, 0.0)]
2445 # these should not be close to any rel_tol
2446 self.assertAllNotClose(near_zero_examples, rel_tol=0.9)
2447 # these should be close to abs_tol=1e-8
2448 self.assertAllClose(near_zero_examples, abs_tol=1e-8)
2449
2450 def test_identical_infinite(self):
2451 # these are close regardless of tolerance -- i.e. they are equal
2452 self.assertIsClose(INF, INF)
2453 self.assertIsClose(INF, INF, abs_tol=0.0)
2454 self.assertIsClose(NINF, NINF)
2455 self.assertIsClose(NINF, NINF, abs_tol=0.0)
2456
2457 def test_inf_ninf_nan(self):
2458 # these should never be close (following IEEE 754 rules for equality)
2459 not_close_examples = [(NAN, NAN),
2460 (NAN, 1e-100),
2461 (1e-100, NAN),
2462 (INF, NAN),
2463 (NAN, INF),
2464 (INF, NINF),
2465 (INF, 1.0),
2466 (1.0, INF),
2467 (INF, 1e308),
2468 (1e308, INF)]
2469 # use largest reasonable tolerance
2470 self.assertAllNotClose(not_close_examples, abs_tol=0.999999999999999)
2471
2472 def test_zero_tolerance(self):
2473 # test with zero tolerance
2474 zero_tolerance_close_examples = [(1.0, 1.0),
2475 (-3.4, -3.4),
2476 (-1e-300, -1e-300)]
2477 self.assertAllClose(zero_tolerance_close_examples, rel_tol=0.0)
2478
2479 zero_tolerance_not_close_examples = [(1.0, 1.000000000000001),
2480 (0.99999999999999, 1.0),
2481 (1.0e200, .999999999999999e200)]
2482 self.assertAllNotClose(zero_tolerance_not_close_examples, rel_tol=0.0)
2483
2484 def test_asymmetry(self):
2485 # test the asymmetry example from PEP 485
2486 self.assertAllClose([(9, 10), (10, 9)], rel_tol=0.1)
2487
2488 def test_integers(self):
2489 # test with integer values
2490 integer_examples = [(100000001, 100000000),
2491 (123456789, 123456788)]
2492
2493 self.assertAllClose(integer_examples, rel_tol=1e-8)
2494 self.assertAllNotClose(integer_examples, rel_tol=1e-9)
2495
2496 def test_decimals(self):
2497 # test with Decimal values
2498 from decimal import Decimal
2499
2500 decimal_examples = [(Decimal('1.00000001'), Decimal('1.0')),
2501 (Decimal('1.00000001e-20'), Decimal('1.0e-20')),
2502 (Decimal('1.00000001e-100'), Decimal('1.0e-100')),
2503 (Decimal('1.00000001e20'), Decimal('1.0e20'))]
2504 self.assertAllClose(decimal_examples, rel_tol=1e-8)
2505 self.assertAllNotClose(decimal_examples, rel_tol=1e-9)
2506
2507 def test_fractions(self):
2508 # test with Fraction values
2509 from fractions import Fraction
2510
2511 fraction_examples = [
2512 (Fraction(1, 100000000) + 1, Fraction(1)),
2513 (Fraction(100000001), Fraction(100000000)),
2514 (Fraction(10**8 + 1, 10**28), Fraction(1, 10**20))]
2515 self.assertAllClose(fraction_examples, rel_tol=1e-8)
2516 self.assertAllNotClose(fraction_examples, rel_tol=1e-9)
2517
2518
2519 def load_tests(loader, tests, pattern):
2520 from doctest import DocFileSuite
2521 tests.addTest(DocFileSuite("ieee754.txt"))
2522 return tests
2523
2524 if __name__ == '__main__':
2525 unittest.main()