
// Make newform 378.4.g.d in Magma, downloaded from the LMFDB on 24 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_378_g();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_378_g_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_378_4_g_d();".
// 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_378_4_g_d();".
// 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 := [209764, 1374, 29779, 721, 3770, 59, 66, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0, 0, 0, 0, 0], [368827486562, 23392170037, 430332705877, 3920788192, 6652953189, -163698896, 115038401, -1049071], [495081144679420, 232323910657043, 62617325900039, 570510371744, 926039756877, -23819679472, 16739134507, -1696542203], [-128122572731930, 49965354534078, -28158496126236, 3215243331501, -543267423074, 75308363320, -9761813387, 863252840], [-39943270058320, 216104308469206, 66670171571461, -20223346800686, 868174142577, -412942482080, 31228732907, -7051508536], [-212042096779230, 19656181548311, -14865162115186, -3607234572013, -384930665533, -58942130264, -1739457099, -1208164720], [74164049534822, 265828073508127, 67560799766893, 33815120349688, 1638688334415, 583780276750, 10568597603, 8617899467], [219625364013092, -109817040839384, 90389069998933, 34135187416753, 2482301067297, 500910335965, 20249178479, 9748790105]];
    Rf_basisdens := [1, 3033579204498, 63705163294458, 10617527215743, 63705163294458, 10617527215743, 63705163294458, 63705163294458];
    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_378_g();"
function MakeCharacter_378_g()
    N := 378;
    order := 3;
    char_gens := [29, 325];
    v := [3, 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_378_g_Hecke();"
function MakeCharacter_378_g_Hecke(Kf)
    N := 378;
    order := 3;
    char_gens := [29, 325];
    char_values := [[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 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, 2, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, -1, 0, 0, 0, 0, -1, 0], [3, 0, 0, -1, -1, 0, 0, -1], [14, 14, 2, 1, 0, 1, 0, 0], [-2, 0, 3, 0, 0, 1, -3, 1], [-30, -30, -2, -1, 2, -3, 0, 0], [0, -10, 0, -4, 3, 2, 0, 3], [0, -48, 0, 0, -8, 0, 2, -8], [-67, 0, 11, -4, 0, 2, -11, -6], [71, 71, -12, -1, -8, 7, 0, 0], [0, 47, 0, 6, -3, -3, 24, -3], [2, 0, -2, -15, 0, 8, 2, -22], [-193, 0, 0, -4, 0, 14, 0, 6], [0, -3, 0, -20, -18, 10, 3, -18], [122, 122, 28, 8, -8, 16, 0, 0], [-76, -76, -12, 17, 8, 9, 0, 0], [0, -110, 0, -12, -34, 6, 27, -34], [330, 330, 45, 9, -1, 10, 0, 0], [-235, 0, -39, -6, 0, -2, 39, -14], [-360, -360, -36, 2, 17, -15, 0, 0], [0, -185, 0, -54, -25, 27, -12, -25], [-204, 0, -22, 4, 0, 6, 22, 14], [0, 218, 0, -6, -8, 3, -32, -8], [132, 0, 9, -29, 0, 42, -9, -16], [171, 171, 23, -30, -26, -4, 0, 0], [0, -406, 0, -20, 9, 10, 3, 9], [0, -460, 0, -12, -2, 6, -14, -2], [474, 474, -33, 6, -22, 28, 0, 0], [-348, 0, 46, -7, 0, -36, -46, -50], [-872, 0, -3, 2, 0, 0, 3, 4], [0, -88, 0, 40, 30, -20, -88, 30], [138, 138, 32, -66, -104, 38, 0, 0], [36, 0, -33, 47, 0, -41, 33, 53], [0, -1205, 0, 128, 104, -64, 95, 104], [648, 648, 81, -56, -10, -46, 0, 0], [-719, -719, 105, -27, -48, 21, 0, 0], [0, 674, 0, -94, -36, 47, 105, -36], [-60, 0, -170, 54, 0, -170, 170, -62], [0, 2290, 0, 4, 82, -2, -102, 82], [1508, 1508, 118, -57, 16, -73, 0, 0], [1525, 0, 99, -91, 0, 135, -99, -47], [0, -1713, 0, -76, 72, 38, 51, 72], [1327, 1327, -168, -38, -75, 37, 0, 0], [-1330, 0, 162, 8, 0, 144, -162, 160], [-302, -302, 321, 26, -54, 80, 0, 0], [959, 0, 60, 50, 0, 20, -60, 120], [1358, 0, -402, 84, 0, -108, 402, 60], [2548, 2548, -238, -86, -112, 26, 0, 0], [0, 291, 0, 10, 34, -5, -48, 34], [0, 1426, 0, 32, -66, -16, -26, -66], [-2617, 0, 103, -40, 0, -68, -103, -148], [1429, 1429, 42, 74, 228, -154, 0, 0], [1440, 0, 42, -18, 0, 24, -42, -12], [0, 244, 0, 24, -82, -12, 230, -82], [-1997, -1997, 281, 12, -52, 64, 0, 0], [1222, 1222, -74, -52, 0, -52, 0, 0], [0, -1220, 0, 60, 50, -30, -177, 50], [925, 925, 216, 209, 234, -25, 0, 0], [-4038, 0, -112, -121, 0, 64, 112, -178], [-87, -87, 144, -14, 146, -160, 0, 0], [2141, 0, 79, -230, 0, 312, -79, -148], [1794, 0, 51, 29, 0, -284, -51, -226], [6035, 6035, 63, 58, 134, -76, 0, 0], [0, -6612, 0, 48, -23, -24, 264, -23], [0, -2343, 0, 68, -84, -34, -261, -84], [0, 3140, 0, 260, 429, -130, -246, 429], [1666, 0, -222, 188, 0, -255, 222, 121], [-162, -162, -294, 6, -180, 186, 0, 0], [-2439, 0, -384, 121, 0, -240, 384, 2], [4228, 4228, 560, 236, -16, 252, 0, 0], [0, -1692, 0, -276, 146, 138, 286, 146], [5737, 5737, -243, -111, -21, -90, 0, 0], [0, 2079, 0, -362, 121, 181, -123, 121], [2265, 0, -72, 26, 0, 199, 72, 251], [0, 2100, 0, -324, 22, 162, 158, 22], [-1308, -1308, 200, 74, 346, -272, 0, 0], [0, -1364, 0, 8, -250, -4, 237, -250], [0, -8426, 0, -210, -88, 105, -82, -88], [-4280, -4280, -411, -3, -45, 42, 0, 0], [-4438, 0, -44, 321, 0, -46, 44, 596], [2359, 0, -15, -217, 0, 51, 15, -383], [6419, 6419, 529, 276, 16, 260, 0, 0], [1718, 0, 357, -229, 0, 242, -357, -216], [0, -1334, 0, -68, 368, 34, -258, 368], [0, -8182, 0, 200, -34, -100, 198, -34], [-10220, 0, 270, -11, 0, 342, -270, 320], [0, 7368, 0, -362, -356, 181, 597, -356], [4499, 0, 41, -188, 0, -104, -41, -480], [6900, 0, 78, 154, 0, -225, -78, 83], [0, 7998, 0, 58, 350, -29, -44, 350], [8087, 8087, -793, -34, 540, -574, 0, 0], [-8684, -8684, 306, -118, -57, -61, 0, 0], [-1690, 0, 232, 44, 0, 622, -232, 710], [0, 6342, 0, 914, 22, -457, 645, 22], [6864, 0, 234, 136, 0, -92, -234, 180], [0, 6892, 0, 0, 98, 0, 722, 98], [-3772, -3772, 730, 16, 430, -414, 0, 0], [0, -2929, 0, 88, -111, -44, 210, -111], [0, 8326, 0, 248, -133, -124, -246, -133], [-4478, 0, -771, 165, 0, -290, 771, 40], [2611, 2611, -53, -352, 180, -532, 0, 0], [5344, 5344, -930, -476, -452, -24, 0, 0], [0, -8376, 0, 410, -30, -205, -354, -30], [-4078, -4078, -192, 452, 769, -317, 0, 0], [7218, 7218, 333, 633, 65, 568, 0, 0], [-3312, 0, 1142, 171, 0, 338, -1142, 680], [0, 44, 0, -306, 478, 153, -242, 478], [1092, 1092, 96, -266, -570, 304, 0, 0], [4256, 0, 591, -389, 0, -38, -591, -816], [0, 8773, 0, -634, 413, 317, -291, 413], [-13657, -13657, 324, -3, -530, 527, 0, 0], [-3956, 0, 1288, 27, 0, -78, -1288, -24], [14055, 14055, 564, -456, -529, 73, 0, 0], [-6751, 0, -114, 527, 0, -1048, 114, 6], [10142, 10142, 242, 513, 414, 99, 0, 0], [1820, 0, -1005, 135, 0, -540, 1005, -270], [-13042, -13042, 226, 172, -452, 624, 0, 0], [0, -15938, 0, -800, 164, 400, -616, 164], [5514, 0, -148, -399, 0, 866, 148, 68], [1707, 1707, 513, -529, -445, -84, 0, 0], [-2176, 0, 204, -226, 0, 407, -204, -45], [0, 804, 0, -692, -756, 346, -468, -756], [2888, 2888, -326, -301, 178, -479, 0, 0], [0, -6184, 0, 1034, 18, -517, 429, 18], [-7940, 0, -264, -620, 0, 150, 264, -1090], [0, 9290, 0, 68, 366, -34, 201, 366], [0, 4583, 0, -388, -1010, 194, -221, -1010], [-9645, 0, 624, 575, 0, 286, -624, 1436], [0, 9136, 0, -1216, -886, 608, -597, -886], [-9229, -9229, -846, -4, -50, 46, 0, 0], [17177, 0, 355, -296, 0, 426, -355, -166], [0, 1291, 0, -610, -157, 305, -1425, -157], [-2093, 0, -600, 123, 0, -152, 600, 94], [0, -5022, 0, 932, -152, -466, -1186, -152], [-2601, 0, -495, -47, 0, 789, 495, 695], [-25400, -25400, 1012, 244, 366, -122, 0, 0], [-1396, -1396, 1263, 1065, 964, 101, 0, 0], [-5413, 0, -1667, -226, 0, 844, 1667, 392], [220, 220, 286, 450, -870, 1320, 0, 0], [23589, 0, -477, 131, 0, 322, 477, 584], [0, -994, 0, -752, -262, 376, -2244, -262], [-4875, -4875, -1380, -311, 86, -397, 0, 0], [-10086, 0, 930, -302, 0, 664, -930, 60], [-11607, -11607, 375, -509, 305, -814, 0, 0], [-2592, 0, 1658, -672, 0, 902, -1658, -442], [3431, 0, -711, -321, 0, -519, 711, -1161], [6460, 6460, -94, -1179, -1246, 67, 0, 0], [0, 1379, 0, 1136, -996, -568, -336, -996], [0, 30432, 0, -856, -814, 428, -1184, -814], [0, 7272, 0, 364, -122, -182, -435, -122], [19764, 0, -1746, -64, 0, -1120, 1746, -1248], [-4300, 0, 1998, -742, 0, 1631, -1998, 147], [0, -21884, 0, -1040, -634, 520, -1030, -634], [12464, 12464, -885, 699, 1447, -748, 0, 0], [3301, 0, 779, 862, 0, -1378, -779, 346], [0, 13482, 0, 908, 892, -454, 1209, 892], [0, -12636, 0, -902, -96, 451, -150, -96], [14186, 0, -153, 519, 0, -933, 153, 105], [9509, 9509, -261, 1290, 2144, -854, 0, 0], [0, 19708, 0, -1190, -386, 595, 2268, -386], [14348, 0, 342, 954, 0, 4, -342, 1912], [-10174, 0, -2487, -206, 0, -995, 2487, -1407], [0, -10840, 0, -732, -638, 366, 484, -638], [-14826, -14826, -12, -70, 402, -472, 0, 0], [-3383, -3383, 437, -272, -1606, 1334, 0, 0], [955, 955, -540, -227, -417, 190, 0, 0], [103, 103, 96, 717, -102, 819, 0, 0]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_378_g_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_378_4_g_d();".
// 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_378_4_g_d(:prec:=8)
    chi := MakeCharacter_378_g();
    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_378_4_g_d();".
// 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_378_4_g_d( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_378_g();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<5,R![9144576, 1850688, 1263600, -155736, 85860, -48, 310, -4, 1]>],Snew);
    return Vf;
end function;