
// Make newform 21.24.g.a in Magma, downloaded from the LMFDB on 25 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_21_g();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_21_g_Hecke();"
// To make the coeffs of the qexp of the newform in the Hecke field type "qexpCoeffs();"
// To make the newform (type ModFrm), type "MakeNewformModFrm_21_24_g_a();".
// This may take a long time!  To see verbose output, uncomment the SetVerbose lines below.
// The precision argument determines an initial guess on how many Fourier coefficients to use.
// This guess is increased enough to uniquely determine the newform.
// To make the Hecke irreducible modular symbols subspace (type ModSym)
// containing the newform, type "MakeNewformModSym_21_24_g_a();".
// This may take a long time!  To see verbose output, uncomment the SetVerbose line below.
// The default sign is -1.  You can change this with the optional parameter "sign".
function ConvertToHeckeField(input: pass_field := false, Kf := [])
    if not pass_field then
        poly := [1, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rfbasis := [Kf.1^i : i in [0..Degree(Kf)-1]];
    inp_vec := Vector(Rfbasis)*ChangeRing(Transpose(Matrix([[elt : elt in row] : row in input])),Kf);
    return Eltseq(inp_vec);
end function;


// To make the character of type GrpDrchElt, type "MakeCharacter_21_g();"
function MakeCharacter_21_g()
    N := 21;
    order := 6;
    char_gens := [8, 10];
    v := [3, 5];
    // chi(gens[i]) = zeta^v[i]
    assert UnitGenerators(DirichletGroup(N)) eq char_gens;
    F := CyclotomicField(order);
    chi := DirichletCharacterFromValuesOnUnitGenerators(DirichletGroup(N,F),[F|F.1^e:e in v]);
    return MinimalBaseRingCharacter(chi);
end function;

// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_21_g_Hecke();"
function MakeCharacter_21_g_Hecke(Kf)
    N := 21;
    order := 6;
    char_gens := [8, 10];
    char_values := [[-1, 0], [0, 1]];
    assert UnitGenerators(DirichletGroup(N)) eq char_gens;
    values := ConvertToHeckeField(char_values : pass_field := true, Kf := Kf); // the value of chi on the gens as elements in the Hecke field
    F := Universe(values);// the Hecke field
    chi := DirichletCharacterFromValuesOnUnitGenerators(DirichletGroup(N,F),values);
    return chi;
end function;


function ExtendMultiplicatively(weight, aps, character)
    prec := NextPrime(NthPrime(#aps)) - 1; // we will able to figure out a_0 ... a_prec
    primes := PrimesUpTo(prec);
    prime_powers := primes;
    assert #primes eq #aps;
    log_prec := Floor(Log(prec)/Log(2)); // prec < 2^(log_prec+1)
    F := Universe(aps);
    FXY<X, Y> := PolynomialRing(F, 2);
    // 1/(1 - a_p T + p^(weight - 1) * char(p) T^2) = 1 + a_p T + a_{p^2} T^2 + ...
    R<T> := PowerSeriesRing(FXY : Precision := log_prec + 1);
    recursion := Coefficients(1/(1 - X*T + Y*T^2));
    coeffs := [F!0: i in [1..(prec+1)]];
    coeffs[1] := 1; //a_1
    for i := 1 to #primes do
        p := primes[i];
        coeffs[p] := aps[i];
        b := p^(weight - 1) * F!character(p);
        r := 2;
        p_power := p * p;
        //deals with powers of p
        while p_power le prec do
            Append(~prime_powers, p_power);
            coeffs[p_power] := Evaluate(recursion[r + 1], [aps[i], b]);
            p_power *:= p;
            r +:= 1;
        end while;    
    end for;
    Sort(~prime_powers);
    for pp in prime_powers do
        for k := 1 to Floor(prec/pp) do
            if GCD(k, pp) eq 1 then
                coeffs[pp*k] := coeffs[pp]*coeffs[k];
            end if;
        end for;
    end for;
    return coeffs;
end function;


function qexpCoeffs()
    // To make the coeffs of the qexp of the newform in the Hecke field type "qexpCoeffs();"
    weight := 24;
    raw_aps := [[0, 0], [-177147, -177147], [0, 0], [3927060206, 2011692651], [0, 0], [-4830757327717, 9661514655434], [0, 0], [999886934447166, -499943467223583], [0, 0], [0, 0], [-162917117739084565, -162917117739084565], [0, 2053267080544957427], [0, 0], [5063598036403118305, 0], [0, 0], [0, 0], [0, 0], [714638362101378972008, -357319181050689486004], [-1890156096633289486793, 1890156096633289486793], [0, 0], [2972303387757082416447, 2972303387757082416447], [0, -211180652241182634413], [0, 0], [0, 0], [-63921290897278826857544, 127842581794557653715088], [0, 0], [-78444557571492105554726, 39222278785746052777363], [0, 0], [-60213994466374414775467, 60213994466374414775467], [0, 0], [-2746146814090739503381117, 0], [0, 0], [0, 0], [4058391790973600030071927, -8116783581947200060143854], [0, 0], [-13261449896376159149343484, 13261449896376159149343484], [9971683289138658727330716, 9971683289138658727330716], [0, 47695365822121162647814504], [0, 0], [0, 0], [0, 0], [-103318946221336958863593555, 206637892442673917727187110], [0, 0], [220229847122451696766732775, -220229847122451696766732775], [0, 0], [96448445376745887825253522, 96448445376745887825253522], [-804441438772152789713357264, 0], [-1110034527327971483845754118, 2220069054655942967691508236], [0, 0], [-1935505204431179376097755706, 967752602215589688048877853], [0, 0], [0, 0], [669126623497422301217293424, 669126623497422301217293424], [0, 0], [0, 0], [0, 0], [0, 0], [3834170099900491161015400660, -1917085049950245580507700330], [-16184303427626996757580987517, 16184303427626996757580987517], [0, 0], [1953443794518654103516239673, 1953443794518654103516239673], [0, 0], [41918331294332277769341851957, -83836662588664555538683703914], [0, 0], [-28359472520630712598031612022, 14179736260315356299015806011], [0, 0], [0, 112348573873768519938725958509], [-92415456190882481585250005, 0], [0, 0], [-167580411722586867927393676540, 335160823445173735854787353080], [0, 0], [0, 0], [-75870651081902053672606755447, -75870651081902053672606755447], [0, -750441936442237053494548883399], [487574607785960944570239002863, 0], [0, 0], [0, 0], [1583987510150541185532912477166, -791993755075270592766456238583], [0, 0], [817185800632086793954708383313, 817185800632086793954708383313], [0, 0], [-3013103997889352333369596465879, 0], [0, 0], [-1325234375526911541550540083779, 2650468751053823083101080167558], [-2447091036949779290708520173316, 1223545518474889645354260086658], [0, 0], [0, 0], [0, 7345204738488937613103115737953], [0, 0], [-3532077397749420092594541384919, 0], [0, 0], [0, 0], [15467918957245559220166959266225, -15467918957245559220166959266225], [0, 0], [0, -21324328973498794663821670184857], [0, 0], [0, 0], [0, 0], [-15627912699280786614720656062918, 7813956349640393307360328031459], [0, 12160778264535961822413436690111], [-61328711140341169483029046357240, 0], [0, 0], [0, 0], [0, 0], [50461961588436814456736255583421, -50461961588436814456736255583421], [65266246444414523223564874702387, 65266246444414523223564874702387], [0, 0], [0, 0], [0, 0], [75951349320901944049039808266199, -151902698641803888098079616532398], [153159991157962210044156772176102, -76579995578981105022078386088051], [227275702806293744752338174483490, -227275702806293744752338174483490], [0, 0], [113368060006215928976945523066815, 113368060006215928976945523066815], [176322857905322217493404509373524, 0], [0, 0], [227242974072137605853973025655857, -454485948144275211707946051311714], [0, 0], [0, 0], [0, 0], [224354820200922803402503967546811, 224354820200922803402503967546811], [369685878201482240187285084184549, 0], [0, 0], [0, 0], [-812609642260580367856232921555918, 406304821130290183928116460777959], [0, 0], [0, -438511388700292372058812007515198], [0, 0], [433032344678172659792805616520779, -866064689356345319585611233041558], [2025901589773586829031771871495146, -1012950794886793414515885935747573], [-866720463839385967696758275250647, 866720463839385967696758275250647], [0, 0], [0, -1303733091579146998271262744607369], [-2440925259766926481079622880464338, 0], [0, 0], [-1738828076434410598894611461047695, 3477656152868821197789222922095390], [0, 0], [2297652400211808113088602353839274, 2297652400211808113088602353839274], [0, 0], [0, 0], [2892989169088918495125419837737266, -5785978338177836990250839675474532], [0, 0], [-5513327827923498548979869561889716, 5513327827923498548979869561889716], [0, 0], [-3985035478360372258700547080917803, -3985035478360372258700547080917803], [0, 0], [-3503665568989373050971679006555281, 7007331137978746101943358013110562], [0, 0], [7347597235231067206317110689235140, -3673798617615533603158555344617570], [0, 0], [0, -13942333895361389784009579500665718], [0, 0], [12813539346053533731249068459426971, 0], [0, 0], [-1046003910978160016080262145989503, 1046003910978160016080262145989503], [0, 0], [0, 8866464481462000734904142931860681], [0, 0], [-2409352772726311500930127102948277, 4818705545452623001860254205896554], [0, 0], [0, 0], [0, 0], [8530409196925898410760204703338357, 0], [0, 0], [0, 0], [0, 0], [-292221981622288509747712451345953, 292221981622288509747712451345953], [271947942171639776303895786473941, 271947942171639776303895786473941]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_21_g_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_21_24_g_a();".
// This may take a long time!  To see verbose output, uncomment the SetVerbose lines below.
// The precision argument determines an initial guess on how many Fourier coefficients to use.
// This guess is increased enough to uniquely determine the newform.
function MakeNewformModFrm_21_24_g_a(:prec:=2)
    chi := MakeCharacter_21_g();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 24));
    S := BaseChange(S, Kf);
    maxprec := NextPrime(997) - 1;
    while true do
        trunc_vec := Vector(Kf, [0] cat [f_vec[i]: i in [1..prec]]);
        B := Basis(S, prec + 1);
        S_basismat := Matrix([AbsEltseq(g): g in B]);
        if Rank(S_basismat) eq Min(NumberOfRows(S_basismat), NumberOfColumns(S_basismat)) then
            S_basismat := ChangeRing(S_basismat,Kf);
            f_lincom := Solution(S_basismat,trunc_vec);
            f := &+[f_lincom[i]*Basis(S)[i] : i in [1..#Basis(S)]];
            return f;
        end if;
        error if prec eq maxprec, "Unable to distinguish newform within newspace";
        prec := Min(Ceiling(1.25 * prec), maxprec);
    end while;
end function;


// To make the Hecke irreducible modular symbols subspace (type ModSym)
// containing the newform, type "MakeNewformModSym_21_24_g_a();".
// This may take a long time!  To see verbose output, uncomment the SetVerbose line below.
// The default sign is -1.  You can change this with the optional parameter "sign".
function MakeNewformModSym_21_24_g_a( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_21_g();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,24,sign)));
    Vf := Kernel([<2,R![0, 1]>],Snew);
    return Vf;
end function;