
// Make newform 20.10.a.b in Magma, downloaded from the LMFDB on 25 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_20_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_20_10_a_b();".
// 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_10_a_b();".
// 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 := [-79, 0, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0], [0, 16]];
    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_20_a();"
function MakeCharacter_20_a()
    N := 20;
    order := 1;
    char_gens := [11, 17];
    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;

function MakeCharacter_20_a_Hecke(Kf)
    return MakeCharacter_20_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 := 10;
    raw_aps := [[0, 0], [-130, 1], [-625, 0], [-190, 69], [51360, 30], [89570, 564], [158010, 348], [68636, 5160], [-332730, -6393], [-3446874, -5880], [145916, -26250], [5630690, -59976], [14886726, 72180], [-5854090, -99615], [31246650, 42573], [4708890, -212532], [-46465428, -373980], [97836962, 721440], [-109883710, 203139], [155603508, -1397610], [-49612030, -2047716], [271130888, 70020], [-628457850, 192957], [-231145926, 5421960], [835858370, -2902956], [-593410074, -3512040], [-221674930, 960723], [-249042630, 5435043], [-726810718, 1177080], [-763442310, -13181592], [4425461570, -7684191], [438215520, -29723790], [-4562549550, 16951536], [3276221276, -21103380], [-3893692326, -15977160], [4241962580, -52919370], [-1802716150, -631704], [5200327670, -33654435], [-3622830, -109829019], [6033752730, 39181368], [-20120817132, -31184580], [1868195030, 9437520], [4045319028, 211723530], [14961338330, 71205372], [10284296370, -4522884], [-9530496952, 90525120], [7052087504, -173409870], [-17392057930, -229646085], [-8107988550, -4030497], [-21212864146, -58986240], [-26817249030, -333620172], [11554367976, -197678220], [16175404814, 140156580], [50380749600, -190455450], [-6281712390, -277620312], [100072707630, -4792821], [41240171058, 817339440], [-15073810540, 302388570], [-11884468870, -1099932648], [44344622406, -910845060], [-101670486130, -712207707], [97046310210, 242777520], [-102274523710, -608327541], [-45587739828, -179012910], [137326658090, 1390226376], [-161227146150, -259723932], [-137606920792, -161514630], [-126530990590, 1506593784], [-74126232030, 1857192975], [360018204950, 883612080], [203891824530, -1071014904], [79341904344, -1817532960], [54375776810, -576658179], [372062485370, -962419128], [-107446254268, -1438135800], [-380822692410, 2341372227], [183838550874, -452220240], [387667343330, -2227520076], [140179190370, 2969575200], [569175787166, -2431842180], [772137282756, -2939060100], [636913820666, -756762120], [459921283236, 5679437490], [-242441264830, 4017285204], [-413950061752, 4805148960], [243183984390, 1246459137], [167496460806, -335582700], [1042843024730, 2155836672], [-513733206210, 5087981880], [-698658521650, 269391303], [-1026679377630, 1390279275], [235494243816, -6217550220], [-992561459110, -5394966303], [70709287200, 1627339350], [658472549276, -1031668560], [3599220270, 11873375979], [1106148875046, -2784123360], [17965062714, -6376147200], [486139326350, 3686895693], [1170694100654, 15672561000], [-2077320826150, -7212961233], [-442620804990, -351145080], [2020367856750, -2408422911], [450217464030, 20787710700], [-3522141156952, -3728230950], [-381299545750, -525114864], [-2823403235910, -106720317], [-2718204624750, -9624184224], [3930607558080, 3829718340], [2072229737270, -17974239060], [-88903639510, -34295369859], [-1731049021150, -4947253596], [-1352323390470, 22350324708], [-2279799676300, 8081101440], [-778435665628, 19319414430], [-2156581307538, 34090131780], [-3295186212850, 7139276073], [-3859099092630, -7099379751], [2119116417930, 1314857004], [7993719098436, -4170063180], [-446412433462, -10977961680], [-1269128866030, -62205321492], [-6998619399630, -13452098124], [-4723454537130, -31960769439], [-381560883352, 3410779230], [4976157968130, -1440325320], [-2322921561154, 69700159560], [-4840236023064, 44637103620], [9620591428370, 11798915733], [5985918236810, -34563357504], [-6468463294540, -56373978780], [9198204807750, 22752569367], [9355741693436, -3971363130], [10156025871050, -15591317904], [1377068364522, 69609472800], [3401690820482, 2853109320], [-1624023880830, -15951738900], [2674204206170, -37808296713], [-6362802246390, 33579090444], [6207288287034, -75692678400], [-7264217059696, 31601446230], [3896141278506, -112998109560], [9044140698470, 59709310791], [-12427495861470, 23036954655], [2412995306402, -57518556480], [106883870352, 5360973660], [5840557301330, -105758149860], [-14242078014510, 53900734296], [-1639572880804, -115064028180], [14062835400390, 118210764507], [4729044128570, -13737984528], [-1099248393618, -107851512420], [-14995451074930, 67606481793], [3496414089810, 88760050341], [24130089529490, -64091125377], [-8197545214068, 42672479670], [2028548491184, -212982755940], [-1832576801322, 11657513940], [-4383092796310, 73293953676], [30239177319822, -62261948640], [34401042140370, 80160703491], [-24533966036550, 61531654848], [5188274037290, 77116045761], [-24836809734264, 139111339290], [3398550777810, -250832562804], [-9610292513490, -81369589341], [-32636549761924, 75535414110], [-22163381320390, -136204402428]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_20_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_20_10_a_b();".
// 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_10_a_b(:prec:=2)
    chi := MakeCharacter_20_a();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 10));
    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_10_a_b();".
// 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_10_a_b( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_20_a();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,10,sign)));
    Vf := Kernel([<3,R![-3324, 260, 1]>],Snew);
    return Vf;
end function;