summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_math.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-06-02 08:16:49 (GMT)
committerGitHub <noreply@github.com>2019-06-02 08:16:49 (GMT)
commit5ae299ac78abb628803ab7dee0997364547f5cc8 (patch)
tree243cb704ac7c8421e7406722912cc50e20b5ebad /Lib/test/test_math.py
parentd71f3170ac9c850f6d1f9bffaa628dc473df5e75 (diff)
downloadcpython-5ae299ac78abb628803ab7dee0997364547f5cc8.zip
cpython-5ae299ac78abb628803ab7dee0997364547f5cc8.tar.gz
cpython-5ae299ac78abb628803ab7dee0997364547f5cc8.tar.bz2
bpo-37128: Add math.perm(). (GH-13731)
Diffstat (limited to 'Lib/test/test_math.py')
-rw-r--r--Lib/test/test_math.py66
1 files changed, 65 insertions, 1 deletions
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py
index e27092e..96e0cf2 100644
--- a/Lib/test/test_math.py
+++ b/Lib/test/test_math.py
@@ -240,6 +240,9 @@ def result_check(expected, got, ulp_tol=5, abs_tol=0.0):
else:
return None
+class IntSubclass(int):
+ pass
+
# Class providing an __index__ method.
class MyIndexable(object):
def __init__(self, value):
@@ -1862,6 +1865,64 @@ class IsCloseTests(unittest.TestCase):
self.assertAllClose(fraction_examples, rel_tol=1e-8)
self.assertAllNotClose(fraction_examples, rel_tol=1e-9)
+ def testPerm(self):
+ perm = math.perm
+ factorial = math.factorial
+ # Test if factorial defintion is satisfied
+ for n in range(100):
+ for k in range(n + 1):
+ self.assertEqual(perm(n, k),
+ factorial(n) // factorial(n - k))
+
+ # Test for Pascal's identity
+ for n in range(1, 100):
+ for k in range(1, n):
+ self.assertEqual(perm(n, k), perm(n - 1, k - 1) * k + perm(n - 1, k))
+
+ # Test corner cases
+ for n in range(1, 100):
+ self.assertEqual(perm(n, 0), 1)
+ self.assertEqual(perm(n, 1), n)
+ self.assertEqual(perm(n, n), factorial(n))
+
+ # Raises TypeError if any argument is non-integer or argument count is
+ # not 2
+ self.assertRaises(TypeError, perm, 10, 1.0)
+ self.assertRaises(TypeError, perm, 10, decimal.Decimal(1.0))
+ self.assertRaises(TypeError, perm, 10, "1")
+ self.assertRaises(TypeError, perm, 10.0, 1)
+ self.assertRaises(TypeError, perm, decimal.Decimal(10.0), 1)
+ self.assertRaises(TypeError, perm, "10", 1)
+
+ self.assertRaises(TypeError, perm, 10)
+ self.assertRaises(TypeError, perm, 10, 1, 3)
+ self.assertRaises(TypeError, perm)
+
+ # Raises Value error if not k or n are negative numbers
+ self.assertRaises(ValueError, perm, -1, 1)
+ self.assertRaises(ValueError, perm, -2**1000, 1)
+ self.assertRaises(ValueError, perm, 1, -1)
+ self.assertRaises(ValueError, perm, 1, -2**1000)
+
+ # Raises value error if k is greater than n
+ self.assertRaises(ValueError, perm, 1, 2)
+ self.assertRaises(ValueError, perm, 1, 2**1000)
+
+ n = 2**1000
+ self.assertEqual(perm(n, 0), 1)
+ self.assertEqual(perm(n, 1), n)
+ self.assertEqual(perm(n, 2), n * (n-1))
+ self.assertRaises((OverflowError, MemoryError), perm, n, n)
+
+ for n, k in (True, True), (True, False), (False, False):
+ self.assertEqual(perm(n, k), 1)
+ self.assertIs(type(perm(n, k)), int)
+ self.assertEqual(perm(IntSubclass(5), IntSubclass(2)), 20)
+ self.assertEqual(perm(MyIndexable(5), MyIndexable(2)), 20)
+ for k in range(3):
+ self.assertIs(type(perm(IntSubclass(5), IntSubclass(k))), int)
+ self.assertIs(type(perm(MyIndexable(5), MyIndexable(k))), int)
+
def testComb(self):
comb = math.comb
factorial = math.factorial
@@ -1925,8 +1986,11 @@ class IsCloseTests(unittest.TestCase):
for n, k in (True, True), (True, False), (False, False):
self.assertEqual(comb(n, k), 1)
self.assertIs(type(comb(n, k)), int)
+ self.assertEqual(comb(IntSubclass(5), IntSubclass(2)), 10)
self.assertEqual(comb(MyIndexable(5), MyIndexable(2)), 10)
- self.assertIs(type(comb(MyIndexable(5), MyIndexable(2))), int)
+ for k in range(3):
+ self.assertIs(type(comb(IntSubclass(5), IntSubclass(k))), int)
+ self.assertIs(type(comb(MyIndexable(5), MyIndexable(k))), int)
def test_main():