initsualt:=function(dd,qq);
onespots:=[];
d:=dd;
q:=qq^2;
e:=d;
H:=SU(d,qq);
G:=Group(constructalt(H));
Print("The group has been constructed.\n");
list:=findsingeralt(d,q,G);
s:=list[1]; eig:=list[2];
Print("The special element s has been constructed.\n");
Print("The eigenvalues of s have been found.\n");

orb:= Orbits( Group( FrobeniusAutomorphism( GF( q ^ e ) )^(DegreeOverPrimeField(GF(q))) ), eig );
l:=identifyevaluesalt(d,q,orb);
Print("The eigenvalues have been labelled.\n");
f:=recordf(s,l);
c:=findc(f);
Print("The constants cij have been computed.");

end;

findsingeralt:=function(d,q,g)
local s,ev,pol,fac,divisors,set,exp;
repeat 
   s:=PseudoRandom(g);
   pol:=CharacteristicPolynomial(s);
   fac:=Factors(pol);
   degrees:=List([1..Length(fac)],
        x -> -1+Length(CoefficientsOfLaurentPolynomial(fac[x])[1]));
   set:=Set(degrees);
   if IsSubset([d/2,d],set) and d in set then 
      ev:=Eigenvalues(GF(q^d),s);
   else 
      ev:=[];
   fi;  
until Length(ev)=Binomial(d,2);
divisors:=Difference(DivisorsInt(d),[d/2,d]);
exp:=Product(divisors,x->(q^x-1));
if s^exp = s^0 then Error(2); fi;
return [s,ev];
end;


initslalt:=function(dd,qq);
onespots:=[];
d:=dd;
q:=qq;
e:=dd;
d:=dd;
H:=SL(d,qq);
G:=conjalt(H);
Print("The group has been constructed.\n");
list:=findsingeralt(d,q,G);
s:=list[1]; eig:=list[2];
Print("The special element s has been constructed.\n");
Print("The eigenvalues of s have been found.\n");

orb:= Orbits( Group( FrobeniusAutomorphism( GF( q ^ e ) )^(DegreeOverPrimeField(GF(q))) ), eig );
l:=identifyevaluesalt(d,q,orb);
Print("The eigenvalues have been labelled.\n");
f:=recordf(s,l);
c:=findc(f);
Print("The constants cij have been computed.");
end;

testelements:=function(G) local g,gg,a,aa,aaa;
g:=PseudoRandom(G);
gg:=PseudoRandom(G);
a:=image(g,c,f);
aa:=image(gg,c,f);
aaa:=image(g*gg,c,f);
return a[1]*aa[1]=aaa[1] or a[1]*aa[1]=-aaa[1];
end;

constructalt:=function ( G )
    local  kron, x, gmod, cf, alt;
    kron := [  ];
    for x  in GeneratorsOfGroup( G )  do
        Add( kron, KroneckerProduct( x, x ) );
    od;
    gmod := GModuleByMats( kron, GF( q ) );
    cf := MTX.CompositionFactors( gmod );
    alt := Filtered( cf, function ( x )
            return x.dimension > d and x.dimension <= d ^ 2 / 2;
        end );
    return alt[1].generators;
end;

constructmod:=function ( G )
    local  kron, x, gmod, cf, alt;
    kron := [  ];
    for x  in GeneratorsOfGroup( G )  do
        Add( kron, KroneckerProduct( x, x ) );
    od;
    gmod := GModuleByMats( kron, GF( q ) );
    cf := MTX.CompositionFactors( gmod );
return cf;
end;

constructsym:=function ( G )
    local  kron, x, gmod, cf, sym;
    kron := [  ];
    for x  in GeneratorsOfGroup( G )  do
        Add( kron, KroneckerProduct( x, x ) );
    od;
    gmod := GModuleByMats( kron, GF( q ) );
    cf := MTX.CompositionFactors( gmod );
    sym := Filtered( cf, function ( x )
            return x.dimension >= 2 and x.dimension >= d ^ 2 / 2;
        end );
    return sym[1].generators;
end;

conjsym:=function ( G )
    local  r, dim, sym;
    sym := constructsym( G );
    dim := Length( sym[1] );
    r := PseudoRandom( GL( dim, q ) );
    return Group( List( sym, x-> x^r) );
end;
conjalt:=function ( G )
    local  r, dim, alt;
    alt := constructalt( G );
    dim := Length( alt[1] );
    r := PseudoRandom( GL( dim, q ) );
    return Group( List( alt, x-> x^r) );
end;

constructtensorbits:=function ( G )
    local  kron, x, gmod, cf, sym;
    kron := [  ];
    for x  in GeneratorsOfGroup( G )  do
        Add( kron, KroneckerProduct( x, x ) );
    od;
    gmod := GModuleByMats( kron, GF( q ) );
    cf := MTX.CompositionFactors( gmod );
    return cf;
end;
codepair:=function(d,i,j) local int;
if i > j then return codepair(d,j,i);else
int:= (i-1)*d+j-(i+1)*(i)/2;
int:=int-Number(onespots, x->int>x);
return int;

fi;
end;

#returns k_{ij,kl}
kappa:=function(kap,i,j,k,l);
return kap[codepair(d,i,j)][codepair(d,k,l)];end;

#computation of B_{ijk} from the paper
bijk:=function(d,q,kap,i,j,k)
local ij, ik, jk, cc, bb, det;

#we compute the entries of B_{ijk} 

if i<j then 
   ij:=codepair(d,i,j);
else 
   ij:=codepair(d,j,i);
fi;
if i<k then 
   ik:=codepair(d,i,k);
else 
   ik:=codepair(d,k,i);
fi;
if j<k then 
   jk:=codepair(d,j,k);
else 
   jk:=codepair(d,k,j);
fi;

cc:=NullMat(3,3,GF(q));
cc[1][1]:=kap[jk][jk];
cc[1][2]:=-kap[ik][jk];
cc[1][3]:=kap[ij][jk];
cc[2][1]:=-kap[jk][ik];
cc[2][2]:=kap[ik][ik];
cc[2][3]:=-kap[ij][ik];
cc[3][1]:=kap[jk][ij];
cc[3][2]:=-kap[ik][ij];
cc[3][3]:=kap[ij][ij];

det:=Determinant(cc);
if det = 0 then 
   return fail;
fi;
det:=SquareRoots(GF(q^d),det)[1];
bb:=cc^(-1);
return bb*det;
end;


recordf:=function(s,l) local f,i,j;
f:=0*[1..Size(s)];
for j in [2..d] do;
f[codepair(d,1,j)]:= NullspaceMat(s-l[codepair(d,1,j)]*IdentityMat(Size(s), GF(q^d)))[1];
od;
for i in [2..d-1] do;
for j in [i+1..d] do;
f[codepair(d,i,j)]:=List(f[codepair(d,i-1,j-1)], x->x^q);
od;od;
return f;
end;

C:=function(kap,i,j,k);
return
[[kappa(kap,j,k,j,k),-kappa(kap,i,k,j,k),kappa(kap,i,j,j,k)],
[-kappa(kap,j,k,i,k),kappa(kap,i,k,i,k),-kappa(kap,i,j,i,k)],
[kappa(kap,j,k,i,j),-kappa(kap,i,k,i,j),kappa(kap,i,j,i,j)]];
end;

BB:=function(kap,i,j,k) local mat, mat2;
mat:=C(kap,i,j,k);
mat2:=mat^(-1)*SquareRoots(GF(q^d),Determinant(mat))[1];
if mat2[1][1] <> a[i][i] then mat2:=-mat2;fi;
return mat2;

end;

findc:=function(f) local B123, B13k, xexp, yexp, B124, B12k, c, kap;
finv:=f^(-1);
g:=PseudoRandom(G);
kap:=g^(finv);

c:=NullMat(d,d,GF(q^d));
xexp:=List([1..d],x-> 0*[1..d]);
yexp:=List([1..d],x-> 0*[1..d]);
c[1][2]:=Z(q^d)^0;
xexp[1][2]:=1;
yexp[1][2]:=0;
c[1][3]:=Z(q^d)^0;
xexp[1][3]:=0;
yexp[1][3]:=1;


B123:=bijk(d,q,kap,1,2,3);
for k in [4,6..Int(e/2)*2] do;
B13k:=bijk(d,q,kap,1,3,k);
if B13k[1][1] <> B123[1][1] then B13k:=-B13k;fi;
c[1][k]:=B123[3][1]/B13k[2][1]*c[1][k-2]^(q^2);
xexp[1][k]:=xexp[1][k-2]*q^2 + 1-q;
yexp[1][k]:=yexp[1][k-2]*q^2;
od;

B123:=bijk(d,q,kap,1,2,3);
B124:=bijk(d,q,kap,1,2,4);
if B124[1][1] <> B123[1][1] then B124:=-B124;fi;
B134:=bijk(d,q,kap,1,3,4);
if B134[1][1] <> B123[1][1] then B134:=-B134;fi;
powerofy:=B123[3][1]*B124[2][1]/(B134[2][1]*B123[2][1]);


for k in [5,7..Int(e/2)*2-1] do;

B12k:=bijk(d,q,kap,1,2,k);
if B12k[1][1] <> B123[1][1] then B12k:=-B12k;fi;
if B12k[1][1] <> B123[1][1] then B12k:=-B12k;fi;
c[1][k]:=(c[1][k-1]^q)*B123[2][1]/B12k[2][1];
xexp[1][k]:= q*xexp[1][k-1] - q;
yexp[1][k]:= q*yexp[1][k-1] +1;
od;

c[1][3]:=Z(q^d)^0;
for i in [2..d-1] do;
for j in [i+1..d] do;
c[i][j]:=(c[i-1][j-1]^q);
xexp[i][j]:=q*xexp[i-1][j-1];
yexp[i][j]:=q*yexp[i-1][j-1];
if yexp[i][j]=q then 
c[i][j]:=c[i][j]*powerofy;
yexp[i][j]:=yexp[i][j] - (q+1);
xexp[i][j]:=xexp[i][j] + (q^2+1);
fi;

if yexp[i][j]=-q then 
c[i][j]:=c[i][j]/powerofy;
yexp[i][j]:=yexp[i][j] + (q+1);
xexp[i][j]:=xexp[i][j] - (q^2+1);
fi;
od;od;

return [c, xexp,yexp];
end;


image:=function(g,cout,f) local  c,i,j,k,x,y, xexp,yexp;
c:=cout[1];
xexp:=cout[2];
yexp:=cout[3];
a:=NullMat(d,d,GF(q^d));
x:=List([1..d],x-> 0*[1..d]);
y:=List([1..d],x-> 0*[1..d]);
kap:=g^(finv);

mat:=C(kap,1,2,3);
B123:=mat^(-1)*SquareRoots(GF(q^d),Determinant(mat))[1];
a[1][1]:=B123[1][1];
a[2][2]:=B123[2][2];
a[3][3]:=B123[3][3];
a[1][2]:=B123[1][2]*c[2][3]/c[1][3];
x[1][2]:=q;
y[1][2]:=-1;

a[2][1]:=B123[2][1]*c[1][3]/c[2][3];
x[2][1]:=-q;
y[2][1]:=1;

for j in [3..d] do;
mat:=C(kap,1,2,j);
B12j:=mat^(-1)*SquareRoots(GF(q^d),Determinant(mat))[1];
if B12j[1][1] <> B123[1][1] then B12j:=-B12j;fi;

a[1][j]:=B12j[1][3]*c[2][j]/c[1][2];
x[1][j]:=xexp[2][j] - xexp[1][2];
y[1][j]:=yexp[2][j] - yexp[1][2];

a[j][1]:=B12j[3][1]*c[1][2]/c[2][j];
x[j][1]:=xexp[1][2] - xexp[2][j];
y[j][1]:=yexp[1][2] - yexp[2][j];
od;

for i in [2..d] do;
for j in [2..d] do;
a[i][j]:=a[i-1][j-1]^q;
x[i][j]:=x[i-1][j-1]*q;
y[i][j]:=y[i-1][j-1]*q;

if y[i][j]=q then 
a[i][j]:=a[i][j]*powerofy;
y[i][j]:=y[i][j] - (q+1);
x[i][j]:=x[i][j] + (q^2+1);
fi;

if y[i][j]=-q then 
a[i][j]:=a[i][j]/powerofy;
y[i][j]:=y[i][j] + (q+1);
x[i][j]:=x[i][j] - (q^2+1);
fi;



od;od;
return [a,x,y];
end;


findB:=function(omega2) local B, i,j, omega;
omega:=SquareRoots(GF(q^d),omega2)[1];
B:=NullMat(d,d,GF(q^d));
for i in [1..d] do;
for j in [1..d] do;
B[i][j]:=(omega^(j-1))^(q^(i-1));
od;od;
return B;
end;


removeonespaces:=function(l,f,s);
if Size(f) > Size(s) then;
onespots:=Positions(l,One(GF(q)));
onespots:=[onespots[Size(onespots)]];
Remove(f,onespots[1]);
Remove(l,onespots[1]);
fi;
end;

identifyevaluesalt:=function(d,q,orbits)
local llist, bad, ready, good, i, evalues, orb, j, ev, oo, x, lij, 
      short, omega;

evalues:=Union(orbits);
ready:=false;
for orb in orbits do
    if not ready and Length(orb) =d then 
       bad:=false;
       #llist contains l_(1,2i)
       llist:=[orb[1],orb[1]^(q^2-q+1)];
       for i in [3..Int(d/2)] do 
          llist[i]:=llist[i-1]^(q^2+1)/llist[i-2]^(q^2);
       od;
       if d mod 2 = 1 then
          omegasq:=llist[(d-1)/2]^(q^2)/(llist[1]^(q-1));
          ev:=[];
          #the matrix good stores the l_{i,j} values identified
          good:=0*[1..d*(d-1)/2];
          if q mod 2 = 0 then
            omega:=omegasq^(q^d/2);
            for i in [1..d-1] do
               for j in [i+1..d] do
                  lij:=omega^(q^(i-1)+q^(j-1));
                  good[codepair(d,i,j)]:=lij;
                  Add(ev, lij);
               od;
            od;
          else
            for i in [1..d-1] do
               for j in [i+1..d] do
                  lij:=omegasq^((q^(i-1)+q^(j-1))/2);
                  good[codepair(d,i,j)]:=lij;
                  Add(ev, lij);
               od;
            od;
          fi;
          ev:=Set(ev);
          if evalues = ev then 
             ready:=true;
          fi;
       elif d = 4 then 
          short:=Filtered(orbits, y->Length(y)=2);
          for x in short[1] do 
            if not ready then 
               omegasq:=x/llist[1]^(q-1);
               ev:=[];
               #the matrix good stores the l_{i,j} values identified
               good:=0*[1..d*(d-1)/2];
               if q mod 2 = 0 then
                  omega:=omegasq^(q^d/2);
                  for i in [1..d-1] do
                    for j in [i+1..d] do
                      lij:=omega^(q^(i-1)+q^(j-1));
                      good[codepair(d,i,j)]:=lij;
                      Add(ev, lij);
                    od;
                  od;
               else
                  for i in [1..d-1] do
                    for j in [i+1..d] do
                      lij:=omegasq^((q^(i-1)+q^(j-1))/2);
                      good[codepair(d,i,j)]:=lij;
                      Add(ev, lij);
                    od;
                  od;
               fi;
               ev:=Set(ev);
               if evalues = ev then 
                 ready:=true;
                 
               fi;
            fi;
          od;
       else
          for oo in orbits do
              if Length(oo)=d then
                 x:=First(oo,y->y^(q+1)=llist[1]^(q^2+1));
                 if x<>fail then
                    omegasq:=x/llist[1]^(q-1);
                    ev:=[];
                    #the matrix good stores the l_{i,j} values identified
                    good:=0*[1..d*(d-1)/2];
                    if q mod 2 = 0 then
                      omega:=omegasq^(q^d/2);
                      for i in [1..d-1] do
                        for j in [i+1..d] do
                           lij:=omega^(q^(i-1)+q^(j-1));
                           good[codepair(d,i,j)]:=lij;
                           Add(ev, lij);
                        od;
                      od;
                    else
                      for i in [1..d-1] do
                        for j in [i+1..d] do
                           lij:=omegasq^(q^(i-1)/2+q^(j-1)/2);
                           good[codepair(d,i,j)]:=lij;
                           Add(ev, lij);
                         od;
                       od;
                    fi;
                    ev:=Set(ev);
                    if ev=evalues then
                        ready:=true;
                        
                        break;
                    fi;
                 fi;                    
              fi;
          od;
       fi;
    fi;
od;
if not ready then 
   Error(111); 
fi;

return good;
end;
