
// Make newform 2160.4.a.o in Magma, downloaded from the LMFDB on 25 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_2160_a();"
// To make the coeffs of the qexp of the newform in the Hecke field type "qexpCoeffs();"
// To make the newform (type ModFrm), type "MakeNewformModFrm_2160_4_a_o();".
// 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_2160_4_a_o();".
// 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
        Kf := Rationals();
    end if;
    return [Kf!elt[1] : elt in input];
end function;


// To make the character of type GrpDrchElt, type "MakeCharacter_2160_a();"
function MakeCharacter_2160_a()
    N := 2160;
    order := 1;
    char_gens := [271, 1621, 2081, 1297];
    v := [1, 1, 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;

function MakeCharacter_2160_a_Hecke(Kf)
    return MakeCharacter_2160_a();
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 := 4;
    raw_aps := [[0], [0], [5], [4], [42], [20], [-93], [-59], [9], [-120], [-47], [-262], [-126], [178], [144], [-741], [-444], [221], [538], [690], [-1126], [-665], [75], [1086], [1544], [132], [892], [-1140], [-1735], [1434], [-686], [-114], [-159], [-2276], [1398], [-2624], [-394], [3346], [-1491], [-2403], [-2640], [1073], [1470], [-4720], [765], [-668], [-4601], [2158], [3123], [2027], [438], [6414], [3431], [7308], [3729], [-1956], [-990], [-8495], [-1366], [-5520], [-5438], [8253], [-9290], [-8112], [-7900], [4419], [8200], [-9556], [-10116], [-6751], [4062], [-8778], [-956], [2300], [-29], [-8127], [-7938], [272], [4554], [1001], [1794], [-16129], [13356], [-11500], [11149], [-3849], [18048], [-4264], [-10242], [-3302], [1923], [-15246], [8206], [16806], [5425], [19665], [-14724], [2058], [-11912], [-5170], [4186], [13026], [10668], [-15372], [14989], [-1066], [621], [-20187], [18228], [-11743], [24418], [2672], [-8601], [-21308], [19015], [-4416], [-7580], [14901], [12915], [-28128], [-8362], [29708], [6762], [19155], [22975], [-6450], [34538], [-27114], [-236], [27128], [-5249], [-13896], [-27665], [-8122], [10584], [-18619], [22251], [-24854], [3681], [-5142], [18484], [25014], [32146], [10977], [36602], [-11076], [36848], [-26961], [415], [45501], [35042], [1080], [20164], [-20067], [26524], [-35568], [23704], [-40590], [-12964], [29922], [-5241], [26214], [-18278], [24942], [-11226], [23073], [-22037], [19082], [2759], [-14439], [28356], [38927], [-1884], [-29956], [11995], [-61668], [6505], [-5904], [54862], [6122], [55438], [1764], [-62134], [14502], [12255], [-68004], [73856], [7756], [51053], [-8376], [-12802], [20805], [-73949], [12264], [-4677], [9525], [3977], [6956], [-64614], [2784], [-4374], [48088], [74510], [-40285], [4992], [-14502], [-33440], [68127], [35100], [-51572], [-16252], [2466], [31840], [-70884], [-82692], [-55063], [40246], [-46248], [21213], [87567], [47858], [11329], [47616], [-47630], [53967], [87491], [12093], [71730], [-40862], [31932], [-12010], [16657], [9088], [49794], [-82952], [46407], [-80875], [72885], [-88194], [85254], [39660], [-13475], [-67118], [11513], [-91890], [-49974], [-77252], [57684], [-75692], [74391], [-5650], [45882], [64635], [-25171], [-70569], [-29616], [-23611], [-53804], [-76281], [-68092], [-92966], [16437], [83087], [86396], [106785], [-7508], [-102696], [-28110], [18934], [-37086], [-70861], [-85166], [48494], [-121151], [-48958], [116212], [16221], [-91519], [-70783], [-12138], [3624], [61765], [-33351], [-114361], [145348], [50400], [18038], [-38574], [-8189], [-105816], [5448], [-102099], [4650], [127518], [100730], [71880], [22801], [25182], [-76848], [44056], [-79066], [159759], [-87392], [105483], [17839], [-134134], [142740], [-9013], [-46026], [26738], [11859], [-92856], [165156], [-63428], [-73029], [12143], [52080], [57210], [-27664], [-30534], [28171], [35372], [-173760], [-114500], [60927], [153710], [-19577], [73060], [-132960], [8073], [-50110], [-52974], [-54272], [185328], [-84260], [82740], [-28345], [11355], [23978], [-51014], [-162652], [-38613], [-39684], [189607], [-2742], [-59766], [-113749], [177640], [129408], [99909], [-28868], [168002], [-123216], [170620], [-65770], [-122061], [-181932], [-16956], [-200166], [-87087], [144392], [-180006], [96300], [-163758], [-83528], [70916], [154959], [-66734], [-127798], [112014], [142357], [-78993], [70446], [-117719], [4172], [77694], [-32010], [40862], [62346], [13730], [172992], [50133], [-18584], [102279], [-217160], [233448], [-242813], [183284], [50698], [-181224], [153650], [28527], [-279306], [-212834], [16566], [-196870], [282679], [-7560], [173563], [41928], [-172510], [-44622], [-45164], [-172650], [128412], [-39755], [10094], [179850], [183328], [13320], [-148138], [165765], [42345], [-142463], [139262], [-165516], [-213510], [204448], [175845], [-201717], [74184], [-230578], [9171], [270774], [18938], [-157563], [-34995], [-16962], [278755], [276390]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_2160_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_2160_4_a_o();".
// 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_2160_4_a_o(:prec:=1)
    chi := MakeCharacter_2160_a();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 4));
    S := BaseChange(S, Kf);
    maxprec := NextPrime(2999) - 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_2160_4_a_o();".
// 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_2160_4_a_o( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_2160_a();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<7,R![-4, 1]>,<11,R![-42, 1]>],Snew);
    return Vf;
end function;