/*
------------------------------------------------------------------------
Efficient Galois Fields in Maxima

by Alasdair McAndrew
and later extended by Fabrizio Caruso and Jacopo Daurizio

it is distribuited together with gf_roots by Jacopo Daurizio

Authors:

Fabrizio Caruso (optimizations, testing)
Jacopo D'Aurizio (optimizations, modular roots)
Alasdair McAndrew (original version of the package, pohlig-helman log, etc... )
------------------------------------------------------------------------*/

/* Released under terms of the GNU General Public License, version 2,
* by permission of the authors to Robert Dodier circa 2007-12-02.
*/

/* Defines a flag for dealing with large fields. If it is set to "false",
then lookup tables are used for exponentiation and logarithms. Otherwise
other algorithms are used */

define_variable(,true,)$
define_variable(,0,)$
define_variable(,0,)$
define_variable(,0,)$
define_variable (, ', )$
define_variable (, ', )$
define_variable (, ', )$
define_variable (, ', )$
define_variable (, ', )$
remvalue(,,,,,,,,,,,,)$


/* --------------------------------------------------------------------------------------------- */
/* Settings */

:false; /* Verbosity */
: true; /* Warnings */
:false; /* Irreducibility test for the minimal polynomial of the extension */

/*
------------------------------------------------------------------------------------------------ */


/* It defines a new current field with gf_char=b, min. pol.= p of deg= e*/
([]):=block([,,,,],
if length()=1 then
(
([1]),
return(true)
)
else
(
if length()=2 then
(
if numberp([2]) then
(
if [2]=0 and then
(
print("WARNING: the irreducible is zero! We assume GF(",[1],")"),
([1]),
return(true)
)
else
(
error("ERROR: you tried to extend with a non-zero constant!"),
return(false)
)
)
else
(
:hipow([2],),

if =1 then
([1]),
:[2],
:,
return(true)
)
)
else
(
:[2],
if =1 then
(
([1]),
:rat([3]),
return(true)
),
:rat([3])
)
),

:[1],
:rat(1,),
:^-1,

:makelist(coeff(,,),,0,),
:[[first(),0]],:1,
for :2 thru +1 do if []=0 then :+1 else ( :endcons([[],],), :1 ),

if not(primep()) then error("ERROR: Gf_Char must be a prime number.")
else
modulus:,
if and
hipow(args(factor([3]))[1],)#hipow(rat([3]),) then
error("ERROR: Polynomial is not irreducible"),

if not() then
(
:(),
:()
)
else
(
if then
print("finding a primitive element..."),

:rat((),),
if then
print("...primitive element found.")

),
modulus:false, /* it resets the modulus */
return(true)

)$


/* Prints out information about the field */
():=block(
print("Prime gf_char value: ",),
print("Exponent: ", ),
print("Multiplicative order: ",),
print("Irreducible polynomial: ",),
print("Primitive element: ",),
if () then
print("Largefield flag is true; powers and logarithms not computed.")
else
print("Largefield flag is false; powers and logarithms computed."),
disp()
)$