
// Make newform 16.15.c.c in Magma, downloaded from the LMFDB on 24 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_16_c();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_16_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_16_15_c_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_16_15_c_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 := [91126116, 9546, 9547, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0], [13606715664, -488959152, 2902288, -25760], [145786588368, 1427772944, 30397648, 73184], [-5498688, 0, 0, -384]];
    Rf_basisdens := [1, 15189277, 45567831, 9547];
    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_16_c();"
function MakeCharacter_16_c()
    N := 16;
    order := 2;
    char_gens := [15, 5];
    v := [1, 2];
    // 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_16_c_Hecke();"
function MakeCharacter_16_c_Hecke(Kf)
    N := 16;
    order := 2;
    char_gens := [15, 5];
    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 := 15;
    raw_aps := [[0, 0, 0, 0], [0, 1, 0, 0], [-21750, 0, 0, 1], [0, 245, -1, 0], [0, 3057, -270, 0], [16716154, 0, 0, -1131], [3279138, 0, 0, -7030], [0, -80045, -112826, 0], [0, 454707, -651807, 0], [-4375446438, 0, 0, -407767], [0, 4798512, -4065288, 0], [-34996433590, 0, 0, 1942029], [165522102642, 0, 0, -2823372], [0, -62935245, 39873372, 0], [0, 107341674, 72228726, 0], [-743793406038, 0, 0, 33160533], [0, 339074283, -249381720, 0], [-1656242712934, 0, 0, -32995419], [0, 1229905543, -679535978, 0], [0, 2286480849, -411388821, 0], [-3008283147278, 0, 0, 355525386], [0, 3951839050, 1805219230, 0], [0, -5754348195, 3410578656, 0], [26576753624274, 0, 0, 1035147034], [23948291484034, 0, 0, 1255201890], [-115087739751990, 0, 0, -608185371], [0, -19409442187, -13949586409, 0], [0, 29920510149, -15565451778, 0], [-185862716086214, 0, 0, -2144432919], [87015219667746, 0, 0, 2845166864], [0, -173829059892, 47300590956, 0], [0, -299519956869, 90338489946, 0], [781479059961522, 0, 0, -8671657532], [0, -51684634381, 14095171028, 0], [578956601448042, 0, 0, -25926542887], [0, 435960475027, -214474362527, 0], [547181775861722, 0, 0, -42759424851], [0, -410605668739, -290050904380, 0], [0, 632302384377, 228089863467, 0], [1266180094387770, 0, 0, 198007647149], [0, 728076791361, 1086603451452, 0], [2004535915285546, 0, 0, 134240346273], [0, 2582559664692, 1559707172964, 0], [-10894830067814206, 0, 0, 202306981458], [7995511010039946, 0, 0, 95639370761], [0, -954296196571, -995372933281, 0], [0, -1859134946935, -2941407611092, 0], [0, 6508051033968, -3041904731928, 0], [0, 5150244855273, 4231594600704, 0], [5305229740618570, 0, 0, -1261254463527], [27894417157907634, 0, 0, 872500951162], [0, 5169973307694, 9603173043306, 0], [3737173756601698, 0, 0, 669428313354], [0, 5055000075867, 12540375114120, 0], [96045024667824642, 0, 0, -1056718250336], [0, -2158492302207, 8377836207435, 0], [60593878261234938, 0, 0, -2842236225599], [0, 33896285828326, -13890916914326, 0], [-168138526477176086, 0, 0, 1273311577125], [70331495376372306, 0, 0, 476430543698], [0, -50381079248007, -18006299537970, 0], [-44735802324230454, 0, 0, 1146084211177], [0, -2769870369213, 17335081745694, 0], [0, 106131562944027, 32213520849681, 0], [-64561224231964078, 0, 0, 7139028934260], [217390834883621658, 0, 0, 9215634039193], [0, 111503059049405, 2566083498062, 0], [-125744707167116702, 0, 0, -16301523519384], [0, -101862013404609, -58914309646044, 0], [-30795391826947366, 0, 0, 18866201099073], [-664523079300590526, 0, 0, -16961392722648], [0, 304211485852581, -116524180696185, 0], [0, 172205091436106, 49404823289894, 0], [13746984990705194, 0, 0, -14651960739891], [0, -315652535023265, 75214404609196, 0], [0, -187493130884880, -50406513823152, 0], [-1162447350974945910, 0, 0, -7173916775283], [1113533758459628282, 0, 0, 16002096624345], [-1053311995554184158, 0, 0, 8835358405690], [1738501155584148370, 0, 0, 20040748019460], [0, 615160234154031, -429254165731338, 0], [-748700809787203382, 0, 0, -90723579140511], [0, -639369178396290, -478401361181334, 0], [-969176038129397278, 0, 0, -4529676725286], [0, 572838124036923, -240094219636143, 0], [0, -668205545321835, -495156890346894, 0], [-2458874517345402174, 0, 0, -49351540599438], [2442237668872165426, 0, 0, 129722698697316], [-1489411083105169542, 0, 0, 160055822743761], [0, 1565590869583610, 181283139535022, 0], [0, 1519699222127463, 513567569830410, 0], [0, -1135031861775264, -35307029690856, 0], [0, -1823314712943223, 874325679819275, 0], [0, -588498397051737, 171111543918336, 0], [0, 204486827165397, -702173228502816, 0], [0, 3527730950502351, -314082500792715, 0], [3145532638617316890, 0, 0, 75685681805997], [-1778020368813166158, 0, 0, -82950271907916], [0, 3245681200468501, -1477329581549546, 0], [4323352016918668762, 0, 0, -74794685538411], [0, -2638548371090401, 1197959140558982, 0], [23831136021352646202, 0, 0, 18920064082853], [0, 836094114455571, 2182926227042862, 0], [8449355187578578002, 0, 0, -239355046765420], [0, 4976278783020013, 77505120935530, 0], [21828979516823394434, 0, 0, -183661010536632], [0, 1921661094765777, 5574171333082914, 0], [8341597281821949282, 0, 0, -36360325990448], [0, 8733941131318119, -1754640258533595, 0], [2285862601188436178, 0, 0, -149209497606822], [0, -2182563441728140, 1328645465171660, 0], [-42614208366608886454, 0, 0, 428898387862305], [-3432003580385895246, 0, 0, 839493110153938], [0, 4828872236010865, -6594937382568278, 0], [0, -2092511501389745, -3725965428021995, 0], [10068739108962912066, 0, 0, 193764905850562], [0, -2930210774400537, -3320731311779898, 0], [0, -5352533250640143, 9122034612238875, 0], [13391028380938573818, 0, 0, -1195579418177391], [0, 18281647889375829, -3465178854049368, 0], [9052415645108459882, 0, 0, 537502561711761], [18247036249791007490, 0, 0, 905889538976370], [91405808912174004810, 0, 0, 151075938856317], [0, -25313729233426761, -3516931770846336, 0], [0, 5344201845565137, 2258303082797388, 0], [-4207401249102382182, 0, 0, -637843872496427], [26087501028193375498, 0, 0, -770321110855155], [0, 3198685701553458, -22510616503927770, 0], [0, 21267492012065511, 8529767765862597, 0], [33498023193911200474, 0, 0, -3873061781275527], [0, 8991612351185049, -12932148612031440, 0], [0, -20709572250204279, -21492362731754421, 0], [0, -20706414220560074, 6231815188842994, 0], [109820299838673032362, 0, 0, 2565801186522489], [-74965602018548482350, 0, 0, -5265334354502348], [91353053536993538114, 0, 0, -1226335439544366], [120233228566081437834, 0, 0, 1151469365610653], [0, -213807723308879, 41636124422763556, 0], [47903712282181608666, 0, 0, 676526667325661], [-313114249924495880334, 0, 0, 2616440301640468], [0, 21223242279604377, -3454024375304382, 0], [139529217244451611818, 0, 0, -3350327761290131], [0, 59915724391150987, -23785224970141439, 0], [0, -96876012350859111, -15129375363913770, 0], [-130305846862407736934, 0, 0, -4587930530545107], [0, 90892115874827757, -40487865508421433, 0], [-332246791898717729686, 0, 0, 3542014524386565], [-144745810020664908270, 0, 0, 8804784909397876], [0, -27304862432226601, -15862665093774532, 0], [0, 78566254717414152, 9652633176914208, 0], [-94565755449073219270, 0, 0, -1269095724243999], [-194728479449518956510, 0, 0, 6727918210490664], [0, 146433082714681247, -3505501374565174, 0], [0, -83154474806820789, 57672512608252113, 0], [0, -120024172445485169, -11147117047991888, 0], [0, -142948904822456466, 31631399672865426, 0], [0, -224533792964234133, 23110345155641337, 0], [-192597628864512254718, 0, 0, -7271668313911918], [-202093731354712521934, 0, 0, 5524496755236378], [1012224745002956279226, 0, 0, -1548875564287399], [0, 117934892981855595, 19095130511886438, 0], [-34493046412306391214, 0, 0, -20989562829384956], [0, 15623969588803741, -157294862256882281, 0], [0, 200251078781454903, 42535815745791528, 0], [-1188298343161549161054, 0, 0, -5983684954060086], [0, -468675561941321073, 146191300649748909, 0], [0, -104175748707415876, -46041546091672972, 0], [-112509136580027639350, 0, 0, -16484212165893891]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_16_c_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_16_15_c_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_16_15_c_c(:prec:=4)
    chi := MakeCharacter_16_c();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 15));
    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_16_15_c_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_16_15_c_c( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_16_c();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,15,sign)));
    Vf := Kernel([<3,R![23813150736384, 0, 19566336, 0, 1]>],Snew);
    return Vf;
end function;