
// Make newform 378.4.f.b in Magma, downloaded from the LMFDB on 13 May 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_378_f();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_378_f_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_f_b();".
// 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_f_b();".
// 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 := [2707, 1543, 7, -166, 38, 53, -2, -2, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0, 0, 0, 0, 0], [-75818, 104222, 13322, -15799, -1570, 809, -152, -45], [1139585, 109080, -58960, -46669, 27893, 9062, -4527, 956], [-97401, -19694, 2915, 7091, -3814, -394, 314, -65], [-635990, 337857, 115456, 16261, -89666, -491, 4665, -2066], [890847, 234695, 23353, -47180, 23098, 10588, -4184, 872], [-10262284, -2126268, 446765, 276374, -269326, -74695, 36450, -8335], [10687202, 1668493, -780263, -345233, 302416, 80167, -40945, 9432]];
    Rf_basisdens := [1, 22491, 247401, 14553, 247401, 35343, 247401, 247401];
    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_f();"
function MakeCharacter_378_f()
    N := 378;
    order := 3;
    char_gens := [29, 325];
    v := [2, 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_378_f_Hecke();"
function MakeCharacter_378_f_Hecke(Kf)
    N := 378;
    order := 3;
    char_gens := [29, 325];
    char_values := [[0, 0, -1, 0, 0, 0, 0, 0], [1, 0, 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 := [[2, 0, -2, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, -1, -1, -1, -1, 1], [7, 0, -7, 0, 0, 0, 0, 0], [-1, 0, 1, 0, 0, -1, -3, 5], [0, 1, 5, 2, -3, -1, -3, -2], [9, 6, 0, 3, 1, 0, 0, 0], [-26, -3, 0, 11, -4, 0, 0, 0], [0, -3, -94, -6, 4, 3, 4, 6], [-69, 0, 69, 0, 0, -6, -7, 8], [0, -13, 52, 11, -9, 13, -9, -11], [-40, 23, 0, 15, -25, 0, 0, 0], [0, -25, 43, 31, 9, 25, 9, -31], [56, 0, -56, 0, 0, -10, -6, 51], [-156, 0, 156, 0, 0, 30, 9, 5], [-26, -5, 0, -22, -40, 0, 0, 0], [0, 7, -49, -56, -8, -7, -8, 56], [310, 0, -310, 0, 0, 7, -14, 44], [0, 38, -23, -47, -29, -38, -29, 47], [321, -8, 0, -52, 5, 0, 0, 0], [-496, 25, 0, -55, -34, 0, 0, 0], [384, 0, -384, 0, 0, -8, -7, -81], [1, 0, -1, 0, 0, -43, 52, 29], [33, -28, 0, 147, 56, 0, 0, 0], [183, 0, -183, 0, 0, -23, -140, 38], [2, 0, -2, 0, 0, 26, 67, -143], [0, 17, 844, 8, -106, -17, -106, -8], [-369, 8, 0, -46, 122, 0, 0, 0], [-182, 48, 0, 9, 75, 0, 0, 0], [0, -32, 40, 68, 126, 32, 126, -68], [3, -110, 0, 25, -26, 0, 0, 0], [0, 90, -693, 50, -83, -90, -83, -50], [784, 0, -784, 0, 0, -118, -208, -5], [0, -29, 96, -139, -64, 29, -64, 139], [0, 200, 1139, 5, -146, -200, -146, -5], [771, 0, -771, 0, 0, -38, -71, -14], [0, 72, 1146, -219, 47, -72, 47, 219], [-71, 31, 0, 33, 60, 0, 0, 0], [0, 139, -431, 40, 21, -139, 21, -40], [1446, 0, -1446, 0, 0, 23, -99, -87], [-208, 258, 0, 303, -79, 0, 0, 0], [-914, 61, 0, -107, 161, 0, 0, 0], [1582, 0, -1582, 0, 0, -3, -91, -385], [0, 223, -15, 84, -42, -223, -42, -84], [-1493, 80, 0, -406, 67, 0, 0, 0], [-2532, -85, 0, -12, -18, 0, 0, 0], [0, 95, 2481, -156, -59, -95, -59, 156], [-495, 0, 495, 0, 0, 219, 385, -146], [-597, 0, 597, 0, 0, 85, -40, 278], [0, -75, 979, 202, 71, 75, 71, -202], [-886, -110, 0, -227, 160, 0, 0, 0], [0, -151, 2035, -356, 189, 151, 189, 356], [1732, 0, -1732, 0, 0, 190, 269, 56], [-537, -546, 0, -107, 351, 0, 0, 0], [0, 427, 328, -490, -151, -427, -151, 490], [-434, 0, 434, 0, 0, 432, -43, 349], [-2831, -202, 0, -412, -175, 0, 0, 0], [-4491, 68, 0, -711, -274, 0, 0, 0], [1829, 0, -1829, 0, 0, -475, -246, -319], [2441, 0, -2441, 0, 0, -357, 410, 333], [0, -603, 518, -161, 219, 603, 219, 161], [0, 4, 2633, -708, 141, -4, 141, 708], [869, -28, 0, 319, -675, 0, 0, 0], [0, -388, 1589, -475, 170, 388, 170, 475], [-1915, 0, 1915, 0, 0, -15, -516, -144], [2037, 0, -2037, 0, 0, 104, -26, 17], [-989, 0, 989, 0, 0, 109, -208, 643], [0, -421, -3619, 404, 256, 421, 256, -404], [0, 305, -1042, -231, -1046, -305, -1046, 231], [-1020, 0, 1020, 0, 0, 220, 190, 540], [-40, 0, 40, 0, 0, -64, 383, 254], [-2439, 63, 0, 965, -646, 0, 0, 0], [-3878, 0, 3878, 0, 0, 153, 531, 403], [0, -527, -5034, 345, 419, 527, 419, -345], [-1231, 411, 0, -440, 376, 0, 0, 0], [0, -57, 954, 1253, -271, 57, -271, -1253], [346, 0, -346, 0, 0, 326, -385, -815], [4798, 159, 0, 1053, 223, 0, 0, 0], [0, 937, 6463, -495, -307, -937, -307, 495], [0, 639, 2732, -566, -707, -639, -707, 566], [0, -441, -7810, -448, -166, 441, -166, 448], [-4160, 0, 4160, 0, 0, -482, -113, -277], [-1675, 338, 0, 46, 7, 0, 0, 0], [-2431, -624, 0, -292, -546, 0, 0, 0], [7347, 0, -7347, 0, 0, 330, -399, 508], [4734, 0, -4734, 0, 0, -167, -123, 1194], [1963, -1006, 0, 175, 725, 0, 0, 0], [-5744, 0, 5744, 0, 0, 41, -58, -1185], [-6085, 0, 6085, 0, 0, -639, -378, 291], [0, -605, -434, -1670, 132, 605, 132, 1670], [-3034, 792, 0, -75, -194, 0, 0, 0], [-2766, 0, 2766, 0, 0, -886, -469, 489], [12631, 236, 0, -826, -17, 0, 0, 0], [0, 46, 6772, -555, 824, -46, 824, 555], [0, -263, -6530, -86, 513, 263, 513, 86], [9217, 1514, 0, -431, -654, 0, 0, 0], [0, 249, 4710, 1318, -246, -249, -246, -1318], [7217, -1170, 0, -936, 1232, 0, 0, 0], [-6455, -696, 0, 420, 1265, 0, 0, 0], [9527, 125, 0, 490, -275, 0, 0, 0], [3746, 0, -3746, 0, 0, -1306, 17, -488], [7981, 362, 0, -84, 821, 0, 0, 0], [0, 125, 5437, -575, -85, -125, -85, 575], [8457, 0, -8457, 0, 0, 622, -226, -1106], [0, 349, -2285, 1008, 692, -349, 692, -1008], [1662, -908, 0, -160, 1929, 0, 0, 0], [-8907, 0, 8907, 0, 0, 507, -929, -211], [-5530, 96, 0, 1005, 563, 0, 0, 0], [0, 524, -4626, 888, -586, -524, -586, -888], [1193, 0, -1193, 0, 0, 607, -827, 1075], [0, 1513, -4973, -116, -769, -1513, -769, 116], [10169, -23, 0, -188, 1083, 0, 0, 0], [0, 609, 7467, -1095, -109, -609, -109, 1095], [-2502, 0, 2502, 0, 0, -1130, -1601, 828], [-12255, -452, 0, -459, -388, 0, 0, 0], [-884, 0, 884, 0, 0, -1036, 1087, -366], [0, -11, 3081, -1706, -1470, 11, -1470, 1706], [-1078, -1048, 0, 1973, 697, 0, 0, 0], [0, -267, 553, 167, -896, 267, -896, -167], [5334, 0, -5334, 0, 0, 1056, 1381, -2013], [0, 162, -19211, -500, -19, -162, -19, 500], [7053, 0, -7053, 0, 0, 1596, 1360, -1573], [-1391, 0, 1391, 0, 0, -1170, -2845, 558], [12240, -871, 0, 1578, 575, 0, 0, 0], [8055, 0, -8055, 0, 0, 1520, 1340, -565], [-4476, 448, 0, -3638, 234, 0, 0, 0], [-1666, 0, 1666, 0, 0, -228, 14, 1096], [-47, 1812, 0, -1484, -1145, 0, 0, 0], [318, 0, -318, 0, 0, 23, -1299, 2409], [0, -283, 7021, 930, -207, 283, -207, -930], [-6579, -2159, 0, 2334, 1390, 0, 0, 0], [0, -89, -15731, -443, -454, 89, -454, 443], [0, -2076, 1600, 701, -539, 2076, -539, -701], [-4865, -1433, 0, 2971, 1460, 0, 0, 0], [0, -1414, 6170, -508, 1020, 1414, 1020, 508], [0, 1469, -4616, -2560, -1202, -1469, -1202, 2560], [-4823, -1191, 0, 1370, -189, 0, 0, 0], [0, 555, 1864, 2553, -77, -555, -77, -2553], [0, 631, -13045, 2949, -1542, -631, -1542, -2949], [-11013, -1080, 0, -5, -787, 0, 0, 0], [-12948, 40, 0, -632, -333, 0, 0, 0], [14084, 0, -14084, 0, 0, 0, -109, 1505], [0, -966, 452, -1476, -954, 966, -954, 1476], [8985, -572, 0, 420, -335, 0, 0, 0], [5406, 34, 0, -1175, 465, 0, 0, 0], [-12073, 0, 12073, 0, 0, -1913, -2585, 1226], [3884, 0, -3884, 0, 0, 950, -1077, 715], [-4518, 0, 4518, 0, 0, -411, -378, 866], [0, 272, 25137, -1840, 652, -272, 652, 1840], [1159, 1607, 0, 379, -874, 0, 0, 0], [0, 1113, -18343, -31, -984, -1113, -984, 31], [21418, -1455, 0, 1055, -1451, 0, 0, 0], [638, 2074, 0, -4551, -62, 0, 0, 0], [0, -543, -3688, 770, -832, 543, -832, -770], [-6583, 0, 6583, 0, 0, -374, -384, 748], [-23567, 0, 23567, 0, 0, -926, 259, 836], [-173, -2830, 0, 485, 2870, 0, 0, 0], [23469, 0, -23469, 0, 0, 1152, 543, -1298], [-6009, 587, 0, 1351, 2670, 0, 0, 0], [0, -1473, 12192, -377, 757, 1473, 757, 377], [-2686, 0, 2686, 0, 0, -2440, -401, 1084], [-4300, -2319, 0, 2808, 1185, 0, 0, 0], [0, 1685, 17953, 1749, 662, -1685, 662, -1749], [2023, -3559, 0, -893, 984, 0, 0, 0], [0, 1404, 23449, -1516, -1124, -1404, -1124, 1516], [-3666, 0, 3666, 0, 0, 589, -1750, 1076], [5654, -488, 0, -399, -2855, 0, 0, 0], [534, 0, -534, 0, 0, -1724, -1116, -2316]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_378_f_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_378_4_f_b();".
// 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_f_b(:prec:=8)
    chi := MakeCharacter_378_f();
    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_f_b();".
// 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_f_b( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_378_f();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<5,R![3467044, -3118850, 2302885, -448526, 73087, -3620, 271, 1, 1]>],Snew);
    return Vf;
end function;