Bill Allombert on Fri, 05 Oct 2007 11:47:03 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
[patch v2] FFELT format for finite fields of characteristic 2 |
On Sat, Sep 01, 2007 at 06:13:56PM +0200, Bill Allombert wrote: > Hello PARI dev, > > Example of use: > a=ffgen(ffinit(2,32,a)); > a^15 > > This patch also adds two new classes of functions, F2x and F2xq. > F2x objects are defined as follows: > > An F2x is a t_VECSMALL: > x[0] = codeword > x[1] = evalvarn(variable number) (signe is not stored). > x[2] = a_0...a_31 x[3] = a_32..a_63, etc. on 32bit systems. > x[2] = a_0...a_63 x[3] = a_64..a_127, etc. on 64bit systems. > where the a_i are bits. > Note: F2x(0)=Flx(0 mod 2) ans F2x(1)=Flx(1 mod 2) > > Limitation: > 1) Only straightforward algorithms are implemented. > 2) Resultants are not implemented. Please find a cleaner version of this patch, with documentations for the F2x and F2xq classes of functions. Cheers, Bill.
Index: doc/usersch4.tex =================================================================== RCS file: /home/cvs/pari/doc/usersch4.tex,v retrieving revision 1.119 diff -u -r1.119 usersch4.tex --- doc/usersch4.tex 10 Sep 2007 00:35:02 -0000 1.119 +++ doc/usersch4.tex 5 Oct 2007 09:32:19 -0000 @@ -1202,6 +1202,11 @@ modulo $p$, and the degree of $A$ is strictly less than the degree of $T$. This represents the element $A\pmod{T}$ in $\F_l[X]/T$. +The format \tet{t_FF_F2xq}:\kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{F2x}, +\kbd{l=z[4]} is the \typ{INT} $2$, $T$ is irreducible +modulo $2$, and the degree of $A$ is strictly less than the degree of $T$. +This represents the element $A\pmod{T}$ in $\F_2[X]/T$. + \subsec{Type \typ{COMPLEX} (complex number)}:% \kbdsidx{t_COMPLEX}\sidx{complex number} \kbd{z[1]} points to the real part, and \kbd{z[2]} to the imaginary part. Index: doc/usersch5.tex =================================================================== RCS file: /home/cvs/pari/doc/usersch5.tex,v retrieving revision 1.329 diff -u -r1.329 usersch5.tex --- doc/usersch5.tex 4 Oct 2007 20:01:23 -0000 1.329 +++ doc/usersch5.tex 5 Oct 2007 09:32:21 -0000 @@ -2518,6 +2518,9 @@ \fun{GEN}{Flx_red}{GEN z, ulong p} converts from \kbd{zx} with non-negative coefficients to \kbd{Flx} (by reducing them mod \kbd{p}). +\fun{int}{Flx_cmp1}{GEN x} returns 1 (true) if the \kbd{Flx x} is equal to~1, +0~(false) otherwise. + \fun{GEN}{Flx_add}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_Fl_add}{GEN y, ulong x, ulong p} @@ -2742,6 +2745,72 @@ \fun{GEN}{FlxqM_ker}{GEN x, GEN T, ulong p} +\subsec{\kbd{F2x}} An \kbd{F2x}~\kbd{z} is a \typ{VECSMALL} +representing a polynomial over $\F_2[X]$. Specifically +\kbd{z[0]} is the usual codeword, \kbd{z[1] = evalvarn($v$)} for some +variable $v$ and the coefficients are given by the bits of remaining +words by increasing degree. + +\subsubsec{Basic operations} + +\fun{GEN}{Flx_to_F2x}{GEN x} + +\fun{GEN}{ZX_to_F2x}{GEN x} + +\fun{GEN}{F2x_to_Flx}{GEN x} + +\fun{GEN}{F2x_to_ZX}{GEN x} + +\fun{GEN}{pol1_F2x}{long sv} returns the \kbd{F2x} in variable $s$ constant to +$1$. + +\fun{GEN}{polx_F2x}{long sv} returns the variable $v$ as degree~1~\kbd{F2x}. + +\fun{GEN}{random_F2x}{long d, long sv} returns a random \kbd{F2x} +in variable \kbd{v}, of degree less than~\kbd{d}. + +\fun{long}{F2x_degree}{GEN x} returns the degree of the \kbd{F2x x}. The degree of $0$ is defined as $-1$. + +\fun{int}{F2x_cmp1}{GEN x} + +\fun{GEN}{F2x_1_add}{GEN y} returns \kbd{y+1} where \kbd{y} is a \kbd{Flx}. + +\fun{GEN}{F2x_add}{GEN x, GEN y} + +\fun{GEN}{F2x_mul}{GEN x, GEN y} + +\fun{GEN}{F2x_sqr}{GEN x} + +\fun{GEN}{F2x_divrem}{GEN x, GEN y, GEN *pr} + +\fun{GEN}{F2x_rem}{GEN x, GEN y} + +\fun{GEN}{F2x_extgcd}{GEN a, GEN b, GEN *ptu, GEN *ptv} + +\fun{GEN}{F2x_gcd}{GEN a, GEN b} + +\subsec{\kbd{F2xq}}. See \kbd{FpXQ} operations. + +\fun{GEN}{F2xq_mul}{GEN x, GEN y, GEN pol} + +\fun{GEN}{F2xq_sqr}{GEN x,GEN pol} + +\fun{GEN}{F2xq_div}{GEN x,GEN y,GEN T} + +\fun{GEN}{F2xq_inv}{GEN x, GEN T} + +\fun{GEN}{F2xq_invsafe}{GEN x, GEN T} + +\fun{GEN}{F2xq_pow}{GEN x, GEN n, GEN pol} + +\fun{GEN}{F2xq_log}{GEN a, GEN g, GEN ord, GEN T} + +\fun{GEN}{F2xq_order}{GEN a, GEN ord, GEN T} + +\fun{GEN}{F2xq_sqrtn}{GEN a, GEN n, GEN T, GEN *zeta} + +\fun{GEN}{gener_F2xq}{GEN T, GEN *po} + \subsec{\kbd{QX}}. \fun{GEN}{QXQ_inv}{GEN A, GEN B} returns the inverse of \kbd{A} modulo \kbd{B} Index: src/basemath/FF.c =================================================================== RCS file: /home/cvs/pari/src/basemath/FF.c,v retrieving revision 1.10 diff -u -r1.10 FF.c --- src/basemath/FF.c 4 Oct 2007 20:01:23 -0000 1.10 +++ src/basemath/FF.c 5 Oct 2007 09:32:21 -0000 @@ -150,6 +150,9 @@ case t_FF_FpXQ: r=pol_1(varn(T)); break; + case t_FF_F2xq: + r=pol1_F2x(T[1]); + break; default: r=pol1_Flx(T[1]); } @@ -186,6 +189,8 @@ { case t_FF_FpXQ: return gel(x,2); + case t_FF_F2xq: + return F2x_to_ZX(gel(x,2)); default: return Flx_to_ZX(gel(x,2)); } @@ -205,6 +210,9 @@ r=gerepileupto(av,FpX_add(gel(x,2),gel(y,2),p)); break; } + case t_FF_F2xq: + r=F2x_add(gel(x,2),gel(y,2)); + break; default: r=Flx_add(gel(x,2),gel(y,2),pp); } @@ -224,6 +232,9 @@ r=gerepileupto(av,FpX_Fp_add(gel(x,2),modii(y,p),p)); break; } + case t_FF_F2xq: + r=mpodd(y)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2)); + break; default: r=Flx_Fl_add(gel(x,2),umodiu(y,pp),pp); } @@ -240,6 +251,9 @@ case t_FF_FpXQ: r=FpX_neg(gel(x,2),p); break; + case t_FF_F2xq: + r=vecsmall_copy(gel(x,2)); + break; default: r=Flx_neg(gel(x,2),pp); } @@ -256,6 +270,9 @@ case t_FF_FpXQ: r=FpX_neg(gel(x,2),p); break; + case t_FF_F2xq: + r=gel(x,2); + break; default: r=Flx_neg(gel(x,2),pp); } @@ -276,6 +293,9 @@ r=gerepileupto(av,FpXQ_mul(gel(x,2),gel(y,2),T,p)); break; } + case t_FF_F2xq: + r=F2xq_mul(gel(x,2),gel(y,2),T); + break; default: r=Flxq_mul(gel(x,2),gel(y,2),T,pp); } @@ -295,6 +315,9 @@ r=gerepileupto(av,FpX_Fp_mul(gel(x,2),modii(y,p),p)); break; } + case t_FF_F2xq: + r=mpodd(y)?vecsmall_copy(gel(x,2)):zero_Flx(mael(x,2,1)); + break; default: r=Flx_Fl_mul(gel(x,2),umodiu(y,pp),pp); } @@ -312,6 +335,10 @@ case t_FF_FpXQ: r=gerepileupto(av,FpX_Fp_mul(gel(x,2),Fp_div(a,b,p),p)); break; + case t_FF_F2xq: + if (mpodd(b)==0) pari_err(gdiver); + r=mpodd(a)?vecsmall_copy(gel(x,2)):zero_Flx(mael(x,2,1)); + break; default: r=gerepileupto(av,Flx_Fl_mul(gel(x,2),Fl_div(umodiu(a,pp),umodiu(b,pp),pp),pp)); } @@ -331,6 +358,9 @@ r=gerepileupto(av,FpXQ_sqr(gel(x,2),T,p)); break; } + case t_FF_F2xq: + r=F2xq_sqr(gel(x,2),T); + break; default: r=Flxq_sqr(gel(x,2),T,pp); } @@ -353,6 +383,10 @@ r=gerepileupto(av,FpX_Fp_mul(gel(x,2),p1,p)); } break; + case t_FF_F2xq: + if (n<0) pari_err(gdiver); + r=n==0?vecsmall_copy(gel(x,2)):zero_Flx(mael(x,2,1)); + break; default: { ulong l1; @@ -375,6 +409,9 @@ case t_FF_FpXQ: r=gerepileupto(av,FpXQ_inv(gel(x,2),T,p)); break; + case t_FF_F2xq: + r=F2xq_inv(gel(x,2),T); + break; default: r=Flxq_inv(gel(x,2),T,pp); } @@ -393,6 +430,9 @@ case t_FF_FpXQ: r=gerepileupto(av,FpXQ_div(gel(x,2),gel(y,2),T,p)); break; + case t_FF_F2xq: + r=gerepileupto(av,F2xq_div(gel(x,2),gel(y,2),T)); + break; default: r=gerepileupto(av,Flxq_div(gel(x,2),gel(y,2),T,pp)); } @@ -410,6 +450,10 @@ case t_FF_FpXQ: r=gerepileupto(av,FpX_Fp_mul(FpXQ_inv(gel(x,2),T,p),modii(n,p),p)); break; + case t_FF_F2xq: + r=F2xq_inv(gel(x,2),T); /*Check for division by 0*/ + if(!mpodd(n)) {avma=av; r=zero_Flx(mael(x,2,1));} + break; default: r=gerepileupto(av,Flx_Fl_mul(Flxq_inv(gel(x,2),T,pp),umodiu(n,pp),pp)); } @@ -426,6 +470,9 @@ case t_FF_FpXQ: r=FpXQ_sqrtn(gel(x,2),n,T,p,zetan); break; + case t_FF_F2xq: + r=F2xq_sqrtn(gel(x,2),n,T,zetan); + break; default: r=Flxq_sqrtn(gel(x,2),n,T,pp,zetan); } @@ -456,6 +503,9 @@ case t_FF_FpXQ: r = FpXQ_pow(gel(x,2), n, T, p); break; + case t_FF_F2xq: + r = F2xq_pow(gel(x,2), n, T); + break; default: r = Flxq_pow(gel(x,2), n, T, pp); } @@ -472,6 +522,8 @@ { case t_FF_FpXQ: return FpXQ_norm(gel(x,2),T,p); + case t_FF_F2xq: + return lgpol(gel(x,2))?gen_1:gen_0; default: return utoi(Flxq_norm(gel(x,2),T,pp)); } @@ -490,6 +542,9 @@ case t_FF_FpXQ: r = quicktrace(gel(x,2), polsym(T, degpol(T)-1)); break; + case t_FF_F2xq: + r = quicktrace(F2x_to_ZX(gel(x,2)), polsym(F2x_to_ZX(T), F2x_degree(T)-1)); + break; default: r = quicktrace(Flx_to_ZX(gel(x,2)), polsym(Flx_to_ZX(T), degpol(T)-1)); } @@ -507,6 +562,9 @@ { case t_FF_FpXQ: return gerepileupto(av,FpXQ_charpoly(gel(x,2), T, p)); + case t_FF_F2xq: + return gerepileupto(av,Flx_to_ZX(Flxq_charpoly(F2x_to_Flx(gel(x,2)), + F2x_to_Flx(T), 2UL))); default: return gerepileupto(av,Flx_to_ZX(Flxq_charpoly(gel(x,2), T, pp))); } @@ -523,6 +581,9 @@ { case t_FF_FpXQ: return gerepileupto(av,FpXQ_minpoly(gel(x,2), T, p)); + case t_FF_F2xq: + return gerepileupto(av,Flx_to_ZX(Flxq_minpoly(F2x_to_Flx(gel(x,2)), + F2x_to_Flx(T), 2UL))); default: return gerepileupto(av,Flx_to_ZX(Flxq_minpoly(gel(x,2), T, pp))); } @@ -553,15 +614,19 @@ GEN r, T, p; _getFF(x,&T,&p,&pp); _checkFF(x,g,"log"); - if (!ord) ord = factor_pn_1(p,degpol(T)); - else - if (!is_Z_factor(ord)) err(typeer, "FF_log"); + if (ord && !is_Z_factor(ord)) err(typeer, "FF_log"); switch(x[1]) { case t_FF_FpXQ: + if (!ord) ord = factor_pn_1(p,degpol(T)); r = FpXQ_log(gel(x,2), gel(g,2), ord, T, p); break; + case t_FF_F2xq: + if (!ord) ord = factor_pn_1(gen_2,F2x_degree(T)); + r = F2xq_log(gel(x,2), gel(g,2), ord, T); + break; default: + if (!ord) ord = factor_pn_1(p,degpol(T)); r = Flxq_log(gel(x,2), gel(g,2), ord, T, pp); } return gerepileuptoint(av, r); @@ -574,13 +639,18 @@ ulong pp; GEN r, T,p; _getFF(x,&T,&p,&pp); - if (!o) o = factor_pn_1(p,degpol(T)); switch(x[1]) { case t_FF_FpXQ: + if (!o) o = factor_pn_1(p,degpol(T)); r = FpXQ_order(gel(x,2), o, T, p); break; + case t_FF_F2xq: + if (!o) o = factor_pn_1(gen_2,F2x_degree(T)); + r = F2xq_order(gel(x,2), o, T); + break; default: + if (!o) o = factor_pn_1(p,degpol(T)); r = Flxq_order(gel(x,2), o, T, pp); } if (!o) r = gerepileuptoint(av,r); @@ -597,6 +667,9 @@ case t_FF_FpXQ: r = gener_FpXQ(T, p, o); break; + case t_FF_F2xq: + r = gener_F2xq(T, o); + break; default: r = gener_Flxq(T, pp, o); } @@ -616,6 +689,9 @@ case t_FF_FpXQ: r=x; break; + case t_FF_F2xq: + r=ZX_to_F2x(x); + break; default: r=ZX_to_Flx(x,pp); } @@ -676,7 +752,16 @@ GEN r, T, p; pari_sp av=avma; _getFF(x,&T,&p,&pp); - if (x[1]) T=Flx_to_ZX(T); + switch(x[1]) + { + case t_FF_FpXQ: + break; + case t_FF_F2xq: + T=F2x_to_ZX(T); + break; + default: + T=Flx_to_ZX(T); + } r = FqX_factor(FFX_to_FqX(P, T,p), T,p); return to_FF_fact(gel(r,1),gel(r,2), x,av); } Index: src/basemath/Flx.c =================================================================== RCS file: /home/cvs/pari/src/basemath/Flx.c,v retrieving revision 1.104 diff -u -r1.104 Flx.c --- src/basemath/Flx.c 4 Oct 2007 20:01:23 -0000 1.104 +++ src/basemath/Flx.c 5 Oct 2007 09:32:21 -0000 @@ -258,7 +258,7 @@ return Flx_renormalize(y,d); } -static int +int Flx_cmp1(GEN x) { return degpol(x)==0 && x[2]==1; Index: src/basemath/polarit2.c =================================================================== RCS file: /home/cvs/pari/src/basemath/polarit2.c,v retrieving revision 1.472 diff -u -r1.472 polarit2.c --- src/basemath/polarit2.c 27 Sep 2007 21:21:31 -0000 1.472 +++ src/basemath/polarit2.c 5 Oct 2007 09:32:22 -0000 @@ -4506,11 +4506,22 @@ { ulong pp=p[2]; long sv=evalvarn(v); - ff[1]=t_FF_Flxq; - gel(ff,2)=polx_Flx(sv); - gel(ff,3)=ZX_to_Flx(lift(T),pp); - mael(ff,3,1)=sv; - gel(ff,4)=icopy(p); + if (pp==2) + { + ff[1]=t_FF_F2xq; + gel(ff,2)=polx_F2x(sv); + gel(ff,3)=ZX_to_F2x(lift(T)); + mael(ff,3,1)=sv; + gel(ff,4)=gen_2; + } + else + { + ff[1]=t_FF_Flxq; + gel(ff,2)=polx_Flx(sv); + gel(ff,3)=ZX_to_Flx(lift(T),pp); + mael(ff,3,1)=sv; + gel(ff,4)=icopy(p); + } } else { Index: src/headers/paricom.h =================================================================== RCS file: /home/cvs/pari/src/headers/paricom.h,v retrieving revision 1.117 diff -u -r1.117 paricom.h --- src/headers/paricom.h 18 Sep 2007 08:49:55 -0000 1.117 +++ src/headers/paricom.h 5 Oct 2007 09:32:23 -0000 @@ -344,10 +344,15 @@ #define FpX_rem(x,y,p) (FpX_divrem((x),(y),(p), ONLY_REM)) #define Flx_div(x,y,p) (Flx_divrem((x),(y),(p), NULL)) #define FpV_FpC_mul(x,y,p) FpV_dotproduct((x),(y),(p)) +#define F2x_div(x,y) (F2x_divrem((x),(y), NULL)) + +#define pol1_F2x(x) (pol1_Flx((x))) +#define F2x_cmp1(x) (Flx_cmp1((x))) #define FpX_renormalize ZX_renormalize #define FpXX_renormalize ZX_renormalize #define FpXQX_renormalize ZX_renormalize +#define F2x_renormalize Flx_renormalize #define ZX_ZXY_resultant(a,b) ZX_ZXY_rnfequation((a),(b),NULL) Index: src/headers/paridecl.h =================================================================== RCS file: /home/cvs/pari/src/headers/paridecl.h,v retrieving revision 1.716 diff -u -r1.716 paridecl.h --- src/headers/paridecl.h 4 Oct 2007 20:01:23 -0000 1.716 +++ src/headers/paridecl.h 5 Oct 2007 09:32:23 -0000 @@ -19,6 +19,34 @@ /* */ /*******************************************************************/ +/* F2x.c */ + +GEN F2x_1_add(GEN y); +GEN F2x_add(GEN x, GEN y); +long F2x_degree(GEN x); +GEN F2x_divrem(GEN x, GEN y, GEN *pr); +GEN F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv); +GEN F2x_gcd(GEN a, GEN b); +GEN F2x_mul(GEN x, GEN y); +GEN F2x_rem(GEN x, GEN y); +GEN F2x_sqr(GEN x); +GEN F2x_to_Flx(GEN x); +GEN F2x_to_ZX(GEN x); +GEN F2xq_div(GEN x,GEN y,GEN T); +GEN F2xq_inv(GEN x, GEN T); +GEN F2xq_invsafe(GEN x, GEN T); +GEN F2xq_log(GEN a, GEN g, GEN ord, GEN T); +GEN F2xq_mul(GEN x, GEN y, GEN pol); +GEN F2xq_order(GEN a, GEN ord, GEN T); +GEN F2xq_pow(GEN x, GEN n, GEN pol); +GEN F2xq_sqr(GEN x,GEN pol); +GEN F2xq_sqrtn(GEN a, GEN n, GEN T, GEN *zeta); +GEN Flx_to_F2x(GEN x); +GEN ZX_to_F2x(GEN x); +GEN gener_F2xq(GEN T, GEN *po); +GEN polx_F2x(long sv); +GEN random_F2x(long d, long vs); + /* Flx.c */ GEN Fl_to_Flx(ulong x, long sv); @@ -34,6 +62,7 @@ GEN Flx_Fl_add(GEN y, ulong x, ulong p); GEN Flx_Fl_mul(GEN y, ulong x, ulong p); GEN Flx_add(GEN x, GEN y, ulong p); +int Flx_cmp1(GEN x); GEN Flx_deflate(GEN x0, long d); GEN Flx_deriv(GEN z, ulong p); GEN Flx_div_by_X_x(GEN a, ulong x, ulong p, ulong *rem); Index: src/headers/paripriv.h =================================================================== RCS file: /home/cvs/pari/src/headers/paripriv.h,v retrieving revision 1.168 diff -u -r1.168 paripriv.h --- src/headers/paripriv.h 18 Sep 2007 08:49:55 -0000 1.168 +++ src/headers/paripriv.h 5 Oct 2007 09:32:24 -0000 @@ -365,7 +365,7 @@ /* Finite field */ -enum { t_FF_FpXQ = 0, t_FF_Flxq =1 }; +enum { t_FF_FpXQ = 0, t_FF_Flxq = 1, t_FF_F2xq = 2 }; #include "parinf.h"