
// Make newform 99.6.a.d in Magma, downloaded from the LMFDB on 23 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_99_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_99_6_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_99_6_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 := [-8, -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_99_a();"
function MakeCharacter_99_a()
    N := 99;
    order := 1;
    char_gens := [56, 46];
    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_99_a_Hecke(Kf)
    return MakeCharacter_99_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 := 6;
    raw_aps := [[-6, -1], [0, 0], [-34, 10], [104, -62], [121, 0], [-102, 74], [178, 372], [-840, 852], [284, -330], [398, -1492], [-4440, -1600], [-2362, 2816], [-18238, -8], [3328, 3112], [-21676, -390], [9638, -7102], [404, 1980], [-11638, -2026], [-26612, 12704], [-13516, -4354], [-20606, -5568], [-2712, -11426], [-50700, 21960], [13750, 26704], [-115822, -9924], [-4906, -17052], [-72336, -5252], [-102140, -5432], [-24550, -19958], [109718, -23752], [205416, 19486], [-43796, 79408], [103766, 72492], [312880, 6204], [-176922, -39536], [75776, -38706], [54358, 49580], [46540, -80592], [-363544, 52412], [103374, 180972], [-597756, -56844], [30686, 2860], [277028, -121806], [-137030, -96444], [-324682, 67684], [-40488, -309036], [102688, 229192], [1072160, -24944], [453884, -154480], [-862242, 59340], [-570158, -240032], [449616, -258996], [-945086, -119484], [-189140, 488772], [742190, -382736], [135792, -308720], [-91666, 75826], [-33224, 303314], [776634, -14674], [1168578, -234108], [-126912, -168568], [307990, -170912], [-833160, 777388], [602076, -286098], [330762, -437264], [-1415042, -599730], [1022740, 27144], [1467146, -1104648], [433932, 218432], [1159250, 17138], [2074814, -700120], [-1344912, 45740], [1299696, 537176], [466826, 924754], [-1745116, 1074448], [-485372, 340430], [1187950, 1155226], [267046, -232908], [-1280466, 45988], [-770326, 1163684], [3602116, -1305772], [-3707626, 549520], [-342328, -627976], [623698, 740904], [1855560, -2356954], [-671292, 2551940], [-3182330, -423388], [-5512246, -753892], [-4115266, 264200], [-2299016, 1066068], [-3556172, 1688824], [2980344, 531712], [1488168, 1926172], [2149812, 459776], [-1582796, -1621624], [7702200, 21068], [-1986866, -631358], [256998, 683964], [-4835680, 339024], [987130, -3061278], [-2245504, 1053780], [-4633282, -689792], [-563788, -1879496], [-2589766, -214348], [13514104, 260636], [2110674, 357900], [6507220, -2554524], [2322826, -844492], [-5624500, 3752398], [-682518, -127232], [3405272, 3539886], [3733426, 311894], [-10669154, -1851104], [-1248708, -2197664], [-1917248, 3249456], [6293494, 1725172], [12702356, -3099624], [-3466932, -1407098], [2973414, 2531702], [16747668, 351752], [256942, -2635428], [-11287958, -2372236], [6260902, -3835652], [2373116, 1620300], [-10646620, -2946720], [6728398, 639080], [-6096226, 3685308], [-9677748, 1716462], [4859512, 5507356], [14431610, 998186], [-4701800, 2331152], [-12400160, 4973196], [13589912, 1086640], [-18741242, 899336], [-18842038, 4101668], [-368662, 1139748], [8243750, -9258526], [-18021736, 1165000], [9141686, 500082], [27279354, -1343280], [1984600, -4560816], [653446, 5065548], [-4437784, -5343040], [-4821364, 7285008], [7534462, 5527680], [15239748, -3421966], [17234034, 3492622], [16064378, 5915184], [-20159132, -389168], [-17674772, 996178], [20947218, 463074], [13764966, -6571592], [27100140, -4813816], [-4760528, -3139804], [-1294340, 2735368], [-676852, 13008278], [15723152, -11126534], [-30770, 3964612], [18310922, -1465248], [-22290994, -178396], [-15601492, 3638696], [-51990406, 1525456], [-27386000, -2728938], [-16569100, 105084], [20900750, -5752468], [4582316, -12410386], [-39482856, 2218496], [-26534582, -8712982]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_99_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_99_6_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_99_6_a_d(:prec:=2)
    chi := MakeCharacter_99_a();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 6));
    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_99_6_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_99_6_a_d( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_99_a();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,6,sign)));
    Vf := Kernel([<2,R![34, 13, 1]>],Snew);
    return Vf;
end function;