Array Classes¶
The galois
library subclasses ndarray
to provide arithmetic over Galois fields and rings (future).
Array
subclasses¶
The main abstract base class is Array
. It has two abstract subclasses: FieldArray
and
RingArray
(future). None of these abstract classes may be instantiated directly. Instead, specific
subclasses for \(\mathrm{GF}(p^m)\) and \(\mathrm{GR}(p^e, m)\) are created at runtime with GF()
and GR()
(future).
FieldArray
subclasses¶
A FieldArray
subclass is created using the class factory function GF()
.
In [1]: GF = galois.GF(3**5)
In [2]: print(GF.properties)
Galois Field:
name: GF(3^5)
characteristic: 3
degree: 5
order: 243
irreducible_poly: x^5 + 2x + 1
is_primitive_poly: True
primitive_element: x
In [3]: GF = galois.GF(3**5, repr="poly")
In [4]: print(GF.properties)
Galois Field:
name: GF(3^5)
characteristic: 3
degree: 5
order: 243
irreducible_poly: x^5 + 2x + 1
is_primitive_poly: True
primitive_element: x
In [5]: GF = galois.GF(3**5, repr="power")
In [6]: print(GF.properties)
Galois Field:
name: GF(3^5)
characteristic: 3
degree: 5
order: 243
irreducible_poly: x^5 + 2x + 1
is_primitive_poly: True
primitive_element: x
Speed up creation of large finite field classes
For very large finite fields, the FieldArray
subclass creation time can be reduced by explicitly specifying
\(p\) and \(m\). This eliminates the need to factor the order \(p^m\).
In [7]: GF = galois.GF(2, 100)
In [8]: print(GF.properties)
Galois Field:
name: GF(2^100)
characteristic: 2
degree: 100
order: 1267650600228229401496703205376
irreducible_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
is_primitive_poly: True
primitive_element: x
Furthermore, if you already know the desired irreducible polynomial is irreducible and the primitive element is a generator of
the multiplicative group, you can specify verify=False
to skip the verification step. This eliminates the need to factor
\(p^m - 1\).
In [9]: GF = galois.GF(109987, 4, irreducible_poly="x^4 + 3x^2 + 100525x + 3", primitive_element="x", verify=False)
In [10]: print(GF.properties)
Galois Field:
name: GF(109987^4)
characteristic: 109987
degree: 4
order: 146340800268433348561
irreducible_poly: x^4 + 3x^2 + 100525x + 3
is_primitive_poly: True
primitive_element: x
The GF
class is a subclass of FieldArray
and a subclasses of ndarray
.
In [11]: issubclass(GF, galois.FieldArray)
Out[11]: True
In [12]: issubclass(GF, galois.Array)
Out[12]: True
In [13]: issubclass(GF, np.ndarray)
Out[13]: True
Class singletons¶
FieldArray
subclasses of the same type (order, irreducible polynomial, and primitive element) are singletons.
Here is the creation (twice) of the field \(\mathrm{GF}(3^5)\) defined with the default irreducible polynomial \(x^5 + 2x + 1\). They are the same class (a singleton), not just equivalent classes.
In [14]: galois.GF(3**5) is galois.GF(3**5)
Out[14]: True
The expense of class creation is incurred only once. So, subsequent calls of galois.GF(3**5)
are extremely inexpensive.
However, the field \(\mathrm{GF}(3^5)\) defined with irreducible polynomial \(x^5 + x^2 + x + 2\), while isomorphic to the
first field, has different arithmetic. As such, GF()
returns a unique FieldArray
subclass.
In [15]: galois.GF(3**5) is galois.GF(3**5, irreducible_poly="x^5 + x^2 + x + 2")
Out[15]: False
Methods and properties¶
All of the methods and properties related to \(\mathrm{GF}(p^m)\), not one of its arrays, are documented as class methods
and class properties in FieldArray
. For example, the irreducible polynomial of the finite field is accessed
with irreducible_poly
.
In [16]: GF.irreducible_poly
Out[16]: Poly(x^5 + 2x + 1, GF(3))
FieldArray
instances¶
A FieldArray
instance is created using GF
’s constructor.
In [17]: x = GF([23, 78, 163, 124])
In [18]: x
Out[18]: GF([ 23, 78, 163, 124], order=3^5)
In [19]: x = GF([23, 78, 163, 124])
In [20]: x
Out[20]:
GF([ 2α^2 + α + 2, 2α^3 + 2α^2 + 2α,
2α^4 + 1, α^4 + α^3 + α^2 + 2α + 1], order=3^5)
In [21]: x = GF([23, 78, 163, 124])
In [22]: x
Out[22]: GF([ α^17, α^132, α^241, α^41], order=3^5)
The array x
is an instance of FieldArray
and also an instance of ndarray
.
In [23]: isinstance(x, GF)
Out[23]: True
In [24]: isinstance(x, galois.FieldArray)
Out[24]: True
In [25]: isinstance(x, galois.Array)
Out[25]: True
In [26]: isinstance(x, np.ndarray)
Out[26]: True
The FieldArray
subclass is easily recovered from a FieldArray
instance using type()
.
In [27]: type(x) is GF
Out[27]: True
Constructors¶
Several classmethods are defined in FieldArray
that function as alternate constructors. By convention,
alternate constructors use PascalCase
while other classmethods use snake_case
.
For example, to generate a random array of given shape call Random()
.
In [28]: GF.Random((3, 2), seed=1)
Out[28]:
GF([[242, 216],
[ 32, 114],
[230, 179]], order=3^5)
In [29]: GF.Random((3, 2), seed=1)
Out[29]:
GF([[2α^4 + 2α^3 + 2α^2 + 2α + 2, 2α^4 + 2α^3],
[ α^3 + α + 2, α^4 + α^3 + 2α],
[ 2α^4 + 2α^3 + α^2 + α + 2, 2α^4 + α^2 + 2α + 2]], order=3^5)
In [30]: GF.Random((3, 2), seed=1)
Out[30]:
GF([[α^185, α^193],
[ α^49, α^231],
[ α^81, α^60]], order=3^5)
Or, create an identity matrix using Identity()
.
In [31]: GF.Identity(4)
Out[31]:
GF([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], order=3^5)
In [32]: GF.Identity(4)
Out[32]:
GF([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], order=3^5)
In [33]: GF.Identity(4)
Out[33]:
GF([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], order=3^5)
Methods¶
All of the methods that act on FieldArray
instances are documented as instance methods in FieldArray
.
For example, the multiplicative order of each finite field element is calculated using multiplicative_order()
.
In [34]: x.multiplicative_order()
Out[34]: array([242, 11, 242, 242])