
// Make newform 135.4.a.f in Magma, downloaded from the LMFDB on 25 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_135_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_135_4_a_f();".
// 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_135_4_a_f();".
// 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 := [6, -23, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0], [0, 1, 0], [-15, -1, 1]];
    Rf_basisdens := [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_135_a();"
function MakeCharacter_135_a()
    N := 135;
    order := 1;
    char_gens := [56, 82];
    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_135_a_Hecke(Kf)
    return MakeCharacter_135_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 := 4;
    raw_aps := [[0, -1, 0], [0, 0, 0], [5, 0, 0], [14, 2, 0], [12, -2, 4], [14, -10, -4], [-3, -2, -8], [59, 14, -4], [-39, 32, 4], [42, 42, -8], [83, -30, 8], [50, -64, -8], [-132, 42, 16], [-16, 78, -8], [-168, 28, 4], [165, 14, 12], [78, -82, -12], [173, 60, 16], [302, -52, 24], [-192, 34, -60], [404, 22, 60], [221, -22, -12], [-489, 120, 60], [756, -66, -48], [440, 64, 8], [-180, -208, 64], [140, 272, -56], [-120, -200, 20], [953, -224, -28], [-342, -116, -20], [-322, -108, 16], [1470, -144, 72], [-1845, 2, -68], [-844, -288, 144], [1380, -210, -80], [-700, 0, 28], [1112, -34, -140], [-2350, -176, -112], [1257, 56, -128], [-909, -34, -80], [-2436, 308, 72], [41, -592, 196], [1182, -56, -24], [-262, 430, 332], [-1905, -154, 4], [-880, 276, 136], [-3295, -242, -40], [-970, 720, 0], [495, 812, 56], [-3049, -228, 20], [30, -64, -8], [234, -188, 160], [1103, -1108, -220], [792, -492, -216], [-1689, -690, 252], [-1188, -268, -268], [294, 580, 16], [-85, -46, 152], [-340, -498, 524], [1254, -290, -184], [-1084, 770, 144], [4227, 698, 28], [-1066, 56, 128], [1914, 662, 340], [4256, -740, -256], [-7707, 90, -56], [-3772, -404, -104], [5246, -1370, -156], [-4164, 168, -760], [4301, -152, 312], [-1134, 116, 256], [-5358, 1660, 128], [-5506, -558, 200], [-2488, -364, -400], [-2491, 822, 232], [465, -1156, 232], [264, -1886, -16], [1586, 1254, 412], [3930, -1120, -320], [7037, -248, 644], [-6900, -2490, 580], [-2797, -48, 112], [6774, -986, 44], [7658, -38, 756], [515, -1746, -1064], [8823, 1444, 164], [3306, 2138, 240], [4148, 2500, -768], [-4518, 1892, -368], [-4642, -1668, 56], [-8865, -180, 592], [3636, 1958, -380], [-3868, 390, -1032], [5154, 764, -376], [6155, -1754, -240], [-10983, -1112, 540], [6636, -2928, -1072], [708, -902, 48], [5054, -2002, 32], [5210, -464, 604], [-1504, -1538, 888], [-66, 3700, 776], [-1440, 2152, 44], [4746, -146, 392], [-4849, 2550, -552], [11552, -82, -596], [5913, -520, 700], [-741, -3098, 1476], [-1878, -2334, -1100], [-13087, 532, -268], [-664, 2334, 712], [-22792, -1072, -232], [-531, 166, -364], [-2584, 4420, 248], [1949, 1202, 1484], [360, 2096, 1432], [-1750, -1690, 0], [-9651, -164, -1760], [-11343, -442, -1312], [13698, -2770, -828], [-7966, -1880, -636], [4430, 2574, 908], [-11406, 2364, -156], [9459, 1632, 1824], [-4711, 4358, -1192], [7542, -1992, -776], [-18130, 2936, -292], [-11034, -1368, -192], [-3904, 3588, -1800], [-8080, -4176, 1728], [2597, 1634, 1808], [-3216, 5144, 1464], [-3499, 498, -1004], [-17422, -3660, -248], [-17442, -698, 176], [-1687, 584, -2492], [8913, -4834, -1400], [620, -3878, -1416], [-7809, -4230, -404], [26412, 730, 648], [12896, -7472, -452], [-19050, -4160, -880], [6368, -1786, -80], [-3195, -7212, -256], [-8350, 3540, -2044], [-4224, 4380, 2104], [-7492, 6572, 1776], [8901, 2786, 864], [14933, -1614, -1088], [-7239, -4820, -2292], [-20344, 2690, 1404], [6222, 7718, -1896], [-18898, 8442, 1272], [7689, -804, 396], [-124, -1416, -2248], [25710, 858, -4], [11864, -2424, 664], [2292, -486, 16], [1832, 5084, -24], [4602, 7416, 880], [10443, 3976, -2428], [14742, -1344, -1600], [-1150, 9120, 1680], [-12090, -368, 1664], [-5598, 8116, -440], [26925, 2652, -180], [14153, 3938, 772], [-17128, -542, -836]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_135_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


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