Testing latest pari + WASM + node.js... and it works?! Wow.
License: GPL3
ubuntu2004
/* Copyright (C) 2000-2003 The PARI group.12This file is part of the PARI/GP package.34PARI/GP is free software; you can redistribute it and/or modify it under the5terms of the GNU General Public License as published by the Free Software6Foundation; either version 2 of the License, or (at your option) any later7version. It is distributed in the hope that it will be useful, but WITHOUT8ANY WARRANTY WHATSOEVER.910Check the License for details. You should have received a copy of it, along11with the package; see the file 'COPYING'. If not, write to the Free Software12Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */1314#include "pari.h"15#include "paripriv.h"1617/*************************************************************************/18/** **/19/** Routines for handling FFELT **/20/** **/21/*************************************************************************/2223/*************************************************************************/24/** **/25/** Low-level constructors **/26/** **/27/*************************************************************************/2829INLINE void30_getFF(GEN x, GEN *T, GEN *p, ulong *pp)31{32*T=gel(x,3);33*p=gel(x,4);34*pp=(*p)[2];35}3637INLINE GEN38_initFF(GEN x, GEN *T, GEN *p, ulong *pp)39{40_getFF(x,T,p,pp);41return cgetg(5,t_FFELT);42}4344INLINE void45_checkFF(GEN x, GEN y, const char *s)46{ if (!FF_samefield(x,y)) pari_err_OP(s,x,y); }4748INLINE GEN49_mkFF(GEN x, GEN z, GEN r)50{51z[1]=x[1];52gel(z,2)=r;53gel(z,3)=gcopy(gel(x,3));54gel(z,4)=icopy(gel(x,4));55return z;56}5758INLINE GEN59_mkFF_i(GEN x, GEN z, GEN r)60{61z[1]=x[1];62gel(z,2)=r;63gel(z,3)=gel(x,3);64gel(z,4)=gel(x,4);65return z;66}6768INLINE GEN69mkFF_i(GEN x, GEN r)70{71GEN z = cgetg(5,t_FFELT);72return _mkFF_i(x,z,r);73}7475/*************************************************************************/76/** **/77/** medium-level constructors **/78/** **/79/*************************************************************************/8081static GEN82Z_to_raw(GEN x, GEN ff)83{84ulong pp;85GEN T, p;86_getFF(ff,&T,&p,&pp);87switch(ff[1])88{89case t_FF_FpXQ:90return scalarpol(x, varn(T));91case t_FF_F2xq:92return Z_to_F2x(x, T[1]);93default:94return Z_to_Flx(x, pp, T[1]);95}96}9798static GEN99Rg_to_raw(GEN x, GEN ff)100{101long tx = typ(x);102switch(tx)103{104case t_INT: case t_FRAC: case t_PADIC: case t_INTMOD:105return Z_to_raw(Rg_to_Fp(x, FF_p_i(ff)), ff);106case t_FFELT:107if (!FF_samefield(x,ff))108pari_err_MODULUS("Rg_to_raw",x,ff);109return gel(x,2);110}111pari_err_TYPE("Rg_to_raw",x);112return NULL;/* LCOV_EXCL_LINE */113}114115static GEN116FFX_to_raw(GEN x, GEN ff)117{118long i, lx;119GEN y = cgetg_copy(x,&lx);120y[1] = x[1];121for(i=2; i<lx; i++)122gel(y, i) = Rg_to_raw(gel(x, i), ff);123switch (ff[1])124{125case t_FF_FpXQ:126return FpXX_renormalize(y, lx);127case t_FF_F2xq:128return F2xX_renormalize(y, lx);129default:130return FlxX_renormalize(y, lx);131}132}133134static GEN135FFC_to_raw(GEN x, GEN ff) { pari_APPLY_same(Rg_to_raw(gel(x, i), ff)) }136static GEN137FFM_to_raw(GEN x, GEN ff) { pari_APPLY_same(FFC_to_raw(gel(x, i), ff)) }138139/* in place */140static GEN141rawFq_to_FF(GEN x, GEN ff)142{143return mkFF_i(ff, typ(x)==t_INT ? scalarpol(x, varn(gel(ff,3))): x);144}145146/* in place */147static GEN148raw_to_FFX(GEN x, GEN ff)149{150long i, lx = lg(x);151for (i=2; i<lx; i++) gel(x,i) = rawFq_to_FF(gel(x,i), ff);152return x;153}154155/* in place */156static GEN157raw_to_FFC(GEN x, GEN ff)158{159long i, lx = lg(x);160for (i=1; i<lx; i++) gel(x,i) = mkFF_i(ff, gel(x,i));161return x;162}163164/* in place */165static GEN166raw_to_FFM(GEN x, GEN ff)167{168long i, lx = lg(x);169for (i=1; i<lx; i++) gel(x,i) = raw_to_FFC(gel(x,i), ff);170return x;171}172173GEN174Fq_to_FF(GEN x, GEN ff)175{176ulong pp;177GEN r, T, p, z=_initFF(ff,&T,&p,&pp);178int is_int = typ(x)==t_INT;179switch(ff[1])180{181case t_FF_FpXQ:182r= is_int ? scalarpol(x, varn(T)): ZX_copy(x);183break;184case t_FF_F2xq:185r= is_int ? Z_to_F2x(x,T[1]): ZX_to_F2x(x);186break;187default:188r= is_int ? Z_to_Flx(x,pp,T[1]): ZX_to_Flx(x,pp);189}190setvarn(r, varn(T)); /* paranoia */191return _mkFF_i(ff,z,r);192}193194/*************************************************************************/195/** **/196/** Public functions **/197/** **/198/*************************************************************************/199200/* Return true if x and y are defined in the same field */201202static int203FF_samechar(GEN x, GEN y)204{ return x[1] == y[1] && equalii(gel(x,4),gel(y,4)); }205206int207FF_samefield(GEN x, GEN y)208{ return FF_samechar(x, y) && gidentical(gel(x,3),gel(y,3)); }209210int211FF_equal(GEN x, GEN y)212{ return FF_samefield(x,y) && gidentical(gel(x,2),gel(y,2)); }213214int215FF_equal0(GEN x)216{217return lgpol(gel(x,2))==0;218}219220int221FF_equal1(GEN x)222{223GEN A = gel(x,2);224switch(x[1])225{226case t_FF_FpXQ:227return degpol(A)==0 && gequal1(gel(A,2));228default:229return degpol(A)==0 && A[2]==1;230}231}232233static int234Fp_cmp_1(GEN x, GEN p)235{ pari_sp av = avma; return gc_bool(av, equalii(x, addis(p,-1))); }236237int238FF_equalm1(GEN x)239{240ulong pp;241GEN T, p, y = gel(x,2);242_getFF(x,&T,&p,&pp);243switch(x[1])244{245case t_FF_FpXQ:246return (degpol(y) == 0 && Fp_cmp_1(gel(y,2), p));247default:248return (degpol(y) == 0 && uel(y,2) == pp-1);249}250}251252GEN253FF_zero(GEN x)254{255ulong pp;256GEN r, T, p, z=_initFF(x,&T,&p,&pp);257switch(x[1])258{259case t_FF_FpXQ:260r=zeropol(varn(T));261break;262case t_FF_F2xq:263r=zero_F2x(T[1]);264break;265default:266r=zero_Flx(T[1]);267}268return _mkFF(x,z,r);269}270271GEN272FF_1(GEN x)273{274ulong pp;275GEN r, T, p, z=_initFF(x,&T,&p,&pp);276switch(x[1])277{278case t_FF_FpXQ:279r=pol_1(varn(T));280break;281case t_FF_F2xq:282r=pol1_F2x(T[1]);283break;284default:285r=pol1_Flx(T[1]);286}287return _mkFF(x,z,r);288}289290GEN291FF_gen(GEN x)292{293ulong pp;294GEN r, T, p, z=_initFF(x,&T,&p,&pp);295switch(x[1])296{297case t_FF_FpXQ:298r = pol_x(varn(T));299if (degpol(T)==1) r = FpX_rem(r, T, p);300break;301case t_FF_F2xq:302r = polx_F2x(T[1]);303if (F2x_degree(T)==1) r = F2x_rem(r, T);304break;305default:306r = polx_Flx(T[1]);307if (degpol(T)==1) r = Flx_rem(r, T, pp);308}309return _mkFF(x,z,r);310}311GEN312FF_q(GEN x)313{314ulong pp;315GEN T, p;316_getFF(x,&T,&p,&pp);317switch(x[1])318{319case t_FF_FpXQ:320return powiu(p, degpol(T));321break;322case t_FF_F2xq:323return int2n(F2x_degree(T));324break;325default:326return powuu(pp,degpol(T));327}328}329330GEN331FF_p(GEN x)332{333return icopy(gel(x,4));334}335336GEN337FF_p_i(GEN x)338{339return gel(x,4);340}341342GEN343FF_mod(GEN x)344{345switch(x[1])346{347case t_FF_FpXQ:348return ZX_copy(gel(x,3));349case t_FF_F2xq:350return F2x_to_ZX(gel(x,3));351default:352return Flx_to_ZX(gel(x,3));353}354}355356long357FF_var(GEN x)358{359switch(x[1])360{361case t_FF_FpXQ:362return varn(gel(x,3));363case t_FF_F2xq:364default:365return gel(x,3)[1]>>VARNSHIFT;366}367}368369long370FF_f(GEN x)371{372switch(x[1])373{374case t_FF_F2xq:375return F2x_degree(gel(x,3));376default:377return degpol(gel(x,3));378}379}380381GEN382FF_to_F2xq(GEN x)383{384switch(x[1])385{386case t_FF_FpXQ:387return ZX_to_F2x(gel(x,2));388case t_FF_F2xq:389return zv_copy(gel(x,2));390default:391return Flx_to_F2x(gel(x,2));392}393}394395GEN396FF_to_F2xq_i(GEN x)397{398switch(x[1])399{400case t_FF_FpXQ:401return ZX_to_F2x(gel(x,2));402case t_FF_F2xq:403return gel(x,2);404default:405return Flx_to_F2x(gel(x,2));406}407}408409GEN410FF_to_Flxq(GEN x)411{412switch(x[1])413{414case t_FF_FpXQ:415return ZX_to_Flx(gel(x,2),itou(gel(x,4)));416case t_FF_F2xq:417return F2x_to_Flx(gel(x,2));418default:419return zv_copy(gel(x,2));420}421}422423GEN424FF_to_Flxq_i(GEN x)425{426switch(x[1])427{428case t_FF_FpXQ:429return ZX_to_Flx(gel(x,2),itou(gel(x,4)));430case t_FF_F2xq:431return F2x_to_Flx(gel(x,2));432default:433return gel(x,2);434}435}436437GEN438FF_to_FpXQ(GEN x)439{440switch(x[1])441{442case t_FF_FpXQ:443return ZX_copy(gel(x,2));444case t_FF_F2xq:445return F2x_to_ZX(gel(x,2));446default:447return Flx_to_ZX(gel(x,2));448}449}450451GEN452FF_to_FpXQ_i(GEN x)453{454switch(x[1])455{456case t_FF_FpXQ:457return gel(x,2);458case t_FF_F2xq:459return F2x_to_ZX(gel(x,2));460default:461return Flx_to_ZX(gel(x,2));462}463}464465GEN466FF_add(GEN x, GEN y)467{468ulong pp;469GEN r, T, p, z=_initFF(x,&T,&p,&pp);470_checkFF(x,y,"+");471switch(x[1])472{473case t_FF_FpXQ:474r=FpX_add(gel(x,2),gel(y,2),p);475break;476case t_FF_F2xq:477r=F2x_add(gel(x,2),gel(y,2));478break;479default:480r=Flx_add(gel(x,2),gel(y,2),pp);481}482return _mkFF(x,z,r);483}484GEN485FF_sub(GEN x, GEN y)486{487ulong pp;488GEN r, T, p, z=_initFF(x,&T,&p,&pp);489_checkFF(x,y,"+");490switch(x[1])491{492case t_FF_FpXQ:493r=FpX_sub(gel(x,2),gel(y,2),p);494break;495case t_FF_F2xq:496r=F2x_add(gel(x,2),gel(y,2));497break;498default:499r=Flx_sub(gel(x,2),gel(y,2),pp);500}501return _mkFF(x,z,r);502}503504GEN505FF_Z_add(GEN x, GEN y)506{507ulong pp;508GEN r, T, p, z=_initFF(x,&T,&p,&pp);509switch(x[1])510{511case t_FF_FpXQ:512{513pari_sp av=avma;514r=gerepileupto(av,FpX_Fp_add(gel(x,2),modii(y,p),p));515break;516}517case t_FF_F2xq:518r=mpodd(y)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2));519break;520default:521r=Flx_Fl_add(gel(x,2),umodiu(y,pp),pp);522}523return _mkFF(x,z,r);524}525526GEN527FF_Q_add(GEN x, GEN y)528{529ulong pp;530GEN r, T, p, z=_initFF(x,&T,&p,&pp);531switch(x[1])532{533case t_FF_FpXQ:534{535pari_sp av=avma;536r=gerepileupto(av,FpX_Fp_add(gel(x,2),Rg_to_Fp(y,p),p));537break;538}539case t_FF_F2xq:540r=Rg_to_Fl(y,pp)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2));541break;542default:543r=Flx_Fl_add(gel(x,2),Rg_to_Fl(y,pp),pp);544}545return _mkFF(x,z,r);546}547548GEN549FF_neg(GEN x)550{551ulong pp;552GEN r, T, p, z=_initFF(x,&T,&p,&pp);553switch(x[1])554{555case t_FF_FpXQ:556r=FpX_neg(gel(x,2),p);557break;558case t_FF_F2xq:559r=vecsmall_copy(gel(x,2));560break;561default:562r=Flx_neg(gel(x,2),pp);563}564return _mkFF(x,z,r);565}566567GEN568FF_neg_i(GEN x)569{570ulong pp;571GEN r, T, p, z=_initFF(x,&T,&p,&pp);572switch(x[1])573{574case t_FF_FpXQ:575r=FpX_neg(gel(x,2),p);576break;577case t_FF_F2xq:578r=gel(x,2);579break;580default:581r=Flx_neg(gel(x,2),pp);582}583return _mkFF_i(x,z,r);584}585586GEN587FF_map(GEN m, GEN x)588{589ulong pp;590GEN r, T, p, z=_initFF(m,&T,&p,&pp);591switch(m[1])592{593case t_FF_FpXQ:594r=FpX_FpXQ_eval(gel(x,2),gel(m,2),T,p);595break;596case t_FF_F2xq:597r=F2x_F2xq_eval(gel(x,2),gel(m,2),T);598break;599default:600r=Flx_Flxq_eval(gel(x,2),gel(m,2),T,pp);601}602return _mkFF(m,z,r);603}604605GEN606FF_Frobenius(GEN x, long e)607{608ulong pp;609GEN r, T, p, z=_initFF(x,&T,&p,&pp);610ulong n = umodsu(e, FF_f(x));611pari_sp av = avma;612if (n==0) return gcopy(x);613switch(x[1])614{615case t_FF_FpXQ:616r=FpX_Frobenius(T,p);617if (n>1) r=FpXQ_autpow(r,n,T,p);618break;619case t_FF_F2xq:620r=F2x_Frobenius(T);621if (n>1) r=F2xq_autpow(r,n,T);622break;623default:624r=Flx_Frobenius(T,pp);625if (n>1) r=Flxq_autpow(r,n,T,pp);626}627r = gerepileupto(av, r);628return _mkFF(x,z,r);629}630631static GEN632FFX_preimage_i(GEN x, GEN y, GEN F, GEN T, GEN p, long pp)633{634GEN r;635F = FFX_to_raw(F, y);636switch(y[1])637{638case t_FF_FpXQ:639r = FpXQX_rem(gel(x,2), F, T, p);640break;641case t_FF_F2xq:642r = F2xqX_rem(F2x_to_F2xX(gel(x,2),T[1]), F, T);643break;644default:645r = FlxqX_rem(Flx_to_FlxX(gel(x,2),T[1]), F, T, pp);646}647return r;648}649650GEN651FFX_preimage(GEN x, GEN F, GEN y)652{653GEN r, T, p, z;654ulong pp;655if (FF_equal0(x)) return FF_zero(y);656z = _initFF(y,&T,&p,&pp);657r = FFX_preimage_i(x, y, F, T, p, pp);658if (degpol(r) > 0) return NULL;659r = (y[1] == t_FF_FpXQ)? Fq_to_FpXQ(gel(r,2),T, p): gel(r,2);660return _mkFF(y,z,r);661}662663GEN664FFX_preimagerel(GEN x, GEN F, GEN y)665{666pari_sp av = avma;667GEN r, T, p;668ulong pp;669if (FF_equal0(x)) return FF_zero(y);670_getFF(y,&T,&p,&pp);671r = FFX_preimage_i(x, y, F, T, p, pp);672return gerepilecopy(av, raw_to_FFX(r, y));673}674675GEN676FF_mul(GEN x, GEN y)677{678ulong pp;679GEN r, T, p, z=_initFF(x,&T,&p,&pp);680pari_sp av=avma;681_checkFF(x,y,"*");682switch(x[1])683{684case t_FF_FpXQ:685r=FpXQ_mul(gel(x,2),gel(y,2),T,p);686break;687case t_FF_F2xq:688r=F2xq_mul(gel(x,2),gel(y,2),T);689break;690default:691r=Flxq_mul(gel(x,2),gel(y,2),T,pp);692}693return _mkFF(x,z,gerepileupto(av, r));694}695696GEN697FF_Z_mul(GEN x, GEN y)698{699ulong pp;700GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp);701switch(x[1])702{703case t_FF_FpXQ: /* modii(y,p) left on stack for efficiency */704r = FpX_Fp_mul(A, modii(y,p),p);705break;706case t_FF_F2xq:707r = mpodd(y)? vecsmall_copy(A): zero_Flx(A[1]);708break;709default:710r = Flx_Fl_mul(A, umodiu(y,pp), pp);711}712return _mkFF(x,z,r);713}714715GEN716FF_Z_Z_muldiv(GEN x, GEN a, GEN b)717{718ulong pp;719GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp);720switch(x[1])721{722case t_FF_FpXQ: /* Fp_div(a,b,p) left on stack for efficiency */723r = FpX_Fp_mul(A, Fp_div(a,b,p), p);724break;725case t_FF_F2xq:726if (!mpodd(b)) pari_err_INV("FF_Z_Z_muldiv", b);727r = mpodd(a)? vecsmall_copy(A): zero_Flx(A[1]);728break;729default:730r = Flx_Fl_mul(A, Fl_div(umodiu(a,pp),umodiu(b,pp),pp),pp);731}732return _mkFF(x,z,r);733}734735GEN736FF_sqr(GEN x)737{738ulong pp;739GEN r, T, p, z=_initFF(x,&T,&p,&pp);740switch(x[1])741{742case t_FF_FpXQ:743{744pari_sp av=avma;745r=gerepileupto(av,FpXQ_sqr(gel(x,2),T,p));746break;747}748case t_FF_F2xq:749r=F2xq_sqr(gel(x,2),T);750break;751default:752r=Flxq_sqr(gel(x,2),T,pp);753}754return _mkFF(x,z,r);755}756757GEN758FF_mul2n(GEN x, long n)759{760ulong pp;761GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp);762switch(x[1])763{764case t_FF_FpXQ:765{766GEN p1; /* left on stack for efficiency */767if (n>0) p1=remii(int2n(n),p);768else p1=Fp_inv(remii(int2n(-n),p),p);769r = FpX_Fp_mul(A, p1, p);770}771break;772case t_FF_F2xq:773if (n<0) pari_err_INV("FF_mul2n", gen_2);774r = n==0? vecsmall_copy(A): zero_Flx(A[1]);775break;776default:777{778ulong l1;779if (n>0) l1 = umodiu(int2n(n),pp);780else l1 = Fl_inv(umodiu(int2n(-n),pp),pp);781r = Flx_Fl_mul(A,l1,pp);782}783}784return _mkFF(x,z,r);785}786787GEN788FF_inv(GEN x)789{790ulong pp;791GEN r, T, p, z=_initFF(x,&T,&p,&pp);792pari_sp av=avma;793switch(x[1])794{795case t_FF_FpXQ:796r=gerepileupto(av,FpXQ_inv(gel(x,2),T,p));797break;798case t_FF_F2xq:799r=F2xq_inv(gel(x,2),T);800break;801default:802r=Flxq_inv(gel(x,2),T,pp);803}804return _mkFF(x,z,r);805}806807GEN808FF_div(GEN x, GEN y)809{810ulong pp;811GEN r, T, p, z=_initFF(x,&T,&p,&pp);812pari_sp av=avma;813_checkFF(x,y,"/");814switch(x[1])815{816case t_FF_FpXQ:817r=gerepileupto(av,FpXQ_div(gel(x,2),gel(y,2),T,p));818break;819case t_FF_F2xq:820r=gerepileupto(av,F2xq_div(gel(x,2),gel(y,2),T));821break;822default:823r=gerepileupto(av,Flxq_div(gel(x,2),gel(y,2),T,pp));824}825return _mkFF(x,z,r);826}827828GEN829Z_FF_div(GEN n, GEN x)830{831ulong pp;832GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp);833pari_sp av=avma;834switch(x[1])835{836case t_FF_FpXQ:837r = gerepileupto(av,FpX_Fp_mul(FpXQ_inv(A,T,p),modii(n,p),p));838break;839case t_FF_F2xq:840r = F2xq_inv(A,T); /*Check for division by 0*/841if(!mpodd(n)) { set_avma(av); r = zero_Flx(A[1]); }842break;843default:844r = gerepileupto(av, Flx_Fl_mul(Flxq_inv(A,T,pp),umodiu(n,pp),pp));845}846return _mkFF(x,z,r);847}848849GEN850FF_sqrtn(GEN x, GEN n, GEN *zetan)851{852ulong pp;853GEN r, T, p, y=_initFF(x,&T,&p,&pp);854switch (x[1])855{856case t_FF_FpXQ:857r=FpXQ_sqrtn(gel(x,2),n,T,p,zetan);858break;859case t_FF_F2xq:860r=F2xq_sqrtn(gel(x,2),n,T,zetan);861break;862default:863r=Flxq_sqrtn(gel(x,2),n,T,pp,zetan);864}865if (!r) pari_err_SQRTN("FF_sqrtn",x);866(void)_mkFF(x, y, r);867if (zetan)868{869GEN z = cgetg(lg(y),t_FFELT);870*zetan=_mkFF(x, z, *zetan);871}872return y;873}874875GEN876FF_sqrt(GEN x)877{878ulong pp;879GEN r, T, p, y=_initFF(x,&T,&p,&pp);880switch (x[1])881{882case t_FF_FpXQ:883r = FpXQ_sqrt(gel(x,2),T,p);884break;885case t_FF_F2xq:886r = F2xq_sqrt(gel(x,2),T);887break;888default:889r = Flxq_sqrt(gel(x,2),T,pp);890}891if (!r) pari_err_SQRTN("FF_sqrt",x);892return _mkFF(x, y, r);893}894895long896FF_issquare(GEN x)897{898GEN T, p;899ulong pp;900_getFF(x, &T, &p, &pp);901switch(x[1])902{903case t_FF_FpXQ:904return FpXQ_issquare(gel(x,2), T, p);905case t_FF_F2xq:906return 1;907default: /* case t_FF_Flxq: */908return Flxq_issquare(gel(x,2), T, pp);909}910}911912long913FF_issquareall(GEN x, GEN *pt)914{915if (!pt) return FF_issquare(x);916return FF_ispower(x, gen_2, pt);917}918919long920FF_ispower(GEN x, GEN K, GEN *pt)921{922ulong pp;923GEN z, r, T, p;924pari_sp av = avma;925926if (FF_equal0(x)) { if (pt) *pt = gcopy(x); return 1; }927_getFF(x, &T, &p, &pp);928z = pt? cgetg(5,t_FFELT): NULL;929switch(x[1])930{931case t_FF_FpXQ:932r = FpXQ_sqrtn(gel(x,2),K,T,p,NULL);933break;934case t_FF_F2xq:935r = F2xq_sqrtn(gel(x,2),K,T,NULL);936break;937default: /* case t_FF_Flxq: */938r = Flxq_sqrtn(gel(x,2),K,T,pp,NULL);939break;940}941if (!r) return gc_long(av,0);942if (pt) { *pt = z; (void)_mkFF(x,z,r); }943return 1;944}945946GEN947FF_pow(GEN x, GEN n)948{949ulong pp;950GEN r, T, p, z=_initFF(x,&T,&p,&pp);951switch(x[1])952{953case t_FF_FpXQ:954r = FpXQ_pow(gel(x,2), n, T, p);955break;956case t_FF_F2xq:957r = F2xq_pow(gel(x,2), n, T);958break;959default:960r = Flxq_pow(gel(x,2), n, T, pp);961}962return _mkFF(x,z,r);963}964965GEN966FF_norm(GEN x)967{968ulong pp;969GEN T,p;970_getFF(x,&T,&p,&pp);971switch (x[1])972{973case t_FF_FpXQ:974return FpXQ_norm(gel(x,2),T,p);975case t_FF_F2xq:976return lgpol(gel(x,2))?gen_1:gen_0;977default:978return utoi(Flxq_norm(gel(x,2),T,pp));979}980}981982GEN983FF_trace(GEN x)984{985ulong pp;986GEN T,p;987_getFF(x,&T,&p,&pp);988switch(x[1])989{990case t_FF_FpXQ:991return FpXQ_trace(gel(x,2),T,p);992case t_FF_F2xq:993return F2xq_trace(gel(x,2),T)?gen_1:gen_0;994default:995return utoi(Flxq_trace(gel(x,2),T,pp));996}997}998999GEN1000FF_conjvec(GEN x)1001{1002ulong pp;1003GEN r,T,p,v;1004long i,l;1005pari_sp av;1006_getFF(x,&T,&p,&pp);1007av = avma;1008switch(x[1])1009{1010case t_FF_FpXQ:1011v = FpXQ_conjvec(gel(x,2), T, p);1012break;1013case t_FF_F2xq:1014v = F2xq_conjvec(gel(x,2), T);1015break;1016default:1017v = Flxq_conjvec(gel(x,2), T, pp);1018}1019l = lg(v); r = cgetg(l, t_COL);1020for(i=1; i<l; i++)1021gel(r,i) = mkFF_i(x, gel(v,i));1022return gerepilecopy(av, r);1023}10241025GEN1026FF_charpoly(GEN x)1027{1028ulong pp;1029GEN T,p;1030pari_sp av=avma;1031_getFF(x,&T,&p,&pp);1032switch(x[1])1033{1034case t_FF_FpXQ:1035return gerepileupto(av,FpXQ_charpoly(gel(x,2), T, p));1036case t_FF_F2xq:1037return gerepileupto(av,Flx_to_ZX(Flxq_charpoly(F2x_to_Flx(gel(x,2)),1038F2x_to_Flx(T), 2UL)));1039default:1040return gerepileupto(av,Flx_to_ZX(Flxq_charpoly(gel(x,2), T, pp)));1041}1042}10431044GEN1045FF_minpoly(GEN x)1046{1047ulong pp;1048GEN T,p;1049pari_sp av=avma;1050_getFF(x,&T,&p,&pp);1051switch(x[1])1052{1053case t_FF_FpXQ:1054return gerepileupto(av,FpXQ_minpoly(gel(x,2), T, p));1055case t_FF_F2xq:1056return gerepileupto(av,Flx_to_ZX(Flxq_minpoly(F2x_to_Flx(gel(x,2)),1057F2x_to_Flx(T), 2UL)));1058default:1059return gerepileupto(av,Flx_to_ZX(Flxq_minpoly(gel(x,2), T, pp)));1060}1061}10621063GEN1064FF_log(GEN x, GEN g, GEN ord)1065{1066pari_sp av=avma;1067ulong pp;1068GEN r, T, p;1069_getFF(x,&T,&p,&pp);1070_checkFF(x,g,"log");1071switch(x[1])1072{1073case t_FF_FpXQ:1074if (!ord) ord = factor_pn_1(p,degpol(T));1075r = FpXQ_log(gel(x,2), gel(g,2), ord, T, p);1076break;1077case t_FF_F2xq:1078if (!ord) ord = factor_pn_1(gen_2,F2x_degree(T));1079r = F2xq_log(gel(x,2), gel(g,2), ord, T);1080break;1081default:1082if (!ord) ord = factor_pn_1(p,degpol(T));1083r = Flxq_log(gel(x,2), gel(g,2), ord, T, pp);1084}1085return gerepileupto(av, r);1086}10871088GEN1089FF_order(GEN x, GEN o)1090{1091pari_sp av=avma;1092ulong pp;1093GEN r, T,p;1094_getFF(x,&T,&p,&pp);1095switch(x[1])1096{1097case t_FF_FpXQ:1098if (!o) o = factor_pn_1(p,degpol(T));1099r = FpXQ_order(gel(x,2), o, T, p);1100break;1101case t_FF_F2xq:1102if (!o) o = factor_pn_1(gen_2,F2x_degree(T));1103r = F2xq_order(gel(x,2), o, T);1104break;1105default:1106if (!o) o = factor_pn_1(p,degpol(T));1107r = Flxq_order(gel(x,2), o, T, pp);1108}1109if (!o) r = gerepileuptoint(av,r);1110return r;1111}11121113GEN1114FF_primroot(GEN x, GEN *o)1115{1116ulong pp;1117GEN r,T,p,z=_initFF(x,&T,&p,&pp);1118switch(x[1])1119{1120case t_FF_FpXQ:1121r = gener_FpXQ(T, p, o);1122break;1123case t_FF_F2xq:1124r = gener_F2xq(T, o);1125break;1126default:1127r = gener_Flxq(T, pp, o);1128}1129return _mkFF(x,z,r);1130}11311132static GEN1133to_FFE(GEN P, GEN fg)1134{1135if(ell_is_inf(P))1136return ellinf();1137else1138retmkvec2(mkFF_i(fg,gel(P,1)), mkFF_i(fg,gel(P,2)));1139}11401141static GEN1142to_FFE_vec(GEN x, GEN ff)1143{1144long i, lx = lg(x);1145for (i=1; i<lx; i++) gel(x,i) = to_FFE(gel(x,i), ff);1146return x;1147}11481149static GEN1150FpXQ_ell_to_a4a6(GEN E, GEN T, GEN p)1151{1152GEN a1, a3, b2, c4, c6;1153a1 = Rg_to_FpXQ(ell_get_a1(E),T,p);1154a3 = Rg_to_FpXQ(ell_get_a3(E),T,p);1155b2 = Rg_to_FpXQ(ell_get_b2(E),T,p);1156c4 = Rg_to_FpXQ(ell_get_c4(E),T,p);1157c6 = Rg_to_FpXQ(ell_get_c6(E),T,p);1158retmkvec3(FpX_neg(FpX_mulu(c4, 27, p), p), FpX_neg(FpX_mulu(c6, 54, p), p),1159mkvec4(Z_to_FpX(utoi(6),p,varn(T)),FpX_mulu(b2,3,p),1160FpX_mulu(a1,3,p),FpX_mulu(a3,108,p)));1161}11621163static GEN1164F3xq_ell_to_a4a6(GEN E, GEN T)1165{1166GEN a1, a3, b2, b4, b6;1167a1 = Rg_to_Flxq(ell_get_a1(E),T,3);1168a3 = Rg_to_Flxq(ell_get_a3(E),T,3);1169b2 = Rg_to_Flxq(ell_get_b2(E),T,3);1170b4 = Rg_to_Flxq(ell_get_b4(E),T,3);1171b6 = Rg_to_Flxq(ell_get_b6(E),T,3);1172if(lgpol(b2)) /* ordinary case */1173{1174GEN b4b2 = Flxq_div(b4,b2,T,3);1175GEN a6 = Flx_sub(b6,Flxq_mul(b4b2,Flx_add(b4,Flxq_sqr(b4b2,T,3),3),T,3),3);1176retmkvec3(mkvec(b2), a6,1177mkvec4(Fl_to_Flx(1,T[1]),b4b2,Flx_neg(a1,3),Flx_neg(a3,3)));1178}1179else /* super-singular case */1180retmkvec3(Flx_neg(b4, 3), b6,1181mkvec4(Fl_to_Flx(1,T[1]),zero_Flx(T[1]), Flx_neg(a1,3), Flx_neg(a3,3)));1182}11831184static GEN1185Flxq_ell_to_a4a6(GEN E, GEN T, ulong p)1186{1187GEN a1, a3, b2, c4, c6;1188if(p==3) return F3xq_ell_to_a4a6(E, T);1189a1 = Rg_to_Flxq(ell_get_a1(E),T,p);1190a3 = Rg_to_Flxq(ell_get_a3(E),T,p);1191b2 = Rg_to_Flxq(ell_get_b2(E),T,p);1192c4 = Rg_to_Flxq(ell_get_c4(E),T,p);1193c6 = Rg_to_Flxq(ell_get_c6(E),T,p);1194retmkvec3(Flx_neg(Flx_mulu(c4, 27, p), p), Flx_neg(Flx_mulu(c6, 54, p), p),1195mkvec4(Fl_to_Flx(6%p,T[1]),Flx_mulu(b2,3,p),1196Flx_mulu(a1,3,p),Flx_mulu(a3,108,p)));1197}11981199static GEN1200F2xq_ell_to_a4a6(GEN E, GEN T)1201{1202long v = T[1];1203GEN a1 = Rg_to_F2xq(ell_get_a1(E),T);1204GEN a2 = Rg_to_F2xq(ell_get_a2(E),T);1205GEN a3 = Rg_to_F2xq(ell_get_a3(E),T);1206GEN a4 = Rg_to_F2xq(ell_get_a4(E),T);1207GEN a6 = Rg_to_F2xq(ell_get_a6(E),T);1208if (lgpol(a1))1209{1210GEN a1i = F2xq_inv(a1,T);1211GEN a1i2 = F2xq_sqr(a1i,T);1212GEN a1i3 = F2xq_mul(a1i,a1i2,T);1213GEN a1i6 = F2xq_sqr(a1i3,T);1214GEN d = F2xq_mul(a3,a1i,T);1215GEN dd = F2xq_mul(d,a1i2,T);1216GEN e = F2xq_mul(F2x_add(a4,F2xq_sqr(d,T)),a1i,T);1217GEN ee = F2xq_mul(e,a1i3,T);1218GEN da2 = F2x_add(a2,d);1219GEN d2 = F2xq_mul(da2,a1i2,T);1220GEN d6 = F2xq_mul(F2x_add(F2x_add(F2xq_mul(F2x_add(F2xq_mul(da2,d,T),a4),d,T),a6),F2xq_sqr(e,T)),a1i6,T);1221retmkvec3(d2, d6, mkvec4(a1i,dd,pol0_F2x(v),ee));1222}1223else1224{ /* allow a1 = a3 = 0: singular curve */1225GEN d4 = F2x_add(F2xq_sqr(a2,T),a4);1226GEN d6 = F2x_add(F2xq_mul(a2,a4,T),a6);1227GEN a3i = lgpol(a3)? F2xq_inv(a3,T): a3;1228retmkvec3(mkvec3(a3,d4,a3i), d6, mkvec4(pol1_F2x(v),a2,pol0_F2x(T[1]),pol0_F2x(T[1])));1229}1230}12311232static GEN1233FqV_to_FpXQV(GEN x, GEN T)1234{1235pari_sp av = avma;1236long v = varn(T), i, s=0, l = lg(x);1237GEN y = shallowcopy(x);1238for(i=1; i<l; i++)1239if (typ(gel(x,i))==t_INT)1240{1241gel(y,i) = scalarpol(gel(x,i), v);1242s = 1;1243}1244if (!s) { set_avma(av); return x; }1245return y;1246}12471248GEN1249FF_ellcard(GEN E)1250{1251GEN T,p;1252ulong pp;1253GEN e = ellff_get_a4a6(E);1254GEN fg = ellff_get_field(E);1255_getFF(fg,&T,&p,&pp);1256switch(fg[1])1257{1258case t_FF_FpXQ:1259return FpXQ_ellcard(Fq_to_FpXQ(gel(e,1),T,p), Fq_to_FpXQ(gel(e,2),T,p),T,p);1260case t_FF_F2xq:1261return F2xq_ellcard(gel(e,1),gel(e,2),T);1262default:1263return Flxq_ellcard(gel(e,1),gel(e,2),T,pp);1264}1265}12661267GEN1268FF_ellcard_SEA(GEN E, long smallfact)1269{1270pari_sp av = avma;1271GEN T,p;1272ulong pp;1273GEN e = ellff_get_a4a6(E), a4, a6, card;1274GEN fg = ellff_get_field(E);1275_getFF(fg,&T,&p,&pp);1276switch(fg[1])1277{1278case t_FF_FpXQ:1279a4 = Fq_to_FpXQ(gel(e,1), T, p);1280a6 = Fq_to_FpXQ(gel(e,2), T, p);1281card = Fq_ellcard_SEA(a4, a6, powiu(p,degpol(T)), T,p, smallfact);1282break;1283case t_FF_F2xq:1284pari_err_IMPL("SEA for char 2");1285default:1286a4 = Flx_to_ZX(gel(e,1));1287a6 = Flx_to_ZX(gel(e,2));1288card = Fq_ellcard_SEA(a4, a6, powuu(pp,degpol(T)), Flx_to_ZX(T), p, smallfact);1289}1290return gerepileuptoint(av, card);1291}12921293/* return G, set m */1294GEN1295FF_ellgroup(GEN E, GEN *pm)1296{1297GEN T, p, e, fg, N;1298ulong pp;12991300N = ellff_get_card(E);1301e = ellff_get_a4a6(E);1302fg = ellff_get_field(E);1303_getFF(fg,&T,&p,&pp);1304switch(fg[1])1305{1306case t_FF_FpXQ:1307return FpXQ_ellgroup(Fq_to_FpXQ(gel(e,1),T,p),1308Fq_to_FpXQ(gel(e,2),T,p),N,T,p,pm);1309case t_FF_F2xq:1310return F2xq_ellgroup(gel(e,1),gel(e,2),N,T,pm);1311default:1312return Flxq_ellgroup(gel(e,1),gel(e,2),N,T,pp,pm);1313}1314}13151316GEN1317FF_ellgens(GEN E)1318{1319GEN D, fg, e, m, T, p, F, e3;1320ulong pp;13211322fg = ellff_get_field(E);1323e = ellff_get_a4a6(E);1324m = ellff_get_m(E);1325D = ellff_get_D(E);1326_getFF(fg,&T,&p,&pp);1327switch(fg[1])1328{1329case t_FF_FpXQ:1330e3 = FqV_to_FpXQV(gel(e,3),T);1331F = FpXQ_ellgens(Fq_to_FpXQ(gel(e,1),T,p),Fq_to_FpXQ(gel(e,2),T,p),e3,D,m,T,p);1332break;1333case t_FF_F2xq:1334F = F2xq_ellgens(gel(e,1),gel(e,2),gel(e,3),D,m,T);1335break;1336default:1337F = Flxq_ellgens(gel(e,1),gel(e,2),gel(e,3),D,m,T, pp);1338break;1339}1340return to_FFE_vec(F,fg);1341}13421343GEN1344FF_elldata(GEN E, GEN fg)1345{1346GEN T,p,e;1347ulong pp;1348_getFF(fg,&T,&p,&pp);1349switch(fg[1])1350{1351case t_FF_FpXQ:1352e = FpXQ_ell_to_a4a6(E,T,p); break;1353case t_FF_F2xq:1354e = F2xq_ell_to_a4a6(E,T); break;1355default:1356e = Flxq_ell_to_a4a6(E,T,pp); break;1357}1358return mkvec2(fg,e);1359}13601361/* allow singular E, set E.j = 0 in this case */1362GEN1363FF_ellinit(GEN E, GEN fg)1364{1365GEN T,p,e, D, c4, y = E;1366ulong pp;1367long i;1368_getFF(fg,&T,&p,&pp);1369switch(fg[1])1370{1371case t_FF_FpXQ:1372e = FpXQ_ell_to_a4a6(E,T,p);1373for(i=1;i<=12;i++) gel(y,i) = mkFF_i(fg,Rg_to_FpXQ(gel(E,i),T,p));1374break;1375case t_FF_F2xq:1376e = F2xq_ell_to_a4a6(E,T);1377for(i=1;i<=12;i++) gel(y,i) = mkFF_i(fg,Rg_to_F2xq(gel(E,i),T));1378break;1379default:1380e = Flxq_ell_to_a4a6(E,T,pp);1381for(i=1;i<=12;i++) gel(y,i) = mkFF_i(fg,Rg_to_Flxq(gel(E,i),T,pp));1382break;1383}1384D = ell_get_disc(y);1385c4 = ell_get_c4(y);1386gel(y,13) = FF_equal0(D)? D: gdiv(gpowgs(c4,3), D);1387gel(y,14) = mkvecsmall(t_ELL_Fq);1388gel(y,15) = mkvec2(fg,e);1389return y;1390}13911392GEN1393FF_elltwist(GEN E)1394{1395pari_sp av = avma;1396GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E);1397GEN T, p, a, a6, V;1398ulong pp;1399_getFF(fg,&T,&p,&pp);1400switch (fg[1])1401{1402case t_FF_FpXQ:1403FpXQ_elltwist(gel(e,1), gel(e,2), T, p, &a, &a6);1404V = mkvec5(gen_0, gen_0, gen_0, mkFF_i(fg, a), mkFF_i(fg, a6));1405break;1406case t_FF_F2xq:1407F2xq_elltwist(gel(e,1), gel(e,2), T, &a, &a6);1408V = typ(a)==t_VECSMALL ?1409mkvec5(gen_1, mkFF_i(fg, a), gen_0, gen_0, mkFF_i(fg, a6)):1410mkvec5(gen_0, gen_0, mkFF_i(fg, gel(a,1)), mkFF_i(fg, gel(a,2)), mkFF_i(fg, a6));1411break;1412default:1413Flxq_elltwist(gel(e,1), gel(e,2), T, pp, &a, &a6);1414V = typ(a)==t_VECSMALL ?1415mkvec5(gen_0, gen_0, gen_0, mkFF_i(fg, a), mkFF_i(fg, a6)):1416mkvec5(gen_0, mkFF_i(fg, gel(a,1)), gen_0, gen_0, mkFF_i(fg, a6));1417}1418return gerepilecopy(av, V);1419}14201421static long1422F3x_equalm1(GEN x) { return degpol(x)==0 && x[2] == 2; }1423GEN1424FF_ellrandom(GEN E)1425{1426pari_sp av = avma;1427GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E), Q;1428GEN T,p;1429ulong pp;1430_getFF(fg,&T,&p,&pp);1431switch (fg[1])1432{1433case t_FF_FpXQ:1434Q = random_FpXQE(Fq_to_FpXQ(gel(e,1),T,p), Fq_to_FpXQ(gel(e,2),T,p), T, p);1435Q = FpXQE_changepoint(Q, FqV_to_FpXQV(gel(e,3), T) , T, p);1436break;1437case t_FF_F2xq:1438{1439long d = F2x_degree(T);1440/* if #E(Fq) = 1 return [0] */1441if (d<=2 && typ(gel(e,1)) == t_VEC)1442{ /* over F2 or F4, supersingular */1443GEN v = gel(e,1), A6 = gel(e,2), a3 = gel(v,1), A4 = gel(v,2);1444if (F2x_equal1(a3) &&1445((d==1 && F2x_equal1(A4) && F2x_equal1(A6))1446|| (d==2 && !lgpol(A4) && F2x_degree(A6)==1))) return ellinf();1447}1448Q = random_F2xqE(gel(e,1), gel(e,2), T);1449Q = F2xqE_changepoint(Q, gel(e,3), T);1450break;1451}1452default:1453/* if #E(Fq) = 1 return [0] */1454if (pp==3 && degpol(T)==1 && typ(gel(e,1))==t_VECSMALL)1455{ /* over F3, supersingular */1456GEN mb4 = gel(e,1), b6 = gel(e,2);1457if (F3x_equalm1(mb4) && F3x_equalm1(b6)) return ellinf();1458}1459Q = random_FlxqE(gel(e,1), gel(e,2), T, pp);1460Q = FlxqE_changepoint(Q, gel(e,3), T, pp);1461}1462return gerepilecopy(av, to_FFE(Q, fg));1463}14641465GEN1466FF_ellmul(GEN E, GEN P, GEN n)1467{1468pari_sp av = avma;1469GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E), Q;1470GEN T,p, Pp, Qp, e3;1471ulong pp;1472_getFF(fg,&T,&p,&pp);1473switch (fg[1])1474{1475case t_FF_FpXQ:1476e3 = FqV_to_FpXQV(gel(e,3),T);1477Pp = FpXQE_changepointinv(RgE_to_FpXQE(P, T, p), e3, T, p);1478Qp = FpXQE_mul(Pp, n, gel(e,1), T, p);1479Q = FpXQE_changepoint(Qp, gel(e,3), T, p);1480break;1481case t_FF_F2xq:1482Pp = F2xqE_changepointinv(RgE_to_F2xqE(P, T), gel(e,3), T);1483Qp = F2xqE_mul(Pp, n, gel(e,1), T);1484Q = F2xqE_changepoint(Qp, gel(e,3), T);1485break;1486default:1487Pp = FlxqE_changepointinv(RgE_to_FlxqE(P, T, pp), gel(e,3), T, pp);1488Qp = FlxqE_mul(Pp, n, gel(e,1), T, pp);1489Q = FlxqE_changepoint(Qp, gel(e,3), T, pp);1490}1491return gerepilecopy(av, to_FFE(Q, fg));1492}14931494GEN1495FF_ellorder(GEN E, GEN P, GEN o)1496{1497pari_sp av = avma;1498GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E);1499GEN r,T,p,Pp,e3;1500ulong pp;1501_getFF(fg,&T,&p,&pp);1502switch (fg[1])1503{1504case t_FF_FpXQ:1505e3 = FqV_to_FpXQV(gel(e,3),T);1506Pp = FpXQE_changepointinv(RgE_to_FpXQE(P,T,p), e3, T, p);1507r = FpXQE_order(Pp, o, gel(e,1), T, p);1508break;1509case t_FF_F2xq:1510Pp = F2xqE_changepointinv(RgE_to_F2xqE(P,T), gel(e,3), T);1511r = F2xqE_order(Pp, o, gel(e,1), T);1512break;1513default:1514Pp = FlxqE_changepointinv(RgE_to_FlxqE(P,T,pp), gel(e,3), T, pp);1515r = FlxqE_order(Pp, o, gel(e,1), T, pp);1516}1517return gerepileupto(av, r);1518}15191520GEN1521FF_elllog(GEN E, GEN P, GEN Q, GEN o)1522{1523pari_sp av = avma;1524GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E);1525GEN r,T,p, Pp,Qp, e3;1526ulong pp;1527_getFF(fg,&T,&p,&pp);1528switch(fg[1])1529{1530case t_FF_FpXQ:1531e3 = FqV_to_FpXQV(gel(e,3),T);1532Pp = FpXQE_changepointinv(RgE_to_FpXQE(P,T,p), e3, T, p);1533Qp = FpXQE_changepointinv(RgE_to_FpXQE(Q,T,p), e3, T, p);1534r = FpXQE_log(Pp, Qp, o, gel(e,1), T, p);1535break;1536case t_FF_F2xq:1537Pp = F2xqE_changepointinv(RgE_to_F2xqE(P,T), gel(e,3), T);1538Qp = F2xqE_changepointinv(RgE_to_F2xqE(Q,T), gel(e,3), T);1539r = F2xqE_log(Pp, Qp, o, gel(e,1), T);1540break;1541default:1542Pp = FlxqE_changepointinv(RgE_to_FlxqE(P,T,pp), gel(e,3), T, pp);1543Qp = FlxqE_changepointinv(RgE_to_FlxqE(Q,T,pp), gel(e,3), T, pp);1544r = FlxqE_log(Pp, Qp, o, gel(e,1), T, pp);1545}1546return gerepileupto(av, r);1547}15481549GEN1550FF_ellweilpairing(GEN E, GEN P, GEN Q, GEN m)1551{1552GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E);1553GEN r,T,p, Pp,Qp, e3;1554ulong pp;1555GEN z=_initFF(fg,&T,&p,&pp);1556pari_sp av = avma;1557switch(fg[1])1558{1559case t_FF_FpXQ:1560e3 = FqV_to_FpXQV(gel(e,3),T);1561Pp = FpXQE_changepointinv(RgE_to_FpXQE(P,T,p), e3, T, p);1562Qp = FpXQE_changepointinv(RgE_to_FpXQE(Q,T,p), e3, T, p);1563r = FpXQE_weilpairing(Pp, Qp, m, gel(e,1), T, p);1564break;1565case t_FF_F2xq:1566Pp = F2xqE_changepointinv(RgE_to_F2xqE(P,T), gel(e,3), T);1567Qp = F2xqE_changepointinv(RgE_to_F2xqE(Q,T), gel(e,3), T);1568r = F2xqE_weilpairing(Pp, Qp, m, gel(e,1), T);1569break;1570default:1571Pp = FlxqE_changepointinv(RgE_to_FlxqE(P,T,pp), gel(e,3), T, pp);1572Qp = FlxqE_changepointinv(RgE_to_FlxqE(Q,T,pp), gel(e,3), T, pp);1573r = FlxqE_weilpairing(Pp, Qp, m, gel(e,1), T, pp);1574}1575r = gerepileupto(av, r);1576return _mkFF(fg,z,r);1577}15781579GEN1580FF_elltatepairing(GEN E, GEN P, GEN Q, GEN m)1581{1582GEN fg = ellff_get_field(E), e = ellff_get_a4a6(E);1583GEN r,T,p, Pp,Qp, e3;1584ulong pp;1585GEN z=_initFF(fg,&T,&p,&pp);1586pari_sp av = avma;1587switch(fg[1])1588{1589case t_FF_FpXQ:1590e3 = FqV_to_FpXQV(gel(e,3),T);1591Pp = FpXQE_changepointinv(RgE_to_FpXQE(P,T,p), e3, T, p);1592Qp = FpXQE_changepointinv(RgE_to_FpXQE(Q,T,p), e3, T, p);1593r = FpXQE_tatepairing(Pp, Qp, m, gel(e,1), T, p);1594break;1595case t_FF_F2xq:1596Pp = F2xqE_changepointinv(RgE_to_F2xqE(P,T), gel(e,3), T);1597Qp = F2xqE_changepointinv(RgE_to_F2xqE(Q,T), gel(e,3), T);1598r = F2xqE_tatepairing(Pp, Qp, m, gel(e,1), T);1599break;1600default:1601Pp = FlxqE_changepointinv(RgE_to_FlxqE(P,T,pp), gel(e,3), T, pp);1602Qp = FlxqE_changepointinv(RgE_to_FlxqE(Q,T,pp), gel(e,3), T, pp);1603r = FlxqE_tatepairing(Pp, Qp, m, gel(e,1), T, pp);1604}1605r = gerepileupto(av, r);1606return _mkFF(fg,z,r);1607}16081609GEN1610FFX_roots(GEN Pf, GEN ff)1611{1612pari_sp av = avma;1613GEN r,T,p;1614ulong pp;1615GEN P = FFX_to_raw(Pf, ff);1616_getFF(ff,&T,&p,&pp);1617switch(ff[1])1618{1619case t_FF_FpXQ:1620r = FpXQX_roots(P, T, p);1621break;1622case t_FF_F2xq:1623r = F2xqX_roots(P, T);1624break;1625default:1626r = FlxqX_roots(P, T, pp);1627}1628return gerepilecopy(av, raw_to_FFC(r, ff));1629}16301631static GEN1632raw_to_FFXC(GEN x, GEN ff) { pari_APPLY_type(t_COL, raw_to_FFX(gel(x,i), ff)); }1633static GEN1634raw_to_FFXM(GEN x, GEN ff) { pari_APPLY_same(raw_to_FFXC(gel(x,i), ff)); }1635static GEN1636raw_to_FFX_fact(GEN F, GEN ff)1637{1638GEN y, u, v;1639GEN P = gel(F,1), E = gel(F,2);1640long j, l = lg(P);1641y = cgetg(3,t_MAT);1642u = cgetg(l,t_COL); gel(y,1) = u;1643v = cgetg(l,t_COL); gel(y,2) = v;1644for (j=1; j<l; j++)1645{1646gel(u,j) = raw_to_FFX(gel(P,j), ff);1647gel(v,j) = utoi(uel(E,j));1648}1649return y;1650}16511652static GEN1653FFX_zero(GEN ff, long v)1654{1655GEN r = cgetg(3,t_POL);1656r[1] = evalvarn(v);1657gel(r,2) = FF_zero(ff);1658return r;1659}16601661GEN1662FFX_add(GEN Pf, GEN Qf, GEN ff)1663{1664pari_sp av = avma;1665GEN r,T,p;1666ulong pp;1667GEN P = FFX_to_raw(Pf, ff);1668GEN Q = FFX_to_raw(Qf, ff);1669_getFF(ff,&T,&p,&pp);1670switch(ff[1])1671{1672case t_FF_FpXQ:1673r = FpXX_add(P, Q, p);1674break;1675case t_FF_F2xq:1676r = F2xX_add(P, Q);1677break;1678default:1679r = FlxX_add(P, Q, pp);1680}1681if (!lgpol(r)) { set_avma(av); return FFX_zero(ff, varn(Pf)); }1682return gerepilecopy(av, raw_to_FFX(r, ff));1683}16841685static GEN1686FFX_wrap2(GEN Pf, GEN Qf, GEN ff, GEN FpXQX(GEN, GEN, GEN, GEN),1687GEN F2xqX(GEN, GEN, GEN), GEN FlxqX(GEN, GEN, GEN, ulong))1688{1689pari_sp av = avma;1690GEN r,T,p;1691ulong pp;1692GEN P = FFX_to_raw(Pf, ff);1693GEN Q = FFX_to_raw(Qf, ff);1694_getFF(ff,&T,&p,&pp);1695switch(ff[1])1696{1697case t_FF_FpXQ:1698r = FpXQX(P, Q, T, p);1699break;1700case t_FF_F2xq:1701r = F2xqX(P, Q, T);1702break;1703default:1704r = FlxqX(P, Q, T, pp);1705}1706if (!lgpol(r)) { set_avma(av); return FFX_zero(ff, varn(Pf)); }1707return gerepilecopy(av, raw_to_FFX(r, ff));1708}17091710GEN1711FFX_mul(GEN Pf, GEN Qf, GEN ff)1712{ return FFX_wrap2(Pf, Qf, ff, FpXQX_mul, F2xqX_mul, FlxqX_mul); }17131714GEN1715FFX_gcd(GEN Pf, GEN Qf, GEN ff)1716{ return FFX_wrap2(Pf, Qf, ff, FpXQX_gcd, F2xqX_gcd, FlxqX_gcd); }17171718GEN1719FFX_sqr(GEN Pf, GEN ff)1720{1721pari_sp av = avma;1722GEN r,T,p;1723ulong pp;1724GEN P = FFX_to_raw(Pf, ff);1725_getFF(ff,&T,&p,&pp);1726switch(ff[1])1727{1728case t_FF_FpXQ:1729r = FpXQX_sqr(P, T, p);1730break;1731case t_FF_F2xq:1732r = F2xqX_sqr(P, T);1733break;1734default:1735r = FlxqX_sqr(P, T, pp);1736}1737if (!lgpol(r)) { set_avma(av); return FFX_zero(ff, varn(Pf)); }1738return gerepilecopy(av, raw_to_FFX(r, ff));1739}17401741GEN1742FFX_rem(GEN Pf, GEN Qf, GEN ff)1743{ return FFX_wrap2(Pf, Qf, ff, FpXQX_rem, F2xqX_rem, FlxqX_rem); }17441745GEN1746FFX_resultant(GEN Pf, GEN Qf, GEN ff)1747{1748pari_sp av = avma;1749GEN r,T,p;1750ulong pp;1751GEN P = FFX_to_raw(Pf, ff);1752GEN Q = FFX_to_raw(Qf, ff);1753GEN z = _initFF(ff,&T,&p,&pp);1754switch(ff[1])1755{1756case t_FF_FpXQ:1757r = FpXQX_resultant(P, Q, T, p);1758break;1759case t_FF_F2xq:1760r = F2xqX_resultant(P, Q, T);1761break;1762default:1763r = FlxqX_resultant(P, Q, T, pp);1764}1765return gerepileupto(av, _mkFF(ff,z,r));1766}17671768GEN1769FFX_disc(GEN Pf, GEN ff)1770{1771pari_sp av = avma;1772GEN r,T,p;1773ulong pp;1774GEN P = FFX_to_raw(Pf, ff);1775GEN z = _initFF(ff,&T,&p,&pp);1776switch(ff[1])1777{1778case t_FF_FpXQ:1779r = FpXQX_disc(P, T, p);1780break;1781case t_FF_F2xq:1782r = F2xqX_disc(P, T);1783break;1784default:1785r = FlxqX_disc(P, T, pp);1786}1787return gerepileupto(av, _mkFF(ff,z,r));1788}17891790static GEN1791gc_gcdext(pari_sp av, GEN r, GEN *u, GEN *v)1792{1793if (!u && !v) return gerepilecopy(av, r);1794if (u && v) gerepileall(av, 3, &r, u, v);1795else gerepileall(av, 2, &r, u ? u: v);1796return r;1797}17981799GEN1800FFX_extgcd(GEN Pf, GEN Qf, GEN ff, GEN *pt_Uf, GEN *pt_Vf)1801{1802pari_sp av = avma;1803GEN r,T,p;1804ulong pp;1805GEN P = FFX_to_raw(Pf, ff);1806GEN Q = FFX_to_raw(Qf, ff);1807_getFF(ff,&T,&p,&pp);1808switch(ff[1])1809{1810case t_FF_FpXQ:1811r = FpXQX_extgcd(P, Q, T, p, pt_Uf, pt_Vf);1812break;1813case t_FF_F2xq:1814r = F2xqX_extgcd(P, Q, T, pt_Uf, pt_Vf);1815break;1816default:1817r = FlxqX_extgcd(P, Q, T, pp, pt_Uf, pt_Vf);1818}1819if (pt_Uf) *pt_Uf = raw_to_FFX(*pt_Uf, ff);1820if (pt_Vf) *pt_Vf = raw_to_FFX(*pt_Vf, ff);1821return gc_gcdext(av, raw_to_FFX(r, ff), pt_Uf, pt_Vf);1822}18231824GEN1825FFX_halfgcd(GEN Pf, GEN Qf, GEN ff)1826{1827pari_sp av = avma;1828GEN r,T,p;1829ulong pp;1830GEN P = FFX_to_raw(Pf, ff);1831GEN Q = FFX_to_raw(Qf, ff);1832_getFF(ff,&T,&p,&pp);1833switch(ff[1])1834{1835case t_FF_FpXQ:1836r = FpXQX_halfgcd(P, Q, T, p);1837break;1838case t_FF_F2xq:1839r = F2xqX_halfgcd(P, Q, T);1840break;1841default:1842r = FlxqX_halfgcd(P, Q, T, pp);1843}1844return gerepilecopy(av, raw_to_FFXM(r, ff));1845}18461847GEN1848FFXQ_sqr(GEN Pf, GEN Qf, GEN ff)1849{ return FFX_wrap2(Pf, Qf, ff, FpXQXQ_sqr, F2xqXQ_sqr, FlxqXQ_sqr); }18501851GEN1852FFXQ_inv(GEN Pf, GEN Qf, GEN ff)1853{ return FFX_wrap2(Pf, Qf, ff, FpXQXQ_inv, F2xqXQ_inv, FlxqXQ_inv); }18541855GEN1856FFXQ_mul(GEN Pf, GEN Qf, GEN Sf, GEN ff)1857{1858pari_sp av = avma;1859GEN r,T,p;1860ulong pp;1861GEN P = FFX_to_raw(Pf, ff);1862GEN Q = FFX_to_raw(Qf, ff);1863GEN S = FFX_to_raw(Sf, ff);1864_getFF(ff,&T,&p,&pp);1865switch(ff[1])1866{1867case t_FF_FpXQ:1868r = FpXQXQ_mul(P, Q, S, T, p);1869break;1870case t_FF_F2xq:1871r = F2xqXQ_mul(P, Q, S, T);1872break;1873default:1874r = FlxqXQ_mul(P, Q, S, T, pp);1875}1876if (!lgpol(r)) { set_avma(av); return FFX_zero(ff, varn(Pf)); }1877return gerepilecopy(av, raw_to_FFX(r, ff));1878}18791880GEN1881FFXQ_minpoly(GEN Pf, GEN Qf, GEN ff)1882{1883pari_sp av = avma;1884GEN r,T,p;1885ulong pp;1886GEN P = FFX_to_raw(Pf, ff);1887GEN Q = FFX_to_raw(Qf, ff);1888_getFF(ff,&T,&p,&pp);1889switch(ff[1])1890{1891case t_FF_FpXQ:1892r = FpXQXQ_minpoly(P, Q, T, p);1893break;1894case t_FF_F2xq:1895r = FlxX_to_F2xX(FlxqXQ_minpoly(F2xX_to_FlxX(P), F2xX_to_FlxX(Q), F2x_to_Flx(T), 2UL));1896break;1897default:1898r = FlxqXQ_minpoly(P, Q, T, pp);1899}1900return gerepilecopy(av, raw_to_FFX(r, ff));1901}19021903long1904FFX_ispower(GEN Pf, long k, GEN ff, GEN *pt_r)1905{1906pari_sp av = avma;1907GEN P,T,p;1908ulong pp;1909long s;1910if (degpol(Pf) % k) return 0;1911P = FFX_to_raw(Pf, ff);1912_getFF(ff,&T,&p,&pp);1913switch(ff[1])1914{1915case t_FF_FpXQ:1916s = FpXQX_ispower(P, k, T, p, pt_r);1917break;1918case t_FF_F2xq:1919s = F2xqX_ispower(P, k, T, pt_r);1920break;1921default:1922s = FlxqX_ispower(P, k, T, pp, pt_r);1923}1924if (s==0) return gc_long(av,0);1925if (pt_r)1926*pt_r = gerepilecopy(av, raw_to_FFX(*pt_r, ff));1927else set_avma(av);1928return 1;1929}19301931GEN1932FFX_factor(GEN Pf, GEN ff)1933{1934pari_sp av = avma;1935GEN r,T,p;1936ulong pp;1937GEN P = FFX_to_raw(Pf, ff);1938_getFF(ff,&T,&p,&pp);1939switch(ff[1])1940{1941case t_FF_FpXQ:1942r = FpXQX_factor(P, T, p);1943break;1944case t_FF_F2xq:1945r = F2xqX_factor(P, T);1946break;1947default:1948r = FlxqX_factor(P, T, pp);1949}1950return gerepilecopy(av, raw_to_FFX_fact(r, ff));1951}19521953GEN1954FFX_factor_squarefree(GEN Pf, GEN ff)1955{1956pari_sp av = avma;1957GEN r,T,p;1958ulong pp;1959GEN P = FFX_to_raw(Pf, ff);1960_getFF(ff,&T,&p,&pp);1961switch(ff[1])1962{1963case t_FF_FpXQ:1964r = FpXQX_factor_squarefree(P, T, p);1965break;1966case t_FF_F2xq:1967r = F2xqX_factor_squarefree(P, T);1968break;1969default:1970r = FlxqX_factor_squarefree(P, T, pp);1971}1972return gerepilecopy(av, raw_to_FFXC(r, ff));1973}19741975GEN1976FFX_ddf(GEN Pf, GEN ff)1977{1978pari_sp av = avma;1979GEN r,T,p;1980ulong pp;1981GEN P = FFX_to_raw(Pf, ff);1982_getFF(ff,&T,&p,&pp);1983switch(ff[1])1984{1985case t_FF_FpXQ:1986r = FpXQX_ddf(P, T, p);1987break;1988case t_FF_F2xq:1989r = F2xqX_ddf(P, T);1990break;1991default:1992r = FlxqX_ddf(P, T, pp);1993}1994return gerepilecopy(av, raw_to_FFX_fact(r, ff));1995}19961997GEN1998FFX_degfact(GEN Pf, GEN ff)1999{2000pari_sp av = avma;2001GEN r,T,p;2002ulong pp;2003GEN P = FFX_to_raw(Pf, ff);2004_getFF(ff, &T, &p, &pp);2005switch(ff[1])2006{2007case t_FF_FpXQ:2008r = FpXQX_degfact(P, T, p);2009break;2010case t_FF_F2xq:2011r = F2xqX_degfact(P, T);2012break;2013default:2014r = FlxqX_degfact(P, T, pp);2015}2016return gerepilecopy(av, r);2017}20182019GEN2020FqX_to_FFX(GEN x, GEN ff)2021{2022long i, lx;2023GEN y = cgetg_copy(x,&lx);2024y[1] = x[1];2025for (i=2; i<lx; i++) gel(y,i) = Fq_to_FF(gel(x,i), ff);2026return y;2027}20282029GEN2030ffgen(GEN T, long v)2031{2032GEN A, p = NULL, ff = cgetg(5,t_FFELT);2033long d;2034switch(typ(T))2035{2036case t_FFELT:2037p = FF_p_i(T); T = FF_mod(T); d = degpol(T);2038break;2039case t_POL:2040d = degpol(T); p = NULL;2041if (d < 1 || !RgX_is_FpX(T, &p) || !p) pari_err_TYPE("ffgen",T);2042T = RgX_to_FpX(T, p);2043/* testing for irreducibility is too costly */2044if (!FpX_is_squarefree(T,p)) pari_err_IRREDPOL("ffgen",T);2045break;2046case t_INT:2047d = ispseudoprimepower(T,&p);2048if (!d) pari_err_PRIME("ffgen",T);2049T = init_Fq(p, d, v);2050break;2051case t_VEC: case t_COL:2052if (lg(T) == 3) {2053p = gel(T,1);2054A = gel(T,2);2055if (typ(p) == t_INT && typ(A) == t_INT)2056{2057d = itos(A);2058T = init_Fq(p, d, v);2059break;2060}2061}2062default:2063pari_err_TYPE("ffgen",T);2064return NULL;/* LCOV_EXCL_LINE */2065}2066if (v < 0) v = varn(T);2067if (lgefint(p)==3)2068{2069ulong pp = p[2];2070long sv = evalvarn(v);2071if (pp==2)2072{2073ff[1] = t_FF_F2xq;2074T = ZX_to_F2x(T); T[1] = sv;2075A = polx_F2x(sv); if (d == 1) A = F2x_rem(A, T);2076p = gen_2;2077}2078else2079{2080ff[1] = t_FF_Flxq;2081T = ZX_to_Flx(T,pp); T[1] = sv;2082A = polx_Flx(sv); if (d == 1) A = Flx_rem(A, T, pp);2083p = icopy(p);2084}2085}2086else2087{2088ff[1] = t_FF_FpXQ;2089setvarn(T,v);2090A = pol_x(v); if (d == 1) A = FpX_rem(A, T, p);2091p = icopy(p);2092}2093gel(ff,2) = A;2094gel(ff,3) = T;2095gel(ff,4) = p; return ff;2096}20972098GEN2099p_to_FF(GEN p, long v)2100{2101GEN A, T;2102GEN ff = cgetg(5,t_FFELT);2103if (lgefint(p)==3)2104{2105ulong pp = p[2];2106long sv = evalvarn(v);2107if (pp==2)2108{2109ff[1] = t_FF_F2xq;2110T = polx_F2x(sv);2111A = pol1_F2x(sv);2112p = gen_2;2113}2114else2115{2116ff[1] = t_FF_Flxq;2117T = polx_Flx(sv);2118A = pol1_Flx(sv);2119p = icopy(p);2120}2121}2122else2123{2124ff[1] = t_FF_FpXQ;2125T = pol_x(v);2126A = pol_1(v);2127p = icopy(p);2128}2129gel(ff,2) = A;2130gel(ff,3) = T;2131gel(ff,4) = p; return ff;2132}2133GEN2134Tp_to_FF(GEN T, GEN p)2135{2136GEN A, ff;2137long v;2138if (!T) return p_to_FF(p,0);2139ff = cgetg(5,t_FFELT);2140v = varn(T);2141if (lgefint(p)==3)2142{2143ulong pp = p[2];2144long sv = evalvarn(v);2145if (pp==2)2146{2147ff[1] = t_FF_F2xq;2148T = ZX_to_F2x(T);2149A = pol1_F2x(sv);2150p = gen_2;2151}2152else2153{2154ff[1] = t_FF_Flxq;2155T = ZX_to_Flx(T, pp);2156A = pol1_Flx(sv);2157p = icopy(p);2158}2159}2160else2161{2162ff[1] = t_FF_FpXQ;2163T = ZX_copy(T);2164A = pol_1(v);2165p = icopy(p);2166}2167gel(ff,2) = A;2168gel(ff,3) = T;2169gel(ff,4) = p; return ff;2170}21712172GEN2173fforder(GEN x, GEN o)2174{2175if (typ(x)!=t_FFELT) pari_err_TYPE("fforder",x);2176return FF_order(x,o);2177}21782179GEN2180ffprimroot(GEN x, GEN *o)2181{2182if (typ(x)!=t_FFELT) pari_err_TYPE("ffprimroot",x);2183return FF_primroot(x,o);2184}21852186GEN2187fflog(GEN x, GEN g, GEN o)2188{2189if (typ(x)!=t_FFELT) pari_err_TYPE("fflog",x);2190if (typ(g)!=t_FFELT) pari_err_TYPE("fflog",g);2191return FF_log(x,g,o);2192}21932194GEN2195ffrandom(GEN ff)2196{2197ulong pp;2198GEN r, T, p, z = _initFF(ff,&T,&p,&pp);2199switch(ff[1])2200{2201case t_FF_FpXQ:2202r = random_FpX(degpol(T), varn(T), p);2203break;2204case t_FF_F2xq:2205r = random_F2x(F2x_degree(T), T[1]);2206break;2207default:2208r = random_Flx(degpol(T), T[1], pp);2209}2210return _mkFF(ff,z,r);2211}22122213int2214Rg_is_FF(GEN c, GEN *ff)2215{2216switch(typ(c))2217{2218case t_FFELT:2219if (!*ff) *ff = c;2220else if (!FF_samefield(*ff, c)) return 0;2221break;2222default:2223return 0;2224}2225return 1;2226}22272228int2229RgC_is_FFC(GEN x, GEN *ff)2230{2231long i, lx = lg(x);2232for (i=lx-1; i>0; i--)2233if (!Rg_is_FF(gel(x,i), ff)) return 0;2234return (*ff != NULL);2235}22362237int2238RgM_is_FFM(GEN x, GEN *ff)2239{2240long j, lx = lg(x);2241for (j=lx-1; j>0; j--)2242if (!RgC_is_FFC(gel(x,j), ff)) return 0;2243return (*ff != NULL);2244}22452246static GEN2247FqC_to_FpXQC(GEN x, GEN T, GEN p)2248{2249long i, lx;2250GEN y = cgetg_copy(x,&lx);2251for(i=1; i<lx; i++)2252gel(y, i) = Fq_to_FpXQ(gel(x, i), T, p);2253return y;2254}22552256static GEN2257FqM_to_FpXQM(GEN x, GEN T, GEN p)2258{2259long i, lx;2260GEN y = cgetg_copy(x,&lx);2261for(i=1; i<lx; i++)2262gel(y, i) = FqC_to_FpXQC(gel(x, i), T, p);2263return y;2264}22652266/* for functions t_MAT -> t_MAT */2267static GEN2268FFM_wrap(GEN M, GEN ff, GEN (*Fq)(GEN,GEN,GEN),2269GEN (*Flxq)(GEN,GEN,ulong),2270GEN (*F2xq)(GEN,GEN))2271{2272pari_sp av = avma;2273ulong pp;2274GEN T, p;2275_getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff);2276switch(ff[1])2277{2278case t_FF_FpXQ: M = Fq(M,T,p); if (M) M = FqM_to_FpXQM(M,T,p);2279break;2280case t_FF_F2xq: M = F2xq(M,T); break;2281default: M = Flxq(M,T,pp); break;2282}2283if (!M) return gc_NULL(av);2284return gerepilecopy(av, raw_to_FFM(M, ff));2285}22862287/* for functions (t_MAT, t_MAT) -> t_MAT */2288static GEN2289FFM_FFM_wrap(GEN M, GEN N, GEN ff,2290GEN (*Fq)(GEN, GEN, GEN, GEN),2291GEN (*Flxq)(GEN, GEN, GEN, ulong),2292GEN (*F2xq)(GEN, GEN, GEN))2293{2294pari_sp av = avma;2295ulong pp;2296GEN T, p;2297int is_sqr = M==N;2298_getFF(ff, &T, &p, &pp);2299M = FFM_to_raw(M, ff);2300N = is_sqr? M: FFM_to_raw(N, ff);2301switch(ff[1])2302{2303case t_FF_FpXQ: M = Fq(M, N, T, p); if (M) M = FqM_to_FpXQM(M, T, p);2304break;2305case t_FF_F2xq: M = F2xq(M, N, T); break;2306default: M = Flxq(M, N, T, pp); break;2307}2308if (!M) return gc_NULL(av);2309return gerepilecopy(av, raw_to_FFM(M, ff));2310}23112312/* for functions (t_MAT, t_COL) -> t_COL */2313static GEN2314FFM_FFC_wrap(GEN M, GEN C, GEN ff,2315GEN (*Fq)(GEN, GEN, GEN, GEN),2316GEN (*Flxq)(GEN, GEN, GEN, ulong),2317GEN (*F2xq)(GEN, GEN, GEN))2318{2319pari_sp av = avma;2320ulong pp;2321GEN T, p;2322_getFF(ff, &T, &p, &pp);2323M = FFM_to_raw(M, ff);2324C = FFC_to_raw(C, ff);2325switch(ff[1])2326{2327case t_FF_FpXQ: C = Fq(M, C, T, p); if (C) C = FqC_to_FpXQC(C, T, p);2328break;2329case t_FF_F2xq: C = F2xq(M, C, T); break;2330default: C = Flxq(M, C, T, pp); break;2331}2332if (!C) return gc_NULL(av);2333return gerepilecopy(av, raw_to_FFC(C, ff));2334}23352336GEN2337FFM_ker(GEN M, GEN ff)2338{ return FFM_wrap(M,ff, &FqM_ker,&FlxqM_ker,&F2xqM_ker); }2339GEN2340FFM_image(GEN M, GEN ff)2341{ return FFM_wrap(M,ff, &FqM_image,&FlxqM_image,&F2xqM_image); }2342GEN2343FFM_inv(GEN M, GEN ff)2344{ return FFM_wrap(M,ff, &FqM_inv,&FlxqM_inv,&F2xqM_inv); }2345GEN2346FFM_suppl(GEN M, GEN ff)2347{ return FFM_wrap(M,ff, &FqM_suppl,&FlxqM_suppl,&F2xqM_suppl); }23482349GEN2350FFM_deplin(GEN M, GEN ff)2351{2352pari_sp av = avma;2353ulong pp;2354GEN C, T, p;2355_getFF(ff, &T, &p, &pp); M = FFM_to_raw(M, ff);2356switch(ff[1]) {2357case t_FF_FpXQ: C = FqM_deplin(M, T, p);2358if (C) C = FqC_to_FpXQC(C, T, p); break;2359case t_FF_F2xq: C = F2xqM_deplin(M, T); break;2360default: C = FlxqM_deplin(M, T, pp); break;2361}2362if (!C) return gc_NULL(av);2363return gerepilecopy(av, raw_to_FFC(C, ff));2364}23652366GEN2367FFM_indexrank(GEN M, GEN ff)2368{2369pari_sp av = avma;2370ulong pp;2371GEN R, T, p;2372_getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff);2373switch(ff[1]) {2374case t_FF_FpXQ: R = FqM_indexrank(M,T,p); break;2375case t_FF_F2xq: R = F2xqM_indexrank(M,T); break;2376default: R = FlxqM_indexrank(M,T,pp); break;2377}2378return gerepileupto(av, R);2379}23802381long2382FFM_rank(GEN M, GEN ff)2383{2384pari_sp av = avma;2385long r;2386ulong pp;2387GEN T, p;2388_getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff);2389switch(ff[1])2390{2391case t_FF_FpXQ: r = FqM_rank(M,T,p); break;2392case t_FF_F2xq: r = F2xqM_rank(M,T); break;2393default: r = FlxqM_rank(M,T,pp); break;2394}2395return gc_long(av,r);2396}2397GEN2398FFM_det(GEN M, GEN ff)2399{2400pari_sp av = avma;2401ulong pp;2402GEN d, T, p;2403_getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff);2404switch(ff[1])2405{2406case t_FF_FpXQ: d = FqM_det(M,T,p); break;2407case t_FF_F2xq: d = F2xqM_det(M,T); break;2408default: d = FlxqM_det(M,T,pp); break;2409}2410return gerepilecopy(av, mkFF_i(ff, d));2411}24122413GEN2414FFM_FFC_gauss(GEN M, GEN C, GEN ff)2415{2416return FFM_FFC_wrap(M, C, ff, FqM_FqC_gauss,2417FlxqM_FlxqC_gauss, F2xqM_F2xqC_gauss);2418}24192420GEN2421FFM_gauss(GEN M, GEN N, GEN ff)2422{2423return FFM_FFM_wrap(M, N, ff, FqM_gauss,2424FlxqM_gauss, F2xqM_gauss);2425}24262427GEN2428FFM_FFC_invimage(GEN M, GEN C, GEN ff)2429{2430return FFM_FFC_wrap(M, C, ff, FqM_FqC_invimage,2431FlxqM_FlxqC_invimage, F2xqM_F2xqC_invimage);2432}24332434GEN2435FFM_invimage(GEN M, GEN N, GEN ff)2436{2437return FFM_FFM_wrap(M, N, ff, FqM_invimage,2438FlxqM_invimage, F2xqM_invimage);2439}24402441GEN2442FFM_FFC_mul(GEN M, GEN C, GEN ff)2443{2444return FFM_FFC_wrap(M, C, ff, FqM_FqC_mul,2445FlxqM_FlxqC_mul, F2xqM_F2xqC_mul);2446}24472448GEN2449FFM_mul(GEN M, GEN N, GEN ff)2450{2451return FFM_FFM_wrap(M, N, ff, FqM_mul, FlxqM_mul, F2xqM_mul);2452}245324542455