# 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 : GF = galois.GF(3**5)

In : 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 : GF = galois.GF(3**5, repr="poly")

In : 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 : GF = galois.GF(3**5, repr="power")

In : 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 : GF = galois.GF(2, 100)

In : 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 : GF = galois.GF(109987, 4, irreducible_poly="x^4 + 3x^2 + 100525x + 3", primitive_element="x", verify=False)

In : 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 : issubclass(GF, galois.FieldArray)
Out: True

In : issubclass(GF, galois.Array)
Out: True

In : issubclass(GF, np.ndarray)
Out: 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 : galois.GF(3**5) is galois.GF(3**5)
Out: 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 : galois.GF(3**5) is galois.GF(3**5, irreducible_poly="x^5 + x^2 + x + 2")
Out: 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 : GF.irreducible_poly
Out: Poly(x^5 + 2x + 1, GF(3))


## FieldArray instances¶

A FieldArray instance is created using GF’s constructor.

In : x = GF([23, 78, 163, 124])

In : x
Out: GF([ 23,  78, 163, 124], order=3^5)

In : x = GF([23, 78, 163, 124])

In : x
Out:
GF([            2α^2 + α + 2,         2α^3 + 2α^2 + 2α,
2α^4 + 1, α^4 + α^3 + α^2 + 2α + 1], order=3^5)

In : x = GF([23, 78, 163, 124])

In : x
Out: GF([ α^17, α^132, α^241,  α^41], order=3^5)


The array x is an instance of FieldArray and also an instance of ndarray.

In : isinstance(x, GF)
Out: True

In : isinstance(x, galois.FieldArray)
Out: True

In : isinstance(x, galois.Array)
Out: True

In : isinstance(x, np.ndarray)
Out: True


The FieldArray subclass is easily recovered from a FieldArray instance using type().

In : type(x) is GF
Out: 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 : GF.Random((3, 2), seed=1)
Out:
GF([[242, 216],
[ 32, 114],
[230, 179]], order=3^5)

In : GF.Random((3, 2), seed=1)
Out:
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 : GF.Random((3, 2), seed=1)
Out:
GF([[α^185, α^193],
[ α^49, α^231],
[ α^81,  α^60]], order=3^5)


Or, create an identity matrix using Identity().

In : GF.Identity(4)
Out:
GF([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], order=3^5)

In : GF.Identity(4)
Out:
GF([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], order=3^5)

In : GF.Identity(4)
Out:
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 : x.multiplicative_order()
Out: array([242,  11, 242, 242])


Last update: Aug 06, 2023