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