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 np.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 operatoions, 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_factory(prime, 1)

In [4]: print(GF)
<Galois Field: GF(36893488147419103183^1), prim_poly = x + 36893488147419103180 (73786976294838206363 decimal)>

In [5]: a = GF.Random(10); a
Out[5]: 
GF([26714485058552108354, 1244164805753230686, 19742515955261471381,
    18077566019025321829, 1388839699300516890, 33652833403576769087,
    7056727101762417399, 3655956211677540946, 29424191678824669853,
    33268427054293910693], order=36893488147419103183)

In [6]: b = GF.Random(10); b
Out[6]: 
GF([10228839155758638246, 2285545502070465186, 10470309180703397009,
    9606210048228912820, 23354753642180355990, 19598951885252347546,
    5137062489844492890, 32502597402742854671, 9112746521197008700,
    3826746707042298586], order=36893488147419103183)

In [7]: a + b
Out[7]: 
GF([49836066891643417, 3529710307823695872, 30212825135964868390,
    27683776067254234649, 24743593341480872880, 16358297141410013450,
    12193789591606910289, 36158553614420395617, 1643450052602575370,
    201685613917106096], order=36893488147419103183)

Large GF(2^m) fields

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

In [9]: print(GF)
<Galois Field: GF(2^100), prim_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 (1267650600228486663289456659305 decimal)>

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

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

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

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

In [17]: a * b
Out[17]: 
GF([x^99, x^61, x^75,
    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],
   order=2^100)