# Galois: A performant numpy extension for Galois fields¶

## Installation¶

The latest version of galois can be installed from PyPI via pip.

```pip3 install galois
```

The the lastest code from master can be checked out and installed locally in an “editable” fashion.

```git clone https://github.com/mhostetter/galois.git
pip3 install -e galois
```

## API v0.0.8¶

 `galois` A performant numpy extension for Galois fields.

## Basic Usage¶

Construct Galois field array classes using the GF_factory() class factory function.

```In [1]: import numpy as np

In [2]: import galois

In [3]: GF = galois.GF_factory(31, 1)

In [4]: print(GF)
<Galois Field: GF(31^1), prim_poly = x + 28 (59 decimal)>

In [5]: print(GF.alpha)
GF31(3)

In [6]: print(GF.prim_poly)
Poly(x + 28, GF31)
```

Create arrays from existing numpy arrays.

```# Represents an existing numpy array
In [7]: array = np.random.randint(0, GF.order, 10, dtype=int); array
Out[7]: array([14, 29, 28,  5, 19, 14, 12, 15,  1,  9])

# Explicit Galois field construction
In [8]: GF(array)
Out[8]: GF31([14, 29, 28,  5, 19, 14, 12, 15,  1,  9])

# Numpy view casting to a Galois field
In [9]: array.view(GF)
Out[9]: GF31([14, 29, 28,  5, 19, 14, 12, 15,  1,  9])
```

Or, create Galois field arrays using alternate constructors.

```In [10]: x = GF.Random(10); x
Out[10]: GF31([ 7, 18, 24, 18, 10,  9, 22,  2, 29, 30])

# Construct a random array without zeros to prevent ZeroDivisonError
In [11]: y = GF.Random(10, low=1); y
Out[11]: GF31([28, 26, 15,  9, 12,  1, 29, 16, 22, 28])
```

Galois field arrays support traditional numpy array operations

```In [12]: x + y
Out[12]: GF31([ 4, 13,  8, 27, 22, 10, 20, 18, 20, 27])

In [13]: -x
Out[13]: GF31([24, 13,  7, 13, 21, 22,  9, 29,  2,  1])

In [14]: x * y
Out[14]: GF31([10,  3, 19,  7, 27,  9, 18,  1, 18,  3])

In [15]: x / y
Out[15]: GF31([ 8, 15, 14,  2,  6,  9, 20,  4, 14, 21])

# Multiple addition of a Galois field array with any integer
In [16]: x * -3  # NOTE: -3 is outside the field
Out[16]: GF31([10,  8, 21,  8,  1,  4, 27, 25,  6,  3])

# Exponentiate a Galois field array with any integer
In [17]: y ** -2  # NOTE: 87 is outside the field
Out[17]: GF31([ 7,  5,  4, 18, 14,  1,  8,  4, 18,  7])

# Log base alpha (the field's primitive element)
In [18]: np.log(y)
Out[18]: array([16,  5, 21,  2, 19,  0,  9,  6, 17, 16])
```

Galois field arrays support numpy array broadcasting.

```In [19]: a = GF.Random((2,5)); a
Out[19]:
GF31([[21, 23, 30,  1, 10],
[ 3, 21, 27, 26,  7]])

In [20]: b = GF.Random(5); b
Out[20]: GF31([11, 28, 23, 11, 15])

In [21]: a + b
Out[21]:
GF31([[ 1, 20, 22, 12, 25],
[14, 18, 19,  6, 22]])
```

Galois field arrays also support numpy ufunc methods.

```# Valid ufunc methods include "reduce", "accumulate", "reduceat", "outer", "at"
In [22]: np.multiply.reduce(a, axis=0)
Out[22]: GF31([ 1, 18,  4, 26,  8])

In [23]: np.multiply.outer(x, y)
Out[23]:
GF31([[10, 27, 12,  1, 22,  7, 17, 19, 30, 10],
[ 8,  3, 22,  7, 30, 18, 26,  9, 24,  8],
[21,  4, 19, 30,  9, 24, 14, 12,  1, 21],
[ 8,  3, 22,  7, 30, 18, 26,  9, 24,  8],
[ 1, 12, 26, 28, 27, 10, 11,  5,  3,  1],
[ 4, 17, 11, 19, 15,  9, 13, 20, 12,  4],
[27, 14, 20, 12, 16, 22, 18, 11, 19, 27],
[25, 21, 30, 18, 24,  2, 27,  1, 13, 25],
[ 6, 10,  1, 13,  7, 29,  4, 30, 18,  6],
[ 3,  5, 16, 22, 19, 30,  2, 15,  9,  3]])
```

Construct Galois field polynomials.

```# Construct a polynomial by specifying all the coefficients in descending-degree order
In [24]: p = galois.Poly([1, 22, 0, 17, 25], field=GF); p
Out[24]: Poly(x^4 + 22x^3 + 17x + 25, GF31)

# Construct a polynomial by specifying only the non-zero coefficients
In [25]: q = galois.Poly.NonZero([4, 14],  [2, 0], field=GF); q
Out[25]: Poly(4x^2 + 14, GF31)
```

Galois field polynomial arithmetic is similar to numpy array operations.

```In [26]: p + q
Out[26]: Poly(x^4 + 22x^3 + 4x^2 + 17x + 8, GF31)

In [27]: p // q, p % q
Out[27]: (Poly(8x^2 + 21x + 3, GF31), Poly(2x + 14, GF31))

In [28]: p ** 2
Out[28]: Poly(x^8 + 13x^7 + 19x^6 + 3x^5 + 23x^4 + 15x^3 + 10x^2 + 13x + 5, GF31)
```

Galois field polynomials can also be evaluated at constants or arrays.

```In [29]: p(1)
Out[29]: GF31(3)

In [30]: p(a)
Out[30]:
GF31([[ 7,  6, 18,  3, 17],
[ 7,  7, 14, 16, 16]])
```