
// Make newform 20.8.c.a in Magma, downloaded from the LMFDB on 19 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_20_c();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_20_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_20_8_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_20_8_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 := [93051, 0, 1348, 0, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0], [0, 2, 0, 0], [28308, -2318, 42, -2], [56616, 19384, 84, 16]];
    Rf_basisdens := [1, 1, 105, 105];
    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_20_c();"
function MakeCharacter_20_c()
    N := 20;
    order := 2;
    char_gens := [11, 17];
    v := [2, 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_20_c_Hecke();"
function MakeCharacter_20_c_Hecke(Kf)
    N := 20;
    order := 2;
    char_gens := [11, 17];
    char_values := [[1, 0, 0, 0], [-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 := 8;
    raw_aps := [[0, 0, 0, 0], [0, 1, 0, 0], [-39, -1, 1, 0], [0, -5, -2, 1], [-660, -8, 16, 2], [0, 222, -6, 3], [0, -192, 20, -10], [-9084, 24, -48, -6], [0, 843, 58, -29], [-120474, 48, -96, -12], [40336, -240, 480, 60], [0, 5746, 226, -113], [282366, 172, -344, -43], [0, -3163, -124, 62], [0, -8889, -506, 253], [0, 10194, 1638, -819], [-1936788, -632, 1264, 158], [1076282, 1356, -2712, -339], [0, -33319, 1916, -958], [-301512, -4224, 8448, 1056], [0, -33748, -736, 368], [1429248, 6768, -13536, -1692], [0, -74511, 6076, -3038], [3410394, -2416, 4832, 604], [0, 117032, 14444, -7222], [-800514, -10096, 20192, 2524], [0, 32035, 7306, -3653], [0, 56205, -2424, 1212], [12694682, 252, -504, -63], [0, 291864, -18792, 9396], [0, 347287, -12206, 6103], [-13475820, 15384, -30768, -3846], [0, 17172, 55428, -27714], [12293036, 44088, -88176, -11022], [-26639886, 42556, -85112, -10639], [-31943240, -63888, 127776, 15972], [0, 168062, -51202, 25601], [0, -611231, -18248, 9124], [0, 1243731, -96270, 48135], [0, -127578, -22138, 11069], [-48958572, 89128, -178256, -22282], [65507150, -112272, 224544, 28068], [-10775712, 86112, -172224, -21528], [0, 1644200, -140956, 70478], [0, 1498986, 157510, -78755], [-4887432, -17472, 34944, 4368], [-111456156, 112632, -225264, -28158], [0, -211081, -112198, 56099], [0, -1811679, -140056, 70028], [35891134, -390576, 781152, 97644], [0, 442620, 128336, -64168], [165345696, -161488, 322976, 40372], [-31902266, -312228, 624456, 78057], [-56540100, 24120, -48240, -6030], [0, -3695232, 63360, -31680], [0, 4229259, -27770, 13885], [111275658, 380076, -760152, -95019], [-276809120, 320208, -640416, -80052], [0, -4639670, 43354, -21677], [354795966, 381756, -763512, -95439], [0, 5983285, 46936, -23468], [0, -6453918, -259494, 129747], [0, -4535919, 231396, -115698], [400008792, -713424, 1426848, 178356], [0, 9922220, -174868, 87434], [0, 6008646, 684554, -342277], [234610588, 1403208, -2806416, -350802], [0, -15736040, -221072, 110536], [0, 7643469, -806028, 403014], [-310077370, 657552, -1315104, -164388], [0, 2398848, -977224, 488612], [-500581176, 1930896, -3861792, -482724], [0, 10348159, 1610674, -805337], [0, 27212058, -59142, 29571], [-553746308, 138360, -276720, -34590], [0, 10641687, -1409710, 704855], [-604531806, -1635556, 3271112, 408889], [0, 8369614, -2219630, 1109815], [468079170, 458480, -916960, -114620], [994351246, -1738452, 3476904, 434613], [-922906524, -71320, 142640, 17830], [-1818638174, -681348, 1362696, 170337], [2144829696, 869776, -1739552, -217444], [0, -18273088, -917476, 458738], [1731813528, -686736, 1373472, 171684], [0, -49933803, 2836560, -1418280], [1215997206, 3433020, -6866040, -858255], [0, 12411460, 3270124, -1635062], [941685270, 4033872, -8067744, -1008468], [0, 5151831, -1616106, 808053], [0, 56275929, 431952, -215976], [1084054176, -4340608, 8681216, 1085152], [0, 609627, -4672890, 2336445], [3128790300, -1444440, 2888880, 361110], [-1061623884, 2532936, -5065872, -633234], [0, -18890853, 1986234, -993117], [-699922554, -256464, 512928, 64116], [3765056634, 3134720, -6269440, -783680], [0, 37677421, 2444224, -1222112], [-799966106, 6273840, -12547680, -1568460], [0, 37011889, 8095936, -4047968], [0, -57683418, 1869606, -934803], [0, -75954567, -6661288, 3330644], [-5744069970, 1897580, -3795160, -474395], [2020580188, 3921240, -7842480, -980310], [0, -35089328, -10307912, 5153956], [0, 105617589, 1806708, -903354], [0, -96599448, -5997672, 2998836], [-103268280, -12042144, 24084288, 3010536], [-918584290, 5623836, -11247672, -1405959], [0, 65272175, -4509418, 2254709], [0, 137973818, -307978, 153989], [0, -102822228, -4940728, 2470364], [-5991300260, 3985896, -7971792, -996474], [-3560650408, 4138992, -8277984, -1034748], [2379086262, -2867108, 5734216, 716777], [0, -53502999, 4022484, -2011242], [0, 23316987, 6344094, -3172047], [0, 134651214, 4736530, -2368265], [2343704916, 2727688, -5455376, -681922], [1649628578, 4397388, -8794776, -1099347], [0, 51207720, 877116, -438558], [0, 32095146, -11931970, 5965985], [0, 49281621, 9400060, -4700030], [-6730416092, -11710248, 23420496, 2927562], [-1140133590, 9754012, -19508024, -2438503], [7605493566, 476784, -953568, -119196], [11531213376, 5168048, -10336096, -1292012], [0, 163733955, 7935846, -3967923], [0, -113829266, 2915974, -1457987], [-8529021820, -12629112, 25258224, 3157278], [0, 43474539, 6991566, -3495783], [-10924708144, 13714368, -27428736, -3428592], [0, -150454358, -7269662, 3634831], [808427802, -2681040, 5362080, 670260], [-9615080958, 277248, -554496, -69312], [0, 40727034, 21366942, -10683471], [0, -184490447, -18651572, 9325786], [0, -46310010, -25451902, 12725951], [-229343526, 13384320, -26768640, -3346080], [4139532844, -37840488, 75680976, 9460122], [5075504226, -33325204, 66650408, 8331301], [0, -98416149, -7476750, 3738375], [0, -457211379, 9190508, -4595254], [-3723496518, -12588852, 25177704, 3147213], [7297554792, 19815184, -39630368, -4953796], [0, -56791934, -15927962, 7963981], [0, -15208020, 37438932, -18719466], [-19702886324, -25596792, 51193584, 6399198], [0, -369959073, 24260430, -12130215], [0, 270038198, -2899522, 1449761], [-499551498, 30315372, -60630744, -7578843], [0, -104298615, 10941936, -5470968], [0, 594950499, -21347586, 10673793], [0, 210378909, -20106312, 10053156], [-22357944768, 4685808, -9371616, -1171452], [-10285779576, -19869216, 39738432, 4967304], [23863787958, -10222404, 20444808, 2555601], [0, -82849060, -6797008, 3398504], [-31893569898, -9358736, 18717472, 2339684], [0, 609106881, -29540580, 14770290], [0, 772270716, -27411916, 13705958], [0, -335211805, 40281122, -20140561], [14654752956, 41693736, -83387472, -10423434], [0, 70011024, -9896916, 4948458], [0, 82964835, -39800842, 19900421], [-1599857504, 29049984, -58099968, -7262496], [0, -510181974, -8654898, 4327449]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_20_c_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_20_8_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_20_8_c_a(:prec:=4)
    chi := MakeCharacter_20_c();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 8));
    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_20_8_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_20_8_c_a( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_20_c();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,8,sign)));
    Vf := Kernel([],Snew);
    return Vf;
end function;