Bill Allombert on Sat, 22 May 2010 19:56:56 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: forqfvec (iterative qfminim) |
Hello PARI-dev, Ariel told me forqfvec did not work with non LLL reduced matrices, so here a new patch that fix that, and a new example: ? my(z=vector(30));forqfvec(v,matid(8),30,z[v~*v]++);z %1 = [8, 56, 224, 568, 1008, 1568, 2752, 4664, 6056, 7056, 10656, 15904, 17584, 19264, 28224, 37432, 39312, 42392, 54880, 71568, 77056, 74592, 97344, 130592, 126008, 123088, 163520, 195392, 195120, 197568] Cheers, Bill.
diff --git a/src/basemath/bibli1.c b/src/basemath/bibli1.c index 69882e0..3b48975 100644 --- a/src/basemath/bibli1.c +++ b/src/basemath/bibli1.c @@ -1648,6 +1648,107 @@ addcolumntomatrix(GEN V, GEN invp, GEN L) return 1; } +struct qfvec +{ + GEN a, r, u; +}; + +static void +forqfvec_init(struct qfvec *qv, GEN a) +{ + if (typ(a) != t_MAT || !RgM_is_ZM(a)) pari_err(typeer, "forqfvec"); + qv->u = lllgramint(a); + if (lg(qv->u) != lg(a)) pari_err(talker, "not a definite form in minim0"); + qv->a = RgM_gtofp(qf_apply_ZM(a, qv->u), DEFAULTPREC); + qv->r = qfgaussred_positive(qv->a); + if (!qv->r) pari_err(precer, "minim0"); +} + +static void +forqfvec(void *E, long (*fun)(void *, GEN, GEN, double), struct qfvec *qv, GEN BORNE) +{ + GEN x, a = qv->a, r = qv->r, u = qv->u; + long n = lg(a), i, j, k; + double p,BOUND,*v,*y,*z,**q; + const double eps = 0.0001; + 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); + n--; + 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"); + + 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) */ + if (fun(E, u, x, p)) break; + } +} + +static long +_gp_forqf(void *E, GEN u, GEN x, double p) +{ + pari_sp av = avma; + set_lex(-1, ZM_zc_mul(u, x)); + closure_evalvoid((GEN)E); + avma = av; + return loop_break(); +} + +void +forqfvec0(GEN a, GEN BORNE, GEN code) +{ + pari_sp av = avma; + struct qfvec qv; + forqfvec_init(&qv, a); + push_lex(gen_0, code); + forqfvec((void*) code, &_gp_forqf, &qv, BORNE); + pop_lex(1); + avma = av; +} + /* 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..c3ee950 --- /dev/null +++ b/src/functions/linear_algebra/forqfvec @@ -0,0 +1,15 @@ +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$. +Variant: The following function is also available: + \fun{void}{forqfvec}{void *E, long (*fun)(void *, GEN, double), GEN q, GEN b}: + Evaluate \kbd{fun(E,v,m)} on all $v$ such that $q(v)<b$, where $v$ is a + \typ{VECSMALL} and $m=q(v)$ is a C double. The function \kbd{fun} must + return $0$, unless \kbd{forqfvec} should stop, in which case, it should + return $1$. diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h index 2708168..9f83d4a 100644 --- a/src/headers/paridecl.h +++ b/src/headers/paridecl.h @@ -1084,6 +1084,7 @@ 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 forqfvec0(GEN a, GEN BORNE, GEN code); GEN gram_matrix(GEN M); GEN lindep(GEN x); GEN lindep0(GEN x, long flag);