diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2019-05-18 11:29:50 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-18 11:29:50 (GMT) |
commit | 73934b9da07daefb203e7d26089e7486a1ce4fdf (patch) | |
tree | 6d5f9d2f8bd86dbd219685a3e6124af44a158811 /Lib/test/test_math.py | |
parent | 410759fba80aded5247b693c60745aa16906f3bb (diff) | |
download | cpython-73934b9da07daefb203e7d26089e7486a1ce4fdf.zip cpython-73934b9da07daefb203e7d26089e7486a1ce4fdf.tar.gz cpython-73934b9da07daefb203e7d26089e7486a1ce4fdf.tar.bz2 |
bpo-36887: add math.isqrt (GH-13244)
* Add math.isqrt function computing the integer square root.
* Code cleanup: remove redundant comments, rename some variables.
* Tighten up code a bit more; use Py_XDECREF to simplify error handling.
* Update Modules/mathmodule.c
Co-Authored-By: Serhiy Storchaka <storchaka@gmail.com>
* Update Modules/mathmodule.c
Use real argument clinic type instead of an alias
Co-Authored-By: Serhiy Storchaka <storchaka@gmail.com>
* Add proof sketch
* Updates from review.
* Correct and expand documentation.
* Fix bad reference handling on error; make some variables block-local; other tidying.
* Style and consistency fixes.
* Add missing error check; don't try to DECREF a NULL a
* Simplify some error returns.
* Another two test cases:
- clarify that floats are rejected even if they happen to be
squares of small integers
- TypeError beats ValueError for a negative float
* Documentation and markup improvements; thanks Serhiy for the suggestions!
* Cleaner Misc/NEWS entry wording.
* Clean up (with one fix) to the algorithm explanation and proof.
Diffstat (limited to 'Lib/test/test_math.py')
-rw-r--r-- | Lib/test/test_math.py | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py index cb05dee..a11a344 100644 --- a/Lib/test/test_math.py +++ b/Lib/test/test_math.py @@ -912,6 +912,57 @@ class MathTests(unittest.TestCase): self.assertEqual(math.dist(p, q), 5*scale) self.assertEqual(math.dist(q, p), 5*scale) + def testIsqrt(self): + # Test a variety of inputs, large and small. + test_values = ( + list(range(1000)) + + list(range(10**6 - 1000, 10**6 + 1000)) + + [3**9999, 10**5001] + ) + + for value in test_values: + with self.subTest(value=value): + s = math.isqrt(value) + self.assertIs(type(s), int) + self.assertLessEqual(s*s, value) + self.assertLess(value, (s+1)*(s+1)) + + # Negative values + with self.assertRaises(ValueError): + math.isqrt(-1) + + # Integer-like things + s = math.isqrt(True) + self.assertIs(type(s), int) + self.assertEqual(s, 1) + + s = math.isqrt(False) + self.assertIs(type(s), int) + self.assertEqual(s, 0) + + class IntegerLike(object): + def __init__(self, value): + self.value = value + + def __index__(self): + return self.value + + s = math.isqrt(IntegerLike(1729)) + self.assertIs(type(s), int) + self.assertEqual(s, 41) + + with self.assertRaises(ValueError): + math.isqrt(IntegerLike(-3)) + + # Non-integer-like things + bad_values = [ + 3.5, "a string", decimal.Decimal("3.5"), 3.5j, + 100.0, -4.0, + ] + for value in bad_values: + with self.subTest(value=value): + with self.assertRaises(TypeError): + math.isqrt(value) def testLdexp(self): self.assertRaises(TypeError, math.ldexp) |