
// Make newform 225.4.e.c in Magma, downloaded from the LMFDB on 25 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_225_e();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_225_e_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_225_4_e_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_225_4_e_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 := [9, -39, 52, -27, 16, -3, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0, 0, 0], [4, -1, 1, 0, 0, 0], [-12, 10, -11, 2, -1, 0], [-39, 88, -40, 30, -5, 2], [126, -289, 141, -103, 18, -7], [147, -334, 157, -117, 20, -8]];
    Rf_basisdens := [1, 1, 3, 3, 3, 3];
    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_225_e();"
function MakeCharacter_225_e()
    N := 225;
    order := 3;
    char_gens := [101, 127];
    v := [1, 3];
    // 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_225_e_Hecke();"
function MakeCharacter_225_e_Hecke(Kf)
    N := 225;
    order := 3;
    char_gens := [101, 127];
    char_values := [[0, 0, 0, 1, 0, 0], [1, 0, 0, 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 := 4;
    raw_aps := [[0, 1, 0, 0, 0, -1], [-1, 0, -1, 0, 0, 1], [0, 0, 0, 0, 0, 0], [-16, 1, 6, -16, 6, -1], [-3, 14, 9, -3, 9, -14], [0, 0, 0, -17, -3, 14], [57, 2, -3, 0, 0, 0], [-55, -10, -9, 0, 0, 0], [0, 0, 0, -48, -36, 9], [117, -14, -30, 117, -30, 14], [0, 0, 0, -127, -33, 62], [-143, 24, 51, 0, 0, 0], [0, 0, 0, 72, -69, 40], [-169, 8, -87, -169, -87, -8], [207, -59, -15, 207, -15, 59], [228, -70, -24, 0, 0, 0], [0, 0, 0, -36, -108, -82], [448, -20, 75, 448, 75, 20], [0, 0, 0, 637, -21, -41], [81, -76, -249, 0, 0, 0], [172, -44, -192, 0, 0, 0], [154, -112, -192, 154, -192, 112], [-360, 105, 354, -360, 354, -105], [549, 168, 240, 0, 0, 0], [-100, -78, -60, -100, -60, 78], [30, 18, 114, 30, 114, -18], [0, 0, 0, 841, -57, 132], [-462, -15, 492, 0, 0, 0], [-388, 246, -123, 0, 0, 0], [0, 0, 0, -366, -252, 262], [1003, 31, 45, 0, 0, 0], [0, 0, 0, -642, 720, -348], [-312, 438, 210, -312, 210, -438], [0, 0, 0, -160, 24, -432], [0, 0, 0, 1740, -459, 10], [667, 334, -201, 667, -201, -334], [0, 0, 0, -1694, 66, 426], [-41, -276, -255, 0, 0, 0], [0, 0, 0, 2919, 111, -273], [78, -192, -318, 78, -318, 192], [1185, 40, 279, 0, 0, 0], [1217, -306, 306, 0, 0, 0], [-225, -236, -537, -225, -537, 236], [0, 0, 0, 925, -1089, -6], [990, 1110, 108, 0, 0, 0], [-139, 266, 171, 0, 0, 0], [0, 0, 0, 35, 15, -654], [467, -663, 99, 467, 99, 663], [-1887, -562, -399, -1887, -399, 562], [0, 0, 0, 449, 120, 902], [-183, 12, -1041, 0, 0, 0], [0, 0, 0, 2430, 1008, -142], [3148, -38, -717, 3148, -717, 38], [-399, 1152, 345, 0, 0, 0], [0, 0, 0, 2346, 456, -264], [-1521, 296, -303, -1521, -303, -296], [2196, -170, -567, 0, 0, 0], [-2509, -406, -219, 0, 0, 0], [-2119, -314, 657, -2119, 657, 314], [1506, -438, 1125, 1506, 1125, 438], [0, 0, 0, 988, 1596, -353], [0, 0, 0, 885, 1029, -1566], [2992, 235, 648, 0, 0, 0], [0, 0, 0, 2193, 2169, -1020], [3809, -1416, 225, 3809, 225, 1416], [-1905, -52, -453, -1905, -453, 52], [790, -1654, -42, 790, -42, 1654], [0, 0, 0, 808, -2670, 1586], [0, 0, 0, -2997, 1569, 364], [-95, 328, 2568, -95, 2568, -328], [4872, 504, 804, 4872, 804, -504], [-1071, -1068, -1779, 0, 0, 0], [-2191, -3008, -1785, -2191, -1785, 3008], [0, 0, 0, 2644, -372, -1066], [-4468, 1640, 1998, 0, 0, 0], [0, 0, 0, 6735, -351, 300], [-1392, 348, -1527, -1392, -1527, -348], [3430, -1916, -2652, 0, 0, 0], [0, 0, 0, 4050, -1506, 1950], [0, 0, 0, -1816, 1170, 864], [0, 0, 0, 2055, 27, 1666], [-1784, -2552, 978, -1784, 978, 2552], [-4452, -456, -1242, 0, 0, 0], [2785, 2326, 453, 0, 0, 0], [-8594, -506, 888, -8594, 888, 506], [-3975, -1497, 1473, -3975, 1473, 1497], [3048, 886, 2532, 0, 0, 0], [-583, -448, 1383, -583, 1383, 448], [-3183, -258, -780, -3183, -780, 258], [0, 0, 0, 475, -861, -698], [-7659, 784, 3987, 0, 0, 0], [-4116, 2304, 390, -4116, 390, -2304], [3205, 4350, 2829, 0, 0, 0], [0, 0, 0, 492, -534, 4390], [0, 0, 0, -5062, -2196, -2006], [-3837, -1457, 1659, 0, 0, 0], [0, 0, 0, -2193, 588, -3328], [-1449, 986, -2454, 0, 0, 0], [-11963, -3641, -1761, 0, 0, 0], [11651, -1364, 2646, 0, 0, 0], [-436, -3523, 1368, -436, 1368, 3523], [1050, -2892, -4212, 0, 0, 0], [0, 0, 0, -2733, -417, 3579], [-7590, -4392, -504, -7590, -504, 4392], [0, 0, 0, -7948, 4032, -1272], [-7412, -846, -2352, 0, 0, 0], [8760, 5781, 1824, 8760, 1824, -5781], [1347, -4532, 3609, 0, 0, 0], [0, 0, 0, -6012, -4638, 832], [2932, 3576, 498, 2932, 498, -3576], [0, 0, 0, 6373, -8541, 5009], [-10139, -686, -2439, 0, 0, 0], [0, 0, 0, -5598, -384, -2166], [769, -4734, -3405, 769, -3405, 4734], [-10498, 3338, 2376, 0, 0, 0], [10080, 3090, 3159, 10080, 3159, -3090], [0, 0, 0, -4967, 45, -4757], [12975, 3953, -129, 0, 0, 0], [0, 0, 0, 19353, 1683, -2320], [10422, -2986, 1644, 10422, 1644, 2986], [0, 0, 0, 13154, -1764, 1828], [1115, -6284, -2013, 1115, -2013, 6284], [13635, 2460, 3627, 13635, 3627, -2460], [-6153, 4992, 3741, 0, 0, 0], [-5096, 2656, 5466, -5096, 5466, -2656], [7026, 1796, 2475, 0, 0, 0], [-7151, 5818, 6618, -7151, 6618, -5818], [14196, 2862, 948, 0, 0, 0], [10841, -423, -1293, 10841, -1293, 423], [0, 0, 0, -19322, 984, 2064], [-22018, 1718, -1242, 0, 0, 0], [0, 0, 0, 2652, 5562, -5417], [0, 0, 0, -5725, 1557, 4948], [-17039, 3142, 8679, 0, 0, 0], [0, 0, 0, 5313, 1704, 3510], [0, 0, 0, 19271, -5544, 702], [9720, 8796, 4620, 0, 0, 0], [0, 0, 0, 8383, 4149, -1192], [0, 0, 0, -8109, -7905, 7964], [-18066, -3538, -4698, 0, 0, 0], [-23614, -4592, -1668, 0, 0, 0], [-17490, -7608, -963, -17490, -963, 7608], [0, 0, 0, -4475, -81, -3237], [-23841, 539, -957, 0, 0, 0], [13250, 4852, 2913, 0, 0, 0], [-1929, -3218, 8985, -1929, 8985, 3218], [11891, 8872, 5871, 11891, 5871, -8872], [741, -1610, 4623, 741, 4623, 1610], [0, 0, 0, -13597, 3837, -2132], [4485, -8345, -4407, 0, 0, 0], [0, 0, 0, -1991, 4971, 2578], [21252, 3340, 711, 0, 0, 0], [16099, -3039, 3135, 0, 0, 0], [0, 0, 0, -10647, 2067, -1812], [-11533, 5653, -3465, -11533, -3465, -5653], [20238, -6118, -8274, 20238, -8274, 6118], [34568, 572, 2946, 0, 0, 0], [-8784, 6988, 1314, -8784, 1314, -6988], [7438, 2954, -72, 0, 0, 0], [0, 0, 0, 8865, -12678, -1406], [2103, 2907, 7629, 2103, 7629, -2907], [27549, -3712, -11799, 0, 0, 0], [0, 0, 0, -11612, 1980, 1395], [-10833, -4494, 2025, 0, 0, 0], [0, 0, 0, -3621, -7341, -4460], [-23982, 1905, 10902, -23982, 10902, -1905], [398, 8142, -1062, 0, 0, 0], [680, 874, -5448, 680, -5448, -874]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_225_e_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_225_4_e_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_225_4_e_c(:prec:=6)
    chi := MakeCharacter_225_e();
    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_225_4_e_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_225_4_e_c( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_225_e();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<2,R![9, 51, 292, -11, 18, 1, 1]>],Snew);
    return Vf;
end function;