Extremely large fields

Arbitrarily-large \(\mathrm{GF}(2^m)\), \(\mathrm{GF}(p)\), \(\mathrm{GF}(p^m)\) fields are supported. Because field elements can’t be represented with numpy.int64, we use dtype=object in the numpy arrays. This enables use of native python int, which doesn’t overflow. It comes at a performance cost though. There are no JIT-compiled arithmetic ufuncs. All the arithmetic is done in pure python. All the same array operations, broadcasting, ufunc methods, etc are supported.

Large GF(p) fields

In [1]: prime = 36893488147419103183

In [2]: galois.is_prime(prime)
Out[2]: True

In [3]: GF = galois.GF(prime)

In [4]: print(GF)
<class 'numpy.ndarray over GF(36893488147419103183)'>

In [5]: a = GF.Random(10); a
Out[5]: 
GF([7923155036299944627, 36632076623422491840, 30355947550312948231,
    9052950877344315106, 32748567907186484565, 31375571613722834188,
    26124482858305326920, 33528567424248247103, 4562230502438267461,
    2314191530880549743], order=36893488147419103183)

In [6]: b = GF.Random(10); b
Out[6]: 
GF([33394811005132998111, 11646208554106222919, 23726788872338339998,
    16227021929137229231, 29074518448983313053, 12133438554981203478,
    21109115358619951253, 22479022333980602151, 1170201339885424188,
    3983278348466569021], order=36893488147419103183)

In [7]: a + b
Out[7]: 
GF([4424477894013839555, 11384797030109611576, 17189248275232185046,
    25279972806481544337, 24929598208750694435, 6615522021284934483,
    10340110069506174990, 19114101610809746071, 5732431842323691649,
    6297469879347118764], order=36893488147419103183)

Large GF(2^m) fields

In [8]: GF = galois.GF(2**100)

In [9]: print(GF)
<class 'numpy.ndarray over GF(2^100)'>

In [10]: a = GF([2**8, 2**21, 2**35, 2**98]); a
Out[10]: 
GF([256, 2097152, 34359738368, 316912650057057350374175801344],
   order=2^100)

In [11]: b = GF([2**91, 2**40, 2**40, 2**2]); b
Out[11]: 
GF([2475880078570760549798248448, 1099511627776, 1099511627776, 4],
   order=2^100)

In [12]: a + b
Out[12]: 
GF([2475880078570760549798248704, 1099513724928, 1133871366144,
    316912650057057350374175801348], order=2^100)

# Display elements as polynomials
In [13]: GF.display("poly")
Out[13]: <galois._fields._main.DisplayContext at 0x7f9c4fed09e8>

In [14]: a
Out[14]: GF([α^8, α^21, α^35, α^98], order=2^100)

In [15]: b
Out[15]: GF([α^91, α^40, α^40, α^2], order=2^100)

In [16]: a + b
Out[16]: GF([α^91 + α^8, α^40 + α^21, α^40 + α^35, α^98 + α^2], order=2^100)

In [17]: a * b
Out[17]: 
GF([α^99, α^61, α^75,
    α^57 + α^56 + α^55 + α^52 + α^48 + α^47 + α^46 + α^45 + α^44 + α^43 + α^41 + α^37 + α^36 + α^35 + α^34 + α^31 + α^30 + α^27 + α^25 + α^24 + α^22 + α^20 + α^19 + α^16 + α^15 + α^11 + α^9 + α^8 + α^6 + α^5 + α^3 + 1],
   order=2^100)

# Reset the display mode
In [18]: GF.display()
Out[18]: <galois._fields._main.DisplayContext at 0x7f9c5c81b5c0>