`Class/Declare`(
 "PK_subfield",
 "An instance of this class represents a subfield of the field $PK$ of functions on $PX(a)$ generated by the functions $w$ and $z$",

 ["Field","stabiliser"::list,"The list of elements of the group $G_{16}$ that act as the identity on this subfield"],
 ["Field","generating_sets"::list,"A list of generating sets for the subfield"],
 ["Field","conversion_rules"::table,"In the $(i,j)$ slot this should have a list of equations expressing the elements of generating set $i$ in terms of generating set $j$.  The $(i,i)$ slots can be left unset."],

 ["Method","check_stabiliser","",
  proc(this)
   local A,B,F,a,T,err,H;

   A := {op(map(op,this["generating_sets"]))};
   F := table():

   for a in A do
    for T in G8 do
     err := simplify(act_PK[T](a) - a);
     F[a,T] := evalb(err = 0);
    od;
   od;

   for a in A do
    for T in this["stabiliser"] do 
     if not(F[a,T]) then
      printf("%A is not fixed by %A\n",a,T);
      return false;
     fi;
    od;
   od;

   for B in this["generating_sets"] do
    H := select(T -> (map(a -> F[a,T],{op(B)}) = {true}),G8);
    if H <> this["stabiliser"] then
     printf("stabiliser(%A) = %A\n",B,H);
     return false;
    fi;
   od:

   return true;
  end
 ],

 ["Method","check_conversion","",
  proc(this)
   local i,j,n,A,B,C,R,E,e,err;

   A := this["generating_sets"];
   n := nops(A);
   R := eval(this["conversion_rules"]);
   for i from 1 to n do
    for j from 1 to n do
     if i <> j then
      B := A[i]; 
      C := A[j];
      E := R[i,j];
      if not(type(E,list(equation))) then
       printf("rule (%d,%d) is not a list of equations \n",i,j);
       return false;
      fi;
      if {op(map(lhs,E))} <> {op(B)} then
       printf("rule (%d,%d) is not a list of equations for generating set %d\n",i,j,i);
       return false;
      fi;
      if indets({op(map(rhs,E))}) minus {op(C)} <> {} then
       printf("rule (%d,%d) does not express generating set %d in terms of generating set %d\n",i,j,i,j);
       return false;
      fi;

      for e in E do 
       if not(PK_check_zero(lhs(e) - rhs(e))) then
        printf("in rule (%d,%d), equation %A is incorrect\n",i,j,e);
        return false;
       fi;
      od;
     fi;
    od;
   od;

   return true;
  end
 ],

 ["Method","check","",
  proc(this)
   this["check_stabiliser"] and this["check_conversion"];
  end
 ]
):

PK_subfields := table():

######################################################################

PK_subfields[ 1] := `new/PK_subfield`():
PK_subfields[ 1]["stabiliser"] := [1];
PK_subfields[ 1]["generating_sets"] := [[z,w],[t[0],u[0]]];
CR := table():
CR[1,2] := [z = t[0],w = u[0]];
CR[2,1] := [t[0] = z,u[0] = w];
PK_subfields[ 1]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 2] := `new/PK_subfield`():
PK_subfields[ 2]["stabiliser"] := [1,LL];
PK_subfields[ 2]["generating_sets"] := [[z],[t[0]]];
CR := table():
CR[1,2] := [z = t[0]];
CR[2,1] := [t[0] = z];
PK_subfields[ 2]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 3] := `new/PK_subfield`():
PK_subfields[ 3]["stabiliser"] := [1,L,LL,LLL];
PK_subfields[ 3]["generating_sets"] := [[t[1]]];
CR := table():
PK_subfields[ 3]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 4] := `new/PK_subfield`():
PK_subfields[ 4]["stabiliser"] := [1,M];
PK_subfields[ 4]["generating_sets"] := [[t[2],u[1]],[t[2],v[1]]];
CR := table():
CR[1,2] := [t[2] = t[2],u[1] = -v[1]*t[2]^3/(2+t[2])];
CR[2,1] := [t[2] = t[2],v[1] = -u[1]*(2+t[2])/t[2]^3];
PK_subfields[ 4]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 5] := `new/PK_subfield`():
PK_subfields[ 5]["stabiliser"] := [1,LM];
PK_subfields[ 5]["generating_sets"] := [[t[3],u[2]],[t[3],v[2]]];
CR := table():
CR[1,2] := [t[3] = t[3],u[2] = -(1-I)/sqrt(2)*v[2]*t[3]^3/(2+t[3])];
CR[2,1] := [t[3] = t[3],v[2] = -(1+I)/sqrt(2)*u[2]*(2+t[3])/t[3]^3];
PK_subfields[ 5]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 6] := `new/PK_subfield`():
PK_subfields[ 6]["stabiliser"] := [1,LLM];
PK_subfields[ 6]["generating_sets"] := [[t[2],u[3]],[t[2],v[3]]];
CR := table():
CR[1,2] := [t[2] = t[2],u[3] = -I*v[3]*t[2]^3/(2-t[2])];
CR[2,1] := [t[2] = t[2],v[3] =  I*u[3]*(2-t[2])/t[2]^3];
PK_subfields[ 6]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 7] := `new/PK_subfield`():
PK_subfields[ 7]["stabiliser"] := [1,LLLM];
PK_subfields[ 7]["generating_sets"] := [[t[3],u[4]],[t[3],v[4]]];
CR := table():
CR[1,2] := [t[3] = t[3],u[4] = -(1+I)/sqrt(2)*v[4]*t[3]^3/(2-t[3])];
CR[2,1] := [t[3] = t[3],v[4] = -(1-I)/sqrt(2)*u[4]*(2-t[3])/t[3]^3];
PK_subfields[ 7]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 8] := `new/PK_subfield`():
PK_subfields[ 8]["stabiliser"] := [1,LL,M,LLM];
PK_subfields[ 8]["generating_sets"] := [[t[2]]];
CR := table():
PK_subfields[ 8]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[ 9] := `new/PK_subfield`():
PK_subfields[ 9]["stabiliser"] := [1,LL,LM,LLLM];
PK_subfields[ 9]["generating_sets"] := [[t[3]]];
CR := table():
PK_subfields[ 9]["conversion_rules"] := eval(CR):

##################################################

PK_subfields[10] := `new/PK_subfield`():
PK_subfields[10]["stabiliser"] := [1,L,LL,LLL,M,LM,LLM,LLLM];
PK_subfields[10]["generating_sets"] := [[t[4]]];
CR := table():
PK_subfields[10]["conversion_rules"] := eval(CR):