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])

Last update: Aug 06, 2023