Peter Bruin on Fri, 28 Mar 2014 16:08:15 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
patch for finite field versions of matinverseimage |
Hello, Some time ago I mentioned having written some functions to speed up matinverseimage for matrices/vectors with t_FFELT entries. I polished the code a bit and added some tests that should cover all new functions; see the attached patch. I realise that the functions gen_matinvimage and gen_matcolinvimage (where the real work is done) is still written in a way that would ideally be replaced by more standard primitives, as in Karim's message quoted below. Since I don't have that much time to spare at the moment, I thought I would just send the patch as it is, hoping it is still useful enough. Thanks, Peter
diff --git a/doc/develop.tex b/doc/develop.tex index a711cec..0cafc15 100644 --- a/doc/develop.tex +++ b/doc/develop.tex @@ -432,10 +432,14 @@ fields: \fun{GEN}{gen_ker}{GEN x, long deplin, void *E, const struct bb_field *ff} +\fun{GEN}{gen_matcolinvimage}{GEN a, GEN b, void *E, const struct bb_field *ff} + \fun{GEN}{gen_matcolmul}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_matid}{long n, void *E, const struct bb_field *ff} +\fun{GEN}{gen_matinvimage}{GEN a, GEN b, void *E, const struct bb_field *ff} + \fun{GEN}{gen_matmul}{GEN a, GEN b, void *E, const struct bb_field *ff} \subsec{Functions returning black box fields} diff --git a/doc/usersch5.tex b/doc/usersch5.tex index d115321..81fca52 100644 --- a/doc/usersch5.tex +++ b/doc/usersch5.tex @@ -3454,6 +3454,8 @@ as \kbd{gauss}, where $b$ is a \kbd{FqM}. \fun{GEN}{FqM_FqC_gauss}{GEN a, GEN b, GEN T, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FqC}. +\fun{GEN}{FqM_FqC_invimage}{GEN a, GEN b, GEN T, GEN p} + \fun{GEN}{FqM_FqC_mul}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqM_ker}{GEN x, GEN T, GEN p} as \kbd{ker} @@ -3463,6 +3465,8 @@ as \kbd{gauss}, where $b$ is a \kbd{FqC}. \fun{GEN}{FqM_inv}{GEN x, GEN T, GEN p} returns the inverse of \kbd{x}, or \kbd{NULL} if \kbd{x} is not invertible. +\fun{GEN}{FqM_invimage}{GEN a, GEN b, GEN T, GEN p} + \fun{GEN}{FqM_mul}{GEN a, GEN b, GEN T, GEN p} \fun{long}{FqM_rank}{GEN x, GEN T, GEN p} as \kbd{rank} @@ -3740,6 +3744,8 @@ and \kbd{y} \fun{GEN}{FlxqM_FlxqC_gauss}{GEN a, GEN b, GEN T, ulong p} +\fun{GEN}{FlxqM_FlxqC_invimage}{GEN a, GEN b, GEN T, ulong p} + \fun{GEN}{FlxqM_FlxqC_mul}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_ker}{GEN x, GEN T, ulong p} @@ -3750,6 +3756,8 @@ and \kbd{y} \fun{GEN}{FlxqM_inv}{GEN x, GEN T, ulong p} +\fun{GEN}{FlxqM_invimage}{GEN a, GEN b, GEN T, ulong p} + \fun{GEN}{FlxqM_mul}{GEN a, GEN b, GEN T, ulong p} \fun{long}{FlxqM_rank}{GEN x, GEN T, ulong p} @@ -5120,6 +5128,8 @@ $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_2[X]/T(X)$. \subsec{\kbd{F2xqV}, \kbd{F2xqM}}. See \kbd{FqV}, \kbd{FqM} operations. +\fun{GEN}{F2xqM_F2xqC_invimage}{GEN a, GEN b, GEN T} + \fun{GEN}{F2xqM_F2xqC_mul}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_ker}{GEN x, GEN T} @@ -5130,6 +5140,8 @@ $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_2[X]/T(X)$. \fun{GEN}{F2xqM_inv}{GEN a, GEN T} +\fun{GEN}{F2xqM_invimage}{GEN a, GEN b, GEN T} + \fun{GEN}{F2xqM_mul}{GEN a, GEN b, GEN T} \fun{long}{F2xqM_rank}{GEN x, GEN T} @@ -9296,6 +9308,11 @@ of the univariate polynomial \kbd{f} over the definition field of the \typ{FFELT} \kbd{a}. The coefficients of \kbd{f} must be of type \typ{INT}, \typ{INTMOD} or \typ{FFELT} and compatible with \kbd{a}. +\fun{GEN}{FFM_FFC_invimage}{GEN M, GEN C, GEN ff} given a matrix +\kbd{M} (\typ{MAT}) and a column vector \kbd{C} (\typ{COL}) over the +finite field given by \kbd{ff} (\typ{FFELT}), return a column vector +\kbd{X} such that $MX=C$, or \kbd{NULL} if no such vector exists. + \fun{GEN}{FFM_FFC_mul}{GEN M, GEN C, GEN ff} returns the product of the matrix~\kbd{M} (\typ{MAT}) and the column vector~\kbd{C} (\typ{COL}) over the finite field given by \kbd{ff} (\typ{FFELT}). @@ -9310,6 +9327,11 @@ by \tet{RgM_is_FFM(M,\&ff)}). \fun{GEN}{FFM_inv}{GEN M, GEN ff} +\fun{GEN}{FFM_invimage}{GEN M, GEN N, GEN ff} given two matrices +\kbd{M} and~\kbd{N} (\typ{MAT}) over the finite field given by +\kbd{ff} (\typ{FFELT}), return a matrix \kbd{X} such that $MX=N$, or +\kbd{NULL} if no such matrix exists. + \fun{GEN}{FFM_mul}{GEN M, GEN N, GEN ff} returns the product of the matrices \kbd{M} and~\kbd{N} (\typ{MAT}) over the finite field given by \kbd{ff} (\typ{FFELT}). diff --git a/src/basemath/FF.c b/src/basemath/FF.c index 1dfb9aa..1bf0a51 100644 --- a/src/basemath/FF.c +++ b/src/basemath/FF.c @@ -1681,6 +1681,7 @@ FqM_to_FpXQM(GEN x, GEN T) return y; } +/* for functions t_MAT -> t_MAT */ static GEN FFM_wrap(GEN M, GEN ff, GEN (*Fq)(GEN,GEN,GEN), GEN (*Flxq)(GEN,GEN,ulong), @@ -1698,6 +1699,53 @@ FFM_wrap(GEN M, GEN ff, GEN (*Fq)(GEN,GEN,GEN), } return gerepilecopy(av, raw_to_FFM(M, ff)); } + +/* for functions (t_MAT, t_MAT) -> t_MAT */ +static GEN +FFM_FFM_wrap(GEN M, GEN N, GEN ff, + GEN (*Fq)(GEN, GEN, GEN, GEN), + GEN (*Flxq)(GEN, GEN, GEN, ulong), + GEN (*F2xq)(GEN, GEN, GEN)) +{ + pari_sp av = avma; + ulong pp; + GEN T, p; + _getFF(ff, &T, &p, &pp); + M = FFM_to_raw(M); + N = FFM_to_raw(N); + switch(ff[1]) + { + case t_FF_FpXQ: M = FqM_to_FpXQM(Fq(M, N, T, p), T); break; + case t_FF_F2xq: M = F2xq(M, N, T); break; + default: M = Flxq(M, N, T, pp); break; + } + if (M == NULL) return NULL; + return gerepilecopy(av, raw_to_FFM(M, ff)); +} + +/* for functions (t_MAT, t_COL) -> t_COL */ +static GEN +FFM_FFC_wrap(GEN M, GEN C, GEN ff, + GEN (*Fq)(GEN, GEN, GEN, GEN), + GEN (*Flxq)(GEN, GEN, GEN, ulong), + GEN (*F2xq)(GEN, GEN, GEN)) +{ + pari_sp av = avma; + ulong pp; + GEN T, p; + _getFF(ff, &T, &p, &pp); + M = FFM_to_raw(M); + C = FFC_to_raw(C); + switch(ff[1]) + { + case t_FF_FpXQ: C = FqC_to_FpXQC(Fq(M, C, T, p), T); break; + case t_FF_F2xq: C = F2xq(M, C, T); break; + default: C = Flxq(M, C, T, pp); break; + } + if (C == NULL) return NULL; + return gerepilecopy(av, raw_to_FFC(C, ff)); +} + GEN FFM_ker(GEN M, GEN ff) { return FFM_wrap(M,ff, &FqM_ker,&FlxqM_ker,&F2xqM_ker); } @@ -1740,37 +1788,26 @@ FFM_det(GEN M, GEN ff) } GEN +FFM_FFC_invimage(GEN M, GEN C, GEN ff) +{ + return FFM_FFC_wrap(M, C, ff, &FqM_FqC_invimage, + &FlxqM_FlxqC_invimage, &F2xqM_F2xqC_invimage); +} + +GEN +FFM_invimage(GEN M, GEN N, GEN ff) +{ + return FFM_FFM_wrap(M, N, ff, &FqM_invimage, &FlxqM_invimage, &F2xqM_invimage); +} + +GEN FFM_FFC_mul(GEN M, GEN C, GEN ff) { - pari_sp av = avma; - ulong pp; - GEN P, T, p; - _getFF(ff, &T, &p, &pp); - M = FFM_to_raw(M); - C = FFC_to_raw(C); - switch (ff[1]) - { - case t_FF_FpXQ: P = FqM_FqC_mul(M, C, T, p); break; - case t_FF_F2xq: P = F2xqM_F2xqC_mul(M, C, T); break; - default: P = FlxqM_FlxqC_mul(M, C, T, pp); break; - } - return gerepilecopy(av, raw_to_FFC(P, ff)); + return FFM_FFC_wrap(M, C, ff, &FqM_FqC_mul, &FlxqM_FlxqC_mul, &F2xqM_F2xqC_mul); } GEN FFM_mul(GEN M, GEN N, GEN ff) { - pari_sp av = avma; - ulong pp; - GEN P, T, p; - _getFF(ff, &T, &p, &pp); - M = FFM_to_raw(M); - N = FFM_to_raw(N); - switch (ff[1]) - { - case t_FF_FpXQ: P = FqM_mul(M, N, T, p); break; - case t_FF_F2xq: P = F2xqM_mul(M, N, T); break; - default: P = FlxqM_mul(M, N, T, pp); break; - } - return gerepilecopy(av, raw_to_FFM(P, ff)); + return FFM_FFM_wrap(M, N, ff, &FqM_mul, &FlxqM_mul, &F2xqM_mul); } diff --git a/src/basemath/alglin1.c b/src/basemath/alglin1.c index d3868dc..dad10a8 100644 --- a/src/basemath/alglin1.c +++ b/src/basemath/alglin1.c @@ -408,6 +408,107 @@ gen_matmul(GEN A, GEN B, void *E, const struct bb_field *ff) } static GEN +gen_colneg(GEN A, void *E, const struct bb_field *ff) +{ + long i, l; + GEN B = cgetg_copy(A, &l); + for (i = 1; i < l; i++) + gel(B, i) = ff->neg(E, gel(A, i)); + return B; +} + +static GEN +gen_matneg(GEN A, void *E, const struct bb_field *ff) +{ + long i, l; + GEN B = cgetg_copy(A, &l); + for (i = 1; i < l; i++) + gel(B, i) = gen_colneg(gel(A, i), E, ff); + return B; +} + +/* assume dim A >= 1, A invertible + upper triangular */ +static GEN +gen_matinv_upper_ind(GEN A, long index, void *E, const struct bb_field *ff) +{ + long n = lg(A) - 1, i, j; + GEN u = cgetg(n + 1, t_COL); + for (i = n; i > index; i--) + gel(u, i) = ff->s(E, 0); + gel(u, i) = ff->inv(E, gcoeff(A, i, i)); + for (i--; i > 0; i--) { + pari_sp av = avma; + GEN m = ff->neg(E, ff->mul(E, gcoeff(A, i, i + 1), gel(u, i + 1))); + for (j = i + 2; j <= n; j++) + m = ff->add(E, m, ff->neg(E, ff->mul(E, gcoeff(A, i, j), gel(u, j)))); + gel(u, i) = gerepileupto(av, ff->red(E, ff->mul(E, m, ff->inv(E, gcoeff(A, i, i))))); + } + return u; +} + +static GEN +gen_matinv_upper(GEN A, void *E, const struct bb_field *ff) +{ + long i, l; + GEN B = cgetg_copy(A, &l); + for (i = 1; i < l; i++) + gel(B,i) = gen_matinv_upper_ind(A, i, E, ff); + return B; +} + +/* find z such that A z = y. Return NULL if no solution */ +GEN +gen_matcolinvimage(GEN A, GEN y, void *E, const struct bb_field *ff) +{ + pari_sp av = avma; + long i, l = lg(A); + GEN M, x, t; + + M = gen_ker(shallowconcat(A, y), 0, E, ff); + i = lg(M) - 1; + if (!i) { avma = av; return NULL; } + + x = gel(M, i); + t = gel(x, l); + if (ff->equal0(t)) { avma = av; return NULL; } + + t = ff->neg(E, ff->inv(E, t)); + setlg(x, l); + for (i = 1; i < l; i++) + gel(x, i) = ff->red(E, ff->mul(E, t, gel(x, i))); + return gerepilecopy(av, x); +} + +/* find Z such that A Z = B. Return NULL if no solution */ +GEN +gen_matinvimage(GEN A, GEN B, void *E, const struct bb_field *ff) +{ + pari_sp av = avma; + GEN d, x, X, Y; + long i, j, nY, nA, nB; + x = gen_ker(shallowconcat(gen_matneg(A, E, ff), B), 0, E, ff); + /* AX = BY, Y in strict upper echelon form with pivots = 1. + * We must find T such that Y T = Id_nB then X T = Z. This exists + * iff Y has at least nB columns and full rank. */ + nY = lg(x) - 1; + nB = lg(B) - 1; + if (nY < nB) { avma = av; return NULL; } + nA = lg(A) - 1; + Y = rowslice(x, nA + 1, nA + nB); /* nB rows */ + d = cgetg(nB + 1, t_VECSMALL); + for (i = nB, j = nY; i >= 1; i--) { + for (; j >= 1; j--) + if (!ff->equal0(gcoeff(Y, i, j))) { d[i] = j; break; } + if (!j) { avma = av; return NULL; } + } + /* reduce to the case Y square, upper triangular with 1s on diagonal */ + Y = vecpermute(Y, d); + x = vecpermute(x, d); + X = rowslice(x, 1, nA); + return gerepileupto(av, gen_matmul(X, gen_matinv_upper(Y, E, ff), E, ff)); +} + +static GEN image_from_pivot(GEN x, GEN d, long r) { GEN y; @@ -966,20 +1067,34 @@ FlxqM_det(GEN a, GEN T, ulong p) } GEN -FlxqM_FlxqC_mul(GEN A, GEN B, GEN T, unsigned long p) { +FlxqM_FlxqC_invimage(GEN A, GEN B, GEN T, ulong p) { + void *E; + const struct bb_field *ff = get_Flxq_field(&E, T, p); + return gen_matcolinvimage(A, B, E, ff); +} + +GEN +FlxqM_FlxqC_mul(GEN A, GEN B, GEN T, ulong p) { void *E; const struct bb_field *ff = get_Flxq_field(&E, T, p); return gen_matcolmul(A, B, E, ff); } GEN -FlxqM_mul(GEN A, GEN B, GEN T, unsigned long p) { +FlxqM_mul(GEN A, GEN B, GEN T, ulong p) { void *E; const struct bb_field *ff = get_Flxq_field(&E, T, p); return gen_matmul(A, B, E, ff); } GEN +FlxqM_invimage(GEN A, GEN B, GEN T, ulong p) { + void *E; + const struct bb_field *ff = get_Flxq_field(&E, T, p); + return gen_matinvimage(A, B, E, ff); +} + +GEN F2xqM_det(GEN a, GEN T) { void *E; @@ -1007,6 +1122,13 @@ F2xqM_inv(GEN a, GEN T) } GEN +F2xqM_F2xqC_invimage(GEN A, GEN B, GEN T) { + void *E; + const struct bb_field *ff = get_F2xq_field(&E, T); + return gen_matcolinvimage(A, B, E, ff); +} + +GEN F2xqM_F2xqC_mul(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); @@ -1020,6 +1142,13 @@ F2xqM_mul(GEN A, GEN B, GEN T) { return gen_matmul(A, B, E, ff); } +GEN +F2xqM_invimage(GEN A, GEN B, GEN T) { + void *E; + const struct bb_field *ff = get_F2xq_field(&E, T); + return gen_matinvimage(A, B, E, ff); +} + static GEN FqM_gauss_pivot_gen(GEN x, GEN T, GEN p, long *rr) { @@ -1069,6 +1198,13 @@ FqM_det(GEN x, GEN T, GEN p) } GEN +FqM_FqC_invimage(GEN A, GEN B, GEN T, GEN p) { + void *E; + const struct bb_field *ff = get_Fq_field(&E, T, p); + return gen_matcolinvimage(A, B, E, ff); +} + +GEN FqM_FqC_mul(GEN A, GEN B, GEN T, GEN p) { void *E; const struct bb_field *ff = get_Fq_field(&E, T, p); @@ -1082,6 +1218,13 @@ FqM_mul(GEN A, GEN B, GEN T, GEN p) { return gen_matmul(A, B, E, ff); } +GEN +FqM_invimage(GEN A, GEN B, GEN T, GEN p) { + void *E; + const struct bb_field *ff = get_Fq_field(&E, T, p); + return gen_matinvimage(A, B, E, ff); +} + static GEN FpM_ker_gen(GEN x, GEN p, long deplin) { @@ -2867,6 +3010,8 @@ RgM_RgC_invimage(GEN A, GEN y) long i, l = lg(A); GEN M, x, t, p = NULL; + if (l==1) return NULL; + if (lg(y) != lgcols(A)) pari_err_DIM("inverseimage"); if (RgM_is_FpM(A, &p) && RgV_is_FpV(y, &p) && p) { ulong pp; @@ -2891,9 +3036,11 @@ RgM_RgC_invimage(GEN A, GEN y) if (!x) { avma = av; return NULL; } return gerepileupto(av, x); } - - if (l==1) return NULL; - if (lg(y) != lgcols(A)) pari_err_DIM("inverseimage"); + { + GEN ff = NULL; + if (RgM_is_FFM(A, &ff) && RgC_is_FFC(y, &ff)) + return FFM_FFC_invimage(A, y, ff); + } M = ker(shallowconcat(A, y)); i = lg(M)-1; if (!i) { avma = av; return NULL; } @@ -3137,6 +3284,11 @@ RgM_invimage(GEN A, GEN B) if (!x) { avma = av; return NULL; } return gerepileupto(av, x); } + { + GEN ff = NULL; + if (RgM_is_FFM(A, &ff) && RgM_is_FFM(B, &ff)) + return FFM_invimage(A, B, ff); + } x = ker(shallowconcat(RgM_neg(A), B)); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists iff diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h index f360963..2cbf0b7 100644 --- a/src/headers/paridecl.h +++ b/src/headers/paridecl.h @@ -969,11 +969,13 @@ GEN F2m_ker(GEN x); GEN F2m_ker_sp(GEN x, long deplin); long F2m_rank(GEN x); GEN F2m_suppl(GEN x); +GEN F2xqM_F2xqC_invimage(GEN a, GEN b, GEN T); GEN F2xqM_F2xqC_mul(GEN a, GEN b, GEN T); GEN F2xqM_det(GEN a, GEN T); GEN F2xqM_ker(GEN x, GEN T); GEN F2xqM_image(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 Flm_Flc_gauss(GEN a, GEN b, ulong p); @@ -991,12 +993,14 @@ GEN Flm_ker_sp(GEN x, ulong p, long deplin); long Flm_rank(GEN x, ulong p); 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_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_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 FpM_FpC_gauss(GEN a, GEN b, GEN p); @@ -1013,6 +1017,7 @@ GEN FpM_ker(GEN x, GEN p); long FpM_rank(GEN x, GEN p); GEN FpM_suppl(GEN x, GEN p); GEN FqM_FqC_gauss(GEN a, GEN b, GEN T, GEN p); +GEN FqM_FqC_invimage(GEN a, GEN b, GEN T, GEN p); GEN FqM_FqC_mul(GEN a, GEN b, GEN T, GEN p); GEN FqM_deplin(GEN x, GEN T, GEN p); GEN FqM_det(GEN x, GEN T, GEN p); @@ -1020,6 +1025,7 @@ 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_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); long FqM_rank(GEN a, GEN T, GEN p); GEN FqM_suppl(GEN x, GEN T, GEN p); @@ -1056,7 +1062,9 @@ GEN gen_Gauss(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff); GEN gen_det(GEN a, void *E, const struct bb_field *ff); GEN gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff); +GEN gen_matcolinvimage(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_matcolmul(GEN a, GEN b, void *E, const struct bb_field *ff); +GEN gen_matinvimage(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_matmul(GEN a, GEN b, void *E, const struct bb_field *ff); GEN image(GEN x); GEN image2(GEN x); @@ -2227,10 +2235,12 @@ GEN FF_to_FpXQ(GEN x); GEN FF_to_FpXQ_i(GEN x); GEN FF_trace(GEN x); GEN FF_zero(GEN a); +GEN FFM_FFC_invimage(GEN M, GEN C, GEN ff); GEN FFM_FFC_mul(GEN M, GEN C, GEN ff); GEN FFM_det(GEN M, GEN ff); GEN FFM_image(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); diff --git a/src/test/32/ff b/src/test/32/ff index d6333d6..6755757 100644 --- a/src/test/32/ff +++ b/src/test/32/ff @@ -240,21 +240,26 @@ t^2 + Mod(1, 5)*t + Mod(3, 5))*x^3 + Mod(Mod(0, 5), Mod(1, 5)*t^4 + Mod(1, 5 od(4, 5)*t, Mod(1, 5)*t^4 + Mod(1, 5)*t^3 + Mod(2, 5)*t^2 + Mod(1, 5)*t + Mo d(3, 5)) 1] -? 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); +? 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);print(matinverseimage(M,matid(3)*t^0)==M^(-1));my(v=[t^0,t^1,t^2]~);print(M*v);print(matinverseimage(M,v)); ? test(2^5) [t^4 + t^3; t^4 + t^3; 1] [t, t^2; t + 1, t^2 + 1] 2 t^4 + t^2 [1, 0, 0; 0, 1, 0; 0, 0, 1] +1 [t^2 + t, t^4 + t^3 + 1, t^4 + t^3 + t]~ +[t^4, t^4 + t^2 + t, t^4 + t^2 + t]~ ? 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] 2 6*t^4 + 2*t^3 + 4*t^2 + 2*t + 2 [1, 0, 0; 0, 1, 0; 0, 0, 1] +1 [3*t^2 + 3*t, 6*t^4 + 5*t^3 + 4*t^2 + 5*t + 6, 6*t^4 + 5*t^3 + 4*t^2 + 6*t]~ +[6*t^4 + 3*t^2 + 4*t + 1, t^4 + 5*t^2 + 2*t + 6, 6*t^4 + 5*t^3 + t^2 + 2*t + + 3]~ ? 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] @@ -262,9 +267,15 @@ t^4 + t^2 2 18446744073709551628*t^4 + 2*t^3 + 18446744073709551626*t^2 + 2*t + 2 [1, 0, 0; 0, 1, 0; 0, 0, 1] +1 [3*t^2 + 3*t, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 1844674407370955162 7*t + 18446744073709551628, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 18446 744073709551628*t]~ +[3488353224204417687*t^4 + 4892000116800957185*t^3 + 9053107177101941144*t^2 + + 13820523250181311982*t + 390363336994303883, 14958390849505133942*t^4 + 1 +3554743956908594444*t^3 + 9393636896607610486*t^2 + 4626220823528239646*t + +18056380736715247746, 8006601209840615835*t^4 + 7890322769033801912*t^3 + 16 +386954550845990710*t^2 + 274084896187489962*t + 13720856015204042904]~ ? p=2^64+13;g=ffprimroot(ffgen(p^2),&o);a=2*g^0; ? v=[I,-1,Mat(1),matid(2)/2]; ? for(i=1,#v,print(iferr(fflog(a,g,v[i]),E,E))); diff --git a/src/test/64/ff b/src/test/64/ff index 2b163ca..69ea16b 100644 --- a/src/test/64/ff +++ b/src/test/64/ff @@ -243,21 +243,26 @@ t^2 + Mod(1, 5)*t + Mod(3, 5))*x^3 + Mod(Mod(0, 5), Mod(1, 5)*t^4 + Mod(1, 5 od(4, 5)*t, Mod(1, 5)*t^4 + Mod(1, 5)*t^3 + Mod(2, 5)*t^2 + Mod(1, 5)*t + Mo d(3, 5)) 1] -? 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); +? 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);print(matinverseimage(M,matid(3)*t^0)==M^(-1));my(v=[t^0,t^1,t^2]~);print(M*v);print(matinverseimage(M,v)); ? test(2^5) [t^4 + t^3; t^4 + t^3; 1] [t, t^2; t + 1, t^2 + 1] 2 t^4 + t^2 [1, 0, 0; 0, 1, 0; 0, 0, 1] +1 [t^2 + t, t^4 + t^3 + 1, t^4 + t^3 + t]~ +[t^4, t^4 + t^2 + t, t^4 + t^2 + t]~ ? 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] 2 6*t^4 + 2*t^3 + 4*t^2 + 2*t + 2 [1, 0, 0; 0, 1, 0; 0, 0, 1] +1 [3*t^2 + 3*t, 6*t^4 + 5*t^3 + 4*t^2 + 5*t + 6, 6*t^4 + 5*t^3 + 4*t^2 + 6*t]~ +[6*t^4 + 3*t^2 + 4*t + 1, t^4 + 5*t^2 + 2*t + 6, 6*t^4 + 5*t^3 + t^2 + 2*t + + 3]~ ? 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] @@ -265,9 +270,15 @@ t^4 + t^2 2 18446744073709551628*t^4 + 2*t^3 + 18446744073709551626*t^2 + 2*t + 2 [1, 0, 0; 0, 1, 0; 0, 0, 1] +1 [3*t^2 + 3*t, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 1844674407370955162 7*t + 18446744073709551628, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 18446 744073709551628*t]~ +[3488353224204417687*t^4 + 4892000116800957185*t^3 + 9053107177101941144*t^2 + + 13820523250181311982*t + 390363336994303883, 14958390849505133942*t^4 + 1 +3554743956908594444*t^3 + 9393636896607610486*t^2 + 4626220823528239646*t + +18056380736715247746, 8006601209840615835*t^4 + 7890322769033801912*t^3 + 16 +386954550845990710*t^2 + 274084896187489962*t + 13720856015204042904]~ ? p=2^64+13;g=ffprimroot(ffgen(p^2),&o);a=2*g^0; ? v=[I,-1,Mat(1),matid(2)/2]; ? for(i=1,#v,print(iferr(fflog(a,g,v[i]),E,E))); diff --git a/src/test/in/ff b/src/test/in/ff index 6404029..2f6b98e 100644 --- a/src/test/in/ff +++ b/src/test/in/ff @@ -95,8 +95,10 @@ test(q)= 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); + print(matinverseimage(M, matid(3)*t^0) == M^(-1)); my(v = [t^0, t^1, t^2]~); print(M*v); + print(matinverseimage(M, v)); } test(2^5) test(7^5)
Karim Belabas wrote: > As a matter of fact, it's a little sad that we have so many "Gauss > pivot" variants as primitives, instead of standard algorithms, > e.g. LUP factorization. Currently > > - RgM_pivots (allow image / supplement / rank profile) > - gauss_pivot_ker (analogous but more expensive, allow kernel) > - gauss (compute A^(-1) B) > > Other operations are then implemented in terms of these non-standard > primitives. (e.g. inverseimage reduces to kernel). These 3 are not too > complicated, and share most non-trivial code (pivot search), but > various minor optimizations related to memory use made them diverge > (e.g. avoid a few operations, specialized gerepile). > > General linear algebra over fields has never been a strong focus of > PARI, but cleaning up this set of ad hoc historical functions would be > useful. Again it's a bit sad that domain specialization (allowing > large efficiency gains!) occured before that cleanup. As I see it, we > could > > - merge RgM_pivots / gauss_pivot_ker > > - replace gauss(A,B) by a proper PA = LU + (independent) > back-substitution to solve triangular linear systems associated to > B. This would allow to implement matinverseimage directly (more > efficiently for fixed A and varying B), without reducing to ker().