galois¶
A performant numpy extension for Galois fields.
Class Factory Functions
|
Factory function to construct Galois field array classes of type \(\mathrm{GF}(p^m)\). |
Classes
|
Create an array over \(\mathrm{GF}(2)\). |
|
Create an array over \(\mathrm{GF}(p^m)\). |
|
Create a polynomial \(p(x)\) over \(\mathrm{GF}(q)\). |
Functions
|
Finds the smallest positive integer \(m\) such that \(a^m \equiv 1 (\textrm{mod}\ n)\) for every integer \(a\) in \(1 \le a < n\) that is coprime to \(n\). |
Solves the simultaneous system of congruences for \(x\). |
|
|
Returns the degree-\(n\) Conway polynomial \(C_{p,n}\) over \(\mathrm{GF}(p)\). |
Counts the positive integers (totatives) in \(1 \le k < n\) that are relatively prime to \(n\), i.e. \(gcd(n, k) = 1\). |
|
|
Returns the positive factors of the integer \(n\). |
Probabilistic primality test of \(n\). |
|
|
Finds the integer multiplicands of \(a\) and \(b\) such that \(a x + b y = gcd(a, b)\). |
|
Determines whether the multiplicative group \(\mathbb{Z}{_n^\times}\) is cyclic. |
|
Checks whether the polynomial \(f(x)\) over \(\mathrm{GF}(p)\) is irreducible. |
|
Determines if \(n\) is prime. |
|
Determines if \(g\) is a primitive root modulo \(n\). |
|
Computes the integer square root of \(n\) such that \(\textrm{isqrt}(n)^2 \le n\). |
|
Returns the \(k\)-th prime. |
|
Returns all known Mersenne exponents \(e\) for \(e \le n\). |
|
Returns all known Mersenne primes \(p\) for \(p \le 2^n - 1\). |
|
Probabilistic primality test of \(n\). |
|
Returns the nearest prime \(p\), such that \(p > x\). |
|
Efficiently exponentiates a polynomial \(f(x)\) to the power \(k\) reducing by modulo \(g(x)\), \(f^k\ \textrm{mod}\ g\). |
|
Finds the greatest common divisor of two polynomials \(a(x)\) and \(b(x)\) over \(\mathrm{GF}(q)\). |
|
Returns the nearest prime \(p\), such that \(p \le x\). |
Computes the prime factors of the positive integer \(x\). |
|
|
Returns the primes \(p \le n\). |
|
Finds the smallest primitive root modulo \(n\). |
|
A generator that finds all primitive roots modulo \(n\). |
|
Returns the positive integers (totatives) in \(1 \le k < n\) that are relatively prime to \(n\), i.e. \(gcd(n, k) = 1\). |
-
class
galois.
GF2
(array, dtype=None, copy=True, order='K', ndmin=0)[source]¶ Bases:
galois.gf.GFArray
Create an array over \(\mathrm{GF}(2)\).
Note
This Galois field class is a pre-made subclass of
galois.GFArray
. It is included in the package because of the ubiquity of \(\mathrm{GF}(2)\) fields.# The pre-made GF(2) class In [1]: print(galois.GF2) <class 'numpy.ndarray' over GF(2)> # The GF class factory for an order of 2 returns `galois.GF2` In [2]: GF2 = galois.GF(2); print(GF2) <class 'numpy.ndarray' over GF(2)> In [3]: GF2 is galois.GF2 Out[3]: True
- Parameters
array (array_like) – The input array to be converted to a Galois field array. The input array is copied, so the original array is unmodified by changes to the Galois field array. Valid input array types are
numpy.ndarray
,list
,tuple
, orint
.dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isnumpy.int64
.
- Returns
The copied input array as a \(\mathrm{GF}(2)\) field array.
- Return type
Examples
Various Galois field properties are accessible as class attributes.
In [4]: print(galois.GF2) <class 'numpy.ndarray' over GF(2)> In [5]: galois.GF2.characteristic Out[5]: 2 In [6]: galois.GF2.degree Out[6]: 1 In [7]: galois.GF2.order Out[7]: 2 In [8]: galois.GF2.prim_poly Out[8]: Poly(x + 1, GF(2))
Construct arrays over \(\mathrm{GF}(2)\).
In [9]: a = galois.GF2([1,0,1,1]); a Out[9]: GF([1, 0, 1, 1], order=2) In [10]: b = galois.GF2([1,1,1,1]); b Out[10]: GF([1, 1, 1, 1], order=2)
Perform array arithmetic over \(\mathrm{GF}(2)\).
# Element-wise addition In [11]: a + b Out[11]: GF([0, 1, 0, 0], order=2) # Element-wise subtraction In [12]: a - b Out[12]: GF([0, 1, 0, 0], order=2) # Element-wise multiplication In [13]: a * b Out[13]: GF([1, 0, 1, 1], order=2) # Element-wise division In [14]: a / b Out[14]: GF([1, 0, 1, 1], order=2)
-
classmethod
Elements
(dtype=None)¶ Create a Galois field array of the field’s elements \(\{0, \dots, p^m-1\}\).
- Parameters
dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.- Returns
A Galois field array of all the field’s elements.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Elements() Out[2]: GF([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], order=31)
-
classmethod
Ones
(shape, dtype=None)¶ Create a Galois field array with all ones.
- Parameters
shape (tuple) – A numpy-compliant
shape
tuple, seenumpy.ndarray.shape
. An empty tuple()
represents a scalar. A single integer or 1-tuple, e.g.N
or(N,)
, represents the size of a 1-dim array. An n-tuple, e.g.(M,N)
, represents an n-dim array with each element indicating the size in each dimension.dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of ones.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Ones((2,5)) Out[2]: GF([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1]], order=31)
-
classmethod
Random
(shape=(), low=0, high=None, dtype=None)¶ Create a Galois field array with random field elements.
- Parameters
shape (tuple) – A numpy-compliant
shape
tuple, seenumpy.ndarray.shape
. An empty tuple()
represents a scalar. A single integer or 1-tuple, e.g.N
or(N,)
, represents the size of a 1-dim array. An n-tuple, e.g.(M,N)
, represents an n-dim array with each element indicating the size in each dimension.low (int, optional) – The lowest value (inclusive) of a random field element. The default is 0.
high (int, optional) – The highest value (exclusive) of a random field element. The default is
None
which represents the field’s order \(p^m\).dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of random field elements.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Random((2,5)) Out[2]: GF([[15, 7, 21, 21, 24], [19, 25, 15, 30, 28]], order=31)
-
classmethod
Range
(start, stop, step=1, dtype=None)¶ Create a Galois field array with a range of field elements.
- Parameters
start (int) – The starting value (inclusive).
stop (int) – The stopping value (exclusive).
step (int, optional) – The space between values. The default is 1.
dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of a range of field elements.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Range(10,20) Out[2]: GF([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], order=31)
-
classmethod
Zeros
(shape, dtype=None)¶ Create a Galois field array with all zeros.
- Parameters
shape (tuple) – A numpy-compliant
shape
tuple, seenumpy.ndarray.shape
. An empty tuple()
represents a scalar. A single integer or 1-tuple, e.g.N
or(N,)
, represents the size of a 1-dim array. An n-tuple, e.g.(M,N)
, represents an n-dim array with each element indicating the size in each dimension.dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of zeros.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Zeros((2,5)) Out[2]: GF([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], order=31)
-
classmethod
display
(mode='int', poly_var='x')¶ Sets the printing mode for arrays.
- Parameters
Examples
Change the display mode by calling the
galois.GFArray.display
method.In [1]: GF = galois.GF(2**3) In [2]: a = GF.Random(4); a Out[2]: GF([5, 2, 5, 6], order=2^3) In [3]: GF.display("poly"); a Out[3]: GF([x^2 + 1, x, x^2 + 1, x^2 + x], order=2^3) In [4]: GF.display("poly", "r"); a Out[4]: GF([r^2 + 1, r, r^2 + 1, r^2 + r], order=2^3) # Reset the print mode In [5]: GF.display(); a Out[5]: GF([5, 2, 5, 6], order=2^3)
The
galois.GFArray.display
method can also be used as a context manager.# The original display mode In [6]: print(a) GF([5, 2, 5, 6], order=2^3) # The new display context In [7]: with GF.display("poly"): ...: print(a) ...: GF([x^2 + 1, x, x^2 + 1, x^2 + x], order=2^3) # Returns to the original display mode In [8]: print(a) GF([5, 2, 5, 6], order=2^3)
-
classmethod
target
(target)[source]¶ Retarget the just-in-time compiled
numba
ufuncs.- Parameters
target (str) – The
target
keyword argument fromnumba.vectorize
, either"cpu"
,"parallel"
, or"cuda"
.
-
alpha
= GF(1, order=2)¶ The primitive element \(\alpha\) of the Galois field \(\mathrm{GF}(p^m)\). The primitive element is a root of the primitive polynomial \(p(x)\), such that \(p(\alpha) = 0\). The primitive element is also a multiplicative generator of the field, such that \(\mathrm{GF}(p^m) = \{0, 1, \alpha^1, \alpha^2, \dots, \alpha^{p^m - 2}\}\).
- Type
-
characteristic
= 2¶ The prime characteristic \(p\) of the Galois field \(\mathrm{GF}(p^m)\). Adding \(p\) copies of any element will always result in \(0\).
- Type
-
degree
= 1¶ The prime characteristic’s degree \(m\) of the Galois field \(\mathrm{GF}(p^m)\). The degree is a positive integer.
- Type
-
dtypes
= [<class 'numpy.uint8'>, <class 'numpy.uint16'>, <class 'numpy.uint32'>, <class 'numpy.int8'>, <class 'numpy.int16'>, <class 'numpy.int32'>, <class 'numpy.int64'>]¶ List of valid integer
numpy.dtype
objects that are compatible with this Galois field. Valid data types are signed and unsinged integers that can represent decimal values in \([0, p^m)\).- Type
-
order
= 2¶ The order \(p^m\) of the Galois field \(\mathrm{GF}(p^m)\). The order of the field is also equal to the field’s size.
- Type
-
prim_poly
= Poly(x + 1, GF(2))¶ The primitive polynomial \(p(x)\) of the Galois field \(\mathrm{GF}(p^m)\). The primitive polynomial is of degree \(m\) in \(\mathrm{GF}(p)[x]\).
- Type
-
ufunc_mode
= 'calculate'¶ The mode for ufunc compilation, either
"lookup"
,"calculate"
,"object"
.- Type
-
class
galois.
GFArray
(array, dtype=None, copy=True, order='K', ndmin=0)[source]¶ Bases:
numpy.ndarray
Create an array over \(\mathrm{GF}(p^m)\).
The
galois.GFArray
class is a parent class for all Galois field array classes. Any Galois field \(\mathrm{GF}(p^m)\) with prime characteristic \(p\) and positive integer \(m\), can be constructed by calling the class factorygalois.GF(p**m)
.Warning
This is an abstract base class for all Galois field array classes.
galois.GFArray
cannot be instantiated directly. Instead, Galois field array classes are created usinggalois.GF
.For example, one can create the \(\mathrm{GF}(7)\) field array class as follows:
In [1]: GF7 = galois.GF(7) In [2]: print(GF7) <class 'numpy.ndarray' over GF(7)>
This subclass can then be used to instantiate arrays over \(\mathrm{GF}(7)\).
In [3]: GF7([3,5,0,2,1]) Out[3]: GF([3, 5, 0, 2, 1], order=7) In [4]: GF7.Random((2,5)) Out[4]: GF([[5, 5, 0, 0, 5], [3, 1, 6, 5, 3]], order=7)
galois.GFArray
is a subclass ofnumpy.ndarray
. Thegalois.GFArray
constructor has the same syntax asnumpy.array
. The returnedgalois.GFArray
object is an array that can be acted upon like any other numpy array.- Parameters
array (array_like) – The input array to be converted to a Galois field array. The input array is copied, so the original array is unmodified by changes to the Galois field array. Valid input array types are
numpy.ndarray
,list
,tuple
, orint
.dtype (numpy.dtype, optional) – The
copy
keyword argument fromnumpy.array
. Settingdtype
will explicitly set the data type of each element. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.copy (bool, optional) – The
copy
keyword argument fromnumpy.array
. The default isTrue
which makes a copy of the input object is it’s an array.order (str, optional) – The
order
keyword argument fromnumpy.array
. Valid values are"K"
(default),"A"
,"C"
, or"F"
.ndmin (int, optional) – The
ndmin
keyword argument fromnumpy.array
. The minimum number of dimensions of the output. The default is 0.
- Returns
The copied input array as a \(\mathrm{GF}(p^m)\) field array.
- Return type
Examples
Construct various kinds of Galois fields using
galois.GF
.# Construct a GF(2^m) class In [5]: GF256 = galois.GF(2**8); print(GF256) <class 'numpy.ndarray' over GF(2^8)> # Construct a GF(p) class In [6]: GF571 = galois.GF(571); print(GF571) <class 'numpy.ndarray' over GF(571)> # Construct a very large GF(2^m) class In [7]: GF2m = galois.GF(2**100); print(GF2m) <class 'numpy.ndarray' over GF(2^100)> # Construct a very large GF(p) class In [8]: GFp = galois.GF(36893488147419103183); print(GFp) <class 'numpy.ndarray' over GF(36893488147419103183)>
Depending on the field’s order (size), only certain
dtype
values will be supported.In [9]: GF256.dtypes Out[9]: [numpy.uint8, numpy.uint16, numpy.uint32, numpy.int16, numpy.int32, numpy.int64] In [10]: GF571.dtypes Out[10]: [numpy.uint16, numpy.uint32, numpy.int16, numpy.int32, numpy.int64]
Very large fields, which can’t be represented using
np.int64
, can only be represented asdtype=np.object_
.In [11]: GF2m.dtypes Out[11]: [numpy.object_] In [12]: GFp.dtypes Out[12]: [numpy.object_]
Newly-created arrays will use the smallest, valid dtype.
In [13]: a = GF256.Random(10); a Out[13]: GF([ 48, 213, 4, 235, 134, 135, 74, 177, 116, 174], order=2^8) In [14]: a.dtype Out[14]: dtype('uint8')
This can be explicitly set by specifying the
dtype
keyword argument.In [15]: a = GF256.Random(10, dtype=np.uint32); a Out[15]: GF([252, 29, 95, 30, 115, 10, 23, 153, 186, 196], order=2^8) In [16]: a.dtype Out[16]: dtype('uint32')
Arrays can also be created explicitly by converting an “array-like” object.
# Construct a Galois field array from a list In [17]: l = [142, 27, 92, 253, 103]; l Out[17]: [142, 27, 92, 253, 103] In [18]: GF256(l) Out[18]: GF([142, 27, 92, 253, 103], order=2^8) # Construct a Galois field array from an existing numpy array In [19]: x_np = np.array(l, dtype=np.int64); x_np Out[19]: array([142, 27, 92, 253, 103]) In [20]: GF256(l) Out[20]: GF([142, 27, 92, 253, 103], order=2^8)
Arrays can also be created by “view casting” from an existing numpy array. This avoids a copy operation, which is especially useful for large data already brought into memory.
In [21]: a = x_np.view(GF256); a Out[21]: GF([142, 27, 92, 253, 103], order=2^8) # Changing `x_np` will change `a` In [22]: x_np[0] = 0; x_np Out[22]: array([ 0, 27, 92, 253, 103]) In [23]: a Out[23]: GF([ 0, 27, 92, 253, 103], order=2^8)
-
classmethod
Elements
(dtype=None)[source]¶ Create a Galois field array of the field’s elements \(\{0, \dots, p^m-1\}\).
- Parameters
dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.- Returns
A Galois field array of all the field’s elements.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Elements() Out[2]: GF([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], order=31)
-
classmethod
Ones
(shape, dtype=None)[source]¶ Create a Galois field array with all ones.
- Parameters
shape (tuple) – A numpy-compliant
shape
tuple, seenumpy.ndarray.shape
. An empty tuple()
represents a scalar. A single integer or 1-tuple, e.g.N
or(N,)
, represents the size of a 1-dim array. An n-tuple, e.g.(M,N)
, represents an n-dim array with each element indicating the size in each dimension.dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of ones.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Ones((2,5)) Out[2]: GF([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1]], order=31)
-
classmethod
Random
(shape=(), low=0, high=None, dtype=None)[source]¶ Create a Galois field array with random field elements.
- Parameters
shape (tuple) – A numpy-compliant
shape
tuple, seenumpy.ndarray.shape
. An empty tuple()
represents a scalar. A single integer or 1-tuple, e.g.N
or(N,)
, represents the size of a 1-dim array. An n-tuple, e.g.(M,N)
, represents an n-dim array with each element indicating the size in each dimension.low (int, optional) – The lowest value (inclusive) of a random field element. The default is 0.
high (int, optional) – The highest value (exclusive) of a random field element. The default is
None
which represents the field’s order \(p^m\).dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of random field elements.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Random((2,5)) Out[2]: GF([[14, 20, 13, 15, 20], [20, 24, 29, 3, 15]], order=31)
-
classmethod
Range
(start, stop, step=1, dtype=None)[source]¶ Create a Galois field array with a range of field elements.
- Parameters
start (int) – The starting value (inclusive).
stop (int) – The stopping value (exclusive).
step (int, optional) – The space between values. The default is 1.
dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of a range of field elements.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Range(10,20) Out[2]: GF([10, 11, 12, 13, 14, 15, 16, 17, 18, 19], order=31)
-
classmethod
Zeros
(shape, dtype=None)[source]¶ Create a Galois field array with all zeros.
- Parameters
shape (tuple) – A numpy-compliant
shape
tuple, seenumpy.ndarray.shape
. An empty tuple()
represents a scalar. A single integer or 1-tuple, e.g.N
or(N,)
, represents the size of a 1-dim array. An n-tuple, e.g.(M,N)
, represents an n-dim array with each element indicating the size in each dimension.dtype (numpy.dtype, optional) – The
numpy.dtype
of the array elements. The default isNone
which represents the smallest valid dtype for this field class, i.e.cls.dtypes[0]
.
- Returns
A Galois field array of zeros.
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: GF.Zeros((2,5)) Out[2]: GF([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], order=31)
-
classmethod
display
(mode='int', poly_var='x')[source]¶ Sets the printing mode for arrays.
- Parameters
Examples
Change the display mode by calling the
galois.GFArray.display
method.In [1]: GF = galois.GF(2**3) In [2]: a = GF.Random(4); a Out[2]: GF([0, 5, 2, 7], order=2^3) In [3]: GF.display("poly"); a Out[3]: GF([0, x^2 + 1, x, x^2 + x + 1], order=2^3) In [4]: GF.display("poly", "r"); a Out[4]: GF([0, r^2 + 1, r, r^2 + r + 1], order=2^3) # Reset the print mode In [5]: GF.display(); a Out[5]: GF([0, 5, 2, 7], order=2^3)
The
galois.GFArray.display
method can also be used as a context manager.# The original display mode In [6]: print(a) GF([0, 5, 2, 7], order=2^3) # The new display context In [7]: with GF.display("poly"): ...: print(a) ...: GF([0, x^2 + 1, x, x^2 + x + 1], order=2^3) # Returns to the original display mode In [8]: print(a) GF([0, 5, 2, 7], order=2^3)
-
classmethod
target
(target, mode, rebuild=False)[source]¶ Retarget the just-in-time compiled numba ufuncs.
-
alpha
= None¶ The primitive element \(\alpha\) of the Galois field \(\mathrm{GF}(p^m)\). The primitive element is a root of the primitive polynomial \(p(x)\), such that \(p(\alpha) = 0\). The primitive element is also a multiplicative generator of the field, such that \(\mathrm{GF}(p^m) = \{0, 1, \alpha^1, \alpha^2, \dots, \alpha^{p^m - 2}\}\).
- Type
-
characteristic
= None¶ The prime characteristic \(p\) of the Galois field \(\mathrm{GF}(p^m)\). Adding \(p\) copies of any element will always result in \(0\).
- Type
-
degree
= None¶ The prime characteristic’s degree \(m\) of the Galois field \(\mathrm{GF}(p^m)\). The degree is a positive integer.
- Type
-
dtypes
= []¶ List of valid integer
numpy.dtype
objects that are compatible with this Galois field. Valid data types are signed and unsinged integers that can represent decimal values in \([0, p^m)\).- Type
-
order
= None¶ The order \(p^m\) of the Galois field \(\mathrm{GF}(p^m)\). The order of the field is also equal to the field’s size.
- Type
-
prim_poly
= None¶ The primitive polynomial \(p(x)\) of the Galois field \(\mathrm{GF}(p^m)\). The primitive polynomial is of degree \(m\) in \(\mathrm{GF}(p)[x]\).
- Type
-
class
galois.
Poly
(coeffs, field=None, order='desc')[source]¶ Bases:
object
Create a polynomial \(p(x)\) over \(\mathrm{GF}(q)\).
The polynomial \(p(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0\) has coefficients \(\{a_{d}, a_{d-1}, \dots, a_1, a_0\}\) in \(\mathrm{GF}(q)\).
- Parameters
coeffs (array_like) – List of polynomial coefficients \(\{a_{d}, a_{d-1}, \dots, a_1, a_0\}\) with type
galois.GFArray
,numpy.ndarray
,list
, ortuple
. The first element is the highest-degree element iforder="desc"
or the first element is the 0-th degree element iforder="asc"
.field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
None
which representsgalois.GF2
. Ifcoeffs
is a Galois field array, then that field is used and thefield
argument is ignored.order (str, optional) – The interpretation of the coefficient degrees, either
"desc"
(default) or"asc"
. For"desc"
, the first element ofcoeffs
is the highest degree coefficient \(x^{d}\)) and the last element is the 0-th degree element \(x^0\).
- Returns
The polynomial \(p(x)\).
- Return type
Examples
Create a polynomial over \(\mathrm{GF}(2)\).
In [1]: galois.Poly([1,0,1,1]) Out[1]: Poly(x^3 + x + 1, GF(2)) In [2]: galois.Poly.Degrees([3,1,0]) Out[2]: Poly(x^3 + x + 1, GF(2))
Create a polynomial over \(\mathrm{GF}(2^8)\).
In [3]: GF = galois.GF(2**8) In [4]: galois.Poly([124,0,223,0,0,15], field=GF) Out[4]: Poly(124x^5 + 223x^3 + 15, GF(2^8)) # Alternate way of constructing the same polynomial In [5]: galois.Poly.Degrees([5,3,0], coeffs=[124,223,15], field=GF) Out[5]: Poly(124x^5 + 223x^3 + 15, GF(2^8))
Polynomial arithmetic using binary operators.
In [6]: a = galois.Poly([117,0,63,37], field=GF); a Out[6]: Poly(117x^3 + 63x + 37, GF(2^8)) In [7]: b = galois.Poly([224,0,21], field=GF); b Out[7]: Poly(224x^2 + 21, GF(2^8)) In [8]: a + b Out[8]: Poly(117x^3 + 224x^2 + 63x + 48, GF(2^8)) In [9]: a - b Out[9]: Poly(117x^3 + 224x^2 + 63x + 48, GF(2^8)) # Compute the quotient of the polynomial division In [10]: a / b Out[10]: Poly(202x, GF(2^8)) # True division and floor division are equivalent In [11]: a / b == a // b Out[11]: True # Compute the remainder of the polynomial division In [12]: a % b Out[12]: Poly(198x + 37, GF(2^8)) # Compute both the quotient and remainder in one pass In [13]: divmod(a, b) Out[13]: (Poly(202x, GF(2^8)), Poly(198x + 37, GF(2^8)))
-
classmethod
Coeffs
(coeffs, field=None, order='desc')[source]¶ Constructs a polynomial over \(\mathrm{GF}(q)\) from its coefficients.
Alias of
galois.Poly
constructor.- Parameters
coeffs (array_like) – List of polynomial coefficients \(\{a_{d}, a_{d-1}, \dots, a_1, a_0\}\) with type
galois.GFArray
,numpy.ndarray
,list
, ortuple
. The first element is the highest-degree element iforder="desc"
or the first element is the 0-th degree element iforder="asc"
.field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
None
which representsgalois.GF2
. Ifcoeffs
is a Galois field array, then that field is used and thefield
argument is ignored.order (str, optional) – The interpretation of the coefficient degrees, either
"desc"
(default) or"asc"
. For"desc"
, the first element ofcoeffs
is the highest degree coefficient \(x^{d}\)) and the last element is the 0-th degree element \(x^0\).
- Returns
The polynomial \(p(x)\).
- Return type
-
classmethod
Degrees
(degrees, coeffs=None, field=None)[source]¶ Constructs a polynomial over \(\mathrm{GF}(q)\) from its non-zero degrees.
- Parameters
degrees (list) – List of polynomial degrees with non-zero coefficients.
coeffs (array_like, optional) – List of corresponding non-zero coefficients. The default is
None
which corresponds to all one coefficients, i.e.[1,]*len(degrees)
.field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is`None` which represents
galois.GF2
.
- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct a polynomial over \(\mathrm{GF}(2)\) by specifying the degrees with non-zero coefficients.
In [1]: galois.Poly.Degrees([3,1,0]) Out[1]: Poly(x^3 + x + 1, GF(2))
Construct a polynomial over \(\mathrm{GF}(2^8)\) by specifying the degrees with non-zero coefficients.
In [2]: GF = galois.GF(2**8) In [3]: galois.Poly.Degrees([3,1,0], coeffs=[251,73,185], field=GF) Out[3]: Poly(251x^3 + 73x + 185, GF(2^8))
-
classmethod
Identity
(field=<class 'galois.gf2.GF2'>)[source]¶ Constructs the identity polynomial \(p(x) = x\) over \(\mathrm{GF}(q)\).
- Parameters
field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
galois.GF2
.- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct the identity polynomial over \(\mathrm{GF}(2)\).
In [1]: galois.Poly.Identity() Out[1]: Poly(x, GF(2))
Construct the identity polynomial over \(\mathrm{GF}(2^8)\).
In [2]: GF = galois.GF(2**8) In [3]: galois.Poly.Identity(field=GF) Out[3]: Poly(x, GF(2^8))
-
classmethod
Integer
(integer, field=<class 'galois.gf2.GF2'>)[source]¶ Constructs a polynomial over \(\mathrm{GF}(q)\) from its integer representation.
The integer value \(i\) represents the polynomial \(p(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0\) over field \(\mathrm{GF}(q)\) if \(i = a_{d}q^{d} + a_{d-1}q^{d-1} + \dots + a_1q + a_0\) using integer arithmetic, not finite field arithmetic.
- Parameters
integer (int) – The integer representation of the polynomial \(p(x)\).
field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
galois.GF2
.
- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct a polynomial over \(\mathrm{GF}(2)\) from its integer representation.
In [1]: galois.Poly.Integer(5) Out[1]: Poly(x^2 + 1, GF(2))
Construct a polynomial over \(\mathrm{GF}(2^8)\) from its integer representation.
In [2]: GF = galois.GF(2**8) In [3]: galois.Poly.Integer(13*256**3 + 117, field=GF) Out[3]: Poly(13x^3 + 117, GF(2^8))
-
classmethod
One
(field=<class 'galois.gf2.GF2'>)[source]¶ Constructs the one polynomial \(p(x) = 1\) over \(\mathrm{GF}(q)\).
- Parameters
field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
galois.GF2
.- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct the one polynomial over \(\mathrm{GF}(2)\).
In [1]: galois.Poly.One() Out[1]: Poly(1, GF(2))
Construct the one polynomial over \(\mathrm{GF}(2^8)\).
In [2]: GF = galois.GF(2**8) In [3]: galois.Poly.One(field=GF) Out[3]: Poly(1, GF(2^8))
-
classmethod
Random
(degree, field=<class 'galois.gf2.GF2'>)[source]¶ Constructs a random polynomial over \(\mathrm{GF}(q)\) with degree \(d\).
- Parameters
degree (int) – The degree of the polynomial.
field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
galois.GF2
.
- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct a random degree-\(5\) polynomial over \(\mathrm{GF}(2)\).
In [1]: galois.Poly.Random(5) Out[1]: Poly(x^5 + x^2 + 1, GF(2))
Construct a random degree-\(5\) polynomial over \(\mathrm{GF}(2^8)\).
In [2]: GF = galois.GF(2**8) In [3]: galois.Poly.Random(5, field=GF) Out[3]: Poly(77x^5 + 180x^4 + 239x^3 + 176x^2 + 166x + 94, GF(2^8))
-
classmethod
Roots
(roots, multiplicities=None, field=None)[source]¶ Constructs a monic polynomial in \(\mathrm{GF}(q)[x]\) from its roots.
The polynomial \(p(x)\) with \(d\) roots \(\{r_0, r_1, \dots, r_{d-1}\}\) is:
\[ \begin{align}\begin{aligned}p(x) &= (x - r_0) (x - r_1) \dots (x - r_{d-1})\\p(x) &= a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0\end{aligned}\end{align} \]- Parameters
roots (array_like) – List of roots in \(\mathrm{GF}(q)\) of the desired polynomial.
multiplicities (array_like, optional) – List of multiplicity of each root. The default is
None
which corresponds to all ones.field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is`None` which represents
galois.GF2
.
- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct a polynomial over \(\mathrm{GF}(2)\) from a list of its roots.
In [1]: roots = [0, 0, 1] In [2]: p = galois.Poly.Roots(roots); p Out[2]: Poly(x^3 + x^2, GF(2)) In [3]: p(roots) Out[3]: GF([0, 0, 0], order=2)
Construct a polynomial over \(\mathrm{GF}(2^8)\) from a list of its roots.
In [4]: GF = galois.GF(2**8) In [5]: roots = [121, 198, 225] In [6]: p = galois.Poly.Roots(roots, field=GF); p Out[6]: Poly(x^3 + 94x^2 + 174x + 89, GF(2^8)) In [7]: p(roots) Out[7]: GF([0, 0, 0], order=2^8)
-
classmethod
Zero
(field=<class 'galois.gf2.GF2'>)[source]¶ Constructs the zero polynomial \(p(x) = 0\) over \(\mathrm{GF}(q)\).
- Parameters
field (galois.GFArray, optional) – The field \(\mathrm{GF}(q)\) the polynomial is over. The default is
galois.GF2
.- Returns
The polynomial \(p(x)\).
- Return type
Examples
Construct the zero polynomial over \(\mathrm{GF}(2)\).
In [1]: galois.Poly.Zero() Out[1]: Poly(0, GF(2))
Construct the zero polynomial over \(\mathrm{GF}(2^8)\).
In [2]: GF = galois.GF(2**8) In [3]: galois.Poly.Zero(field=GF) Out[3]: Poly(0, GF(2^8))
-
derivative
(k=1)[source]¶ Computes the \(k\)-th formal derivative \(\frac{d^k}{dx^k} p(x)\) of the polynomial \(p(x)\).
For the polynomial
\[p(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0\]the first formal derivative is defined as
\[p'(x) = (d) \cdot a_{d} x^{d-1} + (d-1) \cdot a_{d-1} x^{d-2} + \dots + (2) \cdot a_{2} x + a_1\]where \(\cdot\) represents scalar multiplication (repeated addition), not finite field multiplication, e.g. \(3 \cdot a = a + a + a\).
- Parameters
k (int, optional) – The number of derivatives to compute. 1 corresponds to \(p'(x)\), 2 corresponds to \(p''(x)\), etc. The default is 1.
- Returns
The \(k\)-th formal derivative of the polynomial \(p(x)\).
- Return type
References
Examples
Compute the derivatives of a polynomial over \(\mathrm{GF}(2)\).
In [1]: p = galois.Poly.Random(7); p Out[1]: Poly(x^7 + x^6 + x^5 + x^3 + x^2 + x + 1, GF(2)) In [2]: p.derivative() Out[2]: Poly(x^6 + x^4 + x^2 + 1, GF(2)) # k derivatives of a polynomial where k is the Galois field's characteristic will always result in 0 In [3]: p.derivative(2) Out[3]: Poly(0, GF(2))
Compute the derivatives of a polynomial over \(\mathrm{GF}(7)\).
In [4]: GF = galois.GF(7) In [5]: p = galois.Poly.Random(11, field=GF); p Out[5]: Poly(2x^11 + x^8 + 3x^7 + 5x^6 + 5x^5 + 3x^4 + 5x^3 + 2x^2 + x + 1, GF(7)) In [6]: p.derivative() Out[6]: Poly(x^10 + x^7 + 2x^5 + 4x^4 + 5x^3 + x^2 + 4x + 1, GF(7)) In [7]: p.derivative(2) Out[7]: Poly(3x^9 + 3x^4 + 2x^3 + x^2 + 2x + 4, GF(7)) In [8]: p.derivative(3) Out[8]: Poly(6x^8 + 5x^3 + 6x^2 + 2x + 2, GF(7)) # k derivatives of a polynomial where k is the Galois field's characteristic will always result in 0 In [9]: p.derivative(7) Out[9]: Poly(0, GF(2))
Compute the derivatives of a polynomial over \(\mathrm{GF}(2^8)\).
In [10]: GF = galois.GF(2**8) In [11]: p = galois.Poly.Random(7, field=GF); p Out[11]: Poly(148x^7 + 185x^6 + 66x^5 + 133x^4 + 181x^3 + 159x^2 + 208x + 246, GF(2^8)) In [12]: p.derivative() Out[12]: Poly(148x^6 + 66x^4 + 181x^2 + 208, GF(2^8)) # k derivatives of a polynomial where k is the Galois field's characteristic will always result in 0 In [13]: p.derivative(2) Out[13]: Poly(0, GF(2^8))
-
roots
(multiplicity=False)[source]¶ Calculates the roots \(r\) of the polynomial \(p(x)\), such that \(p(r) = 0\).
This implementation uses Chien’s search to find the roots \(\{r_0, r_1, \dots, r_{k-1}\}\) of the degree-\(d\) polynomial
\[p(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0,\]where \(k \le d\). Then, \(p(x)\) can be factored as
\[p(x) = (x - r_0)^{m_0} (x - r_1)^{m_1} \dots (x - r_{k-1})^{m_{k-1}},\]where \(m_i\) is the multiplicity of root \(r_i\) and
\[\sum_{i=0}^{k-1} m_i = d.\]The Galois field elements can be represented as \(\mathrm{GF}(q) = \{0, 1, \alpha, \alpha^2, \dots, \alpha^{q-2}\}\), where \(\alpha\) is a primitive element of \(\mathrm{GF}(q)\).
\(0\) is a root of \(p(x)\) if:
\[a_0 = 0\]\(1\) is a root of \(p(x)\) if:
\[\sum_{j=0}^{d} a_j = 0\]The remaining elements of \(\mathrm{GF}(q)\) are powers of \(\alpha\). The following equations calculate \(p(\alpha^i)\), where \(\alpha^i\) is a root of \(p(x)\) if \(p(\alpha^i) = 0\).
\[ \begin{align}\begin{aligned}p(\alpha^i) &= a_{d}(\alpha^i)^{d} + a_{d-1}(\alpha^i)^{d-1} + \dots + a_1(\alpha^i) + a_0\\p(\alpha^i) &\overset{\Delta}{=} \lambda_{i,d} + \lambda_{i,d-1} + \dots + \lambda_{i,1} + \lambda_{i,0}\\p(\alpha^i) &= \sum_{j=0}^{d} \lambda_{i,j}\end{aligned}\end{align} \]The next power of \(\alpha\) can be easily calculated from the previous calculation.
\[ \begin{align}\begin{aligned}p(\alpha^{i+1}) &= a_{d}(\alpha^{i+1})^{d} + a_{d-1}(\alpha^{i+1})^{d-1} + \dots + a_1(\alpha^{i+1}) + a_0\\p(\alpha^{i+1}) &= a_{d}(\alpha^i)^{d}\alpha^d + a_{d-1}(\alpha^i)^{d-1}\alpha^{d-1} + \dots + a_1(\alpha^i)\alpha + a_0\\p(\alpha^{i+1}) &= \lambda_{i,d}\alpha^d + \lambda_{i,d-1}\alpha^{d-1} + \dots + \lambda_{i,1}\alpha + \lambda_{i,0}\\p(\alpha^{i+1}) &= \sum_{j=0}^{d} \lambda_{i,j}\alpha^j\end{aligned}\end{align} \]- Parameters
multiplicity (bool, optional) – Optionally return the multiplicity of each root. The default is
False
, which only returns the unique roots.- Returns
galois.GFArray – Galois field array of roots of \(p(x)\).
np.ndarray – The multiplicity of each root. Only returned if
multiplicity=True
.
References
Examples
Find the roots of a polynomial over \(\mathrm{GF}(2)\).
In [1]: p = galois.Poly.Roots([0,]*7 + [1,]*13); p Out[1]: Poly(x^20 + x^19 + x^16 + x^15 + x^12 + x^11 + x^8 + x^7, GF(2)) In [2]: p.roots() Out[2]: GF([0, 1], order=2) In [3]: p.roots(multiplicity=True) Out[3]: (GF([0, 1], order=2), array([ 7, 13]))
Find the roots of a polynomial over \(\mathrm{GF}(2^8)\).
In [4]: GF = galois.GF(2**8) In [5]: p = galois.Poly.Roots([18,]*7 + [155,]*13 + [227,]*9, field=GF); p Out[5]: Poly(x^29 + 106x^28 + 27x^27 + 155x^26 + 230x^25 + 38x^24 + 78x^23 + 8x^22 + 46x^21 + 210x^20 + 248x^19 + 214x^18 + 172x^17 + 152x^16 + 82x^15 + 237x^14 + 172x^13 + 230x^12 + 141x^11 + 63x^10 + 103x^9 + 167x^8 + 199x^7 + 127x^6 + 254x^5 + 95x^4 + 93x^3 + 3x^2 + 4x + 208, GF(2^8)) In [6]: p.roots() Out[6]: GF([ 18, 155, 227], order=2^8) In [7]: p.roots(multiplicity=True) Out[7]: (GF([ 18, 155, 227], order=2^8), array([ 7, 13, 9]))
-
property
coeffs
¶ The coefficients of the polynomial in degree-descending order. The entries of
galois.Poly.degrees
are paired withgalois.Poly.coeffs
.Examples
In [1]: GF = galois.GF(7) In [2]: p = galois.Poly([3, 0, 5, 2], field=GF) In [3]: p.coeffs Out[3]: GF([3, 0, 5, 2], order=7)
- Type
-
property
degree
¶ The degree of the polynomial, i.e. the highest degree with non-zero coefficient.
Examples
In [1]: GF = galois.GF(7) In [2]: p = galois.Poly([3, 0, 5, 2], field=GF) In [3]: p.degree Out[3]: 3
- Type
-
property
degrees
¶ An array of the polynomial degrees in degree-descending order. The entries of
galois.Poly.degrees
are paired withgalois.Poly.coeffs
.Examples
In [1]: GF = galois.GF(7) In [2]: p = galois.Poly([3, 0, 5, 2], field=GF) In [3]: p.degrees Out[3]: array([3, 2, 1, 0])
- Type
-
property
field
¶ The Galois field to which the coefficients belong. The
galois.Poly.field
property is a subclass ofgalois.GFArray
. This property is settable.Examples
In [1]: GF = galois.GF(2**8) # The primitive polynomial of the field GF(p^m) is degree-m over GF(p)[x] In [2]: prim_poly = GF.prim_poly; prim_poly Out[2]: Poly(x^8 + x^4 + x^3 + x^2 + 1, GF(2)) In [3]: prim_poly.field Out[3]: galois.gf2.GF2 # Convert the primitive polynomial from GF(p)[x] to GF(p^m)[x] In [4]: prim_poly.field = GF; prim_poly Out[4]: Poly(x^8 + x^4 + x^3 + x^2 + 1, GF(2^8)) # The primitive element alpha is a root of the primitive polynomial in GF(p^m) In [5]: prim_poly(GF.alpha) Out[5]: GF(0, order=2^8)
- Type
-
property
integer
¶ The integer representation of the polynomial. For polynomial \(p(x) = a_{d}x^{d} + a_{d-1}x^{d-1} + \dots + a_1x + a_0\) with elements in \(a_k \in \mathrm{GF}(q)\), the integer representation is \(i = a_{d} q^{d} + a_{d-1} q^{d-1} + \dots + a_1 q + a_0\) (using integer arithmetic, not finite field arithmetic).
Examples
In [1]: GF = galois.GF(7) In [2]: p = galois.Poly([3, 0, 5, 2], field=GF) In [3]: p.integer Out[3]: 1066 In [4]: p.integer == 3*7**3 + 5*7**1 + 2*7**0 Out[4]: True
- Type
-
property
nonzero_coeffs
¶ The non-zero coefficients of the polynomial in degree-descending order. The entries of
galois.Poly.nonzero_degrees
are paired withgalois.Poly.nonzero_coeffs
.Examples
In [1]: GF = galois.GF(7) In [2]: p = galois.Poly([3, 0, 5, 2], field=GF) In [3]: p.nonzero_coeffs Out[3]: GF([3, 5, 2], order=7)
- Type
-
property
nonzero_degrees
¶ An array of the polynomial degrees that have non-zero coefficients, in degree-descending order. The entries of
galois.Poly.nonzero_degrees
are paired withgalois.Poly.nonzero_coeffs
.Examples
In [1]: GF = galois.GF(7) In [2]: p = galois.Poly([3, 0, 5, 2], field=GF) In [3]: p.nonzero_degrees Out[3]: array([3, 1, 0])
- Type
-
galois.
GF
(order, prim_poly=None, target='cpu', mode='auto', rebuild=False)[source]¶ Factory function to construct Galois field array classes of type \(\mathrm{GF}(p^m)\).
- Parameters
order (int) – The order \(p^m\) of the field \(\mathrm{GF}(p^m)\). Order must be a prime power.
prim_poly (galois.Poly, optional) – The primitive polynomial of the field. Default is
None
which will use the Conway polynomial obtained fromgalois.conway_poly
.target (str) – The
target
keyword argument fromnumba.vectorize
, either"cpu"
,"parallel"
, or"cuda"
.mode (str, optional) – The type of field computation, either
"auto"
,"lookup"
, or"calculate"
. The default is"auto"
. The “lookup” mode will use Zech log, log, and anti-log lookup tables for speed. The “calculate” mode will not store any lookup tables, but perform field arithmetic on the fly. The “calculate” mode is designed for large fields that cannot store lookup tables in RAM. Generally, “calculate” will be slower than “lookup”. The “auto” mode will determine whether to use “lookup” or “calculate” based on the field size. For “auto”, field’s withorder <= 2**16
will use the “lookup” mode.rebuild (bool, optional) – Indicates whether to force a rebuild of the lookup tables. The default is
False
.
- Returns
A new Galois field array class that is a subclass of
galois.GFArray
.- Return type
Examples
Construct various Galois field array classes.
# Construct a GF(2^m) class In [1]: GF256 = galois.GF(2**8); print(GF256) <class 'numpy.ndarray' over GF(2^8)> # Construct a GF(p) class In [2]: GF571 = galois.GF(571); print(GF571) <class 'numpy.ndarray' over GF(571)> # Construct a very large GF(2^m) class In [3]: GF2m = galois.GF(2**100); print(GF2m) <class 'numpy.ndarray' over GF(2^100)> # Construct a very large GF(p) class In [4]: GFp = galois.GF(36893488147419103183); print(GFp) <class 'numpy.ndarray' over GF(36893488147419103183)>
See
galois.GFArray
for more examples of what Galois field arrays can do.
-
galois.
carmichael
(n)[source]¶ Finds the smallest positive integer \(m\) such that \(a^m \equiv 1 (\textrm{mod}\ n)\) for every integer \(a\) in \(1 \le a < n\) that is coprime to \(n\).
Implements the Carmichael function \(\lambda(n)\).
- Parameters
n (int) – A positive integer.
- Returns
The smallest positive integer \(m\) such that \(a^m \equiv 1 (\textrm{mod}\ n)\) for every \(a\) in \(1 \le a < n\) that is coprime to \(n\).
- Return type
References
Examples
In [1]: n = 20 In [2]: lambda_ = galois.carmichael(n); lambda_ Out[2]: 4 # Find the totatives that are relatively coprime with n In [3]: totatives = [i for i in range(n) if math.gcd(i, n) == 1]; totatives Out[3]: [1, 3, 7, 9, 11, 13, 17, 19] In [4]: for a in totatives: ...: result = pow(a, lambda_, n) ...: print("{:2d}^{} = {} (mod {})".format(a, lambda_, result, n)) ...: 1^4 = 1 (mod 20) 3^4 = 1 (mod 20) 7^4 = 1 (mod 20) 9^4 = 1 (mod 20) 11^4 = 1 (mod 20) 13^4 = 1 (mod 20) 17^4 = 1 (mod 20) 19^4 = 1 (mod 20) # For prime n, phi and lambda are always n-1 In [5]: galois.euler_totient(13), galois.carmichael(13) Out[5]: (12, 12)
-
galois.
chinese_remainder_theorem
(a, m)[source]¶ Solves the simultaneous system of congruences for \(x\).
\[ \begin{align}\begin{aligned}x &\equiv a_1\ (\textrm{mod}\ m_1)\\x &\equiv a_2\ (\textrm{mod}\ m_2)\\x &\equiv \ldots\\x &\equiv a_n\ (\textrm{mod}\ m_n)\end{aligned}\end{align} \]- Parameters
a (array_like) – The integer remainders \(a_i\).
m (array_like) – The integer modulii \(m_i\).
- Returns
The simultaneous solution \(x\) to the system of congruences.
- Return type
Examples
In [1]: a = [0, 3, 4] In [2]: m = [3, 4, 5] In [3]: x = galois.chinese_remainder_theorem(a, m); x Out[3]: 39 In [4]: for i in range(len(a)): ...: ai = x % m[i] ...: print(f"{x} = {ai} (mod {m[i]}), Valid congruence: {ai == a[i]}") ...: 39 = 0 (mod 3), Valid congruence: True 39 = 3 (mod 4), Valid congruence: True 39 = 4 (mod 5), Valid congruence: True
-
galois.
conway_poly
(p, n)[source]¶ Returns the degree-\(n\) Conway polynomial \(C_{p,n}\) over \(\mathrm{GF}(p)\).
A Conway polynomial is a an irreducible polynomial over \(\mathrm{GF}(p)\) that provides a standard representation of \(\mathrm{GF}(p^n)\) as a splitting field of \(C_{p,n}\). Conway polynomials provide compatability between fields and their subfields, and hence are the common way to represent extension fields.
The Conway polynomial \(C_{p,n}\) is defined as the lexicographically-minimal monic irreducible polynomial of degree \(n\) over \(\mathrm{GF}(p)\) that is compatible with all \(C_{p,m}\), for \(m\) dividing \(n\).
This function uses Frank Luebeck’s Conway polynomial database for fast lookup, not construction.
- Parameters
- Returns
The degree-\(n\) Conway polynomial \(C_{p,n}\) over \(\mathrm{GF}(p)\).
- Return type
- Raises
LookupError – If the Conway polynomial \(C_{p,n}\) is not found in Frank Luebeck’s database.
Warning
If the \(\mathrm{GF}(p)\) field hasn’t already been created, it will be created in this function since it’s needed in the return polynomial.
Examples
In [1]: galois.conway_poly(2, 100) Out[1]: Poly(x^100 + x^57 + x^56 + x^55 + x^52 + x^48 + x^47 + x^46 + x^45 + x^44 + x^43 + x^41 + x^37 + x^36 + x^35 + x^34 + x^31 + x^30 + x^27 + x^25 + x^24 + x^22 + x^20 + x^19 + x^16 + x^15 + x^11 + x^9 + x^8 + x^6 + x^5 + x^3 + 1, GF(2)) In [2]: galois.conway_poly(7, 13) Out[2]: Poly(x^13 + 6x^2 + 4, GF(7))
-
galois.
euler_totient
(n)[source]¶ Counts the positive integers (totatives) in \(1 \le k < n\) that are relatively prime to \(n\), i.e. \(gcd(n, k) = 1\).
Implements the Euler Totient function \(\phi(n)\).
- Parameters
n (int) – A positive integer.
- Returns
The number of totatives that are relatively prime to \(n\).
- Return type
References
Examples
In [1]: n = 20 In [2]: phi = galois.euler_totient(n); phi Out[2]: 8 # Find the totatives that are coprime with n In [3]: totatives = [k for k in range(n) if math.gcd(k, n) == 1]; totatives Out[3]: [1, 3, 7, 9, 11, 13, 17, 19] # The number of totatives is phi In [4]: len(totatives) == phi Out[4]: True # For prime n, phi is always n-1 In [5]: galois.euler_totient(13) Out[5]: 12
-
galois.
factors
(n)[source]¶ Returns the positive factors of the integer \(n\).
- Parameters
n (int) – An integer to be factored.
- Returns
Sorted array of factors of \(n\).
- Return type
Examples
In [1]: galois.factors(120) Out[1]: [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120]
-
galois.
fermat_primality_test
(n)[source]¶ Probabilistic primality test of \(n\).
This function implements Fermat’s primality test. The test says that for an integer \(n\), select an integer \(a\) coprime with \(n\). If \(a^{n-1} \equiv 1 (\textrm{mod}\ n)\), then \(n\) is prime or pseudoprime.
- Parameters
n (int) – A positive integer.
- Returns
False
if \(n\) is known to be composite.True
if \(n\) is prime or pseudoprime.- Return type
Examples
# List of some primes In [1]: primes = [257, 24841, 65497] In [2]: for prime in primes: ...: is_prime = galois.fermat_primality_test(prime) ...: p, k = galois.prime_factors(prime) ...: print("Prime = {:5d}, Fermat's Prime Test = {}, Prime factors = {}".format(prime, is_prime, list(p))) ...: Prime = 257, Fermat's Prime Test = True, Prime factors = [257] Prime = 24841, Fermat's Prime Test = True, Prime factors = [24841] Prime = 65497, Fermat's Prime Test = True, Prime factors = [65497] # List of some strong pseudoprimes with base 2 In [3]: pseudoprimes = [2047, 29341, 65281] In [4]: for pseudoprime in pseudoprimes: ...: is_prime = galois.fermat_primality_test(pseudoprime) ...: p, k = galois.prime_factors(pseudoprime) ...: print("Pseudoprime = {:5d}, Fermat's Prime Test = {}, Prime factors = {}".format(pseudoprime, is_prime, list(p))) ...: Pseudoprime = 2047, Fermat's Prime Test = True, Prime factors = [23, 89] Pseudoprime = 29341, Fermat's Prime Test = True, Prime factors = [13, 37, 61] Pseudoprime = 65281, Fermat's Prime Test = True, Prime factors = [97, 673]
-
galois.
gcd
(a, b)[source]¶ Finds the integer multiplicands of \(a\) and \(b\) such that \(a x + b y = gcd(a, b)\).
This implementation uses the Extended Euclidean Algorithm.
- Parameters
- Returns
int – Greatest common divisor of \(a\) and \(b\).
int – Integer \(x\), such that \(a x + b y = gcd(a, b)\).
int – Integer \(y\), such that \(a x + b y = gcd(a, b)\).
References
Moon, “Error Correction Coding”, Section 5.2.2: The Euclidean Algorithm and Euclidean Domains, p. 181
https://en.wikipedia.org/wiki/Euclidean_algorithm#Extended_Euclidean_algorithm
Examples
In [1]: a = 2 In [2]: b = 13 In [3]: gcd, x, y = galois.gcd(a, b) In [4]: gcd, x, y Out[4]: (1, -6, 1) In [5]: a*x + b*y == gcd Out[5]: True
-
galois.
is_cyclic
(n)[source]¶ Determines whether the multiplicative group \(\mathbb{Z}{_n^\times}\) is cyclic.
The multiplicative group \(\mathbb{Z}{_n^\times}\) is the set of positive integers \(1 \le a < n\) that are coprime with \(n\). \(\mathbb{Z}{_n^\times}\) being cyclic means that some primitive root (or generator) \(g\) can generate the group \(\mathbb{Z}{_n^\times} = \{g, g^2, \dots, g^k\}\), where \(k\) is order of the group. The order of the group is defined by Euler’s totient function, \(\phi(n) = k\). If \(\mathbb{Z}{_n^\times}\) is cyclic, the number of primitive roots is found by \(\phi(k)\) or \(\phi(\phi(n))\).
\(\mathbb{Z}{_n^\times}\) is cyclic if and only if \(n\) is \(2\), \(4\), \(p^k\), or \(2p^k\), where \(p\) is an odd prime and \(k\) is a positive integer.
- Parameters
n (int) – A positive integer.
- Returns
True
if the multiplicative group \(\mathbb{Z}{_n^\times}\) is cyclic.- Return type
References
Examples
The elements of \(\mathbb{Z}{_n^\times}\) are the positive integers less than \(n\) that are coprime with \(n\). For example when \(n = 14\), then \(\mathbb{Z}{_{14}^\times} = \{1, 3, 5, 9, 11, 13\}\).
# n is of type 2*p^k, which is cyclic In [1]: n = 14 In [2]: galois.is_cyclic(n) Out[2]: True # The congruence class coprime with n In [3]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[3]: {1, 3, 5, 9, 11, 13} # Euler's totient function counts the "totatives", positive integers coprime with n In [4]: phi = galois.euler_totient(n); phi Out[4]: 6 In [5]: len(Znx) == phi Out[5]: True # The primitive roots are the elements in Znx that multiplicatively generate the group In [6]: for a in Znx: ...: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ...: primitive_root = span == Znx ...: print("Element: {:2d}, Span: {:<20}, Primitive root: {}".format(a, str(span), primitive_root)) ...: Element: 1, Span: {1} , Primitive root: False Element: 3, Span: {1, 3, 5, 9, 11, 13}, Primitive root: True Element: 5, Span: {1, 3, 5, 9, 11, 13}, Primitive root: True Element: 9, Span: {9, 11, 1} , Primitive root: False Element: 11, Span: {9, 11, 1} , Primitive root: False Element: 13, Span: {1, 13} , Primitive root: False # To find the primitive roots 3 and 5, you can just call `primitive_roots()` In [7]: roots = list(galois.primitive_roots(n)); roots Out[7]: [3, 5] # Euler's totient function phi(phi(n)) counts the primitive roots of n In [8]: len(roots) == galois.euler_totient(phi) Out[8]: True
A counterexample is \(n = 15 = 3*5\), which doesn’t fit the condition for cyclicness. \(\mathbb{Z}{_{15}^\times} = \{1, 2, 4, 7, 8, 11, 13, 14\}\).
# n is of type p1^k1 * p2^k2, which is not cyclic In [9]: n = 15 In [10]: galois.is_cyclic(n) Out[10]: False # The congruence class coprime with n In [11]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[11]: {1, 2, 4, 7, 8, 11, 13, 14} # Euler's totient function counts the "totatives", positive integers coprime with n In [12]: phi = galois.euler_totient(n); phi Out[12]: 8 In [13]: len(Znx) == phi Out[13]: True # The primitive roots are the elements in Znx that multiplicatively generate the group In [14]: for a in Znx: ....: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ....: primitive_root = span == Znx ....: print("Element: {:2d}, Span: {:<13}, Primitive root: {}".format(a, str(span), primitive_root)) ....: Element: 1, Span: {1} , Primitive root: False Element: 2, Span: {8, 1, 2, 4} , Primitive root: False Element: 4, Span: {1, 4} , Primitive root: False Element: 7, Span: {1, 4, 13, 7}, Primitive root: False Element: 8, Span: {8, 1, 2, 4} , Primitive root: False Element: 11, Span: {1, 11} , Primitive root: False Element: 13, Span: {1, 4, 13, 7}, Primitive root: False Element: 14, Span: {1, 14} , Primitive root: False In [15]: roots = list(galois.primitive_roots(n)); roots Out[15]: [] # Note the max order of any element is 4, not 8, which is Carmichael's lambda function In [16]: galois.carmichael(n) Out[16]: 4
-
galois.
is_irreducible
(poly)[source]¶ Checks whether the polynomial \(f(x)\) over \(\mathrm{GF}(p)\) is irreducible.
This function implementats Rabin’s irreducibility test. It says a degree-\(n\) polynomial \(f(x)\) over \(\mathrm{GF}(p)\) for prime \(p\) is irreducible if and only if \(f(x)\ |\ (x^{p^n} - x)\) and \(\textrm{gcd}(f(x),\ x^{p^{m_i}} - x) = 1\) for \(1 \le i \le k\), where \(m_i = n/p_i\) for the \(k\) prime divisors \(p_i\) of \(n\).
- Parameters
poly (galois.Poly) – A polynomial \(f(x)\) over \(\mathrm{GF}(p)\).
- Returns
True
if the polynomial is irreducible.- Return type
References
Rabin. Probabilistic algorithms in finite fields. SIAM Journal on Computing (1980), 273–280. https://apps.dtic.mil/sti/pdfs/ADA078416.pdf
Gao and D. Panarino. Tests and constructions of irreducible polynomials over finite fields. https://www.math.clemson.edu/~sgao/papers/GP97a.pdf
https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields
-
galois.
is_prime
(n)[source]¶ Determines if \(n\) is prime.
This algorithm will first run Fermat’s primality test to check \(n\) for compositeness. If it determines \(n\) is composite, the function will quickly return. If Fermat’s primality test returns
True
, then \(n\) could be prime or pseudoprime. If so, then this function will run seven rounds of Miller-Rabin’s primality test. With this many rounds, a result ofTrue
should have high probability of being a true prime, not a pseudoprime.- Parameters
n (int) – A positive integer.
- Returns
True
if the integer \(n\) is prime.- Return type
Examples
In [1]: galois.is_prime(13) Out[1]: True In [2]: galois.is_prime(15) Out[2]: False
The algorithm is also efficient on very large \(n\).
In [3]: galois.is_prime(1000000000000000035000061) Out[3]: True
-
galois.
is_primitive_root
(g, n)[source]¶ Determines if \(g\) is a primitive root modulo \(n\).
\(g\) is a primitive root if the totatives of \(n\), the positive integers \(1 \le a < n\) that are coprime with \(n\), can be generated by powers of \(g\).
- Parameters
- Returns
True
if \(g\) is a primitive root modulo \(n\).- Return type
Examples
In [1]: galois.is_primitive_root(2, 7) Out[1]: False In [2]: galois.is_primitive_root(3, 7) Out[2]: True In [3]: list(galois.primitive_roots(7)) Out[3]: [3, 5]
-
galois.
isqrt
(n)[source]¶ Computes the integer square root of \(n\) such that \(\textrm{isqrt}(n)^2 \le n\).
This is here for Python versions before 3.8. For Python 3.8 and later, use
math.isqrt
.- Parameters
n (int) – A non-negative integer
- Returns
The integer square root of \(n\) such that \(\textrm{isqrt}(n)^2 \le n\).
- Return type
Examples
# Use a large Mersenne prime In [1]: p = galois.mersenne_primes(2000)[-1]; p Out[1]: 10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087 In [2]: sqrt_p = galois.isqrt(p); sqrt_p Out[2]: 3226132699481594337650229932669505772017441235628244885631123722785761803162998767122846394796285964908262519578341713326387400858087872534573955058079614218029097609909460991319304989482693499 In [3]: sqrt_p**2 <= p Out[3]: True In [4]: (sqrt_p + 1)**2 <= p Out[4]: False
-
galois.
kth_prime
(k)[source]¶ Returns the \(k\)-th prime.
- Parameters
k (int) – The prime index, where \(k = \{1,2,3,4,\dots\}\) for primes \(p = \{2,3,5,7,\dots\}\).
- Returns
The \(k\)-th prime.
- Return type
Examples
In [1]: galois.kth_prime(1) Out[1]: 2 In [2]: galois.kth_prime(3) Out[2]: 5 In [3]: galois.kth_prime(1000) Out[3]: 7919
-
galois.
mersenne_exponents
(n=None)[source]¶ Returns all known Mersenne exponents \(e\) for \(e \le n\).
A Mersenne exponent \(e\) is an exponent of \(2\) such that \(2^e - 1\) is prime.
- Parameters
n (int, optional) – The max exponent of 2. The default is
None
which returns all known Mersenne exponents.- Returns
The list of Mersenne exponents \(e\) for \(e \le n\).
- Return type
References
Examples
# List all Mersenne exponents for Mersenne primes up to 4000 bits In [1]: e = galois.mersenne_exponents(4000); e Out[1]: [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217] # Select one Merseene exponent and compute its Mersenne prime In [2]: p = 2**e[-1] - 1; p Out[2]: 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071 In [3]: galois.is_prime(p) Out[3]: True # Display all known Mersenne exponenets In [4]: galois.mersenne_exponents() Out[4]: [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657, 37156667, 42643801, 43112609]
-
galois.
mersenne_primes
(n=None)[source]¶ Returns all known Mersenne primes \(p\) for \(p \le 2^n - 1\).
Mersenne primes are primes that are one less than a power of 2.
- Parameters
n (int, optional) – The max power of 2. The default is
None
which returns all known Mersenne exponents.- Returns
The list of known Mersenne primes \(p\) for \(p \le 2^n - 1\).
- Return type
References
Examples
# List all Mersenne primes up to 2000 bits In [1]: p = galois.mersenne_primes(2000); p Out[1]: [3, 7, 31, 127, 8191, 131071, 524287, 2147483647, 2305843009213693951, 618970019642690137449562111, 162259276829213363391578010288127, 170141183460469231731687303715884105727, 6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151, 531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127, 10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087] In [2]: galois.is_prime(p[-1]) Out[2]: True
-
galois.
miller_rabin_primality_test
(n, a=None, rounds=1)[source]¶ Probabilistic primality test of \(n\).
This function implements the Miller-Rabin primality test. The test says that for an integer \(n\), select an integer \(a\) such that \(a < n\). Factor \(n - 1\) such that \(2^s d = n - 1\). Then, \(n\) is composite, if \(a^d \not\equiv 1 (\textrm{mod}\ n)\) and \(a^{2^r d} \not\equiv n - 1 (\textrm{mod}\ n)\) for \(1 \le r < s\).
- Parameters
n (int) – A positive integer.
a (int, optional) – Initial composite witness value, \(1 \le a < n\). On subsequent rounds, \(a\) will be a different value. The default is a random value.
rounds (int, optional) – The number of iterations attempting to detect \(n\) as composite. Additional rounds will choose new \(a\). Sufficient rounds have arbitrarily-high probability of detecting a composite.
- Returns
False
if \(n\) is known to be composite.True
if \(n\) is prime or pseudoprime.- Return type
References
Examples
# List of some primes In [1]: primes = [257, 24841, 65497] In [2]: for prime in primes: ...: is_prime = galois.miller_rabin_primality_test(prime) ...: p, k = galois.prime_factors(prime) ...: print("Prime = {:5d}, Miller-Rabin Prime Test = {}, Prime factors = {}".format(prime, is_prime, list(p))) ...: Prime = 257, Miller-Rabin Prime Test = True, Prime factors = [257] Prime = 24841, Miller-Rabin Prime Test = True, Prime factors = [24841] Prime = 65497, Miller-Rabin Prime Test = True, Prime factors = [65497] # List of some strong pseudoprimes with base 2 In [3]: pseudoprimes = [2047, 29341, 65281] # Single round of Miller-Rabin, sometimes fooled by pseudoprimes In [4]: for pseudoprime in pseudoprimes: ...: is_prime = galois.miller_rabin_primality_test(pseudoprime) ...: p, k = galois.prime_factors(pseudoprime) ...: print("Pseudoprime = {:5d}, Miller-Rabin Prime Test = {}, Prime factors = {}".format(pseudoprime, is_prime, list(p))) ...: Pseudoprime = 2047, Miller-Rabin Prime Test = False, Prime factors = [23, 89] Pseudoprime = 29341, Miller-Rabin Prime Test = False, Prime factors = [13, 37, 61] Pseudoprime = 65281, Miller-Rabin Prime Test = False, Prime factors = [97, 673] # 7 rounds of Miller-Rabin, never fooled by pseudoprimes In [5]: for pseudoprime in pseudoprimes: ...: is_prime = galois.miller_rabin_primality_test(pseudoprime, rounds=7) ...: p, k = galois.prime_factors(pseudoprime) ...: print("Pseudoprime = {:5d}, Miller-Rabin Prime Test = {}, Prime factors = {}".format(pseudoprime, is_prime, list(p))) ...: Pseudoprime = 2047, Miller-Rabin Prime Test = False, Prime factors = [23, 89] Pseudoprime = 29341, Miller-Rabin Prime Test = False, Prime factors = [13, 37, 61] Pseudoprime = 65281, Miller-Rabin Prime Test = False, Prime factors = [97, 673]
-
galois.
next_prime
(x)[source]¶ Returns the nearest prime \(p\), such that \(p > x\).
Examples
In [1]: galois.next_prime(13) Out[1]: 17 In [2]: galois.next_prime(15) Out[2]: 17
-
galois.
poly_exp_mod
(poly, power, modulus)[source]¶ Efficiently exponentiates a polynomial \(f(x)\) to the power \(k\) reducing by modulo \(g(x)\), \(f^k\ \textrm{mod}\ g\).
The algorithm is more efficient than exponentiating first and then reducing modulo \(g(x)\). Instead, this algorithm repeatedly squares \(f\), reducing modulo \(g\) at each step.
- Parameters
poly (galois.Poly) – The polynomial to be exponentiated \(f(x)\).
power (int) – The non-negative exponent \(k\).
modulus (galois.Poly) – The reducing polynomial \(g(x)\).
- Returns
The resulting polynomial \(h(x) = f^k\ \textrm{mod}\ g\).
- Return type
Examples
In [1]: GF = galois.GF(31) In [2]: f = galois.Poly.Random(10, field=GF); f Out[2]: Poly(9x^10 + 7x^9 + 2x^8 + 6x^7 + x^6 + 19x^5 + 10x^4 + 29x^3 + 15x^2 + 25x + 27, GF(31)) In [3]: g = galois.Poly.Random(7, field=GF); g Out[3]: Poly(23x^7 + 10x^6 + x^5 + 18x^4 + 27x^3 + 23x^2 + 24x + 28, GF(31)) # %timeit f**200 % g # 1.23 s ± 41.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) In [4]: f**200 % g Out[4]: Poly(12x^6 + 7x^5 + 4x^4 + 3x^3 + 3x^2 + 7x + 11, GF(31)) # %timeit galois.poly_exp_mod(f, 200, g) # 41.7 ms ± 468 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) In [5]: galois.poly_exp_mod(f, 200, g) Out[5]: Poly(12x^6 + 7x^5 + 4x^4 + 3x^3 + 3x^2 + 7x + 11, GF(31))
-
galois.
poly_gcd
(a, b)[source]¶ Finds the greatest common divisor of two polynomials \(a(x)\) and \(b(x)\) over \(\mathrm{GF}(q)\).
This implementation uses the Extended Euclidean Algorithm.
- Parameters
a (galois.Poly) – A polynomial \(a(x)\) over \(\mathrm{GF}(q)\).
b (galois.Poly) – A polynomial \(b(x)\) over \(\mathrm{GF}(q)\).
- Returns
galois.Poly – Polynomial greatest common divisor of \(a(x)\) and \(b(x)\).
galois.Poly – Polynomial \(x(x)\), such that \(a x + b y = gcd(a, b)\).
galois.Poly – Polynomial \(y(x)\), such that \(a x + b y = gcd(a, b)\).
Examples
In [1]: GF = galois.GF(7) In [2]: a = galois.Poly.Roots([2,2,2,3,6], field=GF); a Out[2]: Poly(x^5 + 6x^4 + x + 3, GF(7)) # a(x) and b(x) only share the root 2 in common In [3]: b = galois.Poly.Roots([1,2], field=GF); b Out[3]: Poly(x^2 + 4x + 2, GF(7)) In [4]: gcd, x, y = galois.poly_gcd(a, b) # The GCD has only 2 as a root with multiplicity 1 In [5]: gcd.roots(multiplicity=True) Out[5]: (GF([2], order=7), array([1])) In [6]: a*x + b*y == gcd Out[6]: True
-
galois.
prev_prime
(x)[source]¶ Returns the nearest prime \(p\), such that \(p \le x\).
Examples
In [1]: galois.prev_prime(13) Out[1]: 13 In [2]: galois.prev_prime(15) Out[2]: 13
-
galois.
prime_factors
(x)[source]¶ Computes the prime factors of the positive integer \(x\).
The integer \(x\) can be factored into \(x = p_1^{k_1} p_2^{k_2} \dots p_{n-1}^{k_{n-1}}\).
- Parameters
x (int) – The positive integer to be factored.
- Returns
list – Sorted list of prime factors \(p = [p_1, p_2, \dots, p_{n-1}]\) with \(p_1 < p_2 < \dots < p_{n-1}\).
list – List of corresponding prime powers \(k = [k_1, k_2, \dots, k_{n-1}]\).
Examples
In [1]: p, k = galois.prime_factors(120) In [2]: p, k Out[2]: ([2, 3, 5], [3, 1, 1]) # The product of the prime powers is the factored integer In [3]: np.multiply.reduce(np.array(p) ** np.array(k)) Out[3]: 120
Prime factorization of 1 less than a large prime.
In [4]: prime =1000000000000000035000061 In [5]: galois.is_prime(prime) Out[5]: True In [6]: p, k = galois.prime_factors(prime - 1) In [7]: p, k Out[7]: ([2, 3, 5, 17, 19, 51599587203302375387], [2, 1, 1, 1, 1, 1]) In [8]: np.multiply.reduce(np.array(p) ** np.array(k)) Out[8]: 1000000000000000035000060
-
galois.
primes
(n)[source]¶ Returns the primes \(p \le n\).
- Parameters
n (int) – A positive integer.
- Returns
The primes up to and including \(n\).
- Return type
Examples
In [1]: galois.primes(19) Out[1]: [2, 3, 5, 7, 11, 13, 17, 19]
-
galois.
primitive_root
(n, start=1, stop=None, largest=False)[source]¶ Finds the smallest primitive root modulo \(n\).
\(g\) is a primitive root if the totatives of \(n\), the positive integers \(1 \le a < n\) that are coprime with \(n\), can be generated by powers of \(g\).
Alternatively said, \(g\) is a primitive root modulo \(n\) if and only if \(g\) is a generator of the multiplicative group of integers modulo \(n\), \(\mathbb{Z}{_n^\times}\). That is, \(\mathbb{Z}{_n^\times} = \{g, g^2, \dots, g^k\}\), where \(k\) is order of the group. The order of the group \(\mathbb{Z}{_n^\times}\) is defined by Euler’s totient function, \(\phi(n) = k\). If \(\mathbb{Z}{_n^\times}\) is cyclic, the number of primitive roots modulo \(n\) is given by \(\phi(k)\) or \(\phi(\phi(n))\).
See
galois.is_cyclic
.- Parameters
n (int) – A positive integer.
start (int, optional) – Starting value (inclusive) for the search for a primitive root. The default is
1
. The resulting primitive root, if found, will be \(\textrm{start} \le g < \textrm{stop}\).stop (int, optional) – Stopping value (exclusive) in the search for a primitive root. The default is
None
which corresponds ton
. The resulting primitive root, if found, will be \(\textrm{start} \le g < \textrm{stop}\).largest (bool, optional) – Return the largest primitive root in the specified range, not the smallest. Default is
False
.
- Returns
The smallest primitive root modulo \(n\). Returns
None
if no primitive roots exist.- Return type
References
https://www.ams.org/journals/bull/1942-48-10/S0002-9904-1942-07767-6/S0002-9904-1942-07767-6.pdf
http://www.numbertheory.org/courses/MP313/lectures/lecture7/page1.html
Examples
Here is an example with one primitive root, \(n = 6 = 2 * 3^1\), which fits the definition of cyclicness, see
galois.is_cyclic
. Because \(n = 6\) is not prime, the primitive root isn’t a multiplicative generator of \(\mathbb{Z}/\textbf{n}\mathbb{Z}\).In [1]: n = 6 In [2]: root = galois.primitive_root(n); root Out[2]: 5 # The congruence class coprime with n In [3]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[3]: {1, 5} # Euler's totient function counts the "totatives", positive integers coprime with n In [4]: phi = galois.euler_totient(n); phi Out[4]: 2 In [5]: len(Znx) == phi Out[5]: True # The primitive roots are the elements in Znx that multiplicatively generate the group In [6]: for a in Znx: ...: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ...: primitive_root = span == Znx ...: print("Element: {}, Span: {:<6}, Primitive root: {}".format(a, str(span), primitive_root)) ...: Element: 1, Span: {1} , Primitive root: False Element: 5, Span: {1, 5}, Primitive root: True
Here is an example with two primitive roots, \(n = 7 = 7^1\), which fits the definition of cyclicness, see
galois.is_cyclic
. Since \(n = 7\) is prime, the primitive root is a multiplicative generator of \(\mathbb{Z}/\textbf{n}\mathbb{Z}\).In [7]: n = 7 In [8]: root = galois.primitive_root(n); root Out[8]: 3 # The congruence class coprime with n In [9]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[9]: {1, 2, 3, 4, 5, 6} # Euler's totient function counts the "totatives", positive integers coprime with n In [10]: phi = galois.euler_totient(n); phi Out[10]: 6 In [11]: len(Znx) == phi Out[11]: True # The primitive roots are the elements in Znx that multiplicatively generate the group In [12]: for a in Znx: ....: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ....: primitive_root = span == Znx ....: print("Element: {}, Span: {:<18}, Primitive root: {}".format(a, str(span), primitive_root)) ....: Element: 1, Span: {1} , Primitive root: False Element: 2, Span: {1, 2, 4} , Primitive root: False Element: 3, Span: {1, 2, 3, 4, 5, 6}, Primitive root: True Element: 4, Span: {1, 2, 4} , Primitive root: False Element: 5, Span: {1, 2, 3, 4, 5, 6}, Primitive root: True Element: 6, Span: {1, 6} , Primitive root: False
The algorithm is also efficient for very large \(n\).
In [13]: n = 1000000000000000035000061 In [14]: galois.primitive_root(n) Out[14]: 7 In [15]: galois.primitive_root(n, largest=True) Out[15]: 1000000000000000035000054
Here is a counterexample with no primitive roots, \(n = 8 = 2^3\), which does not fit the definition of cyclicness, see
galois.is_cyclic
.In [16]: n = 8 In [17]: root = galois.primitive_root(n); root # The congruence class coprime with n In [18]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[18]: {1, 3, 5, 7} # Euler's totient function counts the "totatives", positive integers coprime with n In [19]: phi = galois.euler_totient(n); phi Out[19]: 4 In [20]: len(Znx) == phi Out[20]: True # Test all elements for being primitive roots. The powers of a primitive span the congruence classes mod n. In [21]: for a in Znx: ....: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ....: primitive_root = span == Znx ....: print("Element: {}, Span: {:<6}, Primitive root: {}".format(a, str(span), primitive_root)) ....: Element: 1, Span: {1} , Primitive root: False Element: 3, Span: {1, 3}, Primitive root: False Element: 5, Span: {1, 5}, Primitive root: False Element: 7, Span: {1, 7}, Primitive root: False # Note the max order of any element is 2, not 4, which is Carmichael's lambda function In [22]: galois.carmichael(n) Out[22]: 2
-
galois.
primitive_roots
(n, start=1, stop=None, reverse=False)[source]¶ A generator that finds all primitive roots modulo \(n\).
\(g\) is a primitive root if the totatives of \(n\), the positive integers \(1 \le a < n\) that are coprime with \(n\), can be generated by powers of \(g\).
Alternatively said, \(g\) is a primitive root modulo \(n\) if and only if \(g\) is a generator of the multiplicative group of integers modulo \(n\), \(\mathbb{Z}{_n^\times}\). That is, \(\mathbb{Z}{_n^\times} = \{g, g^2, \dots, g^k\}\), where \(k\) is order of the group. The order of the group \(\mathbb{Z}{_n^\times}\) is defined by Euler’s totient function, \(\phi(n) = k\). If \(\mathbb{Z}{_n^\times}\) is cyclic, the number of primitive roots modulo \(n\) is given by \(\phi(k)\) or \(\phi(\phi(n))\).
See
galois.is_cyclic
.- Parameters
n (int) – A positive integer.
start (int, optional) – Starting value (inclusive) for the search for a primitive root. The default is 1. The resulting primitive roots, if found, will be \(\textrm{start} \le x < \textrm{stop}\).
stop (int, optional) – Stopping value (exclusive) in the search for a primitive root. The default is
None
which corresponds ton
. The resulting primitive roots, if found, will be \(\textrm{start} \le x < \textrm{stop}\).reverse (bool, optional) – List all primitive roots in descending order, i.e. largest to smallest. Default is
False
.
- Returns
A generator of all the positive primitive \(n\)-th roots of unity, \(x\). Use
list(galois.primitive_roots(n))
to retrieve them all instantly. Otherwise, you can access them in afor
loop or list comprehension.- Return type
References
https://www.ams.org/journals/bull/1942-48-10/S0002-9904-1942-07767-6/S0002-9904-1942-07767-6.pdf
http://www.numbertheory.org/courses/MP313/lectures/lecture7/page1.html
Examples
Here is an example with one primitive root, \(n = 6 = 2 * 3^1\), which fits the definition of cyclicness, see
galois.is_cyclic
. Because \(n = 6\) is not prime, the primitive root isn’t a multiplicative generator of \(\mathbb{Z}/\textbf{n}\mathbb{Z}\).In [1]: n = 6 In [2]: roots = list(galois.primitive_roots(n)); roots Out[2]: [5] # The congruence class coprime with n In [3]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[3]: {1, 5} # Euler's totient function counts the "totatives", positive integers coprime with n In [4]: phi = galois.euler_totient(n); phi Out[4]: 2 In [5]: len(Znx) == phi Out[5]: True # Test all elements for being primitive roots. The powers of a primitive span the congruence classes mod n. In [6]: for a in Znx: ...: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ...: primitive_root = span == Znx ...: print("Element: {}, Span: {:<6}, Primitive root: {}".format(a, str(span), primitive_root)) ...: Element: 1, Span: {1} , Primitive root: False Element: 5, Span: {1, 5}, Primitive root: True # Euler's totient function phi(phi(n)) counts the primitive roots of n In [7]: len(roots) == galois.euler_totient(phi) Out[7]: True
Here is an example with two primitive roots, \(n = 7 = 7^1\), which fits the definition of cyclicness, see
galois.is_cyclic
. Since \(n = 7\) is prime, the primitive root is a multiplicative generator of \(\mathbb{Z}/\textbf{n}\mathbb{Z}\).In [8]: n = 7 In [9]: roots = list(galois.primitive_roots(n)); roots Out[9]: [3, 5] # The congruence class coprime with n In [10]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[10]: {1, 2, 3, 4, 5, 6} # Euler's totient function counts the "totatives", positive integers coprime with n In [11]: phi = galois.euler_totient(n); phi Out[11]: 6 In [12]: len(Znx) == phi Out[12]: True # Test all elements for being primitive roots. The powers of a primitive span the congruence classes mod n. In [13]: for a in Znx: ....: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ....: primitive_root = span == Znx ....: print("Element: {}, Span: {:<18}, Primitive root: {}".format(a, str(span), primitive_root)) ....: Element: 1, Span: {1} , Primitive root: False Element: 2, Span: {1, 2, 4} , Primitive root: False Element: 3, Span: {1, 2, 3, 4, 5, 6}, Primitive root: True Element: 4, Span: {1, 2, 4} , Primitive root: False Element: 5, Span: {1, 2, 3, 4, 5, 6}, Primitive root: True Element: 6, Span: {1, 6} , Primitive root: False # Euler's totient function phi(phi(n)) counts the primitive roots of n In [14]: len(roots) == galois.euler_totient(phi) Out[14]: True
The algorithm is also efficient for very large \(n\).
In [15]: n = 1000000000000000035000061 # Euler's totient function phi(phi(n)) counts the primitive roots of n In [16]: galois.euler_totient(galois.euler_totient(n)) Out[16]: 237770897832817345778688 # Only list some of the primitive roots In [17]: list(galois.primitive_roots(n, stop=100)) Out[17]: [7, 21, 28, 34, 35, 38, 39, 43, 47, 52, 58, 65, 67, 73, 88, 97, 98] # The generator can also be used in a for loop In [18]: for r in galois.primitive_roots(n, stop=100): ....: print(r, end=" ") ....: 7 21 28 34 35 38 39 43 47 52 58 65 67 73 88 97 98
Here is a counterexample with no primitive roots, \(n = 8 = 2^3\), which does not fit the definition of cyclicness, see
galois.is_cyclic
.In [19]: n = 8 In [20]: roots = list(galois.primitive_roots(n)); roots Out[20]: [] # The congruence class coprime with n In [21]: Znx = set([a for a in range(1, n) if math.gcd(n, a) == 1]); Znx Out[21]: {1, 3, 5, 7} # Euler's totient function counts the "totatives", positive integers coprime with n In [22]: phi = galois.euler_totient(n); phi Out[22]: 4 In [23]: len(Znx) == phi Out[23]: True # Test all elements for being primitive roots. The powers of a primitive span the congruence classes mod n. In [24]: for a in Znx: ....: span = set([pow(a, i, n) for i in range(1, phi + 1)]) ....: primitive_root = span == Znx ....: print("Element: {}, Span: {:<6}, Primitive root: {}".format(a, str(span), primitive_root)) ....: Element: 1, Span: {1} , Primitive root: False Element: 3, Span: {1, 3}, Primitive root: False Element: 5, Span: {1, 5}, Primitive root: False Element: 7, Span: {1, 7}, Primitive root: False
-
galois.
totatives
(n)[source]¶ Returns the positive integers (totatives) in \(1 \le k < n\) that are relatively prime to \(n\), i.e. \(gcd(n, k) = 1\).
Examples
In [1]: n = 20 In [2]: totatives = galois.totatives(n); totatives Out[2]: [1, 3, 7, 9, 11, 13, 17, 19] In [3]: phi = galois.euler_totient(n); phi Out[3]: 8 In [4]: len(totatives) == phi Out[4]: True