Does numpy have a gcd function somewhere in its structure of modules?
I\'m aware of fractions.gcd but thought a numpy
You can write it yourself:
def numpy_gcd(a, b):
a, b = np.broadcast_arrays(a, b)
a = a.copy()
b = b.copy()
pos = np.nonzero(b)[0]
while len(pos) > 0:
b2 = b[pos]
a[pos], b[pos] = b2, a[pos] % b2
pos = pos[b[pos]!=0]
return a
Here is the code to test the result and speed:
In [181]:
n = 2000
a = np.random.randint(100, 1000, n)
b = np.random.randint(1, 100, n)
al = a.tolist()
bl = b.tolist()
cl = zip(al, bl)
from fractions import gcd
g1 = numpy_gcd(a, b)
g2 = [gcd(x, y) for x, y in cl]
print np.all(g1 == g2)
True
In [182]:
%timeit numpy_gcd(a, b)
1000 loops, best of 3: 721 us per loop
In [183]:
%timeit [gcd(x, y) for x, y in cl]
1000 loops, best of 3: 1.64 ms per loop
Public service announcement for anyone using Python 3.5
from math import gcd
gcd(2, 4)
And if you want to write it yourself in a one-liner:
def gcd(a: int, b: int): return gcd(b, a % b) if b else a
In case the desired result is not an element-wise gcd but rather the gcd of all numbers in the array, you may use the code below.
import numpy as np
from math import gcd as mathgcd
def numpy_set_gcd(a):
a = np.unique(a)
if not a.dtype == np.int or a[0] <= 0:
raise ValueError("Argument must be an array of positive " +
"integers.")
gcd = a[0]
for i in a[1:]:
gcd = mathgcd(i, gcd)
if gcd == 1:
return 1
return gcd
Depending on the use case, it can be faster to omit the sorting step a = np.unique(a).
An alternative (maybe more elegant but slower) implementation using ufuncs is
import numpy as np
from math import gcd as mathgcd
npmathgcd = np.frompyfunc(mathgcd, 2, 1)
def numpy_set_gcd2(a):
a = np.unique(a)
if not a.dtype == np.int or a[0] <= 0:
raise ValueError("Argument must be an array of positive " +
"integers.")
npmathgcd.at(a[1:], np.arange(a.size-1), a[:-1])
return a[-1]
The functions gcd (Greatest Common Divisor) and lcm (Lowest Common Multiple) have been added to numpy in version 1.15.
It seems there is no gcd function yet in numpy. However, there is a gcd function in fractions module. If you need to perform gcd on numpy arrays, you could build a ufunc using it:
gcd = numpy.frompyfunc(fractions.gcd, 2, 1)