blob: f832246dda3227cdd188f786ce6f1540d5bcfd30 [file] [log] [blame]
Guido van Rossumfcce6301996-08-08 18:26:25 +00001# Python test set -- math module
2# XXXX Should not do tests around zero only
3
Eric Smithf24a0d92010-12-04 13:32:18 +00004from test.support import run_unittest, verbose, requires_IEEE_754
Victor Stinnerfce92332011-06-01 12:28:04 +02005from test import support
Thomas Wouters89f507f2006-12-13 04:49:30 +00006import unittest
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -07007import itertools
Pablo Galindoe9ba3702018-09-03 22:20:06 +01008import decimal
Thomas Wouters89f507f2006-12-13 04:49:30 +00009import math
Christian Heimes53876d92008-04-19 00:31:39 +000010import os
Mark Dickinson85746542016-09-04 09:58:51 +010011import platform
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -070012import random
Mark Dickinson12c4bdb2009-09-28 19:21:11 +000013import struct
Mark Dickinson85746542016-09-04 09:58:51 +010014import sys
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020015
Guido van Rossumfcce6301996-08-08 18:26:25 +000016
Christian Heimes53876d92008-04-19 00:31:39 +000017eps = 1E-05
18NAN = float('nan')
19INF = float('inf')
20NINF = float('-inf')
Mark Dickinson31ba1c32016-09-04 12:29:14 +010021FLOAT_MAX = sys.float_info.max
Raymond Hettingerc6dabe32018-07-28 07:48:04 -070022FLOAT_MIN = sys.float_info.min
Christian Heimes53876d92008-04-19 00:31:39 +000023
Mark Dickinson5c567082009-04-24 16:39:07 +000024# detect evidence of double-rounding: fsum is not always correctly
25# rounded on machines that suffer from double rounding.
26x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer
27HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
28
Christian Heimes53876d92008-04-19 00:31:39 +000029# locate file with test values
30if __name__ == '__main__':
31 file = sys.argv[0]
32else:
33 file = __file__
34test_dir = os.path.dirname(file) or os.curdir
Mark Dickinson12c4bdb2009-09-28 19:21:11 +000035math_testcases = os.path.join(test_dir, 'math_testcases.txt')
Christian Heimes53876d92008-04-19 00:31:39 +000036test_file = os.path.join(test_dir, 'cmath_testcases.txt')
37
Mark Dickinson96f774d2016-09-03 19:30:22 +010038
Mark Dickinson12c4bdb2009-09-28 19:21:11 +000039def to_ulps(x):
40 """Convert a non-NaN float x to an integer, in such a way that
41 adjacent floats are converted to adjacent integers. Then
42 abs(ulps(x) - ulps(y)) gives the difference in ulps between two
43 floats.
44
45 The results from this function will only make sense on platforms
Mark Dickinson96f774d2016-09-03 19:30:22 +010046 where native doubles are represented in IEEE 754 binary64 format.
Mark Dickinson12c4bdb2009-09-28 19:21:11 +000047
Mark Dickinson96f774d2016-09-03 19:30:22 +010048 Note: 0.0 and -0.0 are converted to 0 and -1, respectively.
Mark Dickinson12c4bdb2009-09-28 19:21:11 +000049 """
Mark Dickinsond412ab52009-10-17 07:10:00 +000050 n = struct.unpack('<q', struct.pack('<d', x))[0]
Mark Dickinson12c4bdb2009-09-28 19:21:11 +000051 if n < 0:
52 n = ~(n+2**63)
53 return n
54
Mark Dickinson05d2e082009-12-11 20:17:17 +000055
Mark Dickinson96f774d2016-09-03 19:30:22 +010056def ulp(x):
57 """Return the value of the least significant bit of a
58 float x, such that the first float bigger than x is x+ulp(x).
59 Then, given an expected result x and a tolerance of n ulps,
60 the result y should be such that abs(y-x) <= n * ulp(x).
61 The results from this function will only make sense on platforms
62 where native doubles are represented in IEEE 754 binary64 format.
63 """
64 x = abs(float(x))
65 if math.isnan(x) or math.isinf(x):
66 return x
Mark Dickinson05d2e082009-12-11 20:17:17 +000067
Mark Dickinson96f774d2016-09-03 19:30:22 +010068 # Find next float up from x.
69 n = struct.unpack('<q', struct.pack('<d', x))[0]
70 x_next = struct.unpack('<d', struct.pack('<q', n + 1))[0]
71 if math.isinf(x_next):
72 # Corner case: x was the largest finite float. Then it's
73 # not an exact power of two, so we can take the difference
74 # between x and the previous float.
75 x_prev = struct.unpack('<d', struct.pack('<q', n - 1))[0]
76 return x - x_prev
77 else:
78 return x_next - x
Mark Dickinson05d2e082009-12-11 20:17:17 +000079
Mark Dickinson4c8a9a22010-05-15 17:02:38 +000080# Here's a pure Python version of the math.factorial algorithm, for
81# documentation and comparison purposes.
82#
83# Formula:
84#
85# factorial(n) = factorial_odd_part(n) << (n - count_set_bits(n))
86#
87# where
88#
89# factorial_odd_part(n) = product_{i >= 0} product_{0 < j <= n >> i; j odd} j
90#
91# The outer product above is an infinite product, but once i >= n.bit_length,
92# (n >> i) < 1 and the corresponding term of the product is empty. So only the
93# finitely many terms for 0 <= i < n.bit_length() contribute anything.
94#
95# We iterate downwards from i == n.bit_length() - 1 to i == 0. The inner
96# product in the formula above starts at 1 for i == n.bit_length(); for each i
97# < n.bit_length() we get the inner product for i from that for i + 1 by
98# multiplying by all j in {n >> i+1 < j <= n >> i; j odd}. In Python terms,
99# this set is range((n >> i+1) + 1 | 1, (n >> i) + 1 | 1, 2).
100
101def count_set_bits(n):
102 """Number of '1' bits in binary expansion of a nonnnegative integer."""
103 return 1 + count_set_bits(n & n - 1) if n else 0
104
105def partial_product(start, stop):
106 """Product of integers in range(start, stop, 2), computed recursively.
107 start and stop should both be odd, with start <= stop.
108
109 """
110 numfactors = (stop - start) >> 1
111 if not numfactors:
112 return 1
113 elif numfactors == 1:
114 return start
115 else:
116 mid = (start + numfactors) | 1
117 return partial_product(start, mid) * partial_product(mid, stop)
118
119def py_factorial(n):
120 """Factorial of nonnegative integer n, via "Binary Split Factorial Formula"
121 described at http://www.luschny.de/math/factorial/binarysplitfact.html
122
123 """
124 inner = outer = 1
125 for i in reversed(range(n.bit_length())):
126 inner *= partial_product((n >> i + 1) + 1 | 1, (n >> i) + 1 | 1)
127 outer *= inner
128 return outer << (n - count_set_bits(n))
129
Mark Dickinson96f774d2016-09-03 19:30:22 +0100130def ulp_abs_check(expected, got, ulp_tol, abs_tol):
131 """Given finite floats `expected` and `got`, check that they're
132 approximately equal to within the given number of ulps or the
133 given absolute tolerance, whichever is bigger.
Mark Dickinson05d2e082009-12-11 20:17:17 +0000134
Mark Dickinson96f774d2016-09-03 19:30:22 +0100135 Returns None on success and an error message on failure.
136 """
137 ulp_error = abs(to_ulps(expected) - to_ulps(got))
138 abs_error = abs(expected - got)
139
140 # Succeed if either abs_error <= abs_tol or ulp_error <= ulp_tol.
141 if abs_error <= abs_tol or ulp_error <= ulp_tol:
Mark Dickinson05d2e082009-12-11 20:17:17 +0000142 return None
Mark Dickinson96f774d2016-09-03 19:30:22 +0100143 else:
144 fmt = ("error = {:.3g} ({:d} ulps); "
145 "permitted error = {:.3g} or {:d} ulps")
146 return fmt.format(abs_error, ulp_error, abs_tol, ulp_tol)
Mark Dickinson12c4bdb2009-09-28 19:21:11 +0000147
148def parse_mtestfile(fname):
149 """Parse a file with test values
150
151 -- starts a comment
152 blank lines, or lines containing only a comment, are ignored
153 other lines are expected to have the form
154 id fn arg -> expected [flag]*
155
156 """
157 with open(fname) as fp:
158 for line in fp:
159 # strip comments, and skip blank lines
160 if '--' in line:
161 line = line[:line.index('--')]
162 if not line.strip():
163 continue
164
165 lhs, rhs = line.split('->')
166 id, fn, arg = lhs.split()
167 rhs_pieces = rhs.split()
168 exp = rhs_pieces[0]
169 flags = rhs_pieces[1:]
170
171 yield (id, fn, float(arg), float(exp), flags)
172
Mark Dickinson96f774d2016-09-03 19:30:22 +0100173
Christian Heimes53876d92008-04-19 00:31:39 +0000174def parse_testfile(fname):
175 """Parse a file with test values
176
177 Empty lines or lines starting with -- are ignored
178 yields id, fn, arg_real, arg_imag, exp_real, exp_imag
179 """
180 with open(fname) as fp:
181 for line in fp:
182 # skip comment lines and blank lines
183 if line.startswith('--') or not line.strip():
184 continue
185
186 lhs, rhs = line.split('->')
187 id, fn, arg_real, arg_imag = lhs.split()
188 rhs_pieces = rhs.split()
189 exp_real, exp_imag = rhs_pieces[0], rhs_pieces[1]
190 flags = rhs_pieces[2:]
191
192 yield (id, fn,
193 float(arg_real), float(arg_imag),
194 float(exp_real), float(exp_imag),
Mark Dickinson96f774d2016-09-03 19:30:22 +0100195 flags)
196
197
198def result_check(expected, got, ulp_tol=5, abs_tol=0.0):
199 # Common logic of MathTests.(ftest, test_testcases, test_mtestcases)
200 """Compare arguments expected and got, as floats, if either
201 is a float, using a tolerance expressed in multiples of
202 ulp(expected) or absolutely (if given and greater).
203
204 As a convenience, when neither argument is a float, and for
205 non-finite floats, exact equality is demanded. Also, nan==nan
206 as far as this function is concerned.
207
208 Returns None on success and an error message on failure.
209 """
210
211 # Check exactly equal (applies also to strings representing exceptions)
212 if got == expected:
213 return None
214
215 failure = "not equal"
216
217 # Turn mixed float and int comparison (e.g. floor()) to all-float
218 if isinstance(expected, float) and isinstance(got, int):
219 got = float(got)
220 elif isinstance(got, float) and isinstance(expected, int):
221 expected = float(expected)
222
223 if isinstance(expected, float) and isinstance(got, float):
224 if math.isnan(expected) and math.isnan(got):
225 # Pass, since both nan
226 failure = None
227 elif math.isinf(expected) or math.isinf(got):
228 # We already know they're not equal, drop through to failure
229 pass
230 else:
231 # Both are finite floats (now). Are they close enough?
232 failure = ulp_abs_check(expected, got, ulp_tol, abs_tol)
233
234 # arguments are not equal, and if numeric, are too far apart
235 if failure is not None:
236 fail_fmt = "expected {!r}, got {!r}"
237 fail_msg = fail_fmt.format(expected, got)
238 fail_msg += ' ({})'.format(failure)
239 return fail_msg
240 else:
241 return None
Guido van Rossumfcce6301996-08-08 18:26:25 +0000242
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200243class FloatLike:
244 def __init__(self, value):
245 self.value = value
246
247 def __float__(self):
248 return self.value
249
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +0300250class IntSubclass(int):
251 pass
252
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +0300253# Class providing an __index__ method.
254class MyIndexable(object):
255 def __init__(self, value):
256 self.value = value
257
258 def __index__(self):
259 return self.value
260
Thomas Wouters89f507f2006-12-13 04:49:30 +0000261class MathTests(unittest.TestCase):
Guido van Rossumfcce6301996-08-08 18:26:25 +0000262
Mark Dickinson96f774d2016-09-03 19:30:22 +0100263 def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
264 """Compare arguments expected and got, as floats, if either
265 is a float, using a tolerance expressed in multiples of
266 ulp(expected) or absolutely, whichever is greater.
267
268 As a convenience, when neither argument is a float, and for
269 non-finite floats, exact equality is demanded. Also, nan==nan
270 in this function.
271 """
272 failure = result_check(expected, got, ulp_tol, abs_tol)
273 if failure is not None:
274 self.fail("{}: {}".format(name, failure))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000275
Thomas Wouters89f507f2006-12-13 04:49:30 +0000276 def testConstants(self):
Mark Dickinson96f774d2016-09-03 19:30:22 +0100277 # Ref: Abramowitz & Stegun (Dover, 1965)
278 self.ftest('pi', math.pi, 3.141592653589793238462643)
279 self.ftest('e', math.e, 2.718281828459045235360287)
Guido van Rossum0a891d72016-08-15 09:12:52 -0700280 self.assertEqual(math.tau, 2*math.pi)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000281
Thomas Wouters89f507f2006-12-13 04:49:30 +0000282 def testAcos(self):
283 self.assertRaises(TypeError, math.acos)
284 self.ftest('acos(-1)', math.acos(-1), math.pi)
285 self.ftest('acos(0)', math.acos(0), math.pi/2)
286 self.ftest('acos(1)', math.acos(1), 0)
Christian Heimes53876d92008-04-19 00:31:39 +0000287 self.assertRaises(ValueError, math.acos, INF)
288 self.assertRaises(ValueError, math.acos, NINF)
Mark Dickinson31ba1c32016-09-04 12:29:14 +0100289 self.assertRaises(ValueError, math.acos, 1 + eps)
290 self.assertRaises(ValueError, math.acos, -1 - eps)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000291 self.assertTrue(math.isnan(math.acos(NAN)))
Christian Heimes53876d92008-04-19 00:31:39 +0000292
293 def testAcosh(self):
294 self.assertRaises(TypeError, math.acosh)
295 self.ftest('acosh(1)', math.acosh(1), 0)
296 self.ftest('acosh(2)', math.acosh(2), 1.3169578969248168)
297 self.assertRaises(ValueError, math.acosh, 0)
298 self.assertRaises(ValueError, math.acosh, -1)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000299 self.assertEqual(math.acosh(INF), INF)
Christian Heimes53876d92008-04-19 00:31:39 +0000300 self.assertRaises(ValueError, math.acosh, NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000301 self.assertTrue(math.isnan(math.acosh(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000302
Thomas Wouters89f507f2006-12-13 04:49:30 +0000303 def testAsin(self):
304 self.assertRaises(TypeError, math.asin)
305 self.ftest('asin(-1)', math.asin(-1), -math.pi/2)
306 self.ftest('asin(0)', math.asin(0), 0)
307 self.ftest('asin(1)', math.asin(1), math.pi/2)
Christian Heimes53876d92008-04-19 00:31:39 +0000308 self.assertRaises(ValueError, math.asin, INF)
309 self.assertRaises(ValueError, math.asin, NINF)
Mark Dickinson31ba1c32016-09-04 12:29:14 +0100310 self.assertRaises(ValueError, math.asin, 1 + eps)
311 self.assertRaises(ValueError, math.asin, -1 - eps)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000312 self.assertTrue(math.isnan(math.asin(NAN)))
Christian Heimes53876d92008-04-19 00:31:39 +0000313
314 def testAsinh(self):
315 self.assertRaises(TypeError, math.asinh)
316 self.ftest('asinh(0)', math.asinh(0), 0)
317 self.ftest('asinh(1)', math.asinh(1), 0.88137358701954305)
318 self.ftest('asinh(-1)', math.asinh(-1), -0.88137358701954305)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000319 self.assertEqual(math.asinh(INF), INF)
320 self.assertEqual(math.asinh(NINF), NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000321 self.assertTrue(math.isnan(math.asinh(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000322
Thomas Wouters89f507f2006-12-13 04:49:30 +0000323 def testAtan(self):
324 self.assertRaises(TypeError, math.atan)
325 self.ftest('atan(-1)', math.atan(-1), -math.pi/4)
326 self.ftest('atan(0)', math.atan(0), 0)
327 self.ftest('atan(1)', math.atan(1), math.pi/4)
Christian Heimes53876d92008-04-19 00:31:39 +0000328 self.ftest('atan(inf)', math.atan(INF), math.pi/2)
Christian Heimesa342c012008-04-20 21:01:16 +0000329 self.ftest('atan(-inf)', math.atan(NINF), -math.pi/2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000330 self.assertTrue(math.isnan(math.atan(NAN)))
Christian Heimes53876d92008-04-19 00:31:39 +0000331
332 def testAtanh(self):
333 self.assertRaises(TypeError, math.atan)
334 self.ftest('atanh(0)', math.atanh(0), 0)
335 self.ftest('atanh(0.5)', math.atanh(0.5), 0.54930614433405489)
336 self.ftest('atanh(-0.5)', math.atanh(-0.5), -0.54930614433405489)
337 self.assertRaises(ValueError, math.atanh, 1)
338 self.assertRaises(ValueError, math.atanh, -1)
339 self.assertRaises(ValueError, math.atanh, INF)
340 self.assertRaises(ValueError, math.atanh, NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000341 self.assertTrue(math.isnan(math.atanh(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000342
Thomas Wouters89f507f2006-12-13 04:49:30 +0000343 def testAtan2(self):
344 self.assertRaises(TypeError, math.atan2)
345 self.ftest('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
346 self.ftest('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4)
347 self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
348 self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
349 self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000350
Christian Heimese57950f2008-04-21 13:08:03 +0000351 # math.atan2(0, x)
352 self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
353 self.ftest('atan2(0., -2.3)', math.atan2(0., -2.3), math.pi)
354 self.ftest('atan2(0., -0.)', math.atan2(0., -0.), math.pi)
355 self.assertEqual(math.atan2(0., 0.), 0.)
356 self.assertEqual(math.atan2(0., 2.3), 0.)
357 self.assertEqual(math.atan2(0., INF), 0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000358 self.assertTrue(math.isnan(math.atan2(0., NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000359 # math.atan2(-0, x)
360 self.ftest('atan2(-0., -inf)', math.atan2(-0., NINF), -math.pi)
361 self.ftest('atan2(-0., -2.3)', math.atan2(-0., -2.3), -math.pi)
362 self.ftest('atan2(-0., -0.)', math.atan2(-0., -0.), -math.pi)
363 self.assertEqual(math.atan2(-0., 0.), -0.)
364 self.assertEqual(math.atan2(-0., 2.3), -0.)
365 self.assertEqual(math.atan2(-0., INF), -0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000366 self.assertTrue(math.isnan(math.atan2(-0., NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000367 # math.atan2(INF, x)
368 self.ftest('atan2(inf, -inf)', math.atan2(INF, NINF), math.pi*3/4)
369 self.ftest('atan2(inf, -2.3)', math.atan2(INF, -2.3), math.pi/2)
370 self.ftest('atan2(inf, -0.)', math.atan2(INF, -0.0), math.pi/2)
371 self.ftest('atan2(inf, 0.)', math.atan2(INF, 0.0), math.pi/2)
372 self.ftest('atan2(inf, 2.3)', math.atan2(INF, 2.3), math.pi/2)
373 self.ftest('atan2(inf, inf)', math.atan2(INF, INF), math.pi/4)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000374 self.assertTrue(math.isnan(math.atan2(INF, NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000375 # math.atan2(NINF, x)
376 self.ftest('atan2(-inf, -inf)', math.atan2(NINF, NINF), -math.pi*3/4)
377 self.ftest('atan2(-inf, -2.3)', math.atan2(NINF, -2.3), -math.pi/2)
378 self.ftest('atan2(-inf, -0.)', math.atan2(NINF, -0.0), -math.pi/2)
379 self.ftest('atan2(-inf, 0.)', math.atan2(NINF, 0.0), -math.pi/2)
380 self.ftest('atan2(-inf, 2.3)', math.atan2(NINF, 2.3), -math.pi/2)
381 self.ftest('atan2(-inf, inf)', math.atan2(NINF, INF), -math.pi/4)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000382 self.assertTrue(math.isnan(math.atan2(NINF, NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000383 # math.atan2(+finite, x)
384 self.ftest('atan2(2.3, -inf)', math.atan2(2.3, NINF), math.pi)
385 self.ftest('atan2(2.3, -0.)', math.atan2(2.3, -0.), math.pi/2)
386 self.ftest('atan2(2.3, 0.)', math.atan2(2.3, 0.), math.pi/2)
387 self.assertEqual(math.atan2(2.3, INF), 0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000388 self.assertTrue(math.isnan(math.atan2(2.3, NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000389 # math.atan2(-finite, x)
390 self.ftest('atan2(-2.3, -inf)', math.atan2(-2.3, NINF), -math.pi)
391 self.ftest('atan2(-2.3, -0.)', math.atan2(-2.3, -0.), -math.pi/2)
392 self.ftest('atan2(-2.3, 0.)', math.atan2(-2.3, 0.), -math.pi/2)
393 self.assertEqual(math.atan2(-2.3, INF), -0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000394 self.assertTrue(math.isnan(math.atan2(-2.3, NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000395 # math.atan2(NAN, x)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000396 self.assertTrue(math.isnan(math.atan2(NAN, NINF)))
397 self.assertTrue(math.isnan(math.atan2(NAN, -2.3)))
398 self.assertTrue(math.isnan(math.atan2(NAN, -0.)))
399 self.assertTrue(math.isnan(math.atan2(NAN, 0.)))
400 self.assertTrue(math.isnan(math.atan2(NAN, 2.3)))
401 self.assertTrue(math.isnan(math.atan2(NAN, INF)))
402 self.assertTrue(math.isnan(math.atan2(NAN, NAN)))
Christian Heimese57950f2008-04-21 13:08:03 +0000403
Thomas Wouters89f507f2006-12-13 04:49:30 +0000404 def testCeil(self):
405 self.assertRaises(TypeError, math.ceil)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000406 self.assertEqual(int, type(math.ceil(0.5)))
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200407 self.assertEqual(math.ceil(0.5), 1)
408 self.assertEqual(math.ceil(1.0), 1)
409 self.assertEqual(math.ceil(1.5), 2)
410 self.assertEqual(math.ceil(-0.5), 0)
411 self.assertEqual(math.ceil(-1.0), -1)
412 self.assertEqual(math.ceil(-1.5), -1)
413 self.assertEqual(math.ceil(0.0), 0)
414 self.assertEqual(math.ceil(-0.0), 0)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000415 #self.assertEqual(math.ceil(INF), INF)
416 #self.assertEqual(math.ceil(NINF), NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000417 #self.assertTrue(math.isnan(math.ceil(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000418
Guido van Rossum13e05de2007-08-23 22:56:55 +0000419 class TestCeil:
420 def __ceil__(self):
421 return 42
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200422 class FloatCeil(float):
423 def __ceil__(self):
424 return 42
Guido van Rossum13e05de2007-08-23 22:56:55 +0000425 class TestNoCeil:
426 pass
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200427 self.assertEqual(math.ceil(TestCeil()), 42)
428 self.assertEqual(math.ceil(FloatCeil()), 42)
429 self.assertEqual(math.ceil(FloatLike(42.5)), 43)
Guido van Rossum13e05de2007-08-23 22:56:55 +0000430 self.assertRaises(TypeError, math.ceil, TestNoCeil())
431
432 t = TestNoCeil()
433 t.__ceil__ = lambda *args: args
434 self.assertRaises(TypeError, math.ceil, t)
435 self.assertRaises(TypeError, math.ceil, t, 0)
436
Mark Dickinson63566232009-09-18 21:04:19 +0000437 @requires_IEEE_754
438 def testCopysign(self):
Mark Dickinson06b59e02010-02-06 23:16:50 +0000439 self.assertEqual(math.copysign(1, 42), 1.0)
440 self.assertEqual(math.copysign(0., 42), 0.0)
441 self.assertEqual(math.copysign(1., -42), -1.0)
442 self.assertEqual(math.copysign(3, 0.), 3.0)
443 self.assertEqual(math.copysign(4., -0.), -4.0)
444
Mark Dickinson63566232009-09-18 21:04:19 +0000445 self.assertRaises(TypeError, math.copysign)
446 # copysign should let us distinguish signs of zeros
Ezio Melottib3aedd42010-11-20 19:04:17 +0000447 self.assertEqual(math.copysign(1., 0.), 1.)
448 self.assertEqual(math.copysign(1., -0.), -1.)
449 self.assertEqual(math.copysign(INF, 0.), INF)
450 self.assertEqual(math.copysign(INF, -0.), NINF)
451 self.assertEqual(math.copysign(NINF, 0.), INF)
452 self.assertEqual(math.copysign(NINF, -0.), NINF)
Mark Dickinson63566232009-09-18 21:04:19 +0000453 # and of infinities
Ezio Melottib3aedd42010-11-20 19:04:17 +0000454 self.assertEqual(math.copysign(1., INF), 1.)
455 self.assertEqual(math.copysign(1., NINF), -1.)
456 self.assertEqual(math.copysign(INF, INF), INF)
457 self.assertEqual(math.copysign(INF, NINF), NINF)
458 self.assertEqual(math.copysign(NINF, INF), INF)
459 self.assertEqual(math.copysign(NINF, NINF), NINF)
Mark Dickinson06b59e02010-02-06 23:16:50 +0000460 self.assertTrue(math.isnan(math.copysign(NAN, 1.)))
461 self.assertTrue(math.isnan(math.copysign(NAN, INF)))
462 self.assertTrue(math.isnan(math.copysign(NAN, NINF)))
463 self.assertTrue(math.isnan(math.copysign(NAN, NAN)))
Mark Dickinson63566232009-09-18 21:04:19 +0000464 # copysign(INF, NAN) may be INF or it may be NINF, since
465 # we don't know whether the sign bit of NAN is set on any
466 # given platform.
Mark Dickinson06b59e02010-02-06 23:16:50 +0000467 self.assertTrue(math.isinf(math.copysign(INF, NAN)))
Mark Dickinson63566232009-09-18 21:04:19 +0000468 # similarly, copysign(2., NAN) could be 2. or -2.
Ezio Melottib3aedd42010-11-20 19:04:17 +0000469 self.assertEqual(abs(math.copysign(2., NAN)), 2.)
Christian Heimes53876d92008-04-19 00:31:39 +0000470
Thomas Wouters89f507f2006-12-13 04:49:30 +0000471 def testCos(self):
472 self.assertRaises(TypeError, math.cos)
Mark Dickinson96f774d2016-09-03 19:30:22 +0100473 self.ftest('cos(-pi/2)', math.cos(-math.pi/2), 0, abs_tol=ulp(1))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000474 self.ftest('cos(0)', math.cos(0), 1)
Mark Dickinson96f774d2016-09-03 19:30:22 +0100475 self.ftest('cos(pi/2)', math.cos(math.pi/2), 0, abs_tol=ulp(1))
Thomas Wouters89f507f2006-12-13 04:49:30 +0000476 self.ftest('cos(pi)', math.cos(math.pi), -1)
Christian Heimes53876d92008-04-19 00:31:39 +0000477 try:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000478 self.assertTrue(math.isnan(math.cos(INF)))
479 self.assertTrue(math.isnan(math.cos(NINF)))
Christian Heimes53876d92008-04-19 00:31:39 +0000480 except ValueError:
481 self.assertRaises(ValueError, math.cos, INF)
482 self.assertRaises(ValueError, math.cos, NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000483 self.assertTrue(math.isnan(math.cos(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000484
Paul Monsonf3550692019-06-19 13:09:54 -0700485 @unittest.skipIf(sys.platform == 'win32' and platform.machine() in ('ARM', 'ARM64'),
486 "Windows UCRT is off by 2 ULP this test requires accuracy within 1 ULP")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000487 def testCosh(self):
488 self.assertRaises(TypeError, math.cosh)
489 self.ftest('cosh(0)', math.cosh(0), 1)
490 self.ftest('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert
Ezio Melottib3aedd42010-11-20 19:04:17 +0000491 self.assertEqual(math.cosh(INF), INF)
492 self.assertEqual(math.cosh(NINF), INF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000493 self.assertTrue(math.isnan(math.cosh(NAN)))
Raymond Hettinger64108af2002-05-13 03:55:01 +0000494
Thomas Wouters89f507f2006-12-13 04:49:30 +0000495 def testDegrees(self):
496 self.assertRaises(TypeError, math.degrees)
497 self.ftest('degrees(pi)', math.degrees(math.pi), 180.0)
498 self.ftest('degrees(pi/2)', math.degrees(math.pi/2), 90.0)
499 self.ftest('degrees(-pi/4)', math.degrees(-math.pi/4), -45.0)
Mark Dickinson31ba1c32016-09-04 12:29:14 +0100500 self.ftest('degrees(0)', math.degrees(0), 0)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000501
Thomas Wouters89f507f2006-12-13 04:49:30 +0000502 def testExp(self):
503 self.assertRaises(TypeError, math.exp)
504 self.ftest('exp(-1)', math.exp(-1), 1/math.e)
505 self.ftest('exp(0)', math.exp(0), 1)
506 self.ftest('exp(1)', math.exp(1), math.e)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000507 self.assertEqual(math.exp(INF), INF)
508 self.assertEqual(math.exp(NINF), 0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000509 self.assertTrue(math.isnan(math.exp(NAN)))
Mark Dickinson31ba1c32016-09-04 12:29:14 +0100510 self.assertRaises(OverflowError, math.exp, 1000000)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000511
Thomas Wouters89f507f2006-12-13 04:49:30 +0000512 def testFabs(self):
513 self.assertRaises(TypeError, math.fabs)
514 self.ftest('fabs(-1)', math.fabs(-1), 1)
515 self.ftest('fabs(0)', math.fabs(0), 0)
516 self.ftest('fabs(1)', math.fabs(1), 1)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000517
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000518 def testFactorial(self):
Mark Dickinson4c8a9a22010-05-15 17:02:38 +0000519 self.assertEqual(math.factorial(0), 1)
Mark Dickinson4c8a9a22010-05-15 17:02:38 +0000520 total = 1
521 for i in range(1, 1000):
522 total *= i
523 self.assertEqual(math.factorial(i), total)
Mark Dickinson4c8a9a22010-05-15 17:02:38 +0000524 self.assertEqual(math.factorial(i), py_factorial(i))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000525 self.assertRaises(ValueError, math.factorial, -1)
Mark Dickinson5990d282014-04-10 09:29:39 -0400526 self.assertRaises(ValueError, math.factorial, -10**100)
Mark Dickinson5990d282014-04-10 09:29:39 -0400527
Pablo Galindoe9ba3702018-09-03 22:20:06 +0100528 def testFactorialNonIntegers(self):
Serhiy Storchaka231aad32019-06-17 16:57:27 +0300529 with self.assertWarns(DeprecationWarning):
530 self.assertEqual(math.factorial(5.0), 120)
531 with self.assertWarns(DeprecationWarning):
532 self.assertRaises(ValueError, math.factorial, 5.2)
533 with self.assertWarns(DeprecationWarning):
534 self.assertRaises(ValueError, math.factorial, -1.0)
535 with self.assertWarns(DeprecationWarning):
536 self.assertRaises(ValueError, math.factorial, -1e100)
537 self.assertRaises(TypeError, math.factorial, decimal.Decimal('5'))
538 self.assertRaises(TypeError, math.factorial, decimal.Decimal('5.2'))
Pablo Galindoe9ba3702018-09-03 22:20:06 +0100539 self.assertRaises(TypeError, math.factorial, "5")
540
Mark Dickinson5990d282014-04-10 09:29:39 -0400541 # Other implementations may place different upper bounds.
542 @support.cpython_only
543 def testFactorialHugeInputs(self):
Serhiy Storchaka1b8a46d2019-06-17 16:58:32 +0300544 # Currently raises OverflowError for inputs that are too large
Mark Dickinson5990d282014-04-10 09:29:39 -0400545 # to fit into a C long.
546 self.assertRaises(OverflowError, math.factorial, 10**100)
Serhiy Storchaka231aad32019-06-17 16:57:27 +0300547 with self.assertWarns(DeprecationWarning):
548 self.assertRaises(OverflowError, math.factorial, 1e100)
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000549
Thomas Wouters89f507f2006-12-13 04:49:30 +0000550 def testFloor(self):
551 self.assertRaises(TypeError, math.floor)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000552 self.assertEqual(int, type(math.floor(0.5)))
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200553 self.assertEqual(math.floor(0.5), 0)
554 self.assertEqual(math.floor(1.0), 1)
555 self.assertEqual(math.floor(1.5), 1)
556 self.assertEqual(math.floor(-0.5), -1)
557 self.assertEqual(math.floor(-1.0), -1)
558 self.assertEqual(math.floor(-1.5), -2)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000559 #self.assertEqual(math.ceil(INF), INF)
560 #self.assertEqual(math.ceil(NINF), NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000561 #self.assertTrue(math.isnan(math.floor(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000562
Guido van Rossum13e05de2007-08-23 22:56:55 +0000563 class TestFloor:
564 def __floor__(self):
565 return 42
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200566 class FloatFloor(float):
567 def __floor__(self):
568 return 42
Guido van Rossum13e05de2007-08-23 22:56:55 +0000569 class TestNoFloor:
570 pass
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +0200571 self.assertEqual(math.floor(TestFloor()), 42)
572 self.assertEqual(math.floor(FloatFloor()), 42)
573 self.assertEqual(math.floor(FloatLike(41.9)), 41)
Guido van Rossum13e05de2007-08-23 22:56:55 +0000574 self.assertRaises(TypeError, math.floor, TestNoFloor())
575
576 t = TestNoFloor()
577 t.__floor__ = lambda *args: args
578 self.assertRaises(TypeError, math.floor, t)
579 self.assertRaises(TypeError, math.floor, t, 0)
580
Thomas Wouters89f507f2006-12-13 04:49:30 +0000581 def testFmod(self):
582 self.assertRaises(TypeError, math.fmod)
Mark Dickinson5bc7a442011-05-03 21:13:40 +0100583 self.ftest('fmod(10, 1)', math.fmod(10, 1), 0.0)
584 self.ftest('fmod(10, 0.5)', math.fmod(10, 0.5), 0.0)
585 self.ftest('fmod(10, 1.5)', math.fmod(10, 1.5), 1.0)
586 self.ftest('fmod(-10, 1)', math.fmod(-10, 1), -0.0)
587 self.ftest('fmod(-10, 0.5)', math.fmod(-10, 0.5), -0.0)
588 self.ftest('fmod(-10, 1.5)', math.fmod(-10, 1.5), -1.0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000589 self.assertTrue(math.isnan(math.fmod(NAN, 1.)))
590 self.assertTrue(math.isnan(math.fmod(1., NAN)))
591 self.assertTrue(math.isnan(math.fmod(NAN, NAN)))
Christian Heimes53876d92008-04-19 00:31:39 +0000592 self.assertRaises(ValueError, math.fmod, 1., 0.)
593 self.assertRaises(ValueError, math.fmod, INF, 1.)
594 self.assertRaises(ValueError, math.fmod, NINF, 1.)
595 self.assertRaises(ValueError, math.fmod, INF, 0.)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000596 self.assertEqual(math.fmod(3.0, INF), 3.0)
597 self.assertEqual(math.fmod(-3.0, INF), -3.0)
598 self.assertEqual(math.fmod(3.0, NINF), 3.0)
599 self.assertEqual(math.fmod(-3.0, NINF), -3.0)
600 self.assertEqual(math.fmod(0.0, 3.0), 0.0)
601 self.assertEqual(math.fmod(0.0, NINF), 0.0)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000602
Thomas Wouters89f507f2006-12-13 04:49:30 +0000603 def testFrexp(self):
604 self.assertRaises(TypeError, math.frexp)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000605
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000606 def testfrexp(name, result, expected):
607 (mant, exp), (emant, eexp) = result, expected
Thomas Wouters89f507f2006-12-13 04:49:30 +0000608 if abs(mant-emant) > eps or exp != eexp:
609 self.fail('%s returned %r, expected %r'%\
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000610 (name, result, expected))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000611
Thomas Wouters89f507f2006-12-13 04:49:30 +0000612 testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1))
613 testfrexp('frexp(0)', math.frexp(0), (0, 0))
614 testfrexp('frexp(1)', math.frexp(1), (0.5, 1))
615 testfrexp('frexp(2)', math.frexp(2), (0.5, 2))
Guido van Rossumfcce6301996-08-08 18:26:25 +0000616
Ezio Melottib3aedd42010-11-20 19:04:17 +0000617 self.assertEqual(math.frexp(INF)[0], INF)
618 self.assertEqual(math.frexp(NINF)[0], NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000619 self.assertTrue(math.isnan(math.frexp(NAN)[0]))
Christian Heimes53876d92008-04-19 00:31:39 +0000620
Mark Dickinson63566232009-09-18 21:04:19 +0000621 @requires_IEEE_754
Mark Dickinson5c567082009-04-24 16:39:07 +0000622 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
623 "fsum is not exact on machines with double rounding")
Mark Dickinsonaa7633a2008-08-01 08:16:13 +0000624 def testFsum(self):
625 # math.fsum relies on exact rounding for correct operation.
626 # There's a known problem with IA32 floating-point that causes
627 # inexact rounding in some situations, and will cause the
628 # math.fsum tests below to fail; see issue #2937. On non IEEE
629 # 754 platforms, and on IEEE 754 platforms that exhibit the
630 # problem described in issue #2937, we simply skip the whole
631 # test.
632
Mark Dickinsonaa7633a2008-08-01 08:16:13 +0000633 # Python version of math.fsum, for comparison. Uses a
634 # different algorithm based on frexp, ldexp and integer
635 # arithmetic.
636 from sys import float_info
637 mant_dig = float_info.mant_dig
638 etiny = float_info.min_exp - mant_dig
639
640 def msum(iterable):
641 """Full precision summation. Compute sum(iterable) without any
642 intermediate accumulation of error. Based on the 'lsum' function
643 at http://code.activestate.com/recipes/393090/
644
645 """
646 tmant, texp = 0, 0
647 for x in iterable:
648 mant, exp = math.frexp(x)
649 mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
650 if texp > exp:
651 tmant <<= texp-exp
652 texp = exp
653 else:
654 mant <<= exp-texp
655 tmant += mant
656 # Round tmant * 2**texp to a float. The original recipe
657 # used float(str(tmant)) * 2.0**texp for this, but that's
658 # a little unsafe because str -> float conversion can't be
659 # relied upon to do correct rounding on all platforms.
660 tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
661 if tail > 0:
662 h = 1 << (tail-1)
663 tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
664 texp += tail
665 return math.ldexp(tmant, texp)
666
667 test_values = [
668 ([], 0.0),
669 ([0.0], 0.0),
670 ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
671 ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
672 ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
673 ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
674 ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
675 ([1./n for n in range(1, 1001)],
676 float.fromhex('0x1.df11f45f4e61ap+2')),
677 ([(-1.)**n/n for n in range(1, 1001)],
678 float.fromhex('-0x1.62a2af1bd3624p-1')),
679 ([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0),
680 ([1e16, 1., 1e-16], 10000000000000002.0),
681 ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
682 # exercise code for resizing partials array
683 ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
684 [-2.**1022],
685 float.fromhex('0x1.5555555555555p+970')),
686 ]
687
688 for i, (vals, expected) in enumerate(test_values):
689 try:
690 actual = math.fsum(vals)
691 except OverflowError:
692 self.fail("test %d failed: got OverflowError, expected %r "
693 "for math.fsum(%.100r)" % (i, expected, vals))
694 except ValueError:
695 self.fail("test %d failed: got ValueError, expected %r "
696 "for math.fsum(%.100r)" % (i, expected, vals))
697 self.assertEqual(actual, expected)
698
699 from random import random, gauss, shuffle
700 for j in range(1000):
701 vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
702 s = 0
703 for i in range(200):
704 v = gauss(0, random()) ** 7 - s
705 s += v
706 vals.append(v)
707 shuffle(vals)
708
709 s = msum(vals)
710 self.assertEqual(msum(vals), math.fsum(vals))
711
Serhiy Storchaka48e47aa2015-05-13 00:19:51 +0300712 def testGcd(self):
713 gcd = math.gcd
714 self.assertEqual(gcd(0, 0), 0)
715 self.assertEqual(gcd(1, 0), 1)
716 self.assertEqual(gcd(-1, 0), 1)
717 self.assertEqual(gcd(0, 1), 1)
718 self.assertEqual(gcd(0, -1), 1)
719 self.assertEqual(gcd(7, 1), 1)
720 self.assertEqual(gcd(7, -1), 1)
721 self.assertEqual(gcd(-23, 15), 1)
722 self.assertEqual(gcd(120, 84), 12)
723 self.assertEqual(gcd(84, -120), 12)
724 self.assertEqual(gcd(1216342683557601535506311712,
725 436522681849110124616458784), 32)
726 c = 652560
727 x = 434610456570399902378880679233098819019853229470286994367836600566
728 y = 1064502245825115327754847244914921553977
729 a = x * c
730 b = y * c
731 self.assertEqual(gcd(a, b), c)
732 self.assertEqual(gcd(b, a), c)
733 self.assertEqual(gcd(-a, b), c)
734 self.assertEqual(gcd(b, -a), c)
735 self.assertEqual(gcd(a, -b), c)
736 self.assertEqual(gcd(-b, a), c)
737 self.assertEqual(gcd(-a, -b), c)
738 self.assertEqual(gcd(-b, -a), c)
739 c = 576559230871654959816130551884856912003141446781646602790216406874
740 a = x * c
741 b = y * 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 self.assertEqual(gcd(a, -b), c)
747 self.assertEqual(gcd(-b, a), c)
748 self.assertEqual(gcd(-a, -b), c)
749 self.assertEqual(gcd(-b, -a), c)
750
751 self.assertRaises(TypeError, gcd, 120.0, 84)
752 self.assertRaises(TypeError, gcd, 120, 84.0)
753 self.assertEqual(gcd(MyIndexable(120), MyIndexable(84)), 12)
754
Thomas Wouters89f507f2006-12-13 04:49:30 +0000755 def testHypot(self):
Raymond Hettingerc6dabe32018-07-28 07:48:04 -0700756 from decimal import Decimal
757 from fractions import Fraction
758
759 hypot = math.hypot
760
761 # Test different numbers of arguments (from zero to five)
762 # against a straightforward pure python implementation
763 args = math.e, math.pi, math.sqrt(2.0), math.gamma(3.5), math.sin(2.1)
764 for i in range(len(args)+1):
765 self.assertAlmostEqual(
766 hypot(*args[:i]),
767 math.sqrt(sum(s**2 for s in args[:i]))
768 )
769
770 # Test allowable types (those with __float__)
771 self.assertEqual(hypot(12.0, 5.0), 13.0)
772 self.assertEqual(hypot(12, 5), 13)
773 self.assertEqual(hypot(Decimal(12), Decimal(5)), 13)
774 self.assertEqual(hypot(Fraction(12, 32), Fraction(5, 32)), Fraction(13, 32))
775 self.assertEqual(hypot(bool(1), bool(0), bool(1), bool(1)), math.sqrt(3))
776
777 # Test corner cases
778 self.assertEqual(hypot(0.0, 0.0), 0.0) # Max input is zero
779 self.assertEqual(hypot(-10.5), 10.5) # Negative input
780 self.assertEqual(hypot(), 0.0) # Negative input
781 self.assertEqual(1.0,
782 math.copysign(1.0, hypot(-0.0)) # Convert negative zero to positive zero
783 )
Raymond Hettinger00414592018-08-12 12:15:23 -0700784 self.assertEqual( # Handling of moving max to the end
785 hypot(1.5, 1.5, 0.5),
786 hypot(1.5, 0.5, 1.5),
787 )
Raymond Hettingerc6dabe32018-07-28 07:48:04 -0700788
789 # Test handling of bad arguments
790 with self.assertRaises(TypeError): # Reject keyword args
791 hypot(x=1)
792 with self.assertRaises(TypeError): # Reject values without __float__
793 hypot(1.1, 'string', 2.2)
Raymond Hettinger808180c2019-01-28 13:59:56 -0800794 int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5)
795 with self.assertRaises((ValueError, OverflowError)):
796 hypot(1, int_too_big_for_float)
Raymond Hettingerc6dabe32018-07-28 07:48:04 -0700797
798 # Any infinity gives positive infinity.
799 self.assertEqual(hypot(INF), INF)
800 self.assertEqual(hypot(0, INF), INF)
801 self.assertEqual(hypot(10, INF), INF)
802 self.assertEqual(hypot(-10, INF), INF)
803 self.assertEqual(hypot(NAN, INF), INF)
804 self.assertEqual(hypot(INF, NAN), INF)
805 self.assertEqual(hypot(NINF, NAN), INF)
806 self.assertEqual(hypot(NAN, NINF), INF)
807 self.assertEqual(hypot(-INF, INF), INF)
808 self.assertEqual(hypot(-INF, -INF), INF)
809 self.assertEqual(hypot(10, -INF), INF)
810
Raymond Hettinger00414592018-08-12 12:15:23 -0700811 # If no infinity, any NaN gives a NaN.
Raymond Hettingerc6dabe32018-07-28 07:48:04 -0700812 self.assertTrue(math.isnan(hypot(NAN)))
813 self.assertTrue(math.isnan(hypot(0, NAN)))
814 self.assertTrue(math.isnan(hypot(NAN, 10)))
815 self.assertTrue(math.isnan(hypot(10, NAN)))
816 self.assertTrue(math.isnan(hypot(NAN, NAN)))
817 self.assertTrue(math.isnan(hypot(NAN)))
818
819 # Verify scaling for extremely large values
820 fourthmax = FLOAT_MAX / 4.0
821 for n in range(32):
822 self.assertEqual(hypot(*([fourthmax]*n)), fourthmax * math.sqrt(n))
823
824 # Verify scaling for extremely small values
825 for exp in range(32):
826 scale = FLOAT_MIN / 2.0 ** exp
827 self.assertEqual(math.hypot(4*scale, 3*scale), 5*scale)
Guido van Rossumfcce6301996-08-08 18:26:25 +0000828
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700829 def testDist(self):
830 from decimal import Decimal as D
831 from fractions import Fraction as F
832
833 dist = math.dist
834 sqrt = math.sqrt
835
Raymond Hettinger808180c2019-01-28 13:59:56 -0800836 # Simple exact cases
837 self.assertEqual(dist((1.0, 2.0, 3.0), (4.0, 2.0, -1.0)), 5.0)
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700838 self.assertEqual(dist((1, 2, 3), (4, 2, -1)), 5.0)
839
840 # Test different numbers of arguments (from zero to nine)
841 # against a straightforward pure python implementation
842 for i in range(9):
843 for j in range(5):
844 p = tuple(random.uniform(-5, 5) for k in range(i))
845 q = tuple(random.uniform(-5, 5) for k in range(i))
846 self.assertAlmostEqual(
847 dist(p, q),
848 sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))
849 )
850
Raymond Hettinger6b5f1b42019-07-27 14:04:29 -0700851 # Test non-tuple inputs
852 self.assertEqual(dist([1.0, 2.0, 3.0], [4.0, 2.0, -1.0]), 5.0)
853 self.assertEqual(dist(iter([1.0, 2.0, 3.0]), iter([4.0, 2.0, -1.0])), 5.0)
854
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700855 # Test allowable types (those with __float__)
856 self.assertEqual(dist((14.0, 1.0), (2.0, -4.0)), 13.0)
857 self.assertEqual(dist((14, 1), (2, -4)), 13)
858 self.assertEqual(dist((D(14), D(1)), (D(2), D(-4))), D(13))
859 self.assertEqual(dist((F(14, 32), F(1, 32)), (F(2, 32), F(-4, 32))),
860 F(13, 32))
861 self.assertEqual(dist((True, True, False, True, False),
862 (True, False, True, True, False)),
863 sqrt(2.0))
864
865 # Test corner cases
866 self.assertEqual(dist((13.25, 12.5, -3.25),
867 (13.25, 12.5, -3.25)),
868 0.0) # Distance with self is zero
869 self.assertEqual(dist((), ()), 0.0) # Zero-dimensional case
870 self.assertEqual(1.0, # Convert negative zero to positive zero
871 math.copysign(1.0, dist((-0.0,), (0.0,)))
872 )
873 self.assertEqual(1.0, # Convert negative zero to positive zero
874 math.copysign(1.0, dist((0.0,), (-0.0,)))
875 )
Raymond Hettinger00414592018-08-12 12:15:23 -0700876 self.assertEqual( # Handling of moving max to the end
877 dist((1.5, 1.5, 0.5), (0, 0, 0)),
878 dist((1.5, 0.5, 1.5), (0, 0, 0))
879 )
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700880
881 # Verify tuple subclasses are allowed
Raymond Hettinger00414592018-08-12 12:15:23 -0700882 class T(tuple):
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700883 pass
884 self.assertEqual(dist(T((1, 2, 3)), ((4, 2, -1))), 5.0)
885
886 # Test handling of bad arguments
887 with self.assertRaises(TypeError): # Reject keyword args
888 dist(p=(1, 2, 3), q=(4, 5, 6))
889 with self.assertRaises(TypeError): # Too few args
890 dist((1, 2, 3))
891 with self.assertRaises(TypeError): # Too many args
892 dist((1, 2, 3), (4, 5, 6), (7, 8, 9))
893 with self.assertRaises(TypeError): # Scalars not allowed
894 dist(1, 2)
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700895 with self.assertRaises(TypeError): # Reject values without __float__
896 dist((1.1, 'string', 2.2), (1, 2, 3))
897 with self.assertRaises(ValueError): # Check dimension agree
898 dist((1, 2, 3, 4), (5, 6, 7))
899 with self.assertRaises(ValueError): # Check dimension agree
900 dist((1, 2, 3), (4, 5, 6, 7))
Ammar Askarcb08a712019-01-12 01:23:41 -0500901 with self.assertRaises(TypeError): # Rejects invalid types
902 dist("abc", "xyz")
Raymond Hettinger808180c2019-01-28 13:59:56 -0800903 int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5)
904 with self.assertRaises((ValueError, OverflowError)):
905 dist((1, int_too_big_for_float), (2, 3))
906 with self.assertRaises((ValueError, OverflowError)):
907 dist((2, 3), (1, int_too_big_for_float))
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700908
Raymond Hettinger00414592018-08-12 12:15:23 -0700909 # Verify that the one dimensional case is equivalent to abs()
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700910 for i in range(20):
911 p, q = random.random(), random.random()
912 self.assertEqual(dist((p,), (q,)), abs(p - q))
913
914 # Test special values
915 values = [NINF, -10.5, -0.0, 0.0, 10.5, INF, NAN]
916 for p in itertools.product(values, repeat=3):
917 for q in itertools.product(values, repeat=3):
918 diffs = [px - qx for px, qx in zip(p, q)]
919 if any(map(math.isinf, diffs)):
920 # Any infinite difference gives positive infinity.
921 self.assertEqual(dist(p, q), INF)
922 elif any(map(math.isnan, diffs)):
Raymond Hettinger00414592018-08-12 12:15:23 -0700923 # If no infinity, any NaN gives a NaN.
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700924 self.assertTrue(math.isnan(dist(p, q)))
925
926 # Verify scaling for extremely large values
927 fourthmax = FLOAT_MAX / 4.0
928 for n in range(32):
929 p = (fourthmax,) * n
930 q = (0.0,) * n
931 self.assertEqual(dist(p, q), fourthmax * math.sqrt(n))
932 self.assertEqual(dist(q, p), fourthmax * math.sqrt(n))
933
934 # Verify scaling for extremely small values
935 for exp in range(32):
936 scale = FLOAT_MIN / 2.0 ** exp
937 p = (4*scale, 3*scale)
938 q = (0.0, 0.0)
939 self.assertEqual(math.dist(p, q), 5*scale)
940 self.assertEqual(math.dist(q, p), 5*scale)
941
Mark Dickinson73934b92019-05-18 12:29:50 +0100942 def testIsqrt(self):
943 # Test a variety of inputs, large and small.
944 test_values = (
945 list(range(1000))
946 + list(range(10**6 - 1000, 10**6 + 1000))
Mark Dickinson5c08ce92019-05-19 17:51:56 +0100947 + [2**e + i for e in range(60, 200) for i in range(-40, 40)]
Mark Dickinson73934b92019-05-18 12:29:50 +0100948 + [3**9999, 10**5001]
949 )
950
951 for value in test_values:
952 with self.subTest(value=value):
953 s = math.isqrt(value)
954 self.assertIs(type(s), int)
955 self.assertLessEqual(s*s, value)
956 self.assertLess(value, (s+1)*(s+1))
957
958 # Negative values
959 with self.assertRaises(ValueError):
960 math.isqrt(-1)
961
962 # Integer-like things
963 s = math.isqrt(True)
964 self.assertIs(type(s), int)
965 self.assertEqual(s, 1)
966
967 s = math.isqrt(False)
968 self.assertIs(type(s), int)
969 self.assertEqual(s, 0)
970
971 class IntegerLike(object):
972 def __init__(self, value):
973 self.value = value
974
975 def __index__(self):
976 return self.value
977
978 s = math.isqrt(IntegerLike(1729))
979 self.assertIs(type(s), int)
980 self.assertEqual(s, 41)
981
982 with self.assertRaises(ValueError):
983 math.isqrt(IntegerLike(-3))
984
985 # Non-integer-like things
986 bad_values = [
987 3.5, "a string", decimal.Decimal("3.5"), 3.5j,
988 100.0, -4.0,
989 ]
990 for value in bad_values:
991 with self.subTest(value=value):
992 with self.assertRaises(TypeError):
993 math.isqrt(value)
Raymond Hettinger9c18b1a2018-07-31 00:45:49 -0700994
Thomas Wouters89f507f2006-12-13 04:49:30 +0000995 def testLdexp(self):
996 self.assertRaises(TypeError, math.ldexp)
997 self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
998 self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
999 self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
1000 self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2)
Christian Heimes53876d92008-04-19 00:31:39 +00001001 self.assertRaises(OverflowError, math.ldexp, 1., 1000000)
1002 self.assertRaises(OverflowError, math.ldexp, -1., 1000000)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001003 self.assertEqual(math.ldexp(1., -1000000), 0.)
1004 self.assertEqual(math.ldexp(-1., -1000000), -0.)
1005 self.assertEqual(math.ldexp(INF, 30), INF)
1006 self.assertEqual(math.ldexp(NINF, -213), NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001007 self.assertTrue(math.isnan(math.ldexp(NAN, 0)))
Guido van Rossumfcce6301996-08-08 18:26:25 +00001008
Alexandre Vassalotti6461e102008-05-15 22:09:29 +00001009 # large second argument
1010 for n in [10**5, 10**10, 10**20, 10**40]:
Ezio Melottib3aedd42010-11-20 19:04:17 +00001011 self.assertEqual(math.ldexp(INF, -n), INF)
1012 self.assertEqual(math.ldexp(NINF, -n), NINF)
1013 self.assertEqual(math.ldexp(1., -n), 0.)
1014 self.assertEqual(math.ldexp(-1., -n), -0.)
1015 self.assertEqual(math.ldexp(0., -n), 0.)
1016 self.assertEqual(math.ldexp(-0., -n), -0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001017 self.assertTrue(math.isnan(math.ldexp(NAN, -n)))
Alexandre Vassalotti6461e102008-05-15 22:09:29 +00001018
1019 self.assertRaises(OverflowError, math.ldexp, 1., n)
1020 self.assertRaises(OverflowError, math.ldexp, -1., n)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001021 self.assertEqual(math.ldexp(0., n), 0.)
1022 self.assertEqual(math.ldexp(-0., n), -0.)
1023 self.assertEqual(math.ldexp(INF, n), INF)
1024 self.assertEqual(math.ldexp(NINF, n), NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001025 self.assertTrue(math.isnan(math.ldexp(NAN, n)))
Alexandre Vassalotti6461e102008-05-15 22:09:29 +00001026
Thomas Wouters89f507f2006-12-13 04:49:30 +00001027 def testLog(self):
1028 self.assertRaises(TypeError, math.log)
1029 self.ftest('log(1/e)', math.log(1/math.e), -1)
1030 self.ftest('log(1)', math.log(1), 0)
1031 self.ftest('log(e)', math.log(math.e), 1)
1032 self.ftest('log(32,2)', math.log(32,2), 5)
1033 self.ftest('log(10**40, 10)', math.log(10**40, 10), 40)
1034 self.ftest('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
Mark Dickinsonc6037172010-09-29 19:06:36 +00001035 self.ftest('log(10**1000)', math.log(10**1000),
1036 2302.5850929940457)
1037 self.assertRaises(ValueError, math.log, -1.5)
1038 self.assertRaises(ValueError, math.log, -10**1000)
Christian Heimes53876d92008-04-19 00:31:39 +00001039 self.assertRaises(ValueError, math.log, NINF)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001040 self.assertEqual(math.log(INF), INF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001041 self.assertTrue(math.isnan(math.log(NAN)))
Christian Heimes53876d92008-04-19 00:31:39 +00001042
1043 def testLog1p(self):
1044 self.assertRaises(TypeError, math.log1p)
Mark Dickinson31ba1c32016-09-04 12:29:14 +01001045 for n in [2, 2**90, 2**300]:
1046 self.assertAlmostEqual(math.log1p(n), math.log1p(float(n)))
1047 self.assertRaises(ValueError, math.log1p, -1)
1048 self.assertEqual(math.log1p(INF), INF)
Guido van Rossumfcce6301996-08-08 18:26:25 +00001049
Victor Stinnerfa0e3d52011-05-09 01:01:09 +02001050 @requires_IEEE_754
1051 def testLog2(self):
1052 self.assertRaises(TypeError, math.log2)
Victor Stinnerfa0e3d52011-05-09 01:01:09 +02001053
1054 # Check some integer values
1055 self.assertEqual(math.log2(1), 0.0)
1056 self.assertEqual(math.log2(2), 1.0)
1057 self.assertEqual(math.log2(4), 2.0)
1058
1059 # Large integer values
1060 self.assertEqual(math.log2(2**1023), 1023.0)
1061 self.assertEqual(math.log2(2**1024), 1024.0)
1062 self.assertEqual(math.log2(2**2000), 2000.0)
1063
1064 self.assertRaises(ValueError, math.log2, -1.5)
1065 self.assertRaises(ValueError, math.log2, NINF)
1066 self.assertTrue(math.isnan(math.log2(NAN)))
1067
Victor Stinnercd9dd372011-05-10 23:40:17 +02001068 @requires_IEEE_754
Victor Stinnerebbbdaf2011-06-01 13:19:07 +02001069 # log2() is not accurate enough on Mac OS X Tiger (10.4)
1070 @support.requires_mac_ver(10, 5)
Victor Stinnercd9dd372011-05-10 23:40:17 +02001071 def testLog2Exact(self):
1072 # Check that we get exact equality for log2 of powers of 2.
1073 actual = [math.log2(math.ldexp(1.0, n)) for n in range(-1074, 1024)]
1074 expected = [float(n) for n in range(-1074, 1024)]
1075 self.assertEqual(actual, expected)
1076
Thomas Wouters89f507f2006-12-13 04:49:30 +00001077 def testLog10(self):
1078 self.assertRaises(TypeError, math.log10)
1079 self.ftest('log10(0.1)', math.log10(0.1), -1)
1080 self.ftest('log10(1)', math.log10(1), 0)
1081 self.ftest('log10(10)', math.log10(10), 1)
Mark Dickinsonc6037172010-09-29 19:06:36 +00001082 self.ftest('log10(10**1000)', math.log10(10**1000), 1000.0)
1083 self.assertRaises(ValueError, math.log10, -1.5)
1084 self.assertRaises(ValueError, math.log10, -10**1000)
Christian Heimes53876d92008-04-19 00:31:39 +00001085 self.assertRaises(ValueError, math.log10, NINF)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001086 self.assertEqual(math.log(INF), INF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001087 self.assertTrue(math.isnan(math.log10(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +00001088
Thomas Wouters89f507f2006-12-13 04:49:30 +00001089 def testModf(self):
1090 self.assertRaises(TypeError, math.modf)
Guido van Rossumfcce6301996-08-08 18:26:25 +00001091
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001092 def testmodf(name, result, expected):
1093 (v1, v2), (e1, e2) = result, expected
Thomas Wouters89f507f2006-12-13 04:49:30 +00001094 if abs(v1-e1) > eps or abs(v2-e2):
1095 self.fail('%s returned %r, expected %r'%\
Guido van Rossum1bc535d2007-05-15 18:46:22 +00001096 (name, result, expected))
Raymond Hettinger64108af2002-05-13 03:55:01 +00001097
Thomas Wouters89f507f2006-12-13 04:49:30 +00001098 testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0))
1099 testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0))
Guido van Rossumfcce6301996-08-08 18:26:25 +00001100
Ezio Melottib3aedd42010-11-20 19:04:17 +00001101 self.assertEqual(math.modf(INF), (0.0, INF))
1102 self.assertEqual(math.modf(NINF), (-0.0, NINF))
Christian Heimes53876d92008-04-19 00:31:39 +00001103
1104 modf_nan = math.modf(NAN)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001105 self.assertTrue(math.isnan(modf_nan[0]))
1106 self.assertTrue(math.isnan(modf_nan[1]))
Christian Heimes53876d92008-04-19 00:31:39 +00001107
Thomas Wouters89f507f2006-12-13 04:49:30 +00001108 def testPow(self):
1109 self.assertRaises(TypeError, math.pow)
1110 self.ftest('pow(0,1)', math.pow(0,1), 0)
1111 self.ftest('pow(1,0)', math.pow(1,0), 1)
1112 self.ftest('pow(2,1)', math.pow(2,1), 2)
1113 self.ftest('pow(2,-1)', math.pow(2,-1), 0.5)
Christian Heimes53876d92008-04-19 00:31:39 +00001114 self.assertEqual(math.pow(INF, 1), INF)
1115 self.assertEqual(math.pow(NINF, 1), NINF)
1116 self.assertEqual((math.pow(1, INF)), 1.)
1117 self.assertEqual((math.pow(1, NINF)), 1.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001118 self.assertTrue(math.isnan(math.pow(NAN, 1)))
1119 self.assertTrue(math.isnan(math.pow(2, NAN)))
1120 self.assertTrue(math.isnan(math.pow(0, NAN)))
Christian Heimes53876d92008-04-19 00:31:39 +00001121 self.assertEqual(math.pow(1, NAN), 1)
Christian Heimesa342c012008-04-20 21:01:16 +00001122
1123 # pow(0., x)
1124 self.assertEqual(math.pow(0., INF), 0.)
1125 self.assertEqual(math.pow(0., 3.), 0.)
1126 self.assertEqual(math.pow(0., 2.3), 0.)
1127 self.assertEqual(math.pow(0., 2.), 0.)
1128 self.assertEqual(math.pow(0., 0.), 1.)
1129 self.assertEqual(math.pow(0., -0.), 1.)
1130 self.assertRaises(ValueError, math.pow, 0., -2.)
1131 self.assertRaises(ValueError, math.pow, 0., -2.3)
1132 self.assertRaises(ValueError, math.pow, 0., -3.)
1133 self.assertRaises(ValueError, math.pow, 0., NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001134 self.assertTrue(math.isnan(math.pow(0., NAN)))
Christian Heimesa342c012008-04-20 21:01:16 +00001135
1136 # pow(INF, x)
1137 self.assertEqual(math.pow(INF, INF), INF)
1138 self.assertEqual(math.pow(INF, 3.), INF)
1139 self.assertEqual(math.pow(INF, 2.3), INF)
1140 self.assertEqual(math.pow(INF, 2.), INF)
1141 self.assertEqual(math.pow(INF, 0.), 1.)
1142 self.assertEqual(math.pow(INF, -0.), 1.)
1143 self.assertEqual(math.pow(INF, -2.), 0.)
1144 self.assertEqual(math.pow(INF, -2.3), 0.)
1145 self.assertEqual(math.pow(INF, -3.), 0.)
1146 self.assertEqual(math.pow(INF, NINF), 0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001147 self.assertTrue(math.isnan(math.pow(INF, NAN)))
Christian Heimesa342c012008-04-20 21:01:16 +00001148
1149 # pow(-0., x)
1150 self.assertEqual(math.pow(-0., INF), 0.)
1151 self.assertEqual(math.pow(-0., 3.), -0.)
1152 self.assertEqual(math.pow(-0., 2.3), 0.)
1153 self.assertEqual(math.pow(-0., 2.), 0.)
1154 self.assertEqual(math.pow(-0., 0.), 1.)
1155 self.assertEqual(math.pow(-0., -0.), 1.)
1156 self.assertRaises(ValueError, math.pow, -0., -2.)
1157 self.assertRaises(ValueError, math.pow, -0., -2.3)
1158 self.assertRaises(ValueError, math.pow, -0., -3.)
1159 self.assertRaises(ValueError, math.pow, -0., NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001160 self.assertTrue(math.isnan(math.pow(-0., NAN)))
Christian Heimesa342c012008-04-20 21:01:16 +00001161
1162 # pow(NINF, x)
1163 self.assertEqual(math.pow(NINF, INF), INF)
1164 self.assertEqual(math.pow(NINF, 3.), NINF)
1165 self.assertEqual(math.pow(NINF, 2.3), INF)
1166 self.assertEqual(math.pow(NINF, 2.), INF)
1167 self.assertEqual(math.pow(NINF, 0.), 1.)
1168 self.assertEqual(math.pow(NINF, -0.), 1.)
1169 self.assertEqual(math.pow(NINF, -2.), 0.)
1170 self.assertEqual(math.pow(NINF, -2.3), 0.)
1171 self.assertEqual(math.pow(NINF, -3.), -0.)
1172 self.assertEqual(math.pow(NINF, NINF), 0.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001173 self.assertTrue(math.isnan(math.pow(NINF, NAN)))
Christian Heimesa342c012008-04-20 21:01:16 +00001174
1175 # pow(-1, x)
1176 self.assertEqual(math.pow(-1., INF), 1.)
1177 self.assertEqual(math.pow(-1., 3.), -1.)
1178 self.assertRaises(ValueError, math.pow, -1., 2.3)
1179 self.assertEqual(math.pow(-1., 2.), 1.)
1180 self.assertEqual(math.pow(-1., 0.), 1.)
1181 self.assertEqual(math.pow(-1., -0.), 1.)
1182 self.assertEqual(math.pow(-1., -2.), 1.)
1183 self.assertRaises(ValueError, math.pow, -1., -2.3)
1184 self.assertEqual(math.pow(-1., -3.), -1.)
1185 self.assertEqual(math.pow(-1., NINF), 1.)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001186 self.assertTrue(math.isnan(math.pow(-1., NAN)))
Christian Heimesa342c012008-04-20 21:01:16 +00001187
1188 # pow(1, x)
1189 self.assertEqual(math.pow(1., INF), 1.)
1190 self.assertEqual(math.pow(1., 3.), 1.)
1191 self.assertEqual(math.pow(1., 2.3), 1.)
1192 self.assertEqual(math.pow(1., 2.), 1.)
1193 self.assertEqual(math.pow(1., 0.), 1.)
1194 self.assertEqual(math.pow(1., -0.), 1.)
1195 self.assertEqual(math.pow(1., -2.), 1.)
1196 self.assertEqual(math.pow(1., -2.3), 1.)
1197 self.assertEqual(math.pow(1., -3.), 1.)
1198 self.assertEqual(math.pow(1., NINF), 1.)
1199 self.assertEqual(math.pow(1., NAN), 1.)
1200
1201 # pow(x, 0) should be 1 for any x
1202 self.assertEqual(math.pow(2.3, 0.), 1.)
1203 self.assertEqual(math.pow(-2.3, 0.), 1.)
1204 self.assertEqual(math.pow(NAN, 0.), 1.)
1205 self.assertEqual(math.pow(2.3, -0.), 1.)
1206 self.assertEqual(math.pow(-2.3, -0.), 1.)
1207 self.assertEqual(math.pow(NAN, -0.), 1.)
1208
1209 # pow(x, y) is invalid if x is negative and y is not integral
1210 self.assertRaises(ValueError, math.pow, -1., 2.3)
1211 self.assertRaises(ValueError, math.pow, -15., -3.1)
1212
1213 # pow(x, NINF)
1214 self.assertEqual(math.pow(1.9, NINF), 0.)
1215 self.assertEqual(math.pow(1.1, NINF), 0.)
1216 self.assertEqual(math.pow(0.9, NINF), INF)
1217 self.assertEqual(math.pow(0.1, NINF), INF)
1218 self.assertEqual(math.pow(-0.1, NINF), INF)
1219 self.assertEqual(math.pow(-0.9, NINF), INF)
1220 self.assertEqual(math.pow(-1.1, NINF), 0.)
1221 self.assertEqual(math.pow(-1.9, NINF), 0.)
1222
1223 # pow(x, INF)
1224 self.assertEqual(math.pow(1.9, INF), INF)
1225 self.assertEqual(math.pow(1.1, INF), INF)
1226 self.assertEqual(math.pow(0.9, INF), 0.)
1227 self.assertEqual(math.pow(0.1, INF), 0.)
1228 self.assertEqual(math.pow(-0.1, INF), 0.)
1229 self.assertEqual(math.pow(-0.9, INF), 0.)
1230 self.assertEqual(math.pow(-1.1, INF), INF)
1231 self.assertEqual(math.pow(-1.9, INF), INF)
1232
1233 # pow(x, y) should work for x negative, y an integer
1234 self.ftest('(-2.)**3.', math.pow(-2.0, 3.0), -8.0)
1235 self.ftest('(-2.)**2.', math.pow(-2.0, 2.0), 4.0)
1236 self.ftest('(-2.)**1.', math.pow(-2.0, 1.0), -2.0)
1237 self.ftest('(-2.)**0.', math.pow(-2.0, 0.0), 1.0)
1238 self.ftest('(-2.)**-0.', math.pow(-2.0, -0.0), 1.0)
1239 self.ftest('(-2.)**-1.', math.pow(-2.0, -1.0), -0.5)
1240 self.ftest('(-2.)**-2.', math.pow(-2.0, -2.0), 0.25)
1241 self.ftest('(-2.)**-3.', math.pow(-2.0, -3.0), -0.125)
1242 self.assertRaises(ValueError, math.pow, -2.0, -0.5)
1243 self.assertRaises(ValueError, math.pow, -2.0, 0.5)
1244
1245 # the following tests have been commented out since they don't
1246 # really belong here: the implementation of ** for floats is
Ezio Melotti13925002011-03-16 11:05:33 +02001247 # independent of the implementation of math.pow
Christian Heimesa342c012008-04-20 21:01:16 +00001248 #self.assertEqual(1**NAN, 1)
1249 #self.assertEqual(1**INF, 1)
1250 #self.assertEqual(1**NINF, 1)
1251 #self.assertEqual(1**0, 1)
1252 #self.assertEqual(1.**NAN, 1)
1253 #self.assertEqual(1.**INF, 1)
1254 #self.assertEqual(1.**NINF, 1)
1255 #self.assertEqual(1.**0, 1)
Guido van Rossumfcce6301996-08-08 18:26:25 +00001256
Thomas Wouters89f507f2006-12-13 04:49:30 +00001257 def testRadians(self):
1258 self.assertRaises(TypeError, math.radians)
1259 self.ftest('radians(180)', math.radians(180), math.pi)
1260 self.ftest('radians(90)', math.radians(90), math.pi/2)
1261 self.ftest('radians(-45)', math.radians(-45), -math.pi/4)
Mark Dickinson31ba1c32016-09-04 12:29:14 +01001262 self.ftest('radians(0)', math.radians(0), 0)
Guido van Rossumfcce6301996-08-08 18:26:25 +00001263
Mark Dickinsona0ce3752017-04-05 18:34:27 +01001264 @requires_IEEE_754
1265 def testRemainder(self):
1266 from fractions import Fraction
1267
1268 def validate_spec(x, y, r):
1269 """
1270 Check that r matches remainder(x, y) according to the IEEE 754
1271 specification. Assumes that x, y and r are finite and y is nonzero.
1272 """
1273 fx, fy, fr = Fraction(x), Fraction(y), Fraction(r)
1274 # r should not exceed y/2 in absolute value
1275 self.assertLessEqual(abs(fr), abs(fy/2))
1276 # x - r should be an exact integer multiple of y
1277 n = (fx - fr) / fy
1278 self.assertEqual(n, int(n))
1279 if abs(fr) == abs(fy/2):
1280 # If |r| == |y/2|, n should be even.
1281 self.assertEqual(n/2, int(n/2))
1282
1283 # triples (x, y, remainder(x, y)) in hexadecimal form.
1284 testcases = [
1285 # Remainders modulo 1, showing the ties-to-even behaviour.
1286 '-4.0 1 -0.0',
1287 '-3.8 1 0.8',
1288 '-3.0 1 -0.0',
1289 '-2.8 1 -0.8',
1290 '-2.0 1 -0.0',
1291 '-1.8 1 0.8',
1292 '-1.0 1 -0.0',
1293 '-0.8 1 -0.8',
1294 '-0.0 1 -0.0',
1295 ' 0.0 1 0.0',
1296 ' 0.8 1 0.8',
1297 ' 1.0 1 0.0',
1298 ' 1.8 1 -0.8',
1299 ' 2.0 1 0.0',
1300 ' 2.8 1 0.8',
1301 ' 3.0 1 0.0',
1302 ' 3.8 1 -0.8',
1303 ' 4.0 1 0.0',
1304
1305 # Reductions modulo 2*pi
1306 '0x0.0p+0 0x1.921fb54442d18p+2 0x0.0p+0',
1307 '0x1.921fb54442d18p+0 0x1.921fb54442d18p+2 0x1.921fb54442d18p+0',
1308 '0x1.921fb54442d17p+1 0x1.921fb54442d18p+2 0x1.921fb54442d17p+1',
1309 '0x1.921fb54442d18p+1 0x1.921fb54442d18p+2 0x1.921fb54442d18p+1',
1310 '0x1.921fb54442d19p+1 0x1.921fb54442d18p+2 -0x1.921fb54442d17p+1',
1311 '0x1.921fb54442d17p+2 0x1.921fb54442d18p+2 -0x0.0000000000001p+2',
1312 '0x1.921fb54442d18p+2 0x1.921fb54442d18p+2 0x0p0',
1313 '0x1.921fb54442d19p+2 0x1.921fb54442d18p+2 0x0.0000000000001p+2',
1314 '0x1.2d97c7f3321d1p+3 0x1.921fb54442d18p+2 0x1.921fb54442d14p+1',
1315 '0x1.2d97c7f3321d2p+3 0x1.921fb54442d18p+2 -0x1.921fb54442d18p+1',
1316 '0x1.2d97c7f3321d3p+3 0x1.921fb54442d18p+2 -0x1.921fb54442d14p+1',
1317 '0x1.921fb54442d17p+3 0x1.921fb54442d18p+2 -0x0.0000000000001p+3',
1318 '0x1.921fb54442d18p+3 0x1.921fb54442d18p+2 0x0p0',
1319 '0x1.921fb54442d19p+3 0x1.921fb54442d18p+2 0x0.0000000000001p+3',
1320 '0x1.f6a7a2955385dp+3 0x1.921fb54442d18p+2 0x1.921fb54442d14p+1',
1321 '0x1.f6a7a2955385ep+3 0x1.921fb54442d18p+2 0x1.921fb54442d18p+1',
1322 '0x1.f6a7a2955385fp+3 0x1.921fb54442d18p+2 -0x1.921fb54442d14p+1',
1323 '0x1.1475cc9eedf00p+5 0x1.921fb54442d18p+2 0x1.921fb54442d10p+1',
1324 '0x1.1475cc9eedf01p+5 0x1.921fb54442d18p+2 -0x1.921fb54442d10p+1',
1325
1326 # Symmetry with respect to signs.
1327 ' 1 0.c 0.4',
1328 '-1 0.c -0.4',
1329 ' 1 -0.c 0.4',
1330 '-1 -0.c -0.4',
1331 ' 1.4 0.c -0.4',
1332 '-1.4 0.c 0.4',
1333 ' 1.4 -0.c -0.4',
1334 '-1.4 -0.c 0.4',
1335
1336 # Huge modulus, to check that the underlying algorithm doesn't
1337 # rely on 2.0 * modulus being representable.
1338 '0x1.dp+1023 0x1.4p+1023 0x0.9p+1023',
1339 '0x1.ep+1023 0x1.4p+1023 -0x0.ap+1023',
1340 '0x1.fp+1023 0x1.4p+1023 -0x0.9p+1023',
1341 ]
1342
1343 for case in testcases:
1344 with self.subTest(case=case):
1345 x_hex, y_hex, expected_hex = case.split()
1346 x = float.fromhex(x_hex)
1347 y = float.fromhex(y_hex)
1348 expected = float.fromhex(expected_hex)
1349 validate_spec(x, y, expected)
1350 actual = math.remainder(x, y)
1351 # Cheap way of checking that the floats are
1352 # as identical as we need them to be.
1353 self.assertEqual(actual.hex(), expected.hex())
1354
1355 # Test tiny subnormal modulus: there's potential for
1356 # getting the implementation wrong here (for example,
1357 # by assuming that modulus/2 is exactly representable).
1358 tiny = float.fromhex('1p-1074') # min +ve subnormal
1359 for n in range(-25, 25):
1360 if n == 0:
1361 continue
1362 y = n * tiny
1363 for m in range(100):
1364 x = m * tiny
1365 actual = math.remainder(x, y)
1366 validate_spec(x, y, actual)
1367 actual = math.remainder(-x, y)
1368 validate_spec(-x, y, actual)
1369
1370 # Special values.
1371 # NaNs should propagate as usual.
1372 for value in [NAN, 0.0, -0.0, 2.0, -2.3, NINF, INF]:
1373 self.assertIsNaN(math.remainder(NAN, value))
1374 self.assertIsNaN(math.remainder(value, NAN))
1375
1376 # remainder(x, inf) is x, for non-nan non-infinite x.
1377 for value in [-2.3, -0.0, 0.0, 2.3]:
1378 self.assertEqual(math.remainder(value, INF), value)
1379 self.assertEqual(math.remainder(value, NINF), value)
1380
1381 # remainder(x, 0) and remainder(infinity, x) for non-NaN x are invalid
1382 # operations according to IEEE 754-2008 7.2(f), and should raise.
1383 for value in [NINF, -2.3, -0.0, 0.0, 2.3, INF]:
1384 with self.assertRaises(ValueError):
1385 math.remainder(INF, value)
1386 with self.assertRaises(ValueError):
1387 math.remainder(NINF, value)
1388 with self.assertRaises(ValueError):
1389 math.remainder(value, 0.0)
1390 with self.assertRaises(ValueError):
1391 math.remainder(value, -0.0)
1392
Thomas Wouters89f507f2006-12-13 04:49:30 +00001393 def testSin(self):
1394 self.assertRaises(TypeError, math.sin)
1395 self.ftest('sin(0)', math.sin(0), 0)
1396 self.ftest('sin(pi/2)', math.sin(math.pi/2), 1)
1397 self.ftest('sin(-pi/2)', math.sin(-math.pi/2), -1)
Christian Heimes53876d92008-04-19 00:31:39 +00001398 try:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001399 self.assertTrue(math.isnan(math.sin(INF)))
1400 self.assertTrue(math.isnan(math.sin(NINF)))
Christian Heimes53876d92008-04-19 00:31:39 +00001401 except ValueError:
1402 self.assertRaises(ValueError, math.sin, INF)
1403 self.assertRaises(ValueError, math.sin, NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001404 self.assertTrue(math.isnan(math.sin(NAN)))
Guido van Rossumfcce6301996-08-08 18:26:25 +00001405
Thomas Wouters89f507f2006-12-13 04:49:30 +00001406 def testSinh(self):
1407 self.assertRaises(TypeError, math.sinh)
1408 self.ftest('sinh(0)', math.sinh(0), 0)
1409 self.ftest('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
1410 self.ftest('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001411 self.assertEqual(math.sinh(INF), INF)
1412 self.assertEqual(math.sinh(NINF), NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001413 self.assertTrue(math.isnan(math.sinh(NAN)))
Tim Peters1d120612000-10-12 06:10:25 +00001414
Thomas Wouters89f507f2006-12-13 04:49:30 +00001415 def testSqrt(self):
1416 self.assertRaises(TypeError, math.sqrt)
1417 self.ftest('sqrt(0)', math.sqrt(0), 0)
1418 self.ftest('sqrt(1)', math.sqrt(1), 1)
1419 self.ftest('sqrt(4)', math.sqrt(4), 2)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001420 self.assertEqual(math.sqrt(INF), INF)
Mark Dickinson31ba1c32016-09-04 12:29:14 +01001421 self.assertRaises(ValueError, math.sqrt, -1)
Christian Heimes53876d92008-04-19 00:31:39 +00001422 self.assertRaises(ValueError, math.sqrt, NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001423 self.assertTrue(math.isnan(math.sqrt(NAN)))
Tim Peters1d120612000-10-12 06:10:25 +00001424
Thomas Wouters89f507f2006-12-13 04:49:30 +00001425 def testTan(self):
1426 self.assertRaises(TypeError, math.tan)
1427 self.ftest('tan(0)', math.tan(0), 0)
1428 self.ftest('tan(pi/4)', math.tan(math.pi/4), 1)
1429 self.ftest('tan(-pi/4)', math.tan(-math.pi/4), -1)
Christian Heimes53876d92008-04-19 00:31:39 +00001430 try:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001431 self.assertTrue(math.isnan(math.tan(INF)))
1432 self.assertTrue(math.isnan(math.tan(NINF)))
Christian Heimes53876d92008-04-19 00:31:39 +00001433 except:
1434 self.assertRaises(ValueError, math.tan, INF)
1435 self.assertRaises(ValueError, math.tan, NINF)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001436 self.assertTrue(math.isnan(math.tan(NAN)))
Tim Peters1d120612000-10-12 06:10:25 +00001437
Thomas Wouters89f507f2006-12-13 04:49:30 +00001438 def testTanh(self):
1439 self.assertRaises(TypeError, math.tanh)
1440 self.ftest('tanh(0)', math.tanh(0), 0)
Mark Dickinson96f774d2016-09-03 19:30:22 +01001441 self.ftest('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0,
1442 abs_tol=ulp(1))
Christian Heimes53876d92008-04-19 00:31:39 +00001443 self.ftest('tanh(inf)', math.tanh(INF), 1)
1444 self.ftest('tanh(-inf)', math.tanh(NINF), -1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001445 self.assertTrue(math.isnan(math.tanh(NAN)))
Victor Stinnerbe3da382010-11-07 14:14:27 +00001446
1447 @requires_IEEE_754
Victor Stinnerbe3da382010-11-07 14:14:27 +00001448 def testTanhSign(self):
Christian Heimese57950f2008-04-21 13:08:03 +00001449 # check that tanh(-0.) == -0. on IEEE 754 systems
Victor Stinnerbe3da382010-11-07 14:14:27 +00001450 self.assertEqual(math.tanh(-0.), -0.)
1451 self.assertEqual(math.copysign(1., math.tanh(-0.)),
1452 math.copysign(1., -0.))
Tim Peters1d120612000-10-12 06:10:25 +00001453
Christian Heimes400adb02008-02-01 08:12:03 +00001454 def test_trunc(self):
1455 self.assertEqual(math.trunc(1), 1)
1456 self.assertEqual(math.trunc(-1), -1)
1457 self.assertEqual(type(math.trunc(1)), int)
1458 self.assertEqual(type(math.trunc(1.5)), int)
1459 self.assertEqual(math.trunc(1.5), 1)
1460 self.assertEqual(math.trunc(-1.5), -1)
1461 self.assertEqual(math.trunc(1.999999), 1)
1462 self.assertEqual(math.trunc(-1.999999), -1)
1463 self.assertEqual(math.trunc(-0.999999), -0)
1464 self.assertEqual(math.trunc(-100.999), -100)
1465
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +02001466 class TestTrunc:
Christian Heimes400adb02008-02-01 08:12:03 +00001467 def __trunc__(self):
1468 return 23
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +02001469 class FloatTrunc(float):
1470 def __trunc__(self):
1471 return 23
1472 class TestNoTrunc:
Christian Heimes400adb02008-02-01 08:12:03 +00001473 pass
1474
1475 self.assertEqual(math.trunc(TestTrunc()), 23)
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +02001476 self.assertEqual(math.trunc(FloatTrunc()), 23)
Christian Heimes400adb02008-02-01 08:12:03 +00001477
1478 self.assertRaises(TypeError, math.trunc)
1479 self.assertRaises(TypeError, math.trunc, 1, 2)
Serhiy Storchaka5fd5cb82019-11-16 18:00:57 +02001480 self.assertRaises(TypeError, math.trunc, FloatLike(23.5))
Christian Heimes400adb02008-02-01 08:12:03 +00001481 self.assertRaises(TypeError, math.trunc, TestNoTrunc())
1482
Mark Dickinson8e0c9962010-07-11 17:38:24 +00001483 def testIsfinite(self):
1484 self.assertTrue(math.isfinite(0.0))
1485 self.assertTrue(math.isfinite(-0.0))
1486 self.assertTrue(math.isfinite(1.0))
1487 self.assertTrue(math.isfinite(-1.0))
1488 self.assertFalse(math.isfinite(float("nan")))
1489 self.assertFalse(math.isfinite(float("inf")))
1490 self.assertFalse(math.isfinite(float("-inf")))
1491
Christian Heimes072c0f12008-01-03 23:01:04 +00001492 def testIsnan(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001493 self.assertTrue(math.isnan(float("nan")))
Mark Dickinson31ba1c32016-09-04 12:29:14 +01001494 self.assertTrue(math.isnan(float("-nan")))
1495 self.assertTrue(math.isnan(float("inf") * 0.))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001496 self.assertFalse(math.isnan(float("inf")))
1497 self.assertFalse(math.isnan(0.))
1498 self.assertFalse(math.isnan(1.))
Christian Heimes072c0f12008-01-03 23:01:04 +00001499
1500 def testIsinf(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001501 self.assertTrue(math.isinf(float("inf")))
1502 self.assertTrue(math.isinf(float("-inf")))
1503 self.assertTrue(math.isinf(1E400))
1504 self.assertTrue(math.isinf(-1E400))
1505 self.assertFalse(math.isinf(float("nan")))
1506 self.assertFalse(math.isinf(0.))
1507 self.assertFalse(math.isinf(1.))
Christian Heimes072c0f12008-01-03 23:01:04 +00001508
Mark Dickinsona5d0c7c2015-01-11 11:55:29 +00001509 @requires_IEEE_754
1510 def test_nan_constant(self):
1511 self.assertTrue(math.isnan(math.nan))
1512
1513 @requires_IEEE_754
1514 def test_inf_constant(self):
1515 self.assertTrue(math.isinf(math.inf))
1516 self.assertGreater(math.inf, 0.0)
1517 self.assertEqual(math.inf, float("inf"))
1518 self.assertEqual(-math.inf, float("-inf"))
1519
Thomas Wouters89f507f2006-12-13 04:49:30 +00001520 # RED_FLAG 16-Oct-2000 Tim
1521 # While 2.0 is more consistent about exceptions than previous releases, it
1522 # still fails this part of the test on some platforms. For now, we only
1523 # *run* test_exceptions() in verbose mode, so that this isn't normally
1524 # tested.
Serhiy Storchaka43767632013-11-03 21:31:38 +02001525 @unittest.skipUnless(verbose, 'requires verbose mode')
1526 def test_exceptions(self):
1527 try:
1528 x = math.exp(-1000000000)
1529 except:
1530 # mathmodule.c is failing to weed out underflows from libm, or
1531 # we've got an fp format with huge dynamic range
1532 self.fail("underflowing exp() should not have raised "
1533 "an exception")
1534 if x != 0:
1535 self.fail("underflowing exp() should have returned 0")
Tim Peters98c81842000-10-16 17:35:13 +00001536
Serhiy Storchaka43767632013-11-03 21:31:38 +02001537 # If this fails, probably using a strict IEEE-754 conforming libm, and x
1538 # is +Inf afterwards. But Python wants overflows detected by default.
1539 try:
1540 x = math.exp(1000000000)
1541 except OverflowError:
1542 pass
1543 else:
1544 self.fail("overflowing exp() didn't trigger OverflowError")
Thomas Wouters89f507f2006-12-13 04:49:30 +00001545
Serhiy Storchaka43767632013-11-03 21:31:38 +02001546 # If this fails, it could be a puzzle. One odd possibility is that
1547 # mathmodule.c's macros are getting confused while comparing
1548 # Inf (HUGE_VAL) to a NaN, and artificially setting errno to ERANGE
1549 # as a result (and so raising OverflowError instead).
1550 try:
1551 x = math.sqrt(-1.0)
1552 except ValueError:
1553 pass
1554 else:
1555 self.fail("sqrt(-1) didn't raise ValueError")
Thomas Wouters89f507f2006-12-13 04:49:30 +00001556
Mark Dickinson63566232009-09-18 21:04:19 +00001557 @requires_IEEE_754
Christian Heimes53876d92008-04-19 00:31:39 +00001558 def test_testfile(self):
Mark Dickinson85746542016-09-04 09:58:51 +01001559 # Some tests need to be skipped on ancient OS X versions.
1560 # See issue #27953.
1561 SKIP_ON_TIGER = {'tan0064'}
1562
1563 osx_version = None
1564 if sys.platform == 'darwin':
1565 version_txt = platform.mac_ver()[0]
1566 try:
1567 osx_version = tuple(map(int, version_txt.split('.')))
1568 except ValueError:
1569 pass
1570
Mark Dickinson96f774d2016-09-03 19:30:22 +01001571 fail_fmt = "{}: {}({!r}): {}"
1572
1573 failures = []
Christian Heimes53876d92008-04-19 00:31:39 +00001574 for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file):
Mark Dickinson96f774d2016-09-03 19:30:22 +01001575 # Skip if either the input or result is complex
1576 if ai != 0.0 or ei != 0.0:
Christian Heimes53876d92008-04-19 00:31:39 +00001577 continue
1578 if fn in ['rect', 'polar']:
1579 # no real versions of rect, polar
1580 continue
Mark Dickinson85746542016-09-04 09:58:51 +01001581 # Skip certain tests on OS X 10.4.
1582 if osx_version is not None and osx_version < (10, 5):
1583 if id in SKIP_ON_TIGER:
1584 continue
Mark Dickinson96f774d2016-09-03 19:30:22 +01001585
Christian Heimes53876d92008-04-19 00:31:39 +00001586 func = getattr(math, fn)
Mark Dickinson96f774d2016-09-03 19:30:22 +01001587
1588 if 'invalid' in flags or 'divide-by-zero' in flags:
1589 er = 'ValueError'
1590 elif 'overflow' in flags:
1591 er = 'OverflowError'
1592
Christian Heimesa342c012008-04-20 21:01:16 +00001593 try:
1594 result = func(ar)
Mark Dickinson96f774d2016-09-03 19:30:22 +01001595 except ValueError:
1596 result = 'ValueError'
Benjamin Peterson2b7411d2008-05-26 17:36:47 +00001597 except OverflowError:
Mark Dickinson96f774d2016-09-03 19:30:22 +01001598 result = 'OverflowError'
1599
1600 # Default tolerances
1601 ulp_tol, abs_tol = 5, 0.0
1602
1603 failure = result_check(er, result, ulp_tol, abs_tol)
1604 if failure is None:
1605 continue
1606
1607 msg = fail_fmt.format(id, fn, ar, failure)
1608 failures.append(msg)
1609
1610 if failures:
1611 self.fail('Failures in test_testfile:\n ' +
1612 '\n '.join(failures))
Thomas Wouters89f507f2006-12-13 04:49:30 +00001613
Victor Stinnerbe3da382010-11-07 14:14:27 +00001614 @requires_IEEE_754
Mark Dickinson12c4bdb2009-09-28 19:21:11 +00001615 def test_mtestfile(self):
Mark Dickinson96f774d2016-09-03 19:30:22 +01001616 fail_fmt = "{}: {}({!r}): {}"
Mark Dickinson12c4bdb2009-09-28 19:21:11 +00001617
1618 failures = []
1619 for id, fn, arg, expected, flags in parse_mtestfile(math_testcases):
1620 func = getattr(math, fn)
1621
1622 if 'invalid' in flags or 'divide-by-zero' in flags:
1623 expected = 'ValueError'
1624 elif 'overflow' in flags:
1625 expected = 'OverflowError'
1626
1627 try:
1628 got = func(arg)
1629 except ValueError:
1630 got = 'ValueError'
1631 except OverflowError:
1632 got = 'OverflowError'
1633
Mark Dickinson96f774d2016-09-03 19:30:22 +01001634 # Default tolerances
1635 ulp_tol, abs_tol = 5, 0.0
Mark Dickinsonbcdf9da2010-06-13 10:52:38 +00001636
Mark Dickinson96f774d2016-09-03 19:30:22 +01001637 # Exceptions to the defaults
1638 if fn == 'gamma':
1639 # Experimental results on one platform gave
1640 # an accuracy of <= 10 ulps across the entire float
1641 # domain. We weaken that to require 20 ulp accuracy.
1642 ulp_tol = 20
Mark Dickinson12c4bdb2009-09-28 19:21:11 +00001643
Mark Dickinson96f774d2016-09-03 19:30:22 +01001644 elif fn == 'lgamma':
1645 # we use a weaker accuracy test for lgamma;
1646 # lgamma only achieves an absolute error of
1647 # a few multiples of the machine accuracy, in
1648 # general.
1649 abs_tol = 1e-15
Mark Dickinson12c4bdb2009-09-28 19:21:11 +00001650
Mark Dickinson96f774d2016-09-03 19:30:22 +01001651 elif fn == 'erfc' and arg >= 0.0:
1652 # erfc has less-than-ideal accuracy for large
1653 # arguments (x ~ 25 or so), mainly due to the
1654 # error involved in computing exp(-x*x).
1655 #
1656 # Observed between CPython and mpmath at 25 dp:
1657 # x < 0 : err <= 2 ulp
1658 # 0 <= x < 1 : err <= 10 ulp
1659 # 1 <= x < 10 : err <= 100 ulp
1660 # 10 <= x < 20 : err <= 300 ulp
1661 # 20 <= x : < 600 ulp
1662 #
1663 if arg < 1.0:
1664 ulp_tol = 10
1665 elif arg < 10.0:
1666 ulp_tol = 100
1667 else:
1668 ulp_tol = 1000
1669
1670 failure = result_check(expected, got, ulp_tol, abs_tol)
1671 if failure is None:
1672 continue
1673
1674 msg = fail_fmt.format(id, fn, arg, failure)
1675 failures.append(msg)
Mark Dickinson12c4bdb2009-09-28 19:21:11 +00001676
1677 if failures:
1678 self.fail('Failures in test_mtestfile:\n ' +
1679 '\n '.join(failures))
1680
Pablo Galindo04114112019-03-09 19:18:08 +00001681 def test_prod(self):
1682 prod = math.prod
1683 self.assertEqual(prod([]), 1)
1684 self.assertEqual(prod([], start=5), 5)
1685 self.assertEqual(prod(list(range(2,8))), 5040)
1686 self.assertEqual(prod(iter(list(range(2,8)))), 5040)
1687 self.assertEqual(prod(range(1, 10), start=10), 3628800)
1688
1689 self.assertEqual(prod([1, 2, 3, 4, 5]), 120)
1690 self.assertEqual(prod([1.0, 2.0, 3.0, 4.0, 5.0]), 120.0)
1691 self.assertEqual(prod([1, 2, 3, 4.0, 5.0]), 120.0)
1692 self.assertEqual(prod([1.0, 2.0, 3.0, 4, 5]), 120.0)
1693
1694 # Test overflow in fast-path for integers
1695 self.assertEqual(prod([1, 1, 2**32, 1, 1]), 2**32)
1696 # Test overflow in fast-path for floats
1697 self.assertEqual(prod([1.0, 1.0, 2**32, 1, 1]), float(2**32))
1698
1699 self.assertRaises(TypeError, prod)
1700 self.assertRaises(TypeError, prod, 42)
1701 self.assertRaises(TypeError, prod, ['a', 'b', 'c'])
1702 self.assertRaises(TypeError, prod, ['a', 'b', 'c'], '')
1703 self.assertRaises(TypeError, prod, [b'a', b'c'], b'')
1704 values = [bytearray(b'a'), bytearray(b'b')]
1705 self.assertRaises(TypeError, prod, values, bytearray(b''))
1706 self.assertRaises(TypeError, prod, [[1], [2], [3]])
1707 self.assertRaises(TypeError, prod, [{2:3}])
1708 self.assertRaises(TypeError, prod, [{2:3}]*2, {2:3})
1709 self.assertRaises(TypeError, prod, [[1], [2], [3]], [])
1710 with self.assertRaises(TypeError):
1711 prod([10, 20], [30, 40]) # start is a keyword-only argument
1712
1713 self.assertEqual(prod([0, 1, 2, 3]), 0)
1714 self.assertEqual(prod([1, 0, 2, 3]), 0)
1715 self.assertEqual(prod([1, 2, 3, 0]), 0)
1716
1717 def _naive_prod(iterable, start=1):
1718 for elem in iterable:
1719 start *= elem
1720 return start
1721
1722 # Big integers
1723
1724 iterable = range(1, 10000)
1725 self.assertEqual(prod(iterable), _naive_prod(iterable))
1726 iterable = range(-10000, -1)
1727 self.assertEqual(prod(iterable), _naive_prod(iterable))
1728 iterable = range(-1000, 1000)
1729 self.assertEqual(prod(iterable), 0)
1730
1731 # Big floats
1732
1733 iterable = [float(x) for x in range(1, 1000)]
1734 self.assertEqual(prod(iterable), _naive_prod(iterable))
1735 iterable = [float(x) for x in range(-1000, -1)]
1736 self.assertEqual(prod(iterable), _naive_prod(iterable))
1737 iterable = [float(x) for x in range(-1000, 1000)]
1738 self.assertIsNaN(prod(iterable))
1739
1740 # Float tests
1741
1742 self.assertIsNaN(prod([1, 2, 3, float("nan"), 2, 3]))
1743 self.assertIsNaN(prod([1, 0, float("nan"), 2, 3]))
1744 self.assertIsNaN(prod([1, float("nan"), 0, 3]))
1745 self.assertIsNaN(prod([1, float("inf"), float("nan"),3]))
1746 self.assertIsNaN(prod([1, float("-inf"), float("nan"),3]))
1747 self.assertIsNaN(prod([1, float("nan"), float("inf"),3]))
1748 self.assertIsNaN(prod([1, float("nan"), float("-inf"),3]))
1749
1750 self.assertEqual(prod([1, 2, 3, float('inf'),-3,4]), float('-inf'))
1751 self.assertEqual(prod([1, 2, 3, float('-inf'),-3,4]), float('inf'))
1752
1753 self.assertIsNaN(prod([1,2,0,float('inf'), -3, 4]))
1754 self.assertIsNaN(prod([1,2,0,float('-inf'), -3, 4]))
1755 self.assertIsNaN(prod([1, 2, 3, float('inf'), -3, 0, 3]))
1756 self.assertIsNaN(prod([1, 2, 3, float('-inf'), -3, 0, 2]))
1757
1758 # Type preservation
1759
1760 self.assertEqual(type(prod([1, 2, 3, 4, 5, 6])), int)
1761 self.assertEqual(type(prod([1, 2.0, 3, 4, 5, 6])), float)
1762 self.assertEqual(type(prod(range(1, 10000))), int)
1763 self.assertEqual(type(prod(range(1, 10000), start=1.0)), float)
1764 self.assertEqual(type(prod([1, decimal.Decimal(2.0), 3, 4, 5, 6])),
1765 decimal.Decimal)
1766
Mark Dickinsona0ce3752017-04-05 18:34:27 +01001767 # Custom assertions.
1768
1769 def assertIsNaN(self, value):
1770 if not math.isnan(value):
1771 self.fail("Expected a NaN, got {!r}.".format(value))
1772
Mark Dickinson12c4bdb2009-09-28 19:21:11 +00001773
Tal Einatd5519ed2015-05-31 22:05:00 +03001774class IsCloseTests(unittest.TestCase):
Mike53f7a7c2017-12-14 14:04:53 +03001775 isclose = math.isclose # subclasses should override this
Tal Einatd5519ed2015-05-31 22:05:00 +03001776
1777 def assertIsClose(self, a, b, *args, **kwargs):
1778 self.assertTrue(self.isclose(a, b, *args, **kwargs),
1779 msg="%s and %s should be close!" % (a, b))
1780
1781 def assertIsNotClose(self, a, b, *args, **kwargs):
1782 self.assertFalse(self.isclose(a, b, *args, **kwargs),
1783 msg="%s and %s should not be close!" % (a, b))
1784
1785 def assertAllClose(self, examples, *args, **kwargs):
1786 for a, b in examples:
1787 self.assertIsClose(a, b, *args, **kwargs)
1788
1789 def assertAllNotClose(self, examples, *args, **kwargs):
1790 for a, b in examples:
1791 self.assertIsNotClose(a, b, *args, **kwargs)
1792
1793 def test_negative_tolerances(self):
1794 # ValueError should be raised if either tolerance is less than zero
1795 with self.assertRaises(ValueError):
1796 self.assertIsClose(1, 1, rel_tol=-1e-100)
1797 with self.assertRaises(ValueError):
1798 self.assertIsClose(1, 1, rel_tol=1e-100, abs_tol=-1e10)
1799
1800 def test_identical(self):
1801 # identical values must test as close
1802 identical_examples = [(2.0, 2.0),
1803 (0.1e200, 0.1e200),
1804 (1.123e-300, 1.123e-300),
1805 (12345, 12345.0),
1806 (0.0, -0.0),
1807 (345678, 345678)]
1808 self.assertAllClose(identical_examples, rel_tol=0.0, abs_tol=0.0)
1809
1810 def test_eight_decimal_places(self):
1811 # examples that are close to 1e-8, but not 1e-9
1812 eight_decimal_places_examples = [(1e8, 1e8 + 1),
1813 (-1e-8, -1.000000009e-8),
1814 (1.12345678, 1.12345679)]
1815 self.assertAllClose(eight_decimal_places_examples, rel_tol=1e-8)
1816 self.assertAllNotClose(eight_decimal_places_examples, rel_tol=1e-9)
1817
1818 def test_near_zero(self):
1819 # values close to zero
1820 near_zero_examples = [(1e-9, 0.0),
1821 (-1e-9, 0.0),
1822 (-1e-150, 0.0)]
1823 # these should not be close to any rel_tol
1824 self.assertAllNotClose(near_zero_examples, rel_tol=0.9)
1825 # these should be close to abs_tol=1e-8
1826 self.assertAllClose(near_zero_examples, abs_tol=1e-8)
1827
1828 def test_identical_infinite(self):
1829 # these are close regardless of tolerance -- i.e. they are equal
1830 self.assertIsClose(INF, INF)
1831 self.assertIsClose(INF, INF, abs_tol=0.0)
1832 self.assertIsClose(NINF, NINF)
1833 self.assertIsClose(NINF, NINF, abs_tol=0.0)
1834
1835 def test_inf_ninf_nan(self):
1836 # these should never be close (following IEEE 754 rules for equality)
1837 not_close_examples = [(NAN, NAN),
1838 (NAN, 1e-100),
1839 (1e-100, NAN),
1840 (INF, NAN),
1841 (NAN, INF),
1842 (INF, NINF),
1843 (INF, 1.0),
1844 (1.0, INF),
1845 (INF, 1e308),
1846 (1e308, INF)]
1847 # use largest reasonable tolerance
1848 self.assertAllNotClose(not_close_examples, abs_tol=0.999999999999999)
1849
1850 def test_zero_tolerance(self):
1851 # test with zero tolerance
1852 zero_tolerance_close_examples = [(1.0, 1.0),
1853 (-3.4, -3.4),
1854 (-1e-300, -1e-300)]
1855 self.assertAllClose(zero_tolerance_close_examples, rel_tol=0.0)
1856
1857 zero_tolerance_not_close_examples = [(1.0, 1.000000000000001),
1858 (0.99999999999999, 1.0),
1859 (1.0e200, .999999999999999e200)]
1860 self.assertAllNotClose(zero_tolerance_not_close_examples, rel_tol=0.0)
1861
Martin Pantereb995702016-07-28 01:11:04 +00001862 def test_asymmetry(self):
1863 # test the asymmetry example from PEP 485
Tal Einatd5519ed2015-05-31 22:05:00 +03001864 self.assertAllClose([(9, 10), (10, 9)], rel_tol=0.1)
1865
1866 def test_integers(self):
1867 # test with integer values
1868 integer_examples = [(100000001, 100000000),
1869 (123456789, 123456788)]
1870
1871 self.assertAllClose(integer_examples, rel_tol=1e-8)
1872 self.assertAllNotClose(integer_examples, rel_tol=1e-9)
1873
1874 def test_decimals(self):
1875 # test with Decimal values
1876 from decimal import Decimal
1877
1878 decimal_examples = [(Decimal('1.00000001'), Decimal('1.0')),
1879 (Decimal('1.00000001e-20'), Decimal('1.0e-20')),
Mark Dickinson31ba1c32016-09-04 12:29:14 +01001880 (Decimal('1.00000001e-100'), Decimal('1.0e-100')),
1881 (Decimal('1.00000001e20'), Decimal('1.0e20'))]
Tal Einatd5519ed2015-05-31 22:05:00 +03001882 self.assertAllClose(decimal_examples, rel_tol=1e-8)
1883 self.assertAllNotClose(decimal_examples, rel_tol=1e-9)
1884
1885 def test_fractions(self):
1886 # test with Fraction values
1887 from fractions import Fraction
1888
Mark Dickinson31ba1c32016-09-04 12:29:14 +01001889 fraction_examples = [
1890 (Fraction(1, 100000000) + 1, Fraction(1)),
1891 (Fraction(100000001), Fraction(100000000)),
1892 (Fraction(10**8 + 1, 10**28), Fraction(1, 10**20))]
Tal Einatd5519ed2015-05-31 22:05:00 +03001893 self.assertAllClose(fraction_examples, rel_tol=1e-8)
1894 self.assertAllNotClose(fraction_examples, rel_tol=1e-9)
1895
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001896 def testPerm(self):
1897 perm = math.perm
1898 factorial = math.factorial
Min ho Kim96e12d52019-07-22 06:12:33 +10001899 # Test if factorial definition is satisfied
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001900 for n in range(100):
1901 for k in range(n + 1):
1902 self.assertEqual(perm(n, k),
1903 factorial(n) // factorial(n - k))
1904
1905 # Test for Pascal's identity
1906 for n in range(1, 100):
1907 for k in range(1, n):
1908 self.assertEqual(perm(n, k), perm(n - 1, k - 1) * k + perm(n - 1, k))
1909
1910 # Test corner cases
1911 for n in range(1, 100):
1912 self.assertEqual(perm(n, 0), 1)
1913 self.assertEqual(perm(n, 1), n)
1914 self.assertEqual(perm(n, n), factorial(n))
1915
Raymond Hettingere119b3d2019-06-08 08:58:11 -07001916 # Test one argument form
1917 for n in range(20):
1918 self.assertEqual(perm(n), factorial(n))
1919 self.assertEqual(perm(n, None), factorial(n))
1920
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001921 # Raises TypeError if any argument is non-integer or argument count is
Raymond Hettingere119b3d2019-06-08 08:58:11 -07001922 # not 1 or 2
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001923 self.assertRaises(TypeError, perm, 10, 1.0)
1924 self.assertRaises(TypeError, perm, 10, decimal.Decimal(1.0))
1925 self.assertRaises(TypeError, perm, 10, "1")
1926 self.assertRaises(TypeError, perm, 10.0, 1)
1927 self.assertRaises(TypeError, perm, decimal.Decimal(10.0), 1)
1928 self.assertRaises(TypeError, perm, "10", 1)
1929
Raymond Hettingere119b3d2019-06-08 08:58:11 -07001930 self.assertRaises(TypeError, perm)
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001931 self.assertRaises(TypeError, perm, 10, 1, 3)
1932 self.assertRaises(TypeError, perm)
1933
1934 # Raises Value error if not k or n are negative numbers
1935 self.assertRaises(ValueError, perm, -1, 1)
1936 self.assertRaises(ValueError, perm, -2**1000, 1)
1937 self.assertRaises(ValueError, perm, 1, -1)
1938 self.assertRaises(ValueError, perm, 1, -2**1000)
1939
Raymond Hettinger963eb0f2019-06-04 01:23:06 -07001940 # Returns zero if k is greater than n
1941 self.assertEqual(perm(1, 2), 0)
1942 self.assertEqual(perm(1, 2**1000), 0)
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001943
1944 n = 2**1000
1945 self.assertEqual(perm(n, 0), 1)
1946 self.assertEqual(perm(n, 1), n)
1947 self.assertEqual(perm(n, 2), n * (n-1))
Serhiy Storchaka1b8a46d2019-06-17 16:58:32 +03001948 if support.check_impl_detail(cpython=True):
1949 self.assertRaises(OverflowError, perm, n, n)
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03001950
1951 for n, k in (True, True), (True, False), (False, False):
1952 self.assertEqual(perm(n, k), 1)
1953 self.assertIs(type(perm(n, k)), int)
1954 self.assertEqual(perm(IntSubclass(5), IntSubclass(2)), 20)
1955 self.assertEqual(perm(MyIndexable(5), MyIndexable(2)), 20)
1956 for k in range(3):
1957 self.assertIs(type(perm(IntSubclass(5), IntSubclass(k))), int)
1958 self.assertIs(type(perm(MyIndexable(5), MyIndexable(k))), int)
1959
Yash Aggarwal4a686502019-06-01 12:51:27 +05301960 def testComb(self):
1961 comb = math.comb
1962 factorial = math.factorial
Min ho Kim96e12d52019-07-22 06:12:33 +10001963 # Test if factorial definition is satisfied
Yash Aggarwal4a686502019-06-01 12:51:27 +05301964 for n in range(100):
1965 for k in range(n + 1):
1966 self.assertEqual(comb(n, k), factorial(n)
1967 // (factorial(k) * factorial(n - k)))
1968
1969 # Test for Pascal's identity
1970 for n in range(1, 100):
1971 for k in range(1, n):
1972 self.assertEqual(comb(n, k), comb(n - 1, k - 1) + comb(n - 1, k))
1973
1974 # Test corner cases
1975 for n in range(100):
1976 self.assertEqual(comb(n, 0), 1)
1977 self.assertEqual(comb(n, n), 1)
1978
1979 for n in range(1, 100):
1980 self.assertEqual(comb(n, 1), n)
1981 self.assertEqual(comb(n, n - 1), n)
1982
1983 # Test Symmetry
1984 for n in range(100):
1985 for k in range(n // 2):
1986 self.assertEqual(comb(n, k), comb(n, n - k))
1987
1988 # Raises TypeError if any argument is non-integer or argument count is
1989 # not 2
1990 self.assertRaises(TypeError, comb, 10, 1.0)
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03001991 self.assertRaises(TypeError, comb, 10, decimal.Decimal(1.0))
Yash Aggarwal4a686502019-06-01 12:51:27 +05301992 self.assertRaises(TypeError, comb, 10, "1")
Yash Aggarwal4a686502019-06-01 12:51:27 +05301993 self.assertRaises(TypeError, comb, 10.0, 1)
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03001994 self.assertRaises(TypeError, comb, decimal.Decimal(10.0), 1)
1995 self.assertRaises(TypeError, comb, "10", 1)
Yash Aggarwal4a686502019-06-01 12:51:27 +05301996
1997 self.assertRaises(TypeError, comb, 10)
1998 self.assertRaises(TypeError, comb, 10, 1, 3)
1999 self.assertRaises(TypeError, comb)
2000
2001 # Raises Value error if not k or n are negative numbers
2002 self.assertRaises(ValueError, comb, -1, 1)
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03002003 self.assertRaises(ValueError, comb, -2**1000, 1)
Yash Aggarwal4a686502019-06-01 12:51:27 +05302004 self.assertRaises(ValueError, comb, 1, -1)
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03002005 self.assertRaises(ValueError, comb, 1, -2**1000)
Yash Aggarwal4a686502019-06-01 12:51:27 +05302006
Raymond Hettinger963eb0f2019-06-04 01:23:06 -07002007 # Returns zero if k is greater than n
2008 self.assertEqual(comb(1, 2), 0)
2009 self.assertEqual(comb(1, 2**1000), 0)
Yash Aggarwal4a686502019-06-01 12:51:27 +05302010
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03002011 n = 2**1000
2012 self.assertEqual(comb(n, 0), 1)
2013 self.assertEqual(comb(n, 1), n)
2014 self.assertEqual(comb(n, 2), n * (n-1) // 2)
2015 self.assertEqual(comb(n, n), 1)
2016 self.assertEqual(comb(n, n-1), n)
2017 self.assertEqual(comb(n, n-2), n * (n-1) // 2)
Serhiy Storchaka1b8a46d2019-06-17 16:58:32 +03002018 if support.check_impl_detail(cpython=True):
2019 self.assertRaises(OverflowError, comb, n, n//2)
Yash Aggarwal4a686502019-06-01 12:51:27 +05302020
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03002021 for n, k in (True, True), (True, False), (False, False):
2022 self.assertEqual(comb(n, k), 1)
2023 self.assertIs(type(comb(n, k)), int)
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03002024 self.assertEqual(comb(IntSubclass(5), IntSubclass(2)), 10)
Serhiy Storchaka2b843ac2019-06-01 22:09:02 +03002025 self.assertEqual(comb(MyIndexable(5), MyIndexable(2)), 10)
Serhiy Storchaka5ae299a2019-06-02 11:16:49 +03002026 for k in range(3):
2027 self.assertIs(type(comb(IntSubclass(5), IntSubclass(k))), int)
2028 self.assertIs(type(comb(MyIndexable(5), MyIndexable(k))), int)
Yash Aggarwal4a686502019-06-01 12:51:27 +05302029
Pablo Galindo42079072019-02-10 19:56:58 +00002030
Thomas Wouters89f507f2006-12-13 04:49:30 +00002031def test_main():
Christian Heimes53876d92008-04-19 00:31:39 +00002032 from doctest import DocFileSuite
2033 suite = unittest.TestSuite()
2034 suite.addTest(unittest.makeSuite(MathTests))
Tal Einatd5519ed2015-05-31 22:05:00 +03002035 suite.addTest(unittest.makeSuite(IsCloseTests))
Christian Heimes53876d92008-04-19 00:31:39 +00002036 suite.addTest(DocFileSuite("ieee754.txt"))
2037 run_unittest(suite)
Thomas Wouters89f507f2006-12-13 04:49:30 +00002038
2039if __name__ == '__main__':
2040 test_main()