
				Magma
	Computational Algebra Group, University of Sydney

					john@maths.su.oz.au (John Cannon)


Recent advances in Computational Algebra have strongly emphasized the growing
inter-dependence between the various branches of the field. Thus, the new
Holt-Rees technique for splitting KG-modules makes heavy use of factorization 
of polynomials over finite fields. Bosma and H.W. Lenstra Jr have recently used
the Groebner basis technique for polynomial rings to determine minimal systems 
of addition laws for elliptic curves. The Leedham-Green algorithm for computing
the order of a matrix over GF(q) depends upon the ability to factor integers of
the form p^n - 1. Up until the present, advanced algorithms for the various 
branches of algebra, geometry and number theory have tended to be implemented 
in packages designed for a very specific area: E.g. CAYLEY, COCOA, KANT, 
Macaulay, Pari, SAC, SIMATH. In order to provide mathematicians with the 
ability to write programs which may utilize the algorithmic machinery from 
these diverse fields, the Computational Algebra Group at Sydney University has 
designed a new system, known as MAGMA which provides a *unified enviroment* for
efficient computation in the principal structures of modern algebra viz. groups,
rings, fields and modules. This system extends the ideas of *structural 
computation*, successfully developed for group theory over the past two decades
in the CAYLEY system, to algebra generally.

MAGMA has a functional-style programming language in which the principal data 
types are sets, sequences, structures (magmas) and mappings. The kernel 
contains efficient implementations of many of the principal algorithms in 
Module Theory, Ring Theory, Group Theory, Algebraic Number Theory and Algebraic
Combinatorics.


This system is designed to support computation in algebra, number theory,
geometry and algebraic combinatorics. The system has an advanced functional
programming language with many novel features designed for concise and
efficient specification of algebraic algorithms. The system has coded
into its kernel the fundamental algorithms for ring theory (polynomial
rings, matrix rings, integer rings), field theory (general algebraic
number fields -- KANT2, finite fields, real and complex fields), module 
theory, group theory (fp groups, permutation groups, soluble groups
and matrix groups) and algebraic combinatorics (coding theory and graph theory).

The flavour of the language may be gained from the following sample of code
partially implementing polynomial factorization over Z.

-------------------------------------------------------------------------------
function SquarefreeFactorization(apoly)

   P<x> := Parent(apoly); 
   p := Characteristic(CoefficientRing(P));
   deriv := Derivative(apoly,1);
   if IsZero(deriv) then
      /* apoly = u(x^p) = u(x)^p */
      acoeffs := Coefficients(apoly); 
      u := &+[acoeffs[i]*x^((i-1) div p) : 
                    i in [1 .. #acoeffs]];
      v := $$(u); return &cat[v:i in [1 .. p]];
   end if;
   g := Gcd(apoly, deriv);
   if IsOne(g) then
      return [apoly];
   else
      return $$(g) cat $$(apoly div g);
   end if;

end function;


function Qmatrix (apoly)

   P := Parent(apoly); n := Degree(apoly);
   CField := CoefficientRing(P); // GF(p^d)
   p:=Characteristic(CField); 
   d:= Degree(CField); q:=p^d;
   Q<x> := quo<P | Ideal(apoly)>;
   cseq := [Coefficients(Q!1)]; //x^0
   xq := x^q; xqk := xq;
   for k in [1 .. n-1] do
      cseq := cseq cat [Coefficients(xqk)];
      xqk := xqk*xq; // Multiply in Q
   end for; // A sequence of sequences 
   qseq := // Just pad each row out with zeros
   return MatrixRing(CField, n) ! qseq;

end function;

function Hensel(f, g1, h1, k)

   Rp := Parent(g1); // Zp[x]
   p := Modulus(CoefficientRing(Rp));
   Zx := FreeRing(Integers(), ["x"]);
   g := g1; h := h1; pi := p;
   one, grecip, hrecip := Xgcd(g1, h1);
   for i in [2 .. k] do
      pim1 := pi; pi := pi*p;
      Zpi<x> := FreeRing(Integers(pi), ["x"]);
      Zpi1 := FreeRing(Integers(pi*p), ["y"]);
      Disc:=Zpi1!(Zx!(Zpi!f-Zpi!g*Zpi!h)/pim1);
      gcorr:=Rp!(Disc*Zpi1!hrecip) mod g1;
      hcorr:=Rp!(Disc*Zpi1!grecip) mod h1;
      g := Zpi!g + pim1 * Zpi!gcorr;
      h := Zpi!h + pim1 * Zpi!hcorr;
   end for;
   return [g,h];

end function;


