
// Make newform 25.10.b.a in Magma, downloaded from the LMFDB on 29 May 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_25_b();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_25_b_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_25_10_b_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_25_10_b_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 := [1, 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_25_b();"
function MakeCharacter_25_b()
    N := 25;
    order := 2;
    char_gens := [2];
    v := [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;

// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_25_b_Hecke();"
function MakeCharacter_25_b_Hecke(Kf)
    N := 25;
    order := 2;
    char_gens := [2];
    char_values := [[-1, 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 := 10;
    raw_aps := [[0, 4], [0, -57], [0, 0], [0, -2121], [-46208, 0], [0, -57967], [0, -247421], [1008740, 0], [0, -266277], [-4196390, 0], [-3365028, 0], [0, 7465679], [11056262, 0], [0, -3198397], [0, 17779579], [0, 19869293], [85185620, 0], [45748642, 0], [0, 22643079], [-189967468, 0], [0, 206085473], [-95040840, 0], [0, 130853163], [19938630, 0], [0, 9751679], [-216671898, 0], [0, -374117057], [0, -528554421], [2496591070, 0], [0, 557831933], [0, -156026921], [-2817011328, 0], [0, 3576557079], [-2523227420, 0], [-1465305050, 0], [3655152052, 0], [0, -2775953221], [0, -8381868317], [0, -6977466321], [0, 7850005773], [25190159660, 0], [10448152022, 0], [-9686250988, 0], [0, -10221552947], [0, 12621563079], [-8067363400, 0], [-8045889808, 0], [0, 15930902323], [0, -15131051221], [-20610100590, 0], [0, 1808675613], [-2219162920, 0], [25797693262, 0], [-89184805248, 0], [0, 55029120579], [0, 10318713583], [26488963790, 0], [34400398132, 0], [0, 53011445379], [100298985222, 0], [0, -1246481937], [0, -42353402847], [0, -3177534521], [271252675692, 0], [0, 81749461333], [0, -126803039821], [-240064012728, 0], [0, 25690575679], [0, -138279792521], [-466592483350, 0], [0, -50498812407], [166447470120, 0], [0, 148690325379], [0, 97856754173], [167009273660, 0], [0, 36039095163], [-792249454170, 0], [0, 73643815279], [-322101072798, 0], [396422948770, 0], [1231616918140, 0], [-1175003664518, 0], [-232327085628, 0], [0, -75776842687], [521385143480, 0], [0, 550847358603], [-585671911750, 0], [0, 285401866579], [-760278773058, 0], [0, -357144542817], [0, -391260351721], [695738310360, 0], [0, 825977775179], [1199886422912, 0], [-1431456972700, 0], [0, 709164956143], [1164633994970, 0], [-836945778118, 0], [0, -1301440813777], [3074063734062, 0], [0, -664858600421], [0, -1247089761921], [0, 533445688383], [4572783918690, 0], [-2323048560568, 0], [0, -505718183221], [0, 550713088779], [0, 492183079753], [-4513967513600, 0], [-1442119385098, 0], [0, 2060527317379], [0, 692348934833], [0, -311356821021], [-1894376281460, 0], [-1101596159228, 0], [-4852519993938, 0], [0, 787434401103], [0, -3465126785021], [0, -4077493983707], [2925528906620, 0], [-1629205839158, 0], [0, -1437604079127], [0, -1598098260921], [0, -273950700237], [590995901512, 0], [7127384745602, 0], [-909268871230, 0], [-10801666430760, 0], [0, 4888456556879], [0, 176147705413], [2721242355980, 0], [0, -2926553055397], [-5137227734948, 0], [0, 7285639389979], [10393578513642, 0], [3916636065790, 0], [0, -3184468700127], [0, -327671483621], [0, -1918994165221], [-2675805974330, 0], [-23258587112208, 0], [16573982509482, 0], [0, 6866597494123], [0, -9001795459721], [-21111609462690, 0], [3479882780080, 0], [0, 5634293232393], [0, -1876134180521], [-15701443402780, 0], [0, -6965814894917], [0, 7991587466979], [-31622696231378, 0], [0, -7426285775537], [0, 4696623922479], [0, -13221451680321], [-34164452537108, 0], [-31436645730160, 0], [8770070949610, 0], [0, 8314675958379], [-7560516404338, 0], [0, -17046236213121], [0, 17294257116893], [0, -22994555921821], [27266283848232, 0], [0, 24611409949879], [0, 19916845916463], [-25638770426788, 0], [0, 24862048320579]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_25_b_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_25_10_b_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_25_10_b_a(:prec:=2)
    chi := MakeCharacter_25_b();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 10));
    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_25_10_b_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_25_10_b_a( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_25_b();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,10,sign)));
    Vf := Kernel([<2,R![64, 0, 1]>],Snew);
    return Vf;
end function;