
// Make newform 12.12.a.b in Magma, downloaded from the LMFDB on 23 April 2024.
// To make the character of type GrpDrchElt, type "MakeCharacter_12_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_12_12_a_b();".
// 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_12_12_a_b();".
// 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_12_a();"
function MakeCharacter_12_a()
    N := 12;
    order := 1;
    char_gens := [7, 5];
    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_12_a_Hecke(Kf)
    return MakeCharacter_12_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 := 12;
    raw_aps := [[0], [243], [2862], [9128], [668196], [2052950], [1604178], [-230500], [-43012728], [-141745194], [233221904], [278269694], [-1181577510], [856975172], [-1664054928], [-3851181666], [10339000596], [185948102], [2915010572], [12662314200], [-15201270694], [-36644027488], [-9217637028], [30573828810], [145701815906], [-55990373202], [-43967678872], [-149243933916], [1209122102], [-275810573934], [54829242128], [769884878412], [390519407034], [51410226884], [-1398152209698], [-421187206120], [-1279389205594], [-472790863540], [1046276664984], [-1461501724122], [-423853426404], [1831364429390], [-2944975046976], [6253925439938], [-6662780004978], [-7065300309688], [-3119021047300], [13424356217840], [9959199906060], [-11912996102626], [19658754767610], [300145664592], [8825045703698], [1540363511988], [-2367000167166], [1692689382072], [-32498328969306], [8845001866304], [41684692290926], [31377066111306], [39701112943796], [37147292141166], [-58293859900516], [-33826182305976], [76906207556138], [45994262716278], [112182097300292], [-62919189291406], [134319876720084], [64987352165414], [60639780562146], [19595437889976], [102499775294528], [89164507582382], [-261503569554508], [138948140935296], [-183753130390866], [19493174570294], [-233383694188014], [-158513211326326], [-282880390257972], [496374589940510], [397676989829808], [-149631852906862], [-105727846909288], [33108843596148], [-186449175017118], [55246208296730], [7958255059206], [-556636965712384], [90431585997084], [491081065324416], [200848870675016], [74524011193764], [679790361744476], [-323785496900952], [-52627193392842], [-860352232300038], [888718611973796], [-409513462911802], [-199315595276404], [1349036835195366], [-2543162367249540], [2741741368763274], [2767772239331540], [694652892690626], [-904959060206652], [1415401288356402], [2221445936780424], [-2809686593075062], [-767540141090896], [1470311661092606], [1227362734966842], [-1008090438781084], [-2980511445149128], [3591537428794914], [-1786870083540052], [766508119253784], [-256438061049978], [-3632704875031428], [524024478713678], [-3223470233326750], [608104820236878], [163384066186308], [-2574863519070532], [-6951024549707274], [-1641909916265794], [7031549911837392], [-9651454767385384], [5387058295086662], [6232121245122860], [3051316336180248], [3929906199270272], [5246624538781262], [4831773654396042], [-6552299014934782], [2313216589501134], [-14718212451338404], [2504583660667446], [-12940040635068006], [-4704101193232060], [11229554006177886], [8537320572879416], [10209087431930196], [2257851938398118], [-20509858316064744], [13600896659335694], [10391025714009066], [13314188344710740], [8383312755242784], [-15149326822729258], [-2862423495799470], [-4517150484630916], [1468016828107848], [20955764236475684], [1935786283468848], [-33503476875771688], [-16574829325065918], [-11159594246369926], [20867605514109990], [32440271842566684], [36119940830845578], [-435846310992760], [-4012425576747612], [42719098639779666], [-37287455306263704], [-44710117906076272], [-11697575461596418]];
    aps := ConvertToHeckeField(raw_aps);
    chi := MakeCharacter_12_a_Hecke(Universe(aps));
    return ExtendMultiplicatively(weight, aps, chi);
end function;


// To make the newform (type ModFrm), type "MakeNewformModFrm_12_12_a_b();".
// 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_12_12_a_b(:prec:=1)
    chi := MakeCharacter_12_a();
    f_vec := qexpCoeffs();
    Kf := Universe(f_vec);
    // SetVerbose("ModularForms", true);
    // SetVerbose("ModularSymbols", true);
    S := CuspidalSubspace(ModularForms(chi, 12));
    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_12_12_a_b();".
// 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_12_12_a_b( : sign := -1)
    R<x> := PolynomialRing(Rationals());
    chi := MakeCharacter_12_a();
    // SetVerbose("ModularSymbols", true);
    Snew := NewSubspace(CuspidalSubspace(ModularSymbols(chi,12,sign)));
    Vf := Kernel([<5,R![-2862, 1]>],Snew);
    return Vf;
end function;