
// Make newform 378.4.g.f in Magma, downloaded from the LMFDB on 25 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_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_378_4_g_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 := [100, 40, 186, -48, 283, 9, 18, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0, 0, 0, 0, 0], [2144550, -811706, 3812253, -1314483, 165901, -103443, 17661, -5251], [5541150, -43821428, 9850209, -3396399, 771473, -267279, 45633, -5533], [20095080, -24618118, -26303561, 3388681, -1182462, 400691, -123347, 25642], [-13301880, -34372646, 38379473, -7552513, 2393606, -728363, 179291, -26206], [5873470, 3795232, 3475204, 4902586, 417823, 296256, -3492, 16807], [5545466, -7027748, 6404040, -11885520, -84149, -783152, 56798, -42509], [-3549092, -394100, -636190, -13230433, -661525, -821980, 35959, -47855]];
    Rf_basisdens := [1, 2252390, 2252390, 2252390, 2252390, 321770, 450478, 450478];
    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, -1, 0, 0, 0, 0, 0], [2, -2, 0, 0, -1, 0, 0, 0], [8, -8, 0, 0, 0, -1, 1, 0], [0, 1, 0, -1, -2, -1, 2, 2], [-14, 15, 3, -2, 2, 0, 2, 3], [-3, 20, 2, -1, 2, 3, 3, 0], [0, 23, 3, -1, -1, 0, 0, 0], [-28, -2, 0, -6, -4, -6, 4, -5], [-19, 13, -6, 0, 0, -5, 5, -6], [-5, -29, 10, 6, 11, 5, 5, 0], [-92, -10, 0, -6, 4, -6, -4, 1], [105, 0, 0, -2, -2, -2, 2, -10], [-10, -77, -11, -16, -6, 10, 10, 0], [-36, 9, -7, -20, 20, 11, 9, -7], [32, -42, -6, -4, 4, 9, -5, -6], [4, -101, -16, -7, -11, -4, -4, 0], [-231, 246, 8, 7, -7, 1, -8, 8], [-184, 2, 0, -17, -19, -17, 19, -26], [-32, -5, -52, 15, -15, -15, 0, -52], [9, -29, 64, 2, -7, -9, -9, 0], [-376, 10, 0, -24, -34, -24, 34, 42], [-4, -329, 67, 20, 24, 4, 4, 0], [-501, -10, 0, 24, 34, 24, -34, 74], [66, -128, -40, -22, 22, -11, 33, -40], [-7, -669, 30, 34, 41, 7, 7, 0], [10, 790, -72, 8, -2, -10, -10, 0], [-407, 475, 48, 20, -20, -41, 21, 48], [-848, -26, 0, 23, 49, 23, -49, 68], [37, 6, 0, -25, -31, -25, 31, -12], [66, -651, 43, 29, -37, -66, -66, 0], [972, -953, -1, 20, -20, -65, 45, -1], [-454, 43, 0, -14, -57, -14, 57, 8], [100, 595, 3, 62, -38, -100, -100, 0], [-1209, 1089, -102, -18, 18, -19, 37, -102], [706, -622, 18, 66, -66, -60, -6, 18], [-36, -409, -184, -46, -10, 36, 36, 0], [1304, -6, 0, 104, 110, 104, -110, -18], [-58, 415, 17, 1, 59, 58, 58, 0], [-244, 281, -39, 76, -76, -68, -8, -39], [-527, -9, 0, -22, -13, -22, 13, -222], [-60, 677, -11, 64, 124, 60, 60, 0], [-781, 912, 44, 87, -87, -59, -28, 44], [-1928, 36, 0, 40, 4, 40, -4, -120], [-587, 527, 92, -152, 152, 71, 81, 92], [2211, -54, 0, -20, 34, -20, -34, 50], [-1534, 50, 0, -40, -90, -40, 90, 86], [2820, -2727, 109, -16, 16, -59, 75, 109], [122, -3417, -70, 83, -39, -122, -122, 0], [-50, 3147, 45, -95, -45, 50, 50, 0], [-3240, -20, 0, 118, 138, 118, -138, -77], [1335, -947, 310, 78, -78, -4, -74, 310], [2796, 4, 0, -167, -171, -167, 171, -11], [58, -1888, 146, -50, -108, -58, -58, 0], [740, -940, -32, -168, 168, 131, 37, -32], [4660, -4966, -222, -84, 84, 130, -46, -222], [60, -1829, 64, -181, -241, -60, -60, 0], [-1003, 843, -264, 104, -104, 5, -109, -264], [-4152, -34, 0, -133, -99, -133, 99, -144], [-2465, 2587, 106, 16, -16, 44, -60, 106], [3680, -48, 0, -121, -73, -121, 73, 142], [-3427, -230, 0, -290, -60, -290, 60, -112], [1906, -1840, 288, -222, 222, 25, 197, 288], [-35, 1930, -150, 85, 120, 35, 35, 0], [-4, 344, 0, -167, -163, 4, 4, 0], [13, 674, 288, -205, -218, -13, -13, 0], [2977, -9, 0, 206, 215, 206, -215, 18], [364, -596, -152, -80, 80, -6, 86, -152], [-2517, -26, 0, 77, 103, 77, -103, 166], [4908, -5214, -342, 36, -36, 0, -36, -342], [14, 6490, 80, 64, 50, -14, -14, 0], [2, -243, -56, -185, 185, 57, 128, -56], [169, 4098, 214, 329, 160, -169, -169, 0], [-2758, -207, 0, -276, -69, -276, 69, -92], [-314, -1534, 340, -214, 100, 314, 314, 0], [4226, -3465, 647, 114, -114, 29, -143, 647], [-60, 311, -120, -83, -23, 60, 60, 0], [-324, 3356, 340, -185, 139, 324, 324, 0], [-6139, 6120, -140, 121, -121, -21, -100, -140], [4300, -4, 0, -90, -86, -90, 86, -569], [-7649, -31, 0, 4, 35, 4, -35, -256], [-1812, 1902, 34, 56, -56, 79, -135, 34], [-195, 162, 0, 148, -14, 148, 14, 218], [-30, 6738, 2, -288, -258, 30, 30, 0], [298, 1337, -521, 71, -227, -298, -298, 0], [-2968, 56, 0, 274, 218, 274, -218, -97], [206, 1533, -58, 56, -150, -206, -206, 0], [460, 56, 0, 381, 325, 381, -325, 42], [2337, 309, 0, -176, -485, -176, 485, -372], [262, -4150, -396, 141, -121, -262, -262, 0], [3580, -3099, 337, 144, -144, 340, -484, 337], [3890, -4359, -366, -103, 103, 113, -10, -366], [-9600, 286, 0, -140, -426, -140, 426, 430], [38, 7055, 408, 48, 10, -38, -38, 0], [-4916, 84, 0, 307, 223, 307, -223, -667], [82, -6058, -76, 526, 444, -82, -82, 0], [12462, -12444, 132, -114, 114, -234, 348, 132], [-121, 3903, 90, 193, 314, 121, 121, 0], [209, 8516, 500, 307, 98, -209, -209, 0], [-9495, -372, 0, 28, 400, 28, -400, 52], [1740, -1427, -67, 380, -380, 82, -462, -67], [-6732, 7973, 821, 420, -420, -501, 81, 821], [482, 5840, 690, 697, 215, -482, -482, 0], [9418, -9357, 404, -343, 343, 73, 270, 404], [-1353, 1944, 440, 151, -151, -311, 160, 440], [4180, -116, 0, -94, 22, -94, -22, 121], [190, 3046, 144, 77, -113, -190, -190, 0], [10814, -11485, -725, 54, -54, -313, 259, -725], [-7235, 254, 0, 226, -28, 226, 28, -1170], [-321, -6880, -378, 43, 364, 321, 321, 0], [5563, -5355, -24, 232, -232, -403, 171, -24], [-7248, 128, 0, 461, 333, 461, -333, 330], [-1695, 2010, 56, 259, -259, 355, -614, 56], [-1911, 264, 0, -431, -695, -431, 695, 476], [110, 175, 751, -466, 466, -12, 478, 751], [-3025, 270, 0, 144, -126, 144, 126, -552], [17496, -16896, 324, 276, -276, 306, -582, 324], [-308, -5715, 949, -285, 23, 308, 308, 0], [-8744, -372, 0, 196, 568, 196, -568, 117], [-9948, 10401, 430, 23, -23, 597, -620, 430], [-4767, 671, 0, 84, -587, 84, 587, -212], [184, -2444, -168, -40, -224, -184, -184, 0], [-4194, 3672, 80, -602, 602, 305, 297, 80], [-80, 13979, -654, -328, -248, 80, 80, 0], [7844, 450, 0, 71, -379, 71, 379, -915], [-552, 8657, -1180, 23, 575, 552, 552, 0], [-170, 8580, 766, -321, -151, 170, 170, 0], [-14437, 82, 0, 307, 225, 307, -225, -1384], [-52, -14131, -424, 415, 467, 52, 52, 0], [8883, -9889, -1256, 250, -250, -188, -62, -1256], [-1084, -82, 0, -746, -664, -746, 664, 975], [-677, 12314, -32, -449, 228, 677, 677, 0], [-12453, -88, 0, 645, 733, 645, -733, 156], [-424, -3416, 888, -732, -308, 424, 424, 0], [-4851, -501, 0, -254, 247, -254, -247, -108], [18970, -19021, -89, 38, -38, -337, 299, -89], [-11927, 12819, 1080, -188, 188, -436, 624, 1080], [12540, -692, 0, -497, 195, -497, -195, 520], [-6914, 7718, 554, 250, -250, -498, 248, 554], [770, -622, 0, 482, 1104, 482, -1104, -330], [-894, -9266, -1160, -408, 486, 894, 894, 0], [711, -1743, -888, -144, 144, -493, 637, -888], [23308, -444, 0, 562, 1006, 562, -1006, -754], [-2928, 3051, 162, -39, 39, 545, -506, 162], [8692, 38, 0, 30, -8, 30, 8, 1166], [-17503, 319, 0, -524, -843, -524, 843, 28], [-16494, 15330, -550, -614, 614, -121, 735, -550], [-368, -997, 432, -1252, -884, 368, 368, 0], [442, -663, -1573, 539, 97, -442, -442, 0], [838, 14277, -254, 95, -743, -838, -838, 0], [-20968, 772, 0, -141, -913, -141, 913, 1055], [2223, -405, 0, 628, 1033, 628, -1033, 38], [1474, -1398, -332, 858, -616, -1474, -1474, 0], [7741, -5526, 1326, 889, -889, 389, -1278, 1326], [8580, 290, 0, -1276, -1566, -1276, 1566, -115], [488, 2645, 1506, 867, 379, -488, -488, 0], [60, 6757, 1889, 188, 128, -60, -60, 0], [9200, -439, 0, 74, 513, 74, -513, 284], [-25388, 26846, 550, 908, -908, -529, -379, 550], [34, -11147, 1531, 304, 270, -34, -34, 0], [31304, -656, 0, -897, -241, -897, 241, 639], [8698, 43, 0, -111, -154, -111, 154, -610], [-582, 16075, 77, 875, 1457, 582, 582, 0], [4438, -4388, -220, 270, -270, 1924, -2194, -220], [-26646, 28494, 1498, 350, -350, -569, 219, 1498], [-16439, 18056, 1714, -97, 97, 466, -369, 1714], [12495, -14027, -784, -748, 748, 1125, -377, -784]];
    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_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_378_4_g_f(: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_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_378_4_g_f( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_378_g();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<5,R![561121344, -2842560, 7736688, -55632, 82828, -412, 330, 2, 1]>],Snew);
    return Vf;
end function;