
// Make newform 77.4.a.d in Magma, downloaded from the LMFDB on 01 May 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_77_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_77_4_a_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_77_4_a_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 := [1, 5, -12, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0, 0, 0], [-3, -12, 0, 1], [3, -11, -1, 1], [-4, 13, 1, -1]];
    Rf_basisdens := [1, 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_77_a();"
function MakeCharacter_77_a()
    N := 77;
    order := 1;
    char_gens := [45, 57];
    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_77_a_Hecke(Kf)
    return MakeCharacter_77_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, 0, 1, 0], [4, 1, 0, 0], [3, 2, -1, -1], [-7, 0, 0, 0], [-11, 0, 0, 0], [8, -3, -10, -10], [5, -5, 13, 9], [55, -4, -15, -7], [10, 18, -2, -6], [-90, 14, 4, -8], [-15, -9, 7, -25], [20, -16, 14, -32], [27, -23, 51, 23], [66, 2, -74, 0], [-25, -39, -15, 1], [150, -8, -4, 10], [4, 3, 124, -24], [-14, 29, 24, 120], [364, -62, 120, 124], [480, -26, 92, 96], [449, -47, 217, 61], [-320, -6, 28, -114], [87, -76, 25, -43], [-770, -48, 44, -104], [-174, 154, -176, 32], [18, 201, -172, 100], [713, -9, -93, 71], [18, -36, -102, 226], [-868, -94, 174, -34], [-180, 124, -166, -102], [-80, 156, -164, -8], [813, -18, -405, 107], [-944, -36, -74, 64], [481, -72, 303, 215], [-1484, -240, 142, 262], [884, -294, 468, 122], [73, -210, 289, -127], [1388, 130, -104, -488], [-2406, 176, -218, 34], [-1470, -357, -384, 256], [896, -80, 156, -132], [-1969, 68, -93, 311], [1850, -336, -246, -290], [-1526, 168, -708, -552], [-818, -80, -532, -12], [689, 79, -45, -697], [50, -356, -198, -286], [279, 211, 285, -271], [2421, 350, 187, -245], [587, -40, 407, 307], [-756, -390, 150, -250], [-1172, 408, -520, 404], [2243, 241, 19, -441], [1136, -231, 440, 212], [1278, 20, -1132, -168], [-220, 432, -156, -404], [459, -72, -161, -5], [2502, 62, -198, 2], [-3872, -432, -270, 494], [432, -406, 58, 702], [2489, -414, 983, 391], [4258, 21, 536, -120], [2641, 190, -1233, 607], [1475, -261, -551, 813], [1044, -100, 342, -1122], [3546, -448, 332, 916], [276, -296, -456, -820], [1236, 830, 1650, 10], [1010, 466, -650, -292], [-1184, 17, -966, -1270], [2882, -784, 608, 548], [976, 46, -232, -398], [-1707, -1107, 499, 475], [3390, 612, 28, -72], [1600, 322, -292, 928], [-3905, 981, -1235, -1535], [-3296, 44, 54, -2002], [3445, -898, 829, -571], [508, 1024, -1878, 850], [959, 413, -373, 151], [8388, 369, 992, 688], [-6454, 640, 16, -694], [-1324, 1190, 644, 1218], [4858, -1382, 8, -152], [1390, -406, 178, 2670], [-6708, -440, -2352, -884], [2720, -1688, -994, -1248], [-734, -1940, 2476, 212], [-1710, 1539, -1740, -2684], [48, -258, 2644, -324], [6152, 1051, 2748, 164], [-76, -726, 804, 1272], [-1914, -250, -54, 626], [-5340, -46, -2020, -1158], [-3904, 1522, 572, 628], [-7242, -1110, 562, 1394], [-2001, -2232, 1107, -417], [6282, -762, 1680, 688], [7293, 1262, 2571, 495], [-8622, -680, -1128, 1160], [14920, 184, 660, 852], [3138, -580, 800, 3412], [6729, 804, -1913, -1537], [-8372, 442, -2702, -3086], [9184, 156, -524, -2876], [4192, -1266, -118, 826], [-13554, -501, 838, 710], [-1865, 583, 831, -653], [18700, 570, 264, -24], [15661, 269, -799, 1765], [-2788, 600, -540, 1384], [670, 454, 1332, -112], [2982, 184, 1100, -726], [-492, 503, 3528, 32], [962, -288, -4366, -182], [1478, 1964, -172, 2758], [8684, -1235, 308, -2768], [-12191, 1411, -1209, -873], [1084, -408, 1698, 862], [-9586, -194, 634, -1768], [7647, 1466, -1333, 2023], [-6108, -2230, 1446, 1594], [3528, 153, -1026, -1866], [18124, -124, -2680, -952], [-2994, -1027, 942, -66], [9224, -2158, 2386, -1342], [-11076, 1568, -4158, -1770], [-12193, -1239, 2269, 2057], [4825, -849, -4129, 487], [7498, 861, 2792, 1480], [4512, 924, 2924, 2556], [156, 2064, 3424, 340], [-1430, 2538, -4122, -1434], [7408, 972, 2206, -3678], [2007, 1921, -2461, -4561], [-18507, -2013, 2993, -2419], [1045, -260, 181, 2789], [6679, 2028, -4263, -179], [15769, -1710, 1657, -2207], [-5982, 2312, 5476, 840], [-12259, -2982, 5315, -1], [-13368, 1632, -3518, -3318], [12642, -2500, 4642, 6322], [13024, -1614, 2920, 3546], [3303, 2986, -1509, 763], [1607, 409, -7403, -655], [-5168, 2221, 3102, 5302], [-3241, -1259, -1861, 2887], [1420, -307, -3156, -976], [1490, 3348, -4550, -3234], [-16512, 318, 5394, 2566], [-5420, -270, -1274, 4654], [4188, 3916, -4536, -2168], [-2080, 1490, 256, 7012], [14728, 2222, -2412, -3224], [-9426, 774, 3378, 3326], [4440, -2696, 1560, -4992], [13586, -1554, -5648, -1196], [271, 3035, -5593, -2413], [-670, 865, 1272, 1736], [20640, -4016, 2420, -2820], [8646, 660, -3620, -1832], [-12872, 2178, -2424, 2066], [-21692, -1057, 1352, 5704], [22886, 436, -564, -184], [-35165, 1325, -6819, -2331], [-14840, -2694, -1092, 3152], [-1908, -921, -1810, -6114]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_77_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_77_4_a_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_77_4_a_d(:prec:=4)
    chi := MakeCharacter_77_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_77_4_a_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_77_4_a_d( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_77_a();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<2,R![112, -40, -27, 2, 1]>],Snew);
    return Vf;
end function;