summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-05-12 21:19:51 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-05-12 21:19:51 (GMT)
commit48e47aaa28d6dfdae128142ffcbc4b0642422e90 (patch)
treef62918798a55edb3aa09e9c95ec92d965fc5283e /Lib
parentf0eeedf0d8ffff9d7ea8874e60992845595f091f (diff)
downloadcpython-48e47aaa28d6dfdae128142ffcbc4b0642422e90.zip
cpython-48e47aaa28d6dfdae128142ffcbc4b0642422e90.tar.gz
cpython-48e47aaa28d6dfdae128142ffcbc4b0642422e90.tar.bz2
Issue #22486: Added the math.gcd() function. The fractions.gcd() function now is
deprecated. Based on patch by Mark Dickinson.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/fractions.py21
-rw-r--r--Lib/test/test_fractions.py33
-rw-r--r--Lib/test/test_math.py51
3 files changed, 92 insertions, 13 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py
index 5ddc84c..60b0728 100644
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -20,6 +20,17 @@ def gcd(a, b):
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
"""
+ import warnings
+ warnings.warn('fractions.gcd() is deprecated. Use math.gcd() instead.',
+ DeprecationWarning, 2)
+ if type(a) is int is type(b):
+ if (b or a) < 0:
+ return -math.gcd(a, b)
+ return math.gcd(a, b)
+ return _gcd(a, b)
+
+def _gcd(a, b):
+ # Supports non-integers for backward compatibility.
while b:
a, b = b, a%b
return a
@@ -159,7 +170,7 @@ class Fraction(numbers.Rational):
"or a Rational instance")
elif type(numerator) is int is type(denominator):
- pass # *very* normal case
+ pass # *very* normal case
elif (isinstance(numerator, numbers.Rational) and
isinstance(denominator, numbers.Rational)):
@@ -174,7 +185,13 @@ class Fraction(numbers.Rational):
if denominator == 0:
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
if _normalize:
- g = gcd(numerator, denominator)
+ if type(numerator) is int is type(denominator):
+ # *very* normal case
+ g = math.gcd(numerator, denominator)
+ if denominator < 0:
+ g = -g
+ else:
+ g = _gcd(numerator, denominator)
numerator //= g
denominator //= g
self._numerator = numerator
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index 2dd528f..1699852 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -8,6 +8,7 @@ import operator
import fractions
import sys
import unittest
+import warnings
from copy import copy, deepcopy
from pickle import dumps, loads
F = fractions.Fraction
@@ -49,7 +50,7 @@ class DummyRational(object):
"""Test comparison of Fraction with a naive rational implementation."""
def __init__(self, num, den):
- g = gcd(num, den)
+ g = math.gcd(num, den)
self.num = num // g
self.den = den // g
@@ -83,16 +84,26 @@ class DummyFraction(fractions.Fraction):
class GcdTest(unittest.TestCase):
def testMisc(self):
- self.assertEqual(0, gcd(0, 0))
- self.assertEqual(1, gcd(1, 0))
- self.assertEqual(-1, gcd(-1, 0))
- self.assertEqual(1, gcd(0, 1))
- self.assertEqual(-1, gcd(0, -1))
- self.assertEqual(1, gcd(7, 1))
- self.assertEqual(-1, gcd(7, -1))
- self.assertEqual(1, gcd(-23, 15))
- self.assertEqual(12, gcd(120, 84))
- self.assertEqual(-12, gcd(84, -120))
+ # fractions.gcd() is deprecated
+ with self.assertWarnsRegex(DeprecationWarning, r'fractions\.gcd'):
+ gcd(1, 1)
+ with warnings.catch_warnings():
+ warnings.filterwarnings('ignore', r'fractions\.gcd',
+ DeprecationWarning)
+ self.assertEqual(0, gcd(0, 0))
+ self.assertEqual(1, gcd(1, 0))
+ self.assertEqual(-1, gcd(-1, 0))
+ self.assertEqual(1, gcd(0, 1))
+ self.assertEqual(-1, gcd(0, -1))
+ self.assertEqual(1, gcd(7, 1))
+ self.assertEqual(-1, gcd(7, -1))
+ self.assertEqual(1, gcd(-23, 15))
+ self.assertEqual(12, gcd(120, 84))
+ self.assertEqual(-12, gcd(84, -120))
+ self.assertEqual(gcd(120.0, 84), 12.0)
+ self.assertEqual(gcd(120, 84.0), 12.0)
+ self.assertEqual(gcd(F(120), F(84)), F(12))
+ self.assertEqual(gcd(F(120, 77), F(84, 55)), F(12, 385))
def _components(r):
diff --git a/Lib/test/test_math.py b/Lib/test/test_math.py
index 023dea9..fcd78d5 100644
--- a/Lib/test/test_math.py
+++ b/Lib/test/test_math.py
@@ -175,6 +175,14 @@ def parse_testfile(fname):
flags
)
+# Class providing an __index__ method.
+class MyIndexable(object):
+ def __init__(self, value):
+ self.value = value
+
+ def __index__(self):
+ return self.value
+
class MathTests(unittest.TestCase):
def ftest(self, name, value, expected):
@@ -595,6 +603,49 @@ class MathTests(unittest.TestCase):
s = msum(vals)
self.assertEqual(msum(vals), math.fsum(vals))
+ def testGcd(self):
+ gcd = math.gcd
+ self.assertEqual(gcd(0, 0), 0)
+ self.assertEqual(gcd(1, 0), 1)
+ self.assertEqual(gcd(-1, 0), 1)
+ self.assertEqual(gcd(0, 1), 1)
+ self.assertEqual(gcd(0, -1), 1)
+ self.assertEqual(gcd(7, 1), 1)
+ self.assertEqual(gcd(7, -1), 1)
+ self.assertEqual(gcd(-23, 15), 1)
+ self.assertEqual(gcd(120, 84), 12)
+ self.assertEqual(gcd(84, -120), 12)
+ self.assertEqual(gcd(1216342683557601535506311712,
+ 436522681849110124616458784), 32)
+ c = 652560
+ x = 434610456570399902378880679233098819019853229470286994367836600566
+ y = 1064502245825115327754847244914921553977
+ a = x * c
+ b = y * c
+ self.assertEqual(gcd(a, b), c)
+ self.assertEqual(gcd(b, a), c)
+ self.assertEqual(gcd(-a, b), c)
+ self.assertEqual(gcd(b, -a), c)
+ self.assertEqual(gcd(a, -b), c)
+ self.assertEqual(gcd(-b, a), c)
+ self.assertEqual(gcd(-a, -b), c)
+ self.assertEqual(gcd(-b, -a), c)
+ c = 576559230871654959816130551884856912003141446781646602790216406874
+ a = x * c
+ b = y * c
+ self.assertEqual(gcd(a, b), c)
+ self.assertEqual(gcd(b, a), c)
+ self.assertEqual(gcd(-a, b), c)
+ self.assertEqual(gcd(b, -a), c)
+ self.assertEqual(gcd(a, -b), c)
+ self.assertEqual(gcd(-b, a), c)
+ self.assertEqual(gcd(-a, -b), c)
+ self.assertEqual(gcd(-b, -a), c)
+
+ self.assertRaises(TypeError, gcd, 120.0, 84)
+ self.assertRaises(TypeError, gcd, 120, 84.0)
+ self.assertEqual(gcd(MyIndexable(120), MyIndexable(84)), 12)
+
def testHypot(self):
self.assertRaises(TypeError, math.hypot)
self.ftest('hypot(0,0)', math.hypot(0,0), 0)