
// Make newform 1980.4.c.a in Magma, downloaded from the LMFDB on 16 April 2026.
// To make the character of type GrpDrchElt, type "MakeCharacter_1980_c();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_1980_c_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_1980_4_c_a();".
// 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_1980_4_c_a();".
// 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 := [5, -1, 1];
        Kf := NumberField(Polynomial([elt : elt in poly]));
        AssignNames(~Kf, ["nu"]);
    end if;
    Rfbasis := [Kf.1^i : i in [0..Degree(Kf)-1]];
    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_1980_c();"
function MakeCharacter_1980_c()
    N := 1980;
    order := 2;
    char_gens := [991, 1541, 397, 541];
    v := [2, 2, 1, 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_1980_c_Hecke();"
function MakeCharacter_1980_c_Hecke( : Kf := false)
    N := 1980;
    order := 2;
    char_gens := [991, 1541, 397, 541];
    char_values := [[1, 0], [1, 0], [-1, 0], [1, 0]];
    assert UnitGenerators(DirichletGroup(N)) eq char_gens;
    values := ConvertToHeckeField(char_values : pass_field := ISA(Type(Kf), Fld), 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]];
    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], [0, 0], [5, -5], [2, -4], [11, 0], [16, -32], [-6, 12], [68, 0], [-27, 54], [260, 0], [175, 0], [39, -78], [380, 0], [70, -140], [70, -140], [-104, 208], [-143, 0], [676, 0], [-121, 242], [-1035, 0], [76, -152], [-218, 0], [174, -348], [1279, 0], [-177, 354], [-638, 0], [-122, 244], [14, -28], [142, 0], [535, -1070], [224, -448], [-774, 0], [-9, 18], [-2986, 0], [-1546, 0], [3150, 0], [115, -230], [-214, 428], [-448, 896], [-538, 1076], [699, 0], [-2603, 0], [-1329, 0], [320, -640], [534, -1068], [8, 0], [-2840, 0], [-953, 1906], [-566, 1132], [-5813, 0], [464, -928], [-246, 0], [3388, 0], [-1091, 0], [948, -1896], [1602, -3204], [-314, 0], [3180, 0], [890, -1780], [4218, 0], [1916, -3832], [-1460, 2920], [-1516, 3032], [-5812, 0], [-1351, 2702], [2057, -4114], [8683, 0], [1182, -2364], [-12, 24], [-2126, 0], [1741, -3482], [4156, 0], [3051, -6102], [-1290, 2580], [-631, 0], [1627, -3254], [-5613, 0], [3216, -6432], [162, 0], [14142, 0], [-11532, 0], [-3430, 0], [-8658, 0], [-171, 342], [-4532, 0], [-989, 1978], [-2333, 0], [-1588, 3176], [-5332, 0], [-2137, 4274], [-4043, 8086], [-13748, 0], [-941, 1882], [4016, 0], [14236, 0], [-4150, 8300], [-8379, 0], [20277, 0], [2788, -5576], [-4796, 0], [-3852, 7704], [-2262, 4524], [2316, -4632], [-12240, 0], [21224, 0], [-223, 446], [-1758, 3516], [3336, -6672], [-20520, 0], [12726, 0], [-766, 1532], [1252, -2504], [292, -584], [17307, 0], [24977, 0], [23151, 0], [-163, 326], [707, -1414], [-133, 266], [-3458, 0], [-12983, 0], [-7194, 14388], [-2018, 4036], [-1458, 2916], [11819, 0], [-6978, 0], [-17947, 0], [905, 0], [-7103, 14206], [5396, -10792], [-30654, 0], [-9212, 18424], [19735, 0], [2428, -4856], [-6876, 0], [-16956, 0], [-6872, 13744], [252, -504], [-3239, 6478], [-30076, 0], [-7062, 0], [14090, 0], [-2363, 4726], [3696, -7392], [14611, 0], [37259, 0], [-1202, 2404], [-6144, 12288], [-29955, 0], [-3318, 6636], [-5712, 11424], [19987, 0], [-1254, 2508], [-5870, 11740], [-314, 628], [20068, 0], [10946, 0], [-33338, 0], [11812, -23624], [21590, 0], [5373, -10746], [5098, -10196], [3644, -7288], [13965, 0], [8355, -16710], [11435, -22870], [55024, 0], [-11870, 23740], [-49542, 0], [-3461, 6922], [32646, 0], [9842, 0], [19164, 0], [-8992, 17984], [-56107, 0], [-48713, 0], [-3450, 0], [44113, 0], [-8620, 17240], [-25056, 0], [7422, -14844], [-28914, 0], [-6609, 13218], [14862, -29724], [-7671, 15342], [57210, 0], [-10112, 20224], [-13110, 26220], [-59242, 0], [-62186, 0], [8271, -16542], [-3726, 7452], [-27945, 0], [-64230, 0], [-13096, 26192], [10491, -20982], [27458, 0], [6291, -12582], [-11778, 23556], [-17086, 34172], [-13908, 0], [9278, 0], [-4928, 9856], [44536, 0], [15461, 0], [523, -1046], [-45817, 0], [1632, -3264], [63600, 0], [-60952, 0], [8136, -16272], [3143, 0], [16093, -32186], [-10590, 21180], [34998, 0], [49039, 0], [-21112, 42224], [11020, 0], [-10878, 21756], [20381, -40762], [92232, 0], [-79344, 0], [24919, 0], [3945, -7890], [-9096, 18192], [23354, 0], [-7528, 15056], [-71136, 0], [-6556, 13112], [12864, 0], [8075, -16150], [-36372, 0], [97170, 0], [64600, 0], [2615, -5230], [6126, -12252], [90023, 0], [8084, -16168], [-88509, 0], [57355, 0], [10775, -21550], [111684, 0], [-13502, 27004], [-14117, 0], [-12204, 24408], [-17672, 0], [20998, -41996], [46588, 0], [48194, 0], [25354, -50708], [8732, -17464], [-37974, 0], [27667, -55334], [-112442, 0], [19626, -39252], [-35196, 0], [-67062, 0], [-26314, 52628], [28555, -57110], [17518, -35036], [7024, -14048], [8208, -16416], [96394, 0], [6066, -12132], [-2796, 5592], [84888, 0], [-114281, 0], [-80485, 0], [-26366, 52732], [29718, -59436], [42845, 0], [-9753, 19506], [12444, -24888], [-13128, 0], [23592, -47184], [-1001, 2002], [-12087, 24174], [-119966, 0], [3648, 0], [6696, 0], [22368, -44736], [33213, 0], [-592, 1184], [-11590, 0], [30712, -61424], [77827, 0], [-30004, 60008], [-24522, 49044], [-34435, 0], [126042, 0], [52935, 0], [16030, -32060], [12496, -24992], [165258, 0], [-28110, 56220], [31748, 0], [34143, 0], [-6117, 12234], [51718, 0], [-15942, 31884], [36158, -72316], [-11208, 22416], [-144560, 0]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_1980_c_Hecke( : Kf := Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_1980_4_c_a();".
// 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_1980_4_c_a(:prec:=2)
    chi := MakeCharacter_1980_c();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 4));
    S := BaseChange(S, Kf);
    maxprec := NextPrime(1999) - 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_1980_4_c_a();".
// 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_1980_4_c_a( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_1980_c();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,4,sign)));
    Vf := Kernel([<7,R![76, 0, 1]>,<29,R![-260, 1]>],Snew);
    return Vf;
end function;