load "mat_subgroups_of_small_degree.m";

getListOfNonFinites:= function(lst)
	return [x : x in &cat(lst) | not(IsFinite(x))];
end function;

runCharZeroTests:= function(R)
	local lstR2, lstR3, lst;
	local lstNonFiniteR2, lstNonFiniteR3;

	print "Ring = ", R;
	print "  Dim 2:";
		lstR2:= getFiniteMatrixGroupsOfDimTwoOverPIDOfCharZero(R, true, true);
		lst:= &cat(lstR2);
		print "    No. of conjugacy classes = ", #lst;
		print "    Redundancies = ", not(#lst eq #Set(lst));
		try
			lstNonFiniteR2:= getListOfNonFinites(lstR2);
			print "    All groups are finite, result = ", IsEmpty(lstNonFiniteR2);
		catch e
			print "    Unable to test if all groups are finite for this Integral Domain.";
			lstNonFiniteR2:= e;
		end try;	
		//getDescription(lstR2);
	print "  Dim 3:";
		lstR3:= getFiniteMatrixGroupsOfDimThreeOverPIDOfCharZero(R, true, true);
		lst:= &cat(lstR3);
		print "    No. of conjugacy classes = ", #lst;
		print "    Redundancies = ", not(#lst eq #Set(lst));		
		try
			lstNonFiniteR3:= getListOfNonFinites(lstR3);
			print "    All groups are finite, result = ", IsEmpty(lstNonFiniteR3);
		catch e
			print "    Unable to test if all groups are finite for this Intergral Domain.";
			lstNonFiniteR3:= e;
		end try;
		//getDescription(lstR3);		
	return lstR2, lstNonFiniteR2, lstR3, lstNonFiniteR3;
end function;

print "Test 1: Soluble group test";
  L:= getMatrixSubgroupsOverSmallDegree(3, 5, ["soluble","irreducible"]);
  print "No. of soluble groups = ", #L;
  lstNonIrreducibles:= [x : x in L | not(IsIrreducible(x))];
  lstNonSolubles:= [x : x in L | not(IsSoluble(x))];
  print "All groups irreducible, result = ", IsEmpty(lstNonIrreducibles);
  print "All groups soluble, result = ", IsEmpty(lstNonSolubles);

print "\nTest 2: Insoluble groups over SL(3,q)";
	q:=19^6; // alter value of q here
	X:= getInsolubleMatrixGroupsOfDimThreeOverSL(GF(q));
	X:= &cat(X);
	X_not_det1:= [x : x in X | exists{y: y in Generators(x) | Determinant(y) ne 1}];
	X_subset_SL3q:=[x : x in X | x subset SL(3,q)];
	print "  SL Test: all determinant are 1, result = ", IsEmpty(X_not_det1);
	//print "  SL Test: all groups are in SL(3,q), result = ", X_subset_SL3q eq X;

print "\nTest 3: Rational Field";
Q:= Rationals();
lstQ2, lstNonFiniteQ2, lstQ3, lstNonFiniteQ3:= runCharZeroTests(Q);

print "\nTest 4: Integral Ring";
Zz:= Integers();
lstZ2, lstNonFiniteZ2, lstZ3, lstNonFiniteZ3:= runCharZeroTests(Zz);

print "\nTest 5: Gaussian Integers";
GI:= GaussianIntegers();
lstGI2, lstNonFiniteGI2, lstGI3, lstNonFiniteGI3:= runCharZeroTests(GI);

print "\nTest 6: Eisenstein Integer Ring";
E:= EisensteinIntegerRing();
lstE2, lstNonFiniteE2, lstE3, lstNonFiniteE3:= runCharZeroTests(E);

print "\nTest 7: Cyclotomic Fields";
CF:= CyclotomicField(3);
P<x>:= PolynomialRing(CF);
K:= NumberField(x^2 - 5);
lstK2, lstNonFiniteK2, lstK3, lstNonFiniteK3:= runCharZeroTests(K);

print "\nTest 8: Number Field over the Rationals\n";
P<x>:=PolynomialRing(Q);
Q_ru4:= NumberField(x^2 + 1);
Q_ru8:= NumberField(x^4 + 1);
Q_sqrt5:= NumberField(x^2 - 5);
Q_isqrt5:= NumberField(x^4 - 8*x^2 + 36);
Q_sqrtm7:= NumberField(x^2 + 7);
Q_ru3_sqrt5:= NumberField(x^4 + 2*x^3 - 7*x^2 - 8*x + 31);
Q_se:= ext<Q | x^2 + 2*x + 2>;
Q_sthr:= ext<Q | x^2 + 3>;
 
print "Dim 2:";
print "  Rationals + 4th root of unity:";
lstQ_ru4_2, lstNonFiniteQ_ru4_2, lstQ_ru4_3, lstNonFiniteQ_ru4_3:= runCharZeroTests(Q_ru4);

print "  Rationals + 8th root of unity:";
lstQ_ru8_2, lstNonFiniteQ_ru8_2, lstQ_ru8_3, lstNonFiniteQ_ru8_3:= runCharZeroTests(Q_ru8);

print "  Rationals + square root of 5:";
lstQ_sqrt5_2, lstNonFiniteQ_sqrt5_2, lstQ_sqrt5_3, lstNonFiniteQ_sqrt5_3:= runCharZeroTests(Q_sqrt5);

print "  Rationals + i + square root of 5:";
lstQ_isqrt5_2, lstNonFiniteQ_isqrt5_2, lstQ_isqrt5_3, lstNonFiniteQ_isqrt5_3:= runCharZeroTests(Q_isqrt5);

print "  Rationals + cube root of unity + square root of 5:";
lstQ_ru3_sqrt5_2, lstNonFiniteQ_ru3_sqrt5_2, lstQ_ru3_sqrt5_3, lstNonFiniteQ_ru3_sqrt5_3:= runCharZeroTests(Q_ru3_sqrt5);

print "  Rationals + i + square root of -7:";
lstQ_sqrtm7_2, lstNonFiniteQ_sqrtm7_2, lstQ_sqrtm7_3, lstNonFiniteQ_sqrtm7_3:= runCharZeroTests(Q_sqrtm7);

print "  Rationals with x^2 + 2x + 2:";
lstQ_se_2, lstNonFiniteQ_se_2, lstQ_se_3, lstNonFiniteQ_se_3:= runCharZeroTests(Q_se);

print "  Rationals with x^2 + 3:";
lstQ_sthr_2, lstNonFiniteQ_sthr_2, lstQ_sthr_3, lstNonFiniteQ_sthr_3:= runCharZeroTests(Q_sthr);

print "Test 9: Extensions of the Integers\n";
Z_ru4:= Integers(Q_ru4);
Z_ru8:= Integers(Q_ru8);
Z_sqrt5:= Integers(Q_sqrt5);
Z_isqrt5:= Integers(Q_isqrt5);
Q_alpha:= NumberField(x^2 + x + 2);
Z_alpha:= Integers(Q_alpha);
Q_beta:= NumberField(x^4 + x^3 + 2*x^2 - x + 1);
Z_beta:= Integers(Q_beta);

print "  Integers + 4th root of unity:";
lstZ_ru4_2, lstNonFiniteZ_ru4_2, lstZ_ru4_3, lstNonFiniteZ_ru4_3:= runCharZeroTests(Z_ru4);

print "  Integers + 8th root of unity:";
lstZ_ru8_2, lstNonFiniteZ_ru8_2, lstZ_ru8_3, lstNonFiniteZ_ru8_3:= runCharZeroTests(Z_ru8);

print "  Integers + square root of 5:";
lstZ_sqrt5_2, lstNonFiniteZ_sqrt5_2, lstZ_sqrt5_3, lstNonFiniteZ_sqrt5_3:= runCharZeroTests(Z_sqrt5);

print "  Integers + i + square root of 5:";
lstZ_isqrt5_2, lstNonFiniteZ_isqrt5_2, lstZ_isqrt5_3, lstNonFiniteZ_isqrt5_3:= runCharZeroTests(Z_isqrt5);

print "  Integers + alpha (deg 3 case should contain PSL(2,7)):";
lstZ_alpha_2, lstNonFiniteZ_alpha_2, lstZ_alpha_3, lstNonFiniteZ_alpha_3:= runCharZeroTests(Z_alpha);

print "  Integers + alpha (deg 3 case should contain 3.Alt(6)):";
lstZ_beta_2, lstNonFiniteZ_beta_2, lstZ_beta_3, lstNonFiniteZ_beta_3:= runCharZeroTests(Z_beta);

print "\nTest 10: Ensure 3.Alt(6) in some chosen finite groups";
lstGFsWith3A6:= [19,31,49,61,169];

for q in lstGFsWith3A6 do
	L:= getInsolubleNonmodularMatrixGroupsOfDimThreeFF(GF(q), false);
	lstGroupDescs:=[x`Description : x in &cat(L)];
	threeA6:= [x : x in &cat(L) | x`Description eq "3.A6"];
	print "  SL(3," cat IntegerToString (q) cat ") contains one copy of 3.Alt(6), result = ", (#threeA6 eq 1);
	if (#threeA6 eq 1) then
		print "  Size of 3.Alt(6) is correct, result = ", (#threeA6[1] eq 1080);
	end if;
end for;

print "\nTest 11: Check groups given in thesis timings";
lstGFsWithExpectedSizes:= [[5,11],[5^4,326],[5^10,1272],[5^12,7760],[97^5, 736],[17^6,4064]];

for qs in lstGFsWithExpectedSizes do
	q:= qs[1];
	s:= qs[2];
	L:= getInsolubleMatrixGroupsOfDimThreeFF(GF(q), true, true);
	print "  No. of conjugacy classes of insoluble irreducible subgroups of GL(3," cat IntegerToString(q) cat
		  ") is", s, ", result = ", (#&cat(L) eq s);
end for;

print "\nTest 12: Univariate Polynomial Ring over Rationals";
lstP2, lstNonFiniteP2, lstP3, lstNonFiniteP3:= runCharZeroTests(P);