
// Make newform 54.7.b.c in Magma, downloaded from the LMFDB on 04 May 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_54_b();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_54_b_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_54_7_b_c();".
// 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_54_7_b_c();".
// 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, 0, 0, 0, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0], [0, 0, 27, 0], [0, 4, 0, 4], [0, 108, 0, -108]];
    Rf_basisdens := [1, 1, 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_54_b();"
function MakeCharacter_54_b()
    N := 54;
    order := 2;
    char_gens := [29];
    v := [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_54_b_Hecke();"
function MakeCharacter_54_b_Hecke(Kf)
    N := 54;
    order := 2;
    char_gens := [29];
    char_values := [[-1, 0, 0, 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 := 7;
    raw_aps := [[0, 0, 1, 0], [0, 0, 0, 0], [0, 5, 15, 0], [209, 0, 0, 1], [0, 29, -150, 0], [110, 0, 0, -22], [0, 106, 612, 0], [-1672, 0, 0, -46], [0, -260, -1074, 0], [0, 422, -672, 0], [40043, 0, 0, -15], [-37636, 0, 0, 106], [0, 2468, -8130, 0], [22538, 0, 0, 654], [0, 3810, -15396, 0], [0, -43, 42849, 0], [0, 2938, -876, 0], [146036, 0, 0, 312], [-191698, 0, 0, 366], [0, -2762, 59634, 0], [393689, 0, 0, 162], [80750, 0, 0, -4996], [0, 19719, 10938, 0], [0, -1862, 124182, 0], [1108235, 0, 0, 4232], [0, -54131, -41127, 0], [-84022, 0, 0, 3036], [0, -7663, -20520, 0], [-918916, 0, 0, 1110], [0, -47856, 211830, 0], [-543049, 0, 0, 16935], [0, 89291, 227508, 0], [0, -67414, 50790, 0], [32132, 0, 0, -824], [0, 37525, 142989, 0], [2954225, 0, 0, -57], [-3182164, 0, 0, -3780], [902558, 0, 0, -30932], [0, 115398, 239100, 0], [0, -139737, 753609, 0], [0, 104075, -1250136, 0], [1811648, 0, 0, -13196], [0, 99022, -301398, 0], [1026191, 0, 0, 12558], [0, 22297, 973899, 0], [-3803299, 0, 0, 29765], [-4592644, 0, 0, 54830], [1917614, 0, 0, -12144], [0, -288546, -2266908, 0], [8783534, 0, 0, 38688], [0, -756118, 337518, 0], [0, 376368, -278742, 0], [-10357666, 0, 0, 105940], [0, -355582, 2984832, 0], [0, -653394, 822552, 0], [0, -646940, -2780142, 0], [0, -39034, 382860, 0], [-1038985, 0, 0, -63831], [-16303012, 0, 0, -137796], [0, -89374, -1723236, 0], [29410832, 0, 0, -60774], [0, 739690, -628716, 0], [-15954190, 0, 0, 21780], [0, -627688, 2521446, 0], [-22389487, 0, 0, -123542], [0, 1178071, -2775309, 0], [19122554, 0, 0, 196562], [-27345274, 0, 0, 133156], [0, -895935, 282210, 0], [-20468248, 0, 0, 250978], [0, -486208, 11040762, 0], [0, 1015446, -3214908, 0], [456347, 0, 0, 208641], [6022082, 0, 0, -35086], [-17339776, 0, 0, 183040], [0, -2098150, -4219626, 0], [0, 1601533, 1543953, 0], [43362434, 0, 0, -90858], [0, 1721192, -5879136, 0], [30164861, 0, 0, -116240], [0, -133050, 18823344, 0], [-68973964, 0, 0, -206108], [0, -1733306, 15698772, 0], [8988923, 0, 0, -714780], [111698345, 0, 0, 129093], [0, 227994, -2394024, 0], [0, -1994736, -7071930, 0], [-24391267, 0, 0, 323736], [0, 1838519, -621429, 0], [-23186653, 0, 0, -772927], [0, -5944045, 5297922, 0], [0, -3059658, -19614696, 0], [-11329954, 0, 0, 322856], [0, 1509289, -20294508, 0], [-71960614, 0, 0, 375894], [0, 7168356, 8885934, 0], [0, -822973, -31988163, 0], [0, -3218714, 23794596, 0], [-59695162, 0, 0, -729768], [101759060, 0, 0, 568240], [-110614822, 0, 0, -121872], [0, -1090865, -32427441, 0], [0, 3919563, -938406, 0], [0, -5889728, 28997004, 0], [34700942, 0, 0, -128792], [291915470, 0, 0, 116052], [0, 95593, -43399212, 0], [0, -8090078, 1641222, 0], [0, 4382194, 5741916, 0], [-175331203, 0, 0, 1128330], [68415842, 0, 0, -121952], [-11884534, 0, 0, -2161800], [0, -7899520, -13497294, 0], [290117126, 0, 0, 847908], [10096193, 0, 0, 2745769], [0, -5561524, -13326882, 0], [231127400, 0, 0, -256212], [0, -2665692, -48907152, 0], [0, 8303515, 17077029, 0], [0, -3448397, 40546128, 0], [-165565672, 0, 0, 1762614], [-284131321, 0, 0, -1294888], [0, -4726118, 78020904, 0], [0, -1605474, 16140528, 0], [116170220, 0, 0, 1461960], [0, 10276175, 6774597, 0], [-181479616, 0, 0, 1234424], [0, -6265236, -58110408, 0], [209261549, 0, 0, 2995461], [173913104, 0, 0, -1660038], [120542258, 0, 0, -966552], [0, 10044546, 77800254, 0], [2078003, 0, 0, -2477039], [577675154, 0, 0, -105324], [0, 5637096, 68323272, 0], [-225196333, 0, 0, 601994], [0, 3361182, -42539400, 0], [-493295020, 0, 0, -1971672], [0, 14111403, 43210149, 0], [0, -11605430, 65280870, 0], [160397768, 0, 0, 1575486], [0, 14811790, -78934704, 0], [136839161, 0, 0, -3038113], [0, -2070470, 136927224, 0], [-171154510, 0, 0, 5347520], [0, 13461834, 129698850, 0], [442266878, 0, 0, 2656968], [0, -11288430, -9291192, 0], [418799108, 0, 0, 1728160], [0, -25828940, 21028680, 0], [-226007494, 0, 0, -1249292], [0, -1487074, 19084968, 0], [-13266232, 0, 0, 6671678], [0, -9360202, -1094142, 0], [407474948, 0, 0, -1886410], [0, 31093386, -28504824, 0], [-151697203, 0, 0, -3374217], [0, 13897428, 135172812, 0], [-257938099, 0, 0, 3115240], [0, 32739787, 107052603, 0], [0, -41665413, -51434700, 0], [0, 1044672, 27454716, 0], [100863281, 0, 0, 2997375], [0, -9530511, -94926654, 0], [0, -26395814, -111520758, 0], [0, -32147834, 2872380, 0], [275730023, 0, 0, -7067721], [-76333030, 0, 0, -6514734]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_54_b_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_54_7_b_c();".
// 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_54_7_b_c(:prec:=4)
    chi := MakeCharacter_54_b();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 7));
    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_54_7_b_c();".
// 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_54_7_b_c( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_54_b();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,7,sign)));
    Vf := Kernel([<5,R![121550625, 0, 50850, 0, 1]>],Snew);
    return Vf;
end function;