
// Make newform 3.25.b.a in Magma, downloaded from the LMFDB on 25 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_3_b();"
// To make the character of type GrpDrchElt with Codomain the HeckeField, type "MakeCharacter_3_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_3_25_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_3_25_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
        Kf := Rationals();
    end if;
    return [Kf!elt[1] : elt in input];
end function;


// To make the character of type GrpDrchElt, type "MakeCharacter_3_b();"
function MakeCharacter_3_b()
    N := 3;
    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_3_b_Hecke();"
function MakeCharacter_3_b_Hecke(Kf)
    N := 3;
    order := 2;
    char_gens := [2];
    char_values := [[-1]];
    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 := 25;
    raw_aps := [[0], [531441], [0], [-4119710398], [0], [41718377201762], [0], [-4106686428542878], [0], [0], [-1294226424013985278], [-5178171888377036638], [0], [-79863619813179602398], [0], [0], [0], [176759412487640367842], [6445029200733583780322], [0], [-34892253008746830365758], [79223687172395497630082], [0], [0], [1377078975482507968769282], [0], [-1601380187690360619971518], [0], [-3757713294374497430612638], [0], [17054265166412281230608642], [0], [0], [60465627441492230405579042], [0], [-199383414831935543458267198], [-40012458572174912446240798], [143829516000276783426728162], [0], [0], [0], [2471349874069152269525797922], [0], [-841910183632709844149951998], [0], [-7578757943939211063612177598], [2159086074595113586091027042], [-18912932561704998914936616958], [0], [32302623261775046953949074082], [0], [0], [17596737004929709544811653762], [0], [0], [0], [0], [234036893776358638354760542082], [-362534645081609679524710606558], [0], [164842781858944100407736341922], [0], [525258910291784351945350888802], [0], [-1631717538503573809393296085438], [0], [2733394956395234432636758943522], [-4251088494531986421220309952638], [0], [-6390939587562221852204031405598], [0], [0], [-9638124366398811655830993924478], [-5437244491663138629560347822558], [4417150111264008809105052062882], [0], [0], [25261192805235374114901005712482], [0], [-22450055383757448099192363445438], [0], [32804700226864597809982088146082], [0], [35184091317387553256066364424322], [28672136857993682913056370613442], [0], [0], [135333815034157408649148712689602], [0], [110325665698637041802339974143362], [0], [0], [-110216748337767333085902339119038], [0], [453579903269777097725098604508002], [0], [0], [0], [-396348960532685803274457579368158], [-1134117134488592946279827873655838], [1250270049970974240341907733421282], [0], [0], [0], [-799354818066657150580539653716318], [2013537174059793602605078933424642], [0], [0], [0], [2937947766509355227575347924014402], [-4112693013906514972863105438643198], [941107065171476986707652190604962], [0], [-3111557224467375814842396535949278], [7076395753715239681103201399382722], [0], [-9825541329006261652505730763399198], [0], [0], [0], [6199528894258613569831691770494242], [16904989779436956980648015303811842], [0], [0], [-20513051764932163749637013285819038], [0], [-22571784687576190282079845182495838], [0], [-26649286454398800387404949648068158], [-48092642199832927085876991419304478], [33569833134663581364998911566102242], [0], [8810534886719977571552878268764802], [51552205391903811365748982824237602], [0], [55439399812280476861723962414827522], [0], [9931078925178334457621600742334562], [0], [0], [-49183226471533449341921327029755358], [0], [-96514954518186122352356822065508158], [0], [-205771688020341460455045410089516318], [0], [-284523373454574556260643725875409118], [0], [196614937590094032691309090080377762], [0], [-211959362681097317547255279930022558], [0], [-447127040608612594166703597901368478], [0], [93760937763880818302313224953716002], [0], [669668785199566737134266072989097922], [0], [-413764943995748033378326837109931838], [0], [0], [0], [-4705585240360611054775506237938878], [0], [0], [0], [1725222707901145289022291969533429762], [-1506229489254414679062813574148308318]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_3_b_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


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