
// Make newform 400.4.a.x in Magma, downloaded from the LMFDB on 30 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_400_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_400_4_a_x();".
// 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_400_4_a_x();".
// 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 := [-6, 0, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rf_num := [[1, 0], [0, 2]];
    Rf_basisdens := [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_400_a();"
function MakeCharacter_400_a()
    N := 400;
    order := 1;
    char_gens := [351, 101, 177];
    v := [1, 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_400_a_Hecke(Kf)
    return MakeCharacter_400_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], [2, 1], [0, 0], [2, -3], [-20, -8], [-52, 2], [-48, -16], [-20, 8], [142, -13], [-70, -16], [-96, 48], [-100, 34], [-262, 12], [186, 21], [42, 65], [148, 110], [-348, 88], [-346, 28], [158, 7], [-344, -32], [328, -92], [368, -16], [-814, 49], [-330, -48], [-448, -40], [-354, -80], [-322, -85], [-730, 35], [-54, -300], [176, -24], [858, 17], [-60, 56], [88, 84], [-1132, -312], [-174, 308], [1592, -272], [-1916, 174], [2978, 33], [450, -283], [-1332, -22], [-2612, 24], [526, -432], [2496, 32], [-800, 776], [1500, 138], [3800, 96], [980, 408], [1542, 335], [-3554, -481], [1506, 400], [4200, 84], [592, -1104], [2450, 124], [-4324, -648], [3840, -320], [-1602, -749], [-2454, -380], [-944, -720], [-1812, -1286], [-5046, 252], [-3798, 293], [4388, 398], [1870, -1233], [-168, 1072], [-2024, 724], [-636, -890], [-3028, 40], [-3920, 1144], [1654, 1571], [1274, 592], [-3552, -544], [-4936, -656], [10570, 265], [-4492, 246], [100, -1720], [-90, -849], [-5118, -556], [-1548, 398], [562, 1872], [-2122, -716], [-6756, -616], [-2978, 1228], [-1168, -144], [-3312, -1744], [3624, 2576], [-822, 965], [-6402, -92], [4056, -2012], [6102, -2320], [7606, 1231], [1230, -2937], [-1376, 1664], [4898, -2211], [4684, 1480], [7564, -1224], [-2386, 579], [-9446, 496], [-6950, -1920], [-6278, -1411], [20038, 400], [-12514, 2511], [1716, -1706], [7314, -39], [-4650, 2164], [13148, 2136], [16384, 1840], [19430, -293], [20368, -1128], [-15352, -1984], [-7926, 1052], [-19238, -71], [-5308, -3866], [-8104, 1404], [18740, -1288], [-6248, 2544], [15426, -2116], [-5790, 2953], [8066, 3005], [-17652, -1870], [-6804, 1784], [-5074, 1724], [5248, 3432], [7740, -4182], [-15494, -1851], [17460, -328], [-6746, -2356], [1090, 2224], [-22288, 1072], [-7662, 1813], [-516, -3518], [24924, 184], [7326, -3853], [-26960, -512], [17612, -774], [-15062, 2832], [9214, 4224], [-12508, -3066], [3694, 1295], [-32796, -1690], [-15930, 2816], [-1908, -808], [-31218, 540], [7342, 1747], [-30186, -925], [11866, -2588], [-7848, 1776], [-7756, 3390], [-1144, -116], [-17404, -3240], [-6810, 183], [41140, -506], [3730, 3500], [-22126, 1513], [20082, 3701], [-17210, -2797], [17616, -3312], [-5688, 4032], [12638, 7972], [-7208, -1076], [32630, 1872], [-8562, 3071], [29400, -156], [-2974, 1237], [-23892, 2504], [-176, 7840], [622, 10955], [1376, -3072], [8316, -2390], [-12754, 2560], [-8172, -4418], [5092, -4216], [20454, 2288], [19560, 1072], [4424, -5292], [13744, -640], [-16394, -8960], [-2628, -6792], [29150, 2096], [26750, -6421], [7050, -1932], [-20774, -1215], [12420, -1064], [8868, 9654], [14712, 3468], [47862, -1185], [-21230, 80], [-37052, -2898], [15490, 3801], [16198, -5548], [34944, 6208], [-35264, 1840], [10362, 4765], [4244, -7624], [9030, -6228], [3966, -7145], [-45464, -3516], [8530, -4020], [-26308, -7862], [-32192, 32], [-42338, -7061], [62250, -2544], [10256, 10144], [-1076, -1150], [8926, 13328], [-36172, 10168], [8548, -2738], [6656, -9424], [30626, -5863], [28454, 5248], [30956, -6712], [11792, -5888], [-40914, 7948], [28078, 11147], [-8522, 7459], [56056, -768], [-5894, 13996], [42698, 8313], [21362, -3056], [-48398, 9245], [-8036, -822], [-34018, -2628], [-14488, -9456], [-14082, -16464], [9558, -265], [39406, 5839], [-46126, 2468], [8088, 3052], [77536, 5360], [-30910, -10939], [-60660, 9480], [19628, -5918], [-55092, 56], [-47424, 3232], [-40870, -4004], [45338, 8197], [-1878, -7303], [-32050, -4700], [82164, -2002], [-57980, -2120], [91080, 2544], [-23182, -16047], [-32228, 3352], [830, -19149], [-5782, -8816], [-14832, -216], [-5560, 15792], [74746, 9185], [-76572, -8408], [-21900, -7880], [-57578, 12463], [-27516, -17850], [-29886, 10928], [258, -16659], [-67034, -4892], [-42196, -9174], [45228, 1736], [-40210, 9520], [73142, -5421], [2780, 10274], [-69912, -740], [-23354, -3257], [-36610, -19937], [49666, 5456], [-76868, -1438], [-50112, 16584], [-72036, -9576], [-11638, 12304], [44522, -896], [49098, 1925], [-107388, 590], [13270, 12368], [66638, 12263], [-70504, 4860], [-8032, 5328], [-120048, 1896], [44686, -14677], [-2122, 9803], [38682, -496], [-55782, -3236], [-18668, 14248], [37862, 2759], [-9976, -12672], [11218, -2227], [128062, -464], [-33626, 11243], [92304, 8512], [-17744, 13440], [-60468, 20450], [57608, -4544], [-16226, -18252], [9142, -16324], [-3314, -11281], [-13832, -7940], [-54420, -15512], [48492, 12106], [-4038, 22948], [-27104, -3904], [-40716, 3366], [-15068, 8056], [-7106, -25345], [9448, -20340], [70036, 2726], [-38672, 20448], [-74094, 7137], [58492, -3080], [44160, -18552], [68070, 19667], [61642, 14096], [25320, 6448], [49604, 13870], [-50730, 2999], [16338, -19952], [-158, 30976], [77090, -10143], [-117374, 3541], [-9402, -21296], [-36276, -9080], [135232, 3248], [136896, -8448], [-58930, 7092], [81236, -3880], [6344, -20324], [-80122, 5244], [20070, 20023], [110408, 2124], [-80878, -22852], [63548, -19464], [74730, -4715], [64666, 2297], [130948, -5178], [1654, -15780], [9380, 9582], [-31168, 29696], [93154, -9351], [-15444, 34120], [-49322, 1547], [-120326, -3692], [-110816, 13312], [30906, 24572], [-82518, -11471], [-11468, 35526], [-536, 27068], [108034, 16164], [-37528, -34096], [-32388, 9074], [14364, 19544], [24286, -13044], [-10170, 33579], [-22032, -11008], [26924, -9534], [-67708, 17416], [-34280, 21908], [-46890, 13260], [97494, -3769], [-80110, 1328], [-4072, 11004], [-85984, 21264], [-120884, -18936], [82480, -23184], [137294, -2533], [123356, -3302], [-31014, -1872], [136106, -4087], [-33084, -28344], [-61378, 7655], [-13336, 7524], [-106092, -4690], [18686, 36083], [-25846, 4428], [-45660, 41416], [36788, -10584], [119190, 11711], [-122446, 26276], [-4840, 13936], [30404, 38694], [-18452, 32904], [-66912, 29504], [154016, 3504], [-197714, 6116], [27944, -43844], [-113754, 20112], [-182744, -11588], [-108238, 22157], [-115808, 4816], [-48164, -12584], [-238530, -3957], [152112, 480], [-28532, -35254], [11594, 5269], [3642, 4153], [78654, -5772], [-36924, 9358], [-21100, -3128], [20942, 7895], [168760, 2080], [176632, 6052], [-12064, -22464], [-6330, -1344], [33804, -20584], [98062, -35476], [-129318, -12604], [78112, 7064], [-45654, -35015], [101576, 3708], [133602, -5644], [-227384, 96], [50516, 6990], [-72622, -5872], [5170, -13791], [-98884, 1320], [-87536, -3672], [-87828, 28602], [-95958, 34533], [270820, -3720], [18328, 16412], [-77066, -26832], [-4416, -37840], [-69406, 40533], [21136, 6928], [-44818, -5813], [-163462, -16076], [-116356, -2550], [-83286, 1745], [-90012, 29560], [-91800, -39524], [-97452, -2778], [166354, -25983], [15158, -9628], [-54980, 20376], [91432, -23072]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_400_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_400_4_a_x();".
// 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_400_4_a_x(:prec:=2)
    chi := MakeCharacter_400_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(2999) - 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_400_4_a_x();".
// 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_400_4_a_x( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_400_a();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<3,R![-20, -4, 1]>,<7,R![-212, -4, 1]>],Snew);
    return Vf;
end function;