
// Make newform 20.10.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_10_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_10_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 := [2230844, -80251, 1095, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0], [14468, 99, -82, -1], [-48404, 19703, 246, 3], [739084, -13713, -66, -13]];
    Rf_basisdens := [1, 1000, 500, 500];
    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 := 10;
    raw_aps := [[0, 0, 0, 0], [0, 1, 0, 0], [165, 1, 0, -1], [0, 3, 1, -1], [-8700, 0, 26, 26], [0, -282, 57, -57], [0, 1192, 170, -170], [-56916, 0, 258, 258], [0, -13525, 19, -19], [1566414, 0, -2244, -2244], [93616, 0, -1860, -1860], [0, -9390, -2603, 2603], [-4412034, 0, 851, 851], [0, 122901, 11078, -11078], [0, -8137, 21013, -21013], [0, 410106, -8721, 8721], [109748868, 0, 11846, 11846], [-25761118, 0, -85017, -85017], [0, 664065, -28918, 28918], [-126020472, 0, 42048, 42048], [0, -1244412, -104368, 104368], [448738752, 0, 72036, 72036], [0, -2391607, 203338, -203338], [595329546, 0, 249508, 249508], [0, -6424368, -196042, 196042], [-365571594, 0, 137812, 137812], [0, 3036819, -716357, 716357], [0, 1523541, -479028, 479028], [596153378, 0, -758061, -758061], [0, 11908536, 246924, -246924], [0, 5075967, -852017, 852017], [1265065500, 0, 638562, 638562], [0, -2712444, 2323986, -2323986], [-3807717436, 0, -2167734, -2167734], [-5954079894, 0, 1053467, 1053467], [4763400520, 0, -2068764, -2068764], [0, -16286514, -4437469, 4437469], [0, 12062097, -5925644, 5925644], [0, -54599181, 2677575, -2677575], [0, 56263510, -1887289, 1887289], [-6904675428, 0, 1565006, 1565006], [-2276038810, 0, -4147476, -4147476], [1138241568, 0, 15294696, 15294696], [0, 28652736, 520562, -520562], [0, -17092606, 1752655, -1752655], [-660468408, 0, 14348976, 14348976], [10775159244, 0, -8133654, -8133654], [0, -99940113, 4908251, -4908251], [0, -183430607, -24601732, 24601732], [44086410166, 0, 3903108, 3903108], [0, -273516716, -10952152, 10952152], [31484273184, 0, -772556, -772556], [-53816359946, 0, 23752791, 23752791], [28895848500, 0, -32072790, -32072790], [0, -147009408, 17072640, -17072640], [0, 359001539, 18135805, -18135805], [35651536722, 0, 16349007, 16349007], [48565297120, 0, 53856204, 53856204], [0, -551071926, 54106033, -54106033], [-81133682274, 0, -13452537, -13452537], [0, 261259629, -15666812, 15666812], [0, 888511506, -41221887, 41221887], [0, 606019065, -39557658, 39557658], [115668013992, 0, 24459828, 24459828], [0, -1234657572, 13036166, -13036166], [0, -1168739522, -62169007, 62169007], [229716592468, 0, 12974454, 12974454], [0, 281302248, 40865656, -40865656], [0, 359761773, 111670734, -111670734], [-95941588690, 0, 4428084, 4428084], [0, -605299088, 18472028, -18472028], [-150072782664, 0, 54545052, 54545052], [0, -1137915465, -71148977, 71148977], [0, 1715079930, -129049311, 129049311], [53935790068, 0, -219148710, -219148710], [0, 1477171327, 2293775, -2293775], [323047359546, 0, -21055037, -21055037], [0, -368320794, -50977835, 50977835], [-515336088030, 0, -26580260, -26580260], [346860640174, 0, 78826371, 78826371], [512313181644, 0, 248167390, 248167390], [-199290668294, 0, 168751131, 168751131], [-521482052544, 0, 86024348, 86024348], [0, -8223797832, 193858862, -193858862], [490593799272, 0, -421861212, -421861212], [0, 761076477, 133142520, -133142520], [663046800294, 0, 125670015, 125670015], [0, 9857400804, -189983642, 189983642], [-645967051170, 0, -214006044, -214006044], [0, -3984536313, -765766803, 765766803], [0, -4476044247, 210564024, -210564024], [334575061344, 0, -191073056, -191073056], [0, -1384633677, -612498915, 612498915], [-1294042829100, 0, 325093950, 325093950], [-185516158596, 0, -304784538, -304784538], [0, 10252745883, -311137293, 311137293], [-446169027666, 0, -85110468, -85110468], [-338230184886, 0, -178264640, -178264640], [0, -4454653083, 947658592, -947658592], [2286381333454, 0, -26327940, -26327940], [0, 4511908497, 549260512, -549260512], [0, 7780581654, -928749033, 928749033], [0, -12832721639, 871207076, -871207076], [8148681870, 0, -2372201165, -2372201165], [-104195932652, 0, 349386690, 349386690], [0, 11173628256, 1266095836, -1266095836], [0, 2312594469, -734951634, 734951634], [0, 9799626024, -533108916, 533108916], [634403710200, 0, 297712392, 297712392], [3277404846590, 0, 330388863, 330388863], [0, 15417130767, 462164189, -462164189], [0, -1251991854, 2543238311, -2543238311], [0, -24061001900, -346754236, 346754236], [1894693036180, 0, 662689902, 662689902], [-388565068888, 0, -10035324, -10035324], [-3501932915898, 0, 2182432391, 2182432391], [0, 46586030817, -1129716498, 1129716498], [0, -26855004093, 1020175473, -1020175473], [0, 21445367654, -1075522475, 1075522475], [7025299376604, 0, -1271085514, -1271085514], [1768428636698, 0, 3933569679, 3933569679], [0, -22693838736, 1262026398, -1262026398], [0, 17175565234, 1660728155, -1660728155], [0, -1444138219, -1931384390, 1931384390], [225029118988, 0, -2675913774, -2675913774], [-3575650376430, 0, -4118142709, -4118142709], [1345427344374, 0, -2952685332, -2952685332], [1960141125504, 0, 2883746836, 2883746836], [0, -27382777749, -1489766403, 1489766403], [0, -60511209810, -225728873, 225728873], [2736643710380, 0, -696723594, -696723594], [0, 46399282803, 5005045113, -5005045113], [7481134178096, 0, -2556586416, -2556586416], [0, 89054493306, -197013659, 197013659], [-8220653068278, 0, 3417158220, 3417158220], [-3111494956542, 0, -2040206784, -2040206784], [0, -74153428638, 2108270571, -2108270571], [0, -33445586775, -388471454, 388471454], [0, -41544852242, -2682461059, 2682461059], [-2098780166934, 0, -6326780640, -6326780640], [10429141400644, 0, -6512044974, -6512044974], [-11188455401574, 0, -2773503017, -2773503017], [0, 2509895931, -824664105, 824664105], [0, 87383685277, -6612722494, 6612722494], [-8893121168862, 0, -3760676409, -3760676409], [-11217541856232, 0, -3069105412, -3069105412], [0, -56957800182, 605689999, -605689999], [0, 50570683692, 1210937754, -1210937754], [-3905492638556, 0, 3329342406, 3329342406], [0, -52546888113, -8427658335, 8427658335], [0, 13840668150, -3692852749, 3692852749], [-19194977210778, 0, 973241211, 973241211], [0, -86279909511, 196416168, -196416168], [0, 5372095995, 8723941713, -8723941713], [0, 162766480869, 6885562836, -6885562836], [6367945060992, 0, -6509848956, -6509848956], [-2048367662664, 0, -5943786072, -5943786072], [9626490688902, 0, 11036335167, 11036335167], [0, -80884320588, -5505344296, 5505344296], [-20866979027298, 0, 1997145932, 1997145932], [0, -78990735111, -11359132710, 11359132710], [0, -27015464228, -14555293558, 14555293558], [0, 137813111427, -5387633521, 5387633521], [-8923856356044, 0, -15064095522, -15064095522], [0, 54849752520, 10121538678, -10121538678], [0, 97446521707, -1899006091, 1899006091], [15963353109856, 0, 8286537312, 8286537312], [0, 218447141586, 14910145539, -14910145539]];
    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_10_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_10_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, 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_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_10_c_a( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_20_c();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,10,sign)));
    Vf := Kernel([],Snew);
    return Vf;
end function;