| Bill Allombert on Sun, 07 Feb 2010 19:28:31 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| forqfvec (iterative qfminim) |
Hello PARI developers, Please find an experimental patch that provide a function forqfvec that allow to iterate on the vectors that qfminim would returns. This was suggested by Ariel Pacetti. This is the synopsis: forqfvec(v,q,b,expr): q being a square and symmetric matrix representing a positive definite quadratic form, evaluate expr for all vector v such that q(v)<b. Some example of use: my(s);forqfvecsmall(v,matid(8),30,s+=Vec(v));s ## my(s);forqfvecsmall(v,matid(8),,s+=Vec(v));s ## my(s);forqfvecsmall(v,matid(8),30,if(s++<10,print(v))); ## forqfvecsmall(v,matid(8),,return(Vec(v))) Comments welcome! Cheers, Bill.
commit da0037ad04511d5bed3666842297eb3fd7cc792f
Author: Bill Allombert <Bill.Allombert@math.u-bordeaux.fr>
Date: Sun Feb 7 19:16:54 2010 +0100
Add function forqfvec.
diff --git a/src/basemath/bibli1.c b/src/basemath/bibli1.c
index 02e68f0..0a33c92 100644
--- a/src/basemath/bibli1.c
+++ b/src/basemath/bibli1.c
@@ -1647,6 +1647,99 @@ addcolumntomatrix(GEN V, GEN invp, GEN L)
return 1;
}
+void
+forqfvec(void *E, void (*fun)(void *, GEN), GEN a, GEN BORNE)
+{
+ GEN x,u,r;
+ long n = lg(a), i, j, k;
+ pari_sp av1, av=avma, lim;
+ double p,BOUND,*v,*y,*z,**q;
+ const double eps = 0.0001;
+
+ if (typ(a) != t_MAT || !RgM_is_ZM(a)) pari_err(typeer,"forqfvec");
+ if (!BORNE) BORNE = gen_0;
+ else
+ {
+ BORNE = gfloor(BORNE);
+ if (typ(BORNE) != t_INT) pari_err(typeer, "minim0");
+ }
+
+ minim_alloc(n, &q, &x, &y, &z, &v);
+ av1 = avma;
+
+ u = lllgramint(a);
+ if (lg(u) != n) pari_err(talker,"not a definite form in minim0");
+ a = qf_apply_ZM(a,u);
+
+ n--;
+ a = RgM_gtofp(a, DEFAULTPREC);
+ r = qfgaussred_positive(a);
+ if (!r) pari_err(precer, "minim0");
+ for (j=1; j<=n; j++)
+ {
+ v[j] = rtodbl(gcoeff(r,j,j));
+ for (i=1; i<j; i++) q[i][j] = rtodbl(gcoeff(r,i,j));
+ }
+
+ if (gequal0(BORNE))
+ {
+ double c;
+ p = rtodbl(gcoeff(a,1,1));
+ for (i=2; i<=n; i++) { c = rtodbl(gcoeff(a,i,i)); if (c < p) p = c; }
+ BORNE = roundr(dbltor(p));
+ }
+ else
+ p = gtodouble(BORNE);
+ BOUND = p * (1 + eps);
+ if (BOUND == p) pari_err(precer, "minim0");
+
+ av1 = avma; lim = stack_lim(av1,1);
+ k = n; y[n] = z[n] = 0;
+ x[n] = (long)sqrt(BOUND/v[n]);
+ for(;;x[1]--)
+ {
+ do
+ {
+ if (k>1)
+ {
+ long l = k-1;
+ z[l] = 0;
+ for (j=k; j<=n; j++) z[l] += q[l][j]*x[j];
+ p = (double)x[k] + z[k];
+ y[l] = y[k] + p*p*v[k];
+ x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]);
+ k = l;
+ }
+ for(;;)
+ {
+ p = (double)x[k] + z[k];
+ if (y[k] + p*p*v[k] <= BOUND) break;
+ k++; x[k]--;
+ }
+ } while (k > 1);
+ if (! x[1] && y[1]<=eps) break;
+
+ p = (double)x[1] + z[1]; p = y[1] + p*p*v[1]; /* norm(x) */
+ fun(E, x); if (loop_break()) break;
+ }
+ avma = av;
+}
+
+static void
+gp_evalvoid(void *E, GEN x)
+{
+ set_lex(-1,x);
+ closure_evalvoid((GEN)E);
+}
+
+void
+forqfvec0(GEN a, GEN BORNE, GEN code)
+{
+ push_lex(gen_0, code);
+ forqfvec((void*) code, &gp_evalvoid, a, BORNE);
+ pop_lex(1);
+}
+
/* Minimal vectors for the integral definite quadratic form: a.
* Result u:
* u[1]= Number of vectors of square norm <= BORNE
diff --git a/src/functions/linear_algebra/forqfvec b/src/functions/linear_algebra/forqfvec
new file mode 100644
index 0000000..cfb559e
--- /dev/null
+++ b/src/functions/linear_algebra/forqfvec
@@ -0,0 +1,9 @@
+Function: forqfvec
+Section: linear_algebra
+C-Name: forqfvec0
+Prototype: vVGDGI
+Help:forqfvec(v,q,b,expr): q being a square and symmetric matrix
+ representing a positive definite quadratic form, evaluate expr for all
+ vector v such that q(v)<b.
+Doc: $q$ being a square and symmetric matrix representing a positive definite
+ quadratic form, evaluate \kbd{expr} for all vector $v$ such that $q(v)<b$.
diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h
index f55771b..6d6b1b1 100644
--- a/src/headers/paridecl.h
+++ b/src/headers/paridecl.h
@@ -1075,6 +1075,8 @@ GEN Q_from_QR(GEN x, long prec);
GEN R_from_QR(GEN x, long prec);
GEN algdep(GEN x, long n);
GEN algdep0(GEN x, long n, long bit);
+void forqfvec(void *E, void (*fun)(void *, GEN), GEN a, GEN BORNE);
+void forqfvec0(GEN a, GEN BORNE, GEN code);
GEN gram_matrix(GEN M);
GEN lindep(GEN x);
GEN lindep0(GEN x, long flag);