Peter Bruin on Fri, 10 Feb 2017 17:02:30 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
new functions FFM_deplin, FFM_indexrank, FFM_suppl etc. |
Bonjour, I am attaching a patch to add implementations of the following functions using the bb_field framework: FFM_deplin, FFM_indexrank, FFM_suppl F2xqM_deplin, F2xqM_indexrank, F2xqM_suppl FlxqM_deplin, FlxqM_indexrank, FlxqM_suppl FqM_indexrank This increases the range of basic linear algebra functions having specialised implementations for all finite field types. (Note that FqM_deplin and FqM_suppl already exist.) The new functions are very straightforward; I did modify the logic of indexrank very slightly. I also added a few tests so that the new code is completely covered by the testsuite. Here is an example showing the resulting speedup. Setup: ? t = ffgen(2017^3); ? M = matrix(120, 80, i, j, random(t)) * matrix(80, 160, i, j, random(t)); ? default(timer, 1); Before: ? matindexrank(M); time = 272 ms. ? lindep(M); *** lindep: Warning: increasing stack size to 64000000. *** lindep: Warning: increasing stack size to 128000000. *** lindep: Warning: increasing stack size to 256000000. time = 208 ms. ? matsupplement(M); time = 256 ms. After: ? matindexrank(M); time = 104 ms. ? lindep(M); time = 152 ms. ? matsupplement(M); time = 100 ms. Thanks, Peter
>From f0f65853f1422c2924fb7a6e2a577d1a4eada063 Mon Sep 17 00:00:00 2001 From: Peter Bruin <P.J.Bruin@math.leidenuniv.nl> Date: Fri, 10 Feb 2017 11:16:23 +0100 Subject: [PATCH] add FFM_deplin, FFM_indexrank, FFM_suppl and supporting functions --- src/basemath/FF.c | 36 +++++++++++++++ src/basemath/alglin1.c | 119 ++++++++++++++++++++++++++++++++++++++++++++---- src/headers/paridecl.h | 10 ++++ src/test/32/ff | 11 ++++- src/test/in/ff | 3 ++ 5 files changed, 168 insertions(+), 11 deletions(-) diff --git a/src/basemath/FF.c b/src/basemath/FF.c index c0165ca..d4d7a4a 100644 --- a/src/basemath/FF.c +++ b/src/basemath/FF.c @@ -1896,6 +1896,42 @@ FFM_image(GEN M, GEN ff) GEN FFM_inv(GEN M, GEN ff) { return FFM_wrap(M,ff, &FqM_inv,&FlxqM_inv,&F2xqM_inv); } +GEN +FFM_suppl(GEN M, GEN ff) +{ return FFM_wrap(M,ff, &FqM_suppl,&FlxqM_suppl,&F2xqM_suppl); } + +GEN +FFM_deplin(GEN M, GEN ff) +{ + pari_sp av = avma; + ulong pp; + GEN C, T, p; + _getFF(ff, &T, &p, &pp); M = FFM_to_raw(M); + switch(ff[1]) { + case t_FF_FpXQ: C = FqM_deplin(M, T, p); + if (C) C = FqC_to_FpXQC(C, T, p); break; + case t_FF_F2xq: C = F2xqM_deplin(M, T); break; + default: C = FlxqM_deplin(M, T, pp); break; + } + if (!C) { avma = av; return NULL; } + return gerepilecopy(av, raw_to_FFC(C, ff)); +} + +GEN +FFM_indexrank(GEN M, GEN ff) +{ + pari_sp av = avma; + ulong pp; + GEN R, T, p; + _getFF(ff,&T,&p,&pp); M = FFM_to_raw(M); + switch(ff[1]) { + case t_FF_FpXQ: R = FqM_indexrank(M,T,p); break; + case t_FF_F2xq: R = F2xqM_indexrank(M,T); break; + default: R = FlxqM_indexrank(M,T,pp); break; + } + return gerepileupto(av, R); +} + long FFM_rank(GEN M, GEN ff) { diff --git a/src/basemath/alglin1.c b/src/basemath/alglin1.c index af888c9..e64be2b 100644 --- a/src/basemath/alglin1.c +++ b/src/basemath/alglin1.c @@ -1399,6 +1399,12 @@ FlxqM_ker(GEN x, GEN T, ulong p) return FlxqM_ker_i(x, T, p, 0); } +GEN +FlxqM_deplin(GEN x, GEN T, ulong p) +{ + return FlxqM_ker_i(x, T, p, 1); +} + static GEN F2xqM_ker_i(GEN x, GEN T, long deplin) { @@ -1415,6 +1421,13 @@ F2xqM_ker(GEN x, GEN T) { return F2xqM_ker_i(x, T, 0); } + +GEN +F2xqM_deplin(GEN x, GEN T) +{ + return F2xqM_ker_i(x, T, 1); +} + static GEN F2xqM_gauss_pivot(GEN x, GEN T, long *rr) { @@ -2796,7 +2809,7 @@ RgV_deplin(GEN v) GEN deplin(GEN x) { - GEN p = NULL; + GEN p = NULL, ff = NULL; switch(typ(x)) { case t_MAT: break; @@ -2828,6 +2841,7 @@ deplin(GEN x) } return gerepileupto(av, x); } + if (RgM_is_FFM(x, &ff)) return FFM_deplin(x, ff); return deplin_aux(x); } /*******************************************************************/ @@ -3462,7 +3476,7 @@ GEN suppl(GEN x) { pari_sp av = avma; - GEN d, X = x, p = NULL; + GEN d, X = x, p = NULL, ff = NULL; long r; if (typ(x)!=t_MAT) pari_err_TYPE("suppl",x); @@ -3478,6 +3492,7 @@ suppl(GEN x) } return gerepileupto(av, x); } + if (RgM_is_FFM(x, &ff)) return FFM_suppl(x, ff); avma = av; init_suppl(x); d = gauss_pivot(X,&r); avma = av; return get_suppl(X,d,nbrows(X),r,&col_ei); @@ -3511,6 +3526,59 @@ F2m_suppl(GEN x) avma = av; return get_suppl(x,d,mael(x,1,1),r,&F2v_ei); } +/* variable number to be filled in later */ +static GEN +_FlxC_ei(long n, long i) +{ + GEN x = cgetg(n + 1, t_COL); + long j; + for (j = 1; j <= n; j++) + gel(x, j) = (j == i)? pol1_Flx(0): pol0_Flx(0); + return x; +} + +GEN +F2xqM_suppl(GEN x, GEN T) +{ + pari_sp av = avma; + GEN d, y; + long n = nbrows(x), r, sv = get_Flx_var(T); + + init_suppl(x); + d = F2xqM_gauss_pivot(x, T, &r); + avma = av; + y = get_suppl(x, d, n, r, &_FlxC_ei); + if (sv) { + long i, j; + for (j = r + 1; j <= n; j++) { + for (i = 1; i <= n; i++) + gcoeff(y, i, j)[1] = sv; + } + } + return y; +} + +GEN +FlxqM_suppl(GEN x, GEN T, ulong p) +{ + pari_sp av = avma; + GEN d, y; + long n = nbrows(x), r, sv = get_Flx_var(T); + + init_suppl(x); + d = FlxqM_gauss_pivot(x, T, p, &r); + avma = av; + y = get_suppl(x, d, n, r, &_FlxC_ei); + if (sv) { + long i, j; + for (j = r + 1; j <= n; j++) { + for (i = 1; i <= n; i++) + gcoeff(y, i, j)[1] = sv; + } + } + return y; +} + GEN FqM_suppl(GEN x, GEN T, GEN p) { @@ -3639,24 +3707,25 @@ init_indexrank(GEN x) { GEN indexrank(GEN x) { - pari_sp av = avma; + pari_sp av; long r; - GEN d, p = NULL; + GEN d, p = NULL, ff = NULL; if (typ(x)!=t_MAT) pari_err_TYPE("indexrank",x); - init_indexrank(x); if (RgM_is_FpM(x, &p) && p) { ulong pp; x = RgM_Fp_init(x,p,&pp); switch(pp) { - case 0: d = FpM_gauss_pivot(x,p,&r); break; - case 2: d = F2m_gauss_pivot(x,&r); break; - default:d = Flm_gauss_pivot(x,pp,&r); break; + case 0: return FpM_indexrank(x, p); + case 2: return F2m_indexrank(x); + default: return Flm_indexrank(x, pp); } } - else - d = gauss_pivot(x,&r); + if (RgM_is_FFM(x, &ff)) return FFM_indexrank(x, ff); + av = avma; + init_indexrank(x); + d = gauss_pivot(x, &r); avma = av; return indexrank0(lg(x)-1, r, d); } @@ -3689,6 +3758,36 @@ F2m_indexrank(GEN x) { } GEN +F2xqM_indexrank(GEN x, GEN T) { + pari_sp av = avma; + long r; + GEN d; + init_indexrank(x); + d = F2xqM_gauss_pivot(x, T, &r); + avma = av; return indexrank0(lg(x) - 1, r, d); +} + +GEN +FlxqM_indexrank(GEN x, GEN T, ulong p) { + pari_sp av = avma; + long r; + GEN d; + init_indexrank(x); + d = FlxqM_gauss_pivot(x, T, p, &r); + avma = av; return indexrank0(lg(x) - 1, r, d); +} + +GEN +FqM_indexrank(GEN x, GEN T, GEN p) { + pari_sp av = avma; + long r; + GEN d; + init_indexrank(x); + d = FqM_gauss_pivot(x, T, p, &r); + avma = av; return indexrank0(lg(x) - 1, r, d); +} + +GEN ZM_indeximage(GEN x) { pari_sp av = avma; long r; diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h index 0660119..2fc07ff 100644 --- a/src/headers/paridecl.h +++ b/src/headers/paridecl.h @@ -1360,14 +1360,17 @@ GEN F2m_suppl(GEN x); GEN F2xqM_F2xqC_gauss(GEN a, GEN b, GEN T); GEN F2xqM_F2xqC_invimage(GEN a, GEN b, GEN T); GEN F2xqM_F2xqC_mul(GEN a, GEN b, GEN T); +GEN F2xqM_deplin(GEN x, GEN T); GEN F2xqM_det(GEN a, GEN T); GEN F2xqM_gauss(GEN a, GEN b, GEN T); GEN F2xqM_ker(GEN x, GEN T); GEN F2xqM_image(GEN x, GEN T); +GEN F2xqM_indexrank(GEN x, GEN T); GEN F2xqM_inv(GEN a, GEN T); GEN F2xqM_invimage(GEN a, GEN b, GEN T); GEN F2xqM_mul(GEN a, GEN b, GEN T); long F2xqM_rank(GEN x, GEN T); +GEN F2xqM_suppl(GEN x, GEN T); GEN Flm_Flc_gauss(GEN a, GEN b, ulong p); GEN Flm_Flc_invimage(GEN mat, GEN y, ulong p); GEN Flm_deplin(GEN x, ulong p); @@ -1386,14 +1389,17 @@ GEN Flm_suppl(GEN x, ulong p); GEN FlxqM_FlxqC_gauss(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_FlxqC_invimage(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_FlxqC_mul(GEN a, GEN b, GEN T, ulong p); +GEN FlxqM_deplin(GEN x, GEN T, ulong p); GEN FlxqM_det(GEN a, GEN T, ulong p); GEN FlxqM_gauss(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_ker(GEN x, GEN T, ulong p); GEN FlxqM_image(GEN x, GEN T, ulong p); +GEN FlxqM_indexrank(GEN x, GEN T, ulong p); GEN FlxqM_inv(GEN x, GEN T, ulong p); GEN FlxqM_invimage(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_mul(GEN a, GEN b, GEN T, ulong p); long FlxqM_rank(GEN x, GEN T, ulong p); +GEN FlxqM_suppl(GEN x, GEN T, ulong p); GEN FpM_FpC_gauss(GEN a, GEN b, GEN p); GEN FpM_FpC_invimage(GEN m, GEN v, GEN p); GEN FpM_deplin(GEN x, GEN p); @@ -1415,6 +1421,7 @@ GEN FqM_det(GEN x, GEN T, GEN p); GEN FqM_gauss(GEN a, GEN b, GEN T, GEN p); GEN FqM_ker(GEN x, GEN T, GEN p); GEN FqM_image(GEN x, GEN T, GEN p); +GEN FqM_indexrank(GEN x, GEN T, GEN p); GEN FqM_inv(GEN x, GEN T, GEN p); GEN FqM_invimage(GEN a, GEN b, GEN T, GEN p); GEN FqM_mul(GEN a, GEN b, GEN T, GEN p); @@ -2969,14 +2976,17 @@ GEN FF_zero(GEN a); GEN FFM_FFC_invimage(GEN M, GEN C, GEN ff); GEN FFM_FFC_gauss(GEN M, GEN C, GEN ff); GEN FFM_FFC_mul(GEN M, GEN C, GEN ff); +GEN FFM_deplin(GEN M, GEN ff); GEN FFM_det(GEN M, GEN ff); GEN FFM_gauss(GEN M, GEN N, GEN ff); GEN FFM_image(GEN M, GEN ff); +GEN FFM_indexrank(GEN M, GEN ff); GEN FFM_inv(GEN M, GEN ff); GEN FFM_invimage(GEN M, GEN N, GEN ff); GEN FFM_ker(GEN M, GEN ff); GEN FFM_mul(GEN M, GEN N, GEN ff); long FFM_rank(GEN M, GEN ff); +GEN FFM_suppl(GEN M, GEN ff); GEN FFX_factor(GEN f, GEN x); GEN FFX_roots(GEN f, GEN x); GEN FqX_to_FFX(GEN x, GEN ff); diff --git a/src/test/32/ff b/src/test/32/ff index cf08fa6..101e9dc 100644 --- a/src/test/32/ff +++ b/src/test/32/ff @@ -187,7 +187,7 @@ Mod(6687681666819568403, 18446744073944432641) ? conjvec(Mod(x,x^2+Mod(1,3))) [Mod(Mod(1, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3)), Mod(Mod(2, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3))]~ -? test(q)=my(t=ffgen(q,'t),m=[t,t^2,1+t^3;1+t,1+t^2,1+t^3]);print(matker(m));print(matimage(m));print(matrank(m));my(M=[t,2*t^0,3*t^0;t,t^2,1+t^3;1+t,1+t^2,1+t^3]);print(matdet(M));print(M^(-1)*M);my(v=[t^0,t^1,t^2]~);print(M*v);print(M*matsolve(M,v)==v);print(M*matinverseimage(M,v)==v);print(matsolve(M,matid(3)*t^0)==M^(-1));print(matinverseimage(M,matid(3)*t^0)==M^(-1));my(N=t*[0,1;0,0]);iferr(N^-1,e,,errname(e)=="e_INV");iferr(matsolve(N,t*[0,1]~),e,,errname(e)=="e_INV");print(matinverseimage(N,t*[1,0]~));print(matinverseimage(N,t*[0,1]~));print(matinverseimage(N,N^0)); +? test(q)=my(t=ffgen(q,'t),m=[t,t^2,1+t^3;1+t,1+t^2,1+t^3]);print(matker(m));print(matimage(m));print(matrank(m));my(M=[t,2*t^0,3*t^0;t,t^2,1+t^3;1+t,1+t^2,1+t^3]);print(matdet(M));print(M^(-1)*M);my(v=[t^0,t^1,t^2]~);print(M*v);print(M*matsolve(M,v)==v);print(M*matinverseimage(M,v)==v);print(matsolve(M,matid(3)*t^0)==M^(-1));print(matinverseimage(M,matid(3)*t^0)==M^(-1));my(N=t*[0,1;0,0]);iferr(N^-1,e,,errname(e)=="e_INV");iferr(matsolve(N,t*[0,1]~),e,,errname(e)=="e_INV");print(matinverseimage(N,t*[1,0]~));print(matinverseimage(N,t*[0,1]~));print(matinverseimage(N,N^0));print(matindexrank(N));print(matsupplement(t*[0;1]));print(lindep(t*[0,0;1,1])); ? test(2^5) [t^4 + t^3; t^4 + t^3; 1] [t, t^2; t + 1, t^2 + 1] @@ -202,6 +202,9 @@ t^4 + t^2 [0, 1]~ []~ [;] +[Vecsmall([1]), Vecsmall([2])] +[0, 1; t, 0] +[1, 1]~ ? test(7^5) [3*t^4 + 5*t^3 + 6*t^2 + 2*t; 4*t^4 + 2*t^3 + t^2 + 5*t; 1] [t, t^2; t + 1, t^2 + 1] @@ -216,6 +219,9 @@ t^4 + t^2 [0, 1]~ []~ [;] +[Vecsmall([1]), Vecsmall([2])] +[0, 1; t, 0] +[6, 1]~ ? test((2^64+13)^5) [3*t^4 + 5*t^3 + 18446744073709551621*t^2 + 18446744073709551617*t; 18446744 073709551626*t^4 + 18446744073709551624*t^3 + 8*t^2 + 12*t; 1] @@ -233,6 +239,9 @@ t^4 + t^2 [0, 1]~ []~ [;] +[Vecsmall([1]), Vecsmall([2])] +[0, 1; t, 0] +[18446744073709551628, 1]~ ? test(q)=my(t=ffgen(q,'t),M=matrix(10,10,i,j,random(t)));subst(charpoly(M),'x,M)==0; ? test(nextprime(2^7)^5) 1 diff --git a/src/test/in/ff b/src/test/in/ff index 94bd6ab..ae4555e 100644 --- a/src/test/in/ff +++ b/src/test/in/ff @@ -82,6 +82,9 @@ test(q)= print(matinverseimage(N, t*[1, 0]~)); print(matinverseimage(N, t*[0, 1]~)); print(matinverseimage(N, N^0)); + print(matindexrank(N)); + print(matsupplement(t*[0; 1])); + print(lindep(t*[0, 0; 1, 1])); } test(2^5) test(7^5) -- 1.7.9.5