
// Make newform 21.40.c.a in Magma, downloaded from the LMFDB on 19 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_21_c();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_21_c_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_40_c_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_40_c_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;
    Rf_num := [[1, 0], [-9, 18]];
    Rf_basisdens := [1, 1];
    Rf_basisnums := ChangeUniverse([[z : z in elt] : elt in Rf_num], Kf);
    Rfbasis := [Rf_basisnums[i]/Rf_basisdens[i] : i in [1..Degree(Kf)]];
    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_c();"
function MakeCharacter_21_c()
    N := 21;
    order := 2;
    char_gens := [8, 10];
    v := [1, 1];
    // 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_c_Hecke();"
function MakeCharacter_21_c_Hecke(Kf)
    N := 21;
    order := 2;
    char_gens := [8, 10];
    char_values := [[-1, 0], [-1, 0]];
    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 := 40;
    raw_aps := [[0, 0], [0, -129140163], [0, 0], [-27297848160306370, 822450333589249], [0, 0], [0, -23808777184531208684], [0, 0], [0, 251069013050886886717670], [0, 0], [0, 0], [0, 2958359674873253646574531670], [515129446524820262143443074530, 0], [0, 0], [62389305906062855560289197651240, 0], [0, 0], [0, 0], [0, 0], [0, -6688952159052272608758840452660820], [361464960143221075414533040863001040, 0], [0, 0], [0, 202453343549652827172979631325027144], [10941606502204567965371953318710207524, 0], [0, 0], [0, 0], [0, -59084652664404524402596739168330405768], [0, 0], [0, -90059300341895447042511683674846631874], [0, 0], [-6059094863251839839579690121077966129834, 0], [0, 0], [208742795624116991025532132238952936222860, 0], [0, 0], [0, 0], [0, 54312884401904291441671285936166151515890], [0, 0], [-572363106716946866236907880462396573770948, 0], [0, -364083857274445854098726500230065108406148], [3783476436963841455115387459200745548978200, 0], [0, 0], [0, 0], [0, 0], [0, 9072807535840952930434821532518339223242740], [0, 0], [241200530272458590058226343178918139595847550, 0], [0, 0], [0, -85934944215875902438075758847961512606621310], [2889063798343757126623183465345212861323157808, 0], [0, -764396934419514657069525390236257233548642006], [0, 0], [0, -1264961188638725990021724893138711397282228380], [0, 0], [0, 0], [0, -2967590418656376512666190221142992663284109840], [0, 0], [0, 0], [0, 0], [0, 0], [0, -13395381702210659294098139942987215745849258010], [333109288362633266667955087241735314754538587090, 0], [0, 0], [0, -26033069235746478972118433411848364510240706754], [0, 0], [0, 379349219005696239540456607323926941664562723798], [0, 0], [0, 301232696821119385670475271394269169269059664784], [0, 0], [-24056788508393035711239841745010463109218641733472, 0], [-31755098507116785186095093706462366182604144539390, 0], [0, 0], [0, -3680861645485329571740639780003024556894311439580], [0, 0], [0, 0], [0, -7788411666130891326740940398652277634521493047878], [205893874044388338246916595980656178480181043387950, 0], [375161854357859599618906048934529482757668097715624, 0], [0, 0], [0, 0], [0, 33986280922015028837977104837619253582692358192068], [0, 0], [0, -95501484977816000046501131082220550727163591759160], [0, 0], [-225787092837054673663498149288122090752087419720382, 0], [0, 0], [0, 99107556821580047344557587495252671996175912899304], [0, 417748057671226285367032231455518489456181269379570], [0, 0], [0, 0], [-3191350599364836731860980143182034678798655429611270, 0], [0, 0], [-13625515260787200840947440169447868219208455739060, 0], [0, 0], [0, 0], [50879233598524386544713783975351026348816391003750700, 0], [0, 0], [-22459387465907646402923987917674544346464366577888864, 0], [0, 0], [0, 0], [0, 0], [0, -11048323692853372684635046036867573542685757399036094], [-356601510922220447846605964188623713742805149063699238, 0], [364176215775941359238220800027068471585732509305369480, 0], [0, 0], [0, 0], [0, 0], [772380464126318570302815236552721803270265642474385232, 0], [0, 81773458505795410435517588717736189794955484571804808], [0, 0], [0, 0], [0, 0], [0, 194158709105099548715157581649580529862326255932082600], [0, 199237810578559408891577769498679882413521553418324298], [4521015783122901321863068154659007873319016208369168030, 0], [0, 0], [0, -180594015897452615265481124151084489708921774169394670], [5586182159961609820190939352722079514792694852879377172, 0], [0, 0], [0, -468867205137240627824367535711598517715990683041062986], [0, 0], [0, 0], [0, 0], [0, -665697737600165098697238630341876107325791605936627780], [12238447774417520027259828086288715300576691028695867150, 0], [0, 0], [0, 0], [0, 2848529382400728292608314648410406190413244418578992570], [0, 0], [60661616461466188903666839665097330126280612709196999934, 0], [0, 0], [0, 7180265870418850088545487518443240464973078340636145358], [0, 3199710467267357916123571636271856784927806549739075204], [-137793589427648808564010578399888453146661140025495479344, 0], [0, 0], [237603748894486999762858787469623143448036524189780827052, 0], [93361854215257065394127774077684481254153939676828881390, 0], [0, 0], [0, 3953561116969985776183442135439934022564002743094921760], [0, 0], [0, 25399355396658289619470630579680207224045519838325318938], [0, 0], [0, 0], [0, -52296785665925317908508262182288695250337103274359077150], [0, 0], [366108982017854602558615372777350590626986370920001004660, 0], [0, 0], [0, 4209348857136289162509425243364004762170138733093541980], [0, 0], [0, 182173885452826146751137211901720639723666411365640969076], [0, 0], [0, 159802321774900530067373335383423269200367195463333811310], [0, 0], [-4695993922837530200229350811109886660591955350420472325450, 0], [0, 0], [-4753987313131033577139585312952907215014245415539989740440, 0], [0, 0], [474765752960097420846952333679318118037400810146386692920, 0], [0, 0], [-7306386619722177181705677953077839622678212549544676023796, 0], [0, 0], [0, -195827898542360261748500319721452929099456889222706405088], [0, 0], [0, 0], [0, 0], [-6597591461272630711833816070370415852189992384527005000340, 0], [0, 0], [0, 0], [0, 0], [-50114194974701585992746663932890985056165339239238015826612, 0], [0, 3813670560191850672752189163630106343632502745014528754132]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_21_c_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_21_40_c_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_40_c_a(:prec:=2)
    chi := MakeCharacter_21_c();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 40));
    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_40_c_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_40_c_a( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_21_c();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,40,sign)));
    Vf := Kernel([<2,R![0, 1]>],Snew);
    return Vf;
end function;