/* List of functions available:

   getCyclicDesc(r)
   getCyclicDescCent(r)
   cloneAttributesOfMG(~MG, MG_toCopy)
   getRootOfUnityMap(R, intMaxRu)
   makeMG(F, lstMat, lstProps)
   getMatrixGroupsByReplacingPrimElems(G,p,a)
   getRoots(strEqInX, R)

*****************************************************************************/

getCyclicDesc:= function(r)
	if (r gt 1) then
		return " x C_" cat IntegerToString(r);
	else
		return "";
	end if;
end function;

getCyclicDescCent:= function(r,c)
	if (r mod c eq 0) then
		return " o C_" cat IntegerToString(c*r);
	else
		return getCyclicDesc(r);
	end if;
end function;

cloneAttributesOfMG:= procedure(~MG, MG_toCopy)
	MG`CentralQuotient:= MG_toCopy`CentralQuotient;
	MG`Description:= MG_toCopy`Description;
	MG`Field:= MG_toCopy`Field;
	MG`Properties:= MG_toCopy`Properties;
end procedure;

getRootOfUnityMap:= function(R, intMaxRu)
	local P, x, f, rts;
	
	if (Category(R) eq FldCom) then
		return map<Integers() -> R | r :-> RootOfUnity(r)>;
	else
		P<x>:= PolynomialRing(R);
		f:= P! Eltseq(CyclotomicPolynomial(intMaxRu));
		rts:= Roots(f);
		return map<Integers() -> R | r :-> rts[1][1]^(intMaxRu div r)>;
	end if;
end function;

makeMG:= function(F, lstMat, lstProps)
    local MG;
	local d;
	
	d:= #Rows(lstMat[1]);
	
    MG:= MatrixGroup<d, F | lstMat>;
    MG`CentralQuotient := lstProps[1];
    MG`Description := lstProps[2];
    MG`Family := lstProps[3];
    MG`Field := F;
    
	if (#lstProps lt 4) then
		MG`Properties := "Modular, Irreducible, Insoluble";
    else
		MG`Properties := lstProps[4];   
    end if;
	
    return MG;
end function;

getMatrixGroupsByReplacingPrimElems:= function(G,p,a)
	listOfMatrices:= [];
	genG:= Generators(G);

	for matElemGen in genG do
		M:= GL(3,p^a)! matElemGen;
		Append(~listOfMatrices, M);		
	end for;

	return MatrixGroup<3, GF(p^a) | listOfMatrices>;

end function;

getRoots:= function(strEqInX, R)
	local P, x, rts;

	P<x>:= PolynomialRing(R);
	f:= eval(strEqInX);
	
	if (Degree(P! f) lt 2) then return []; end if;
	
	rts:= Roots(f);

	if (#rts ge 2) then
		return [x[1] : x in rts];
	else
		return [];
	end if;
end function;
