/* $Id: base4.c,v 1.241 2006/04/08 12:11:16 kb Exp $ Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*******************************************************************/ /* */ /* BASIC NF OPERATIONS */ /* (continued) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* IDEAL OPERATIONS */ /* */ /*******************************************************************/ /* A valid ideal is either principal (valid nf_element), or prime, or a matrix * on the integer basis (preferably HNF). * A prime ideal is of the form [p,a,e,f,b], where the ideal is p.Z_K+a.Z_K, * p is a rational prime, a belongs to Z_K, e=e(P/p), f=f(P/p), and b * Lenstra constant (p.P^(-1)= p Z_K + b Z_K). * * An idele is a couple[I,V] where I is a valid ideal and V a row vector * with r1+r2 components (real or complex). For instance, if M=(a), V * contains the complex logarithms of the first r1+r2 conjugates of a * (depends on the chosen generator a). All subroutines work with either * ideles or ideals (an omitted V is assumed to be 0). * * All ideals are output in HNF form. */ /* types and conversions */ long idealtyp(GEN *ideal, GEN *arch) { GEN x = *ideal; long t,lx,tx = typ(x); if (tx==t_VEC && lg(x)==3) { *arch = gel(x,2); x = gel(x,1); tx = typ(x); } else *arch = NULL; switch(tx) { case t_MAT: lx = lg(x); if (lx>2) t = id_MAT; else { t = id_PRINCIPAL; x = (lx==2)? gel(x,1): gen_0; } break; case t_VEC: if (lg(x)!=6) pari_err(talker, "incorrect ideal in idealtyp"); t = id_PRIME; break; case t_POL: case t_POLMOD: case t_COL: case t_INT: case t_FRAC: t = id_PRINCIPAL; break; default: pari_err(talker, "incorrect ideal in idealtyp"); return 0; /*not reached*/ } *ideal = x; return t; } static GEN prime_to_ideal_aux(GEN nf, GEN vp) { GEN m = eltmul_get_table(nf, gel(vp,2)); return hnfmodid(m, gel(vp,1)); } /* vp = [a,x,...], a in Z. Return (a,x) [HACK: vp need not be prime] */ GEN prime_to_ideal(GEN nf, GEN vp) { pari_sp av = avma; return gerepileupto(av, prime_to_ideal_aux(nf,vp)); } static GEN vec_mulid(GEN nf, GEN x, long nx, long N) { GEN m = cgetg(nx*N + 1, t_MAT); long i, j, k; for (i=k=1; i<=nx; i++) for (j=1; j<=N; j++) gel(m, k++) = element_mulid(nf, gel(x,i),j); return m; } /* x = ideal in matrix form. Put it in hnf. */ static GEN idealmat_to_hnf(GEN nf, GEN x) { long nx = lg(x)-1, N = degpol(nf[1]); GEN cx; if (!nx) return gscalmat(gen_0,N); x = Q_primitive_part(x, &cx); if (nx < N) x = vec_mulid(nf, x, nx, N); x = hnfmod(x, detint(x)); return cx? gmul(x,cx): x; } int isidentity(GEN x) { long i,j, lx = lg(x); for (j=1; j R1) */ GEN get_arch(GEN nf,GEN x,long prec) { long i, RU, R1 = nf_get_r1(nf); GEN v; RU = lg(nf[6]) - 1; switch(typ(x)) { case t_MAT: return famat_get_arch(nf,x,prec); case t_POLMOD: case t_POL: x = algtobasis_i(nf,x); /* fall through */ case t_COL: if (!RgV_isscalar(x)) break; x = gel(x,1); /* fall through */ default: /* rational number */ return scalar_get_arch(R1, RU, x, prec); } x = gmul(gmael(nf,5,1),x); v = cgetg(RU+1,t_VEC); for (i=1; i<=R1; i++) gel(v,i) = mylog(gel(x,i),prec); for ( ; i<=RU; i++) gel(v,i) = gmul2n(mylog(gel(x,i),prec),1); return v; } GEN get_arch_real(GEN nf,GEN x,GEN *emb,long prec); static GEN famat_get_arch_real(GEN nf,GEN x,GEN *emb,long prec) { GEN A, T, a, t, g = gel(x,1), e = gel(x,2); long i, l = lg(e); if (l <= 1) return get_arch_real(nf, gen_1, emb, prec); A = T = NULL; /* -Wall */ for (i=1; i v_P <= e * v_p */ j = k * e; /* 0 <= v_P(ix) <= floor[v_p(Nix) / f] */ i = i / f; vmax = min(i,j); /* v_P(ix) <= vmax */ t0 = gel(P,5); if (typ(t0) == t_MAT) { /* t0 given by a multiplication table */ mul = t0; do_mul = 0; } else { mul = cgetg(N+1,t_MAT); gel(mul,1) = t0; do_mul = 1; } B = cgetg(N+1,t_MAT); pk = powiu(p, (ulong)ceil((double)vmax / e)); /* B[1] not needed: v_pr(ix[1]) = v_pr(ix \cap Z) is known already */ gel(B,1) = gen_0; /* dummy */ for (j=2; j<=N; j++) { if (do_mul) gel(mul,j) = element_mulid(nf,t0,j); x = gel(ix,j); y = cgetg(N+1, t_COL); gel(B,j) = y; for (i=1; i<=N; i++) { /* compute a = (x.t0)_i, ix in HNF ==> x[j+1..N] = 0 */ a = mulii(gel(x,1), gcoeff(mul,i,1)); for (k=2; k<=j; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k))); /* p | a ? */ gel(y,i) = dvmdii(a,p,&r); if (signe(r)) { avma = av; return vd; } } } vals = cgetg(N+1, t_VECSMALL); /* vals[1] not needed */ for (j = 2; j <= N; j++) { gel(B,j) = Q_primitive_part(gel(B,j), &cx); vals[j] = cx? 1 + e * ggval(cx, p): 1; } av1 = avma; lim = stack_lim(av1,3); y = cgetg(N+1,t_COL); /* can compute mod p^ceil((vmax-v)/e) */ for (v = 1; v < vmax; v++) { /* we know v_pr(Bj) >= v for all j */ if (e == 1 || (vmax - v) % e == 0) pk = diviiexact(pk, p); for (j = 2; j <= N; j++) { x = gel(B,j); if (v < vals[j]) continue; for (i=1; i<=N; i++) { pari_sp av2 = avma; a = mulii(gel(x,1), gcoeff(mul,i,1)); for (k=2; k<=N; k++) a = addii(a, mulii(gel(x,k), gcoeff(mul,i,k))); /* a = (x.t_0)_i; p | a ? */ a = dvmdii(a,p,&r); if (signe(r)) { avma = av; return v + vd; } if (lgefint(a) > lgefint(pk)) a = remii(a, pk); gel(y,i) = gerepileuptoint(av2, a); } gel(B,j) = y; y = x; if (low_stack(lim,stack_lim(av1,3))) { if(DEBUGMEM>1) pari_warn(warnmem,"idealval"); gerepileall(av1,3, &y,&B,&pk); } } } avma = av; return v + vd; } /* gcd and generalized Bezout */ GEN idealadd(GEN nf, GEN x, GEN y) { pari_sp av=avma; long N,tx,ty; GEN z, p1, dx, dy, dz; int modid; tx = idealtyp(&x,&z); ty = idealtyp(&y,&z); nf = checknf(nf); N = degpol(nf[1]); if (tx != id_MAT || lg(x)!=N+1) x = idealhermite_aux(nf,x); if (ty != id_MAT || lg(y)!=N+1) y = idealhermite_aux(nf,y); if (lg(x) == 1) return gerepileupto(av,y); if (lg(y) == 1) return gerepileupto(av,x); /* check for 0 ideal */ dx = Q_denom(x); dy = Q_denom(y); dz = lcmii(dx,dy); if (gcmp1(dz)) dz = NULL; else { x = Q_muli_to_int(x, dz); y = Q_muli_to_int(y, dz); } if (RgV_isscalar(gel(x,1)) && RgV_isscalar(gel(y,1))) { p1 = gcdii(gcoeff(x,1,1), gcoeff(y,1,1)); modid = 1; } else { p1 = gcdii(detint(x), detint(y)); modid = 0; } if (gcmp1(p1)) { if (!dz) { avma = av; return matid(N); } dz = gclone(ginv(dz)); avma = av; z = gscalmat(dz, N); gunclone(dz); return z; } z = shallowconcat(x,y); z = modid? hnfmodid(z,p1): hnfmod(z, p1); if (dz) z = gdiv(z,dz); return gerepileupto(av,z); } GEN get_hnfid(GEN nf, GEN x) { GEN junk; long t = idealtyp(&x, &junk); return (t != id_MAT || lg(x) == 1 || lg(x) != lg(x[1]) || !RgM_ishnf(x)) ? idealhermite_aux(nf,x): x; } GEN idealaddtoone_i(GEN nf, GEN x, GEN y) { GEN xh = get_hnfid(nf, x), yh = get_hnfid(nf, y); GEN a = hnfmerge_get_1(xh, yh); return lllreducemodmatrix(a, idealmulh(nf,xh,yh)); } /* y should be an idele (not mandatory). For internal use. */ static GEN ideleaddone_i(GEN nf, GEN x, GEN y) { GEN p1, p2, u, arch, archp; long i, nba; (void)idealtyp(&y, &arch); u = idealaddtoone_i(nf, x, y); /* u in x, 1-u in y */ if (!arch) return u; if (typ(arch) != t_VEC && lg(arch)-1 != nf_get_r1(nf)) pari_err(talker,"incorrect idele in idealaddtoone"); archp = arch_to_perm(arch); if (lg(archp) == 1) return u; if (gcmp0(u)) u = (GEN)idealhermite_aux(nf,x)[1]; p2 = zarchstar(nf, idealmul(nf,x,y), archp); p2 = gel(p2,2); nba = 0; p1 = gmul(gel(p2,3), zsigne(nf,u,archp)); for (i = 1; i < lg(p1); i++) { GEN t = gel(p1,i); if (mpodd(t)) { nba = 1; u = element_mul(nf,u,gel(p2,i)); } } if (gcmp0(u)) return gcopy(gel(x,1)); /* can happen if y = Z_K */ return nba? u: gcopy(u); } GEN unnf_minus_x(GEN x) { long i, N = lg(x); GEN y = cgetg(N,t_COL); gel(y,1) = gsub(gen_1,gel(x,1)); for (i=2;i1; i--) t = element_mul(nf, t, element_pow(nf, x[i], e[i])); return t; } /* "compare" two nf elt. Goal is to quickly sort for uniqueness of * representation, not uniqueness of represented element ! */ static int elt_cmp(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (ty == tx) return (tx == t_POL || tx == t_POLMOD)? cmp_pol(x,y): lexcmp(x,y); return tx - ty; } static int elt_egal(GEN x, GEN y) { if (typ(x) == typ(y)) return gequal(x,y); return 0; } GEN famat_reduce(GEN fa) { GEN E, G, L, g, e; long i, k, l; if (lg(fa) == 1) return fa; g = gel(fa,1); l = lg(g); e = gel(fa,2); L = gen_sort(g, cmp_IND|cmp_C, &elt_cmp); G = cgetg(l, t_COL); E = cgetg(l, t_COL); /* merge */ for (k=i=1; i 1 && elt_egal(gel(G,k), gel(G,k-1))) { gel(E,k-1) = addii(gel(E,k), gel(E,k-1)); k--; } } /* kill 0 exponents */ l = k; for (k=i=1; i x * (b/p)^v_pr(x) / z^k u, where z = b^e/p^(e-1) * b/p = vp^(-1) times something prime to p; both numerator and denominator * are integral and coprime to pr. Globally, we multiply by (b/p)^v_pr(t) = 1. * * EX = multiple of exponent of (O_K / pr^k)^* used to reduce the product in * case the e[i] are large */ GEN famat_makecoprime(GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN EX) { long i, l = lg(g); GEN prkZ,cx,x,u, zpow = gen_0, p = gel(pr,1), b = gel(pr,5); GEN mul = eltmul_get_table(nf, b); GEN newg = cgetg(l+1, t_VEC); /* room for z */ prkZ = gcoeff(prk, 1,1); for (i=1; i < l; i++) { x = algtobasis_i(nf, gel(g,i)); x = Q_remove_denom(x, &cx); if (cx) { long k = Z_pvalrem(cx, p, &u); if (!gcmp1(u)) /* could avoid the inversion, but prkZ is small--> cheap */ x = gmul(x, Fp_inv(u, prkZ)); if (k) zpow = addii(zpow, mulsi(k, gel(e,i))); } (void)int_elt_val(nf, x, p, mul, &x); gel(newg,i) = colreducemodHNF(x, prk, NULL); } if (zpow == gen_0) setlg(newg, l); else { gel(newg,i) = FpC_red(special_anti_uniformizer(nf, pr), prkZ); e = shallowconcat(e, negi(zpow)); } return famat_to_nf_modideal_coprime(nf, newg, e, prk, EX); } /* prod g[i]^e[i] mod bid, assume (g[i], id) = 1 */ GEN famat_to_nf_modidele(GEN nf, GEN g, GEN e, GEN bid) { GEN t,sarch,module,cyc,fa2; long lc; if (lg(g) == 1) return gscalcol_i(gen_1, degpol(nf[1])); /* 1 */ module = gel(bid,1); fa2 = gel(bid,4); sarch = (GEN)fa2[lg(fa2)-1]; cyc = gmael(bid,2,2); lc = lg(cyc); t = NULL; if (lc != 1) { GEN EX = gel(cyc,1); /* group exponent */ GEN id = gel(module,1); t = famat_to_nf_modideal_coprime(nf, g, e, id, EX); } if (!t) t = gen_1; return set_sign_mod_idele(nf, to_famat(g,e), t, module, sarch); } GEN famat_to_arch(GEN nf, GEN fa, long prec) { GEN g,e, y = NULL; long i,l; if (typ(fa) != t_MAT) return get_arch(nf, fa, prec); if (lg(fa) == 1) return zerovec(lg(nf[6])-1); g = gel(fa,1); e = gel(fa,2); l = lg(e); for (i=1; ity) { res=ax; ax=ay; ay=res; res=x; x=y; y=res; f=tx; tx=ty; ty=f; } f = (ax||ay); res = f? cgetg(3,t_VEC): NULL; /* product is an idele */ nf=checknf(nf); av=avma; switch(tx) { case id_PRINCIPAL: switch(ty) { case id_PRINCIPAL: p1 = idealhermite_aux(nf, element_mul(nf,x,y)); break; case id_PRIME: { GEN mx = eltmul_get_table(nf, x); GEN mpi= eltmul_get_table(nf, gel(y,2)); p1 = shallowconcat(gmul(mx,gel(y,1)), gmul(mx,mpi)); p1 = idealmat_to_hnf(nf, p1); break; } default: /* id_MAT */ p1 = idealmulelt(nf, x,y); }break; case id_PRIME: p1 = (ty==id_PRIME)? prime_to_ideal_aux(nf,y) : idealmat_to_hnf(nf,y); p1 = idealmulprime(nf,p1,x); break; default: /* id_MAT */ p1 = idealmat_mul(nf,x,y); } p1 = gerepileupto(av,p1); if (!f) return p1; if (ax && ay) ax = arch_mul(ax, ay); else ax = gcopy(ax? ax: ay); gel(res,1) = p1; gel(res,2) = ax; return res; } /* assume pr in primedec format */ GEN pr_norm(GEN pr) { GEN F = gel(pr,4), p = gel(pr,1); ulong f = (ulong)F[2]; return powiu(p, f); } /* norm of an ideal */ GEN idealnorm(GEN nf, GEN x) { pari_sp av = avma; long tx; GEN y; nf = checknf(nf); switch(idealtyp(&x,&y)) { case id_PRIME: return pr_norm(x); case id_PRINCIPAL: x = gnorm(basistoalg_i(nf,x)); break; default: if (lg(x) != lg(nf[1])-2) x = idealhermite_aux(nf,x); x = dethnf(x); } tx = typ(x); if (tx == t_INT) return gerepileuptoint(av, absi(x)); if (tx != t_FRAC) pari_err(typeer, "idealnorm"); return gerepileupto(av, gabs(x,0)); } /* inverse */ /* rewritten from original code by P.M & M.H. * * I^(-1) = { x \in K, Tr(x D^(-1) I) \in Z }, D different of K/Q * * nf[5][6] = pp( D^(-1) ) = pp( HNF( T^(-1) ) ), T = (Tr(wi wj)) * nf[5][7] = same in 2-elt form */ static GEN hnfideal_inv(GEN nf, GEN I) { GEN J, dI, IZ,dual; I = Q_remove_denom(I, &dI); if (lg(I)==1) pari_err(talker, "cannot invert zero ideal"); IZ = gcoeff(I,1,1); /* I \cap Z */ if (!signe(IZ)) pari_err(talker, "cannot invert zero ideal"); J = idealmulh(nf,I, gmael(nf,5,7)); /* I in HNF, hence easily inverted; multiply by IZ to get integer coeffs * missing content cancels while solving the linear equation */ dual = shallowtrans( gauss_triangle_i(J, gmael(nf,5,6), IZ) ); dual = hnfmodid(dual, IZ); if (dI) IZ = gdiv(IZ,dI); return gdiv(dual,IZ); } /* return p * P^(-1) [integral] */ GEN pidealprimeinv(GEN nf, GEN x) { GEN y = cgetg(6,t_VEC); y[1] = x[1]; y[2] = x[5]; gel(y,3) = gel(y,5) = gen_0; gel(y,4) = subsi(degpol(nf[1]), gel(x,4)); return prime_to_ideal_aux(nf,y); } /* Calcule le dual de mat_id pour la forme trace */ GEN idealinv(GEN nf, GEN x) { GEN res,ax; pari_sp av=avma; long tx = idealtyp(&x,&ax); res = ax? cgetg(3,t_VEC): NULL; nf=checknf(nf); av=avma; switch (tx) { case id_MAT: if (lg(x) != lg(x[1])) x = idealmat_to_hnf(nf,x); if (lg(x)-1 != degpol(nf[1])) pari_err(consister,"idealinv"); x = hnfideal_inv(nf,x); break; case id_PRINCIPAL: tx = typ(x); if (is_const_t(tx)) x = ginv(x); else { switch(tx) { case t_COL: x = coltoliftalg(nf,x); break; case t_POLMOD: x = gel(x,2); break; } if (typ(x) != t_POL) { x = ginv(x); break; } if (varn(x) != varn(nf[1])) pari_err(talker,"incompatible variables in idealinv"); x = QXQ_inv(x,gel(nf,1)); } x = idealhermite_aux(nf,x); break; case id_PRIME: x = gdiv(pidealprimeinv(nf,x), gel(x,1)); } x = gerepileupto(av,x); if (!ax) return x; gel(res,1) = x; gel(res,2) = arch_inv(ax); return res; } /* return x such that vp^n = x/d */ static GEN idealpowprime_spec(GEN nf, GEN vp, GEN n, GEN *d) { GEN n1, x, r; long s = signe(n); if (s == 0) pari_err(talker, "0th power in idealpowprime_spec"); if (s < 0) n = negi(n); /* now n > 0 */ x = shallowcopy(vp); if (is_pm1(n)) /* n = 1 special cased for efficiency */ { if (s < 0) { x[2] = x[5]; *d = gel(x,1); } else *d = NULL; } else { n1 = dvmdii(n, gel(x,3), &r); if (signe(r)) n1 = addis(n1,1); /* n1 = ceil(n/e) */ gel(x,1) = powgi(gel(x,1),n1); if (s < 0) { gel(x,2) = gdiv(element_pow(nf,gel(x,5),n), powgi(gel(vp,1),subii(n,n1))); *d = gel(x,1); } else { gel(x,2) = element_pow(nf,gel(x,2),n); *d = NULL; } } return x; } static GEN idealpowprime(GEN nf, GEN vp, GEN n) { GEN x, d; long s = signe(n); nf = checknf(nf); if (s == 0) return matid(degpol(nf[1])); x = idealpowprime_spec(nf, vp, n, &d); x = prime_to_ideal_aux(nf,x); if (d) x = gdiv(x, d); return x; } /* x * vp^n. Assume x in HNF (possibly non-integral) */ GEN idealmulpowprime(GEN nf, GEN x, GEN vp, GEN n) { GEN cx,y,dx; if (!signe(n)) return x; nf = checknf(nf); /* inert, special cased for efficiency */ if (itos(gel(vp,4)) == degpol(nf[1])) return gmul(x, powgi(gel(vp,1), n)); y = idealpowprime_spec(nf, vp, n, &dx); x = Q_primitive_part(x, &cx); if (cx && dx) { cx = gdiv(cx, dx); if (typ(cx) != t_FRAC) dx = NULL; else { dx = gel(cx,2); cx = gel(cx,1); } if (is_pm1(cx)) cx = NULL; } x = idealmulspec(nf,x,y); if (cx) x = gmul(x,cx); if (dx) x = gdiv(x,dx); return x; } GEN idealdivpowprime(GEN nf, GEN x, GEN vp, GEN n) { return idealmulpowprime(nf,x,vp, negi(n)); } /* raise the ideal x to the power n (in Z) */ GEN idealpow(GEN nf, GEN x, GEN n) { pari_sp av; long tx, N, s = signe(n); GEN res,ax,m,cx,n1,a,alpha; if (typ(n) != t_INT) pari_err(talker,"non-integral exponent in idealpow"); tx = idealtyp(&x,&ax); res = ax? cgetg(3,t_VEC): NULL; nf = checknf(nf); av = avma; N = degpol(nf[1]); if (!s) x = matid(N); else switch(tx) { case id_PRINCIPAL: tx = typ(x); if (!is_const_t(tx)) switch(tx) { case t_COL: x = coltoalg(nf,x); break; case t_POL: x = gmodulo(x,gel(nf,1)); } x = powgi(x,n); x = idealhermite_aux(nf,x); break; case id_PRIME: x = idealpowprime(nf,x,n); break; default: if (is_pm1(n)) { x = (s < 0)? idealinv(nf, x): gcopy(x); break; } n1 = (s < 0)? negi(n): n; x = Q_primitive_part(x, &cx); a=ideal_two_elt(nf,x); alpha=gel(a,2); a=gel(a,1); alpha = element_pow(nf,alpha,n1); m = eltmul_get_table(nf, alpha); x = hnfmodid(m, powgi(a,n1)); if (s<0) x = hnfideal_inv(nf,x); if (cx) x = gmul(x, powgi(cx,n)); } x = gerepileupto(av, x); if (!ax) return x; ax = arch_pow(ax, n); gel(res,1) = x; gel(res,2) = ax; return res; } /* Return ideal^e in number field nf. e is a C integer. */ GEN idealpows(GEN nf, GEN ideal, long e) { long court[] = {evaltyp(t_INT) | _evallg(3),0,0}; affsi(e,court); return idealpow(nf,ideal,court); } static GEN _idealmulred(GEN nf, GEN x, GEN y, long prec) { return ideallllred(nf,idealmul(nf,x,y), NULL, prec); } typedef struct { GEN nf; long prec; } idealred_muldata; static GEN _mul(void *data, GEN x, GEN y) { idealred_muldata *D = (idealred_muldata *)data; return _idealmulred(D->nf,x,y,D->prec); } static GEN _sqr(void *data, GEN x) { return _mul(data,x,x); } /* compute x^n (x ideal, n integer), reducing along the way */ GEN idealpowred(GEN nf, GEN x, GEN n, long prec) { pari_sp av=avma; long s = signe(n); idealred_muldata D; GEN y; if (typ(n) != t_INT) pari_err(talker,"non-integral exponent in idealpowred"); if (s == 0) return idealpow(nf,x,n); D.nf = nf; D.prec= prec; y = leftright_pow(x, n, (void*)&D, &_sqr, &_mul); if (s < 0) y = idealinv(nf,y); if (s < 0 || is_pm1(n)) y = ideallllred(nf,y,NULL,prec); return gerepileupto(av,y); } GEN idealmulred(GEN nf, GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, _idealmulred(nf,x,y,prec)); } long isideal(GEN nf,GEN x) { pari_sp av; long N,i,j,tx=typ(x),lx; nf=checknf(nf); lx=lg(x); if (tx==t_VEC && lx==3) { x=gel(x,1); tx=typ(x); lx=lg(x); } if (is_scalar_t(tx)) return (tx==t_INT || tx==t_FRAC || tx==t_POL || (tx==t_POLMOD && gequal(gel(nf,1),gel(x,1)))); if (typ(x)==t_VEC) return (lx==6); if (typ(x)!=t_MAT) return 0; N = degpol(nf[1]); if (lx-1 != N) return (lx == 1); if (lg(x[1])-1 != N) return 0; av = avma; x = Q_primpart(x); if (!ZM_ishnf(x)) return 0; for (i=1; i<=N; i++) for (j=2; j<=N; j++) if (! hnf_invimage(x, element_mulid(nf,gel(x,i),j))) { avma = av; return 0; } avma=av; return 1; } GEN idealdiv(GEN nf, GEN x, GEN y) { pari_sp av = avma, tetpil; GEN z = idealinv(nf,y); tetpil = avma; return gerepile(av,tetpil, idealmul(nf,x,z)); } /* This routine computes the quotient x/y of two ideals in the number field nf. * It assumes that the quotient is an integral ideal. The idea is to find an * ideal z dividing y such that gcd(Nx/Nz, Nz) = 1. Then * * x + (Nx/Nz) x * ----------- = --- * y + (Ny/Nz) y * * Proof: we can assume x and y are integral. Let p be any prime ideal * * If p | Nz, then it divides neither Nx/Nz nor Ny/Nz (since Nx/Nz is the * product of the integers N(x/y) and N(y/z)). Both the numerator and the * denominator on the left will be coprime to p. So will x/y, since x/y is * assumed integral and its norm N(x/y) is coprime to p. * * If instead p does not divide Nz, then v_p (Nx/Nz) = v_p (Nx) >= v_p(x). * Hence v_p (x + Nx/Nz) = v_p(x). Likewise for the denominators. QED. * * Peter Montgomery. July, 1994. */ GEN idealdivexact(GEN nf, GEN x0, GEN y0) { pari_sp av = avma; GEN x,y,Nx,Ny,Nz, cy = Q_content(y0); nf = checknf(nf); if (gcmp0(cy)) pari_err(talker, "cannot invert zero ideal"); x = gdiv(x0,cy); Nx = idealnorm(nf,x); if (gcmp0(Nx)) { avma = av; return gcopy(x0); } /* numerator is zero */ y = gdiv(y0,cy); Ny = idealnorm(nf,y); if (!gcmp1(denom(x)) || !dvdii(Nx,Ny)) pari_err(talker, "quotient not integral in idealdivexact"); /* Find a norm Nz | Ny such that gcd(Nx/Nz, Nz) = 1 */ for (Nz = Ny;;) { GEN p1 = gcdii(Nz, diviiexact(Nx,Nz)); if (is_pm1(p1)) break; Nz = diviiexact(Nz,p1); } /* Replace x/y by x+(Nx/Nz) / y+(Ny/Nz) */ x = idealhermite_aux(nf, x); x = hnfmodid(x, diviiexact(Nx,Nz)); /* y reduced to unit ideal ? */ if (Nz == Ny) return gerepileupto(av, x); y = idealhermite_aux(nf, y); y = hnfmodid(y, diviiexact(Ny,Nz)); y = hnfideal_inv(nf,y); return gerepileupto(av, idealmat_mul(nf,x,y)); } GEN idealintersect(GEN nf, GEN x, GEN y) { pari_sp av=avma; long lz,i,N; GEN z,dx,dy; nf = checknf(nf); N = degpol(nf[1]); if (idealtyp(&x,&z) != t_MAT || lg(x) != N+1) x = idealhermite_aux(nf,x); if (idealtyp(&y,&z) != t_MAT || lg(y) != N+1) y = idealhermite_aux(nf,y); if (lg(x) == 1 || lg(y) == 1) { avma = av; return cgetg(1, t_MAT); } x = Q_remove_denom(x, &dx); y = Q_remove_denom(y, &dy); if (dx) y = gmul(y, dx); if (dy) x = gmul(x, dy); dx = mul_content(dx,dy); z = kerint(shallowconcat(x,y)); lz = lg(z); for (i=1; i d = den(I/x) = T / c * J = (d I / x); I[1,1] = I \cap Z --> d I[1,1] belongs to J and Z */ if (RgV_isscalar(gel(I,1))) { b = mulii(gcoeff(I,1,1), c? diviiexact(T, c): T); I = hnfmodid(J,b); } else { b = detint(J); I = hnfmod(J,b); } if (!aI) return gerepileupto(av, I); END: switch(typ(aI)) { case t_POLMOD: y = x; /*Fall through*/ case t_MAT: /* compute y, I0 = J y */ if (!T) y = c1; else { c = mul_content(c,c1); y = c? gmul(y, gdiv(c,T)): gdiv(y, T); } break; case t_COL: if (y) y = vecinv(gmul(gmael(nf,5,1), y)); break; default: if (y) { if (prec <= 0) prec = nfgetprec(nf); y = gneg_i(get_arch(nf,y,prec)); } break; } if (y) aI = arch_mul(aI,y); return gerepilecopy(av, mkvec2(I, aI)); } GEN minideal(GEN nf, GEN x, GEN vdir, long prec) { pari_sp av = avma; long N, tx; GEN y; nf = checknf(nf); vdir = chk_vdir(nf,vdir); N = degpol(nf[1]); tx = idealtyp(&x,&y); if (tx == id_PRINCIPAL) return gcopy(x); if (tx != id_MAT || lg(x) != N+1) x = idealhermite_aux(nf,x); y = gmul(computeGtwist(nf,vdir), x); y = gmul(x, (GEN)lll(y,prec)[1]); return gerepileupto(av, principalidele(nf,y,prec)); } /*******************************************************************/ /* */ /* APPROXIMATION THEOREM */ /* */ /*******************************************************************/ /* write x = x1 x2, x2 maximal s.t. (x2,f) = 1, return x2 */ GEN coprime_part(GEN x, GEN f) { for (;;) { f = gcdii(x, f); if (is_pm1(f)) break; x = diviiexact(x, f); } return x; } /* x t_INT, f ideal. Write x = x1 x2, sqf(x1) | f, (x2,f) = 1. Return x2 */ static GEN nf_coprime_part(GEN nf, GEN x, GEN *listpr) { long v, j, lp = lg(listpr), N = degpol(nf[1]); GEN x1, x2, ex, p, pr; #if 0 /*1) via many gcds. Expensive ! */ GEN f = idealprodprime(nf, (GEN)listpr); f = hnfmodid(f, x); /* first gcd is less expensive since x in Z */ x = gscalmat(x, N); for (;;) { if (gcmp1(gcoeff(f,1,1))) break; x = idealdivexact(nf, x, f); f = hnfmodid(shallowconcat(f,x), gcoeff(x,1,1)); /* gcd(f,x) */ } x2 = x; #else /*2) from prime decomposition */ x1 = NULL; for (j=1; j 0 */ x1 = x1? idealmulpowprime(nf, x1, pr, ex) : idealpow(nf, pr, ex); } x = gscalmat(x, N); x2 = x1? idealdivexact(nf, x, x1): x; #endif return x2; } /* L0 in K^*, assume (L0,f) = 1. Return L integral, L0 = L mod f */ GEN make_integral(GEN nf, GEN L0, GEN f, GEN *listpr) { GEN fZ, t, L, D2, d1, d2, d; L = Q_remove_denom(L0, &d); if (!d) return L0; /* L0 = L / d, L integral */ fZ = gcoeff(f,1,1); /* Kill denom part coprime to fZ */ d2 = coprime_part(d, fZ); t = Fp_inv(d2, fZ); if (!is_pm1(t)) L = gmul(L,t); if (equalii(d, d2)) return L; d1 = diviiexact(d, d2); /* L0 = (L / d1) mod f. d1 not coprime to f * write (d1) = D1 D2, D2 minimal, (D2,f) = 1. */ D2 = nf_coprime_part(nf, d1, listpr); t = idealaddtoone_i(nf, D2, f); /* in D2, 1 mod f */ L = element_muli(nf,t,L); /* if (L0, f) = 1, then L in D1 ==> in D1 D2 = (d1) */ return Q_div_to_int(L, d1); /* exact division */ } /* assume L is a list of prime ideals. Return the product */ GEN idealprodprime(GEN nf, GEN L) { long l = lg(L), i; GEN z; if (l == 1) return matid(degpol(nf[1])); z = prime_to_ideal(nf, gel(L,1)); for (i=2; i = 0 for all other pr. * For optimal performance, all [anti-]uniformizers should be precomputed, * but no support for this yet. * * If nored, do not reduce result. * No garbage collecting */ static GEN idealapprfact_i(GEN nf, GEN x, int nored) { GEN z, d, L, e, e2, F; long i, r; int flagden; nf = checknf(nf); L = gel(x,1); e = gel(x,2); F = init_unif_mod_fZ(L); flagden = 0; z = NULL; r = lg(e); for (i = 1; i < r; i++) { long s = signe(e[i]); GEN pi, q; if (!s) continue; if (s < 0) flagden = 1; pi = unif_mod_fZ(gel(L,i), F); q = element_pow(nf, pi, gel(e,i)); z = z? element_mul(nf, z, q): q; } if (!z) return gscalcol_i(gen_1, degpol(nf[1])); if (nored) { if (flagden) pari_err(impl,"nored + denominator in idealapprfact"); return z; } e2 = cgetg(r, t_VEC); for (i=1; i=v_p(x) for all prime ideals p in the ideal factorization * and v_p(b)>=0 for all other p, using the (standard) proof given in GTM 138. * Certainly not the most efficient, but sure. */ GEN idealchinese(GEN nf, GEN x, GEN w) { pari_sp av = avma; long ty = typ(w), i, N, r; GEN y, L, e, F, s, den; nf = checknf(nf); N = degpol(nf[1]); if (typ(x) != t_MAT || lg(x) != 3) pari_err(talker,"not a prime ideal factorization in idealchinese"); L = gel(x,1); r = lg(L); e = gel(x,2); if (!is_vec_t(ty) || lg(w) != r) pari_err(talker,"not a suitable vector of elements in idealchinese"); if (r == 1) return gscalcol_i(gen_1,N); w = Q_remove_denom(w, &den); if (den) { GEN p = gen_sort(x, cmp_IND|cmp_C, &cmp_prime_ideal); GEN fa = idealfactor(nf, den); /* sorted */ L = vecpermute(L, p); e = vecpermute(e, p); w = vecpermute(w, p); settyp(w, t_VEC); /* make sure typ = t_VEC */ merge_factor(&L, &e, gel(fa,1), gel(fa,2)); i = lg(L); w = shallowconcat(w, zerovec(i - r)); r = i; } else e = shallowcopy(e); /* do not destroy x[2] */ for (i=1; i=1; i--) { GEN d, di = NULL; def--; j=def; while (j>=1 && gcmp0(gcoeff(A,i,j))) j--; if (!j) pari_err(talker,"not a matrix of maximal rank in nfhermite"); if (j==def) j--; else { lswap(A[j], A[def]); lswap(I[j], I[def]); } y = gcoeff(A,i,def); gel(A,def) = element_mulvec(nf, element_inv(nf,y), gel(A,def)); gel(I,def) = idealmulelt(nf, y, gel(I,def)); for ( ; j; j--) { GEN b, u,v,w, S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (gcmp0(b)) continue; S0 = gel(A,def); d = nfbezout(nf, gen_1,b, gel(I,def),gel(I,j), &u,&v,&w,&di); S = colcomb(nf, u,v, S0,T0); T = colcomb(nf, gen_1,gneg(b), T0,S0); gel(A,def) = S; gel(A,j) = T; gel(I,def) = d; gel(I,j) = w; } d = gel(I,def); if (!di) di = idealinv(nf,d); gel(J,def) = di; for (j=def+1; j<=k; j++) { GEN c = element_close(nf,gcoeff(A,i,j), idealmul(nf,d,gel(J,j))); gel(A,j) = colcomb(nf, gen_1,gneg(c), gel(A,j),gel(A,def)); } if (low_stack(lim, stack_lim(av1,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"nfhermite, i = %ld", i); gerepileall(av,3, &A,&I,&J); } } A += k-m; A[0] = evaltyp(t_MAT)|evallg(m+1); I += k-m; I[0] = evaltyp(t_VEC)|evallg(m+1); return gerepilecopy(av0, mkvec2(A, I)); } /* A torsion module M over Z_K will be given by a row vector [A,I,J] with * three components. I=[b_1,...,b_n] is a row vector of k fractional ideals * given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in * HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A * and e_n is the canonical basis of K^n, then * M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n) */ /* x=[A,I,J] a torsion module as above. Output the * smith normal form as K=[c_1,...,c_n] such that x = Z_K/c_1+...+Z_K/c_n */ GEN nfsmith(GEN nf, GEN x) { long i, j, k, l, c, n, m, N; pari_sp av, lim; GEN z,u,v,w,d,dinv,A,I,J; nf = checknf(nf); N = degpol(nf[1]); if (typ(x)!=t_VEC || lg(x)!=4) pari_err(talker,"not a module in nfsmith"); A = gel(x,1); I = gel(x,2); J = gel(x,3); if (typ(A)!=t_MAT) pari_err(talker,"not a matrix in nfsmith"); n = lg(A)-1; if (typ(I)!=t_VEC || lg(I)!=n+1 || typ(J)!=t_VEC || lg(J)!=n+1) pari_err(talker,"not a correct ideal list in nfsmith"); if (!n) pari_err(talker,"not a matrix of maximal rank in nfsmith"); m = lg(A[1])-1; if (n < m) pari_err(talker,"not a matrix of maximal rank in nfsmith"); if (n > m) pari_err(impl,"nfsmith for non square matrices"); av = avma; lim = stack_lim(av,1); A = shallowcopy(A); I = shallowcopy(I); J = shallowcopy(J); for (j=1; j<=n; j++) if (typ(I[j])!=t_MAT) gel(I,j) = idealhermite_aux(nf,gel(I,j)); for (j=1; j<=n; j++) if (typ(J[j])!=t_MAT) gel(J,j) = idealhermite_aux(nf,gel(J,j)); for (i=n; i>=2; i--) { do { GEN a, b; c = 0; for (j=i-1; j>=1; j--) { GEN S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (gcmp0(b)) continue; S0 = gel(A,i); a = gel(S0,i); d = nfbezout(nf, a,b, gel(J,i),gel(J,j), &u,&v,&w,&dinv); S = colcomb(nf, u,v, S0,T0); T = colcomb(nf, a,gneg(b), T0,S0); gel(A,i) = S; gel(A,j) = T; gel(J,i) = d; gel(J,j) = w; } for (j=i-1; j>=1; j--) { GEN ri, rj; b = gcoeff(A,j,i); if (gcmp0(b)) continue; a = gcoeff(A,i,i); d = nfbezout(nf, a,b, gel(I,i),gel(I,j), &u,&v,&w,&dinv); ri = rowcomb(nf, u,v, i,j, A, i); rj = rowcomb(nf, a,gneg(b), j,i, A, i); for (k=1; k<=i; k++) { coeff(A,j,k) = rj[k]; coeff(A,i,k) = ri[k]; } gel(I,i) = d; gel(I,j) = w; c = 1; } if (c) continue; b = gcoeff(A,i,i); if (gcmp0(b)) break; b = idealmulelt(nf, b, idealmul(nf,gel(J,i),gel(I,i))); for (k=1; kN) pari_err(talker,"bug2 in nfsmith"); p1 = element_mulvecrow(nf,gel(b,l),A,k,i); for (l=1; l<=i; l++) gcoeff(A,i,l) = gadd(gcoeff(A,i,l),gel(p1,l)); k = l = i; c = 1; } if (low_stack(lim, stack_lim(av,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"nfsmith"); gerepileall(av,3, &A,&I,&J); } } while (c); } gel(J,1) = idealmul(nf, gcoeff(A,1,1), gel(J,1)); z = cgetg(n+1,t_VEC); for (i=1; i<=n; i++) gel(z,i) = idealmul(nf,gel(I,i),gel(J,i)); return gerepileupto(av, z); } #define trivlift(x) ((typ(x)==t_POLMOD)? gel(x,2): lift_intern(x)) GEN element_mulmodpr(GEN nf, GEN x, GEN y, GEN modpr) { pari_sp av=avma; nf = checknf(nf); return gerepileupto(av, nfreducemodpr(nf, element_mul(nf,x,y), modpr)); } GEN element_divmodpr(GEN nf, GEN x, GEN y, GEN modpr) { pari_sp av = avma; GEN p1, T = gel(nf,1); nf = checknf(nf); p1 = QXQ_inv(coltoliftalg(nf,trivlift(y)), T); p1 = RgXQ_mul(coltoliftalg(nf,trivlift(x)), p1, T); p1 = poltobasis(nf,p1); return gerepileupto(av,nfreducemodpr(nf,p1,modpr)); } GEN element_invmodpr(GEN nf, GEN y, GEN modpr) { pari_sp av=avma; GEN p1; p1 = QXQ_inv(coltoliftalg(nf,trivlift(y)), gel(nf,1)); p1 = poltobasis(nf,p1); return gerepileupto(av, nfreducemodpr(nf,p1,modpr)); } GEN element_powmodpr(GEN nf,GEN x,GEN k,GEN pr) { pari_sp av=avma; GEN z,T,p,modpr; nf = checknf(nf); modpr = nf_to_ff_init(nf,&pr,&T,&p); z = nf_to_ff(nf,lift(x),modpr); z = Fq_pow(z,k,T,p); z = ff_to_nf(z,modpr); return gerepilecopy(av, algtobasis_i(nf,z)); } GEN nfkermodpr(GEN nf, GEN x, GEN pr) { pari_sp av = avma; GEN T,p,modpr; nf = checknf(nf); if (typ(x)!=t_MAT) pari_err(typeer,"nfkermodpr"); modpr = nf_to_ff_init(nf, &pr,&T,&p); x = modprM(lift(x), nf, modpr); return gerepilecopy(av, modprM_lift(FqM_ker(x,T,p), modpr)); } GEN nfsolvemodpr(GEN nf, GEN a, GEN b, GEN pr) { pari_sp av = avma; GEN T,p,modpr; nf = checknf(nf); if (typ(a)!=t_MAT) pari_err(typeer,"nfsolvemodpr"); modpr = nf_to_ff_init(nf, &pr,&T,&p); a = modprM(lift(a), nf, modpr); b = modprM(lift(b), nf, modpr); return gerepilecopy(av, modprM_lift(FqM_gauss(a,b,T,p), modpr)); } #if 0 GEN nfsuppl(GEN nf, GEN x, GEN pr) { pari_sp av = avma; GEN T,p,modpr; nf = checknf(nf); if (typ(x)!=t_MAT) pari_err(typeer,"nfkermodpr"); modpr = nf_to_ff_init(nf, &pr,&T,&p); x = modprM(lift(x), nf, modpr); return gerepilecopy(av, modprM_lift(FqM_suppl(x,T,p), modpr)); } #endif /* Given a pseudo-basis x, outputs a multiple of its ideal determinant */ GEN nfdetint(GEN nf, GEN x) { GEN pass,c,v,det1,piv,pivprec,vi,p1,A,I,id,idprod; long i, j, k, rg, n, m, m1, cm=0, N; pari_sp av = avma, av1, lim; nf = checknf(nf); N = degpol(nf[1]); check_ZKmodule(x, "nfdetint"); A = gel(x,1); I = gel(x,2); n = lg(A)-1; if (!n) return gen_1; m1 = lg(A[1]); m = m1-1; id = matid(N); c = new_chunk(m1); for (k=1; k<=m; k++) c[k] = 0; piv = pivprec = gscalcol_i(gen_1,N); av1 = avma; lim = stack_lim(av1,1); det1 = idprod = gen_0; /* dummy for gerepilemany */ pass = cgetg(m1,t_MAT); v = cgetg(m1,t_COL); for (j=1; j<=m; j++) { gel(pass,j) = zerocol(m); gel(v,j) = gen_0; /* dummy */ } for (rg=0,k=1; k<=n; k++) { long t = 0; for (i=1; i<=m; i++) if (!c[i]) { vi=element_mul(nf,piv,gcoeff(A,i,k)); for (j=1; j<=m; j++) if (c[j]) vi=gadd(vi,element_mul(nf,gcoeff(pass,i,j),gcoeff(A,j,k))); gel(v,i) = vi; if (!t && !gcmp0(vi)) t=i; } if (t) { pivprec = piv; if (rg == m-1) { if (!cm) { cm=1; idprod = id; for (i=1; i<=m; i++) if (i!=t) idprod = (idprod==id)? (GEN)I[c[i]] : idealmul(nf,idprod,(GEN)I[c[i]]); } p1 = idealmul(nf,gel(v,t),gel(I,k)); c[t]=0; det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1); } else { rg++; piv=gel(v,t); c[t]=k; for (i=1; i<=m; i++) if (!c[i]) { for (j=1; j<=m; j++) if (c[j] && j!=t) { p1 = gsub(element_mul(nf,piv,gcoeff(pass,i,j)), element_mul(nf,gel(v,i),gcoeff(pass,t,j))); gcoeff(pass,i,j) = rg>1? element_div(nf,p1,pivprec) : p1; } gcoeff(pass,i,t) = gneg(gel(v,i)); } } } if (low_stack(lim, stack_lim(av1,1))) { if(DEBUGMEM>1) pari_warn(warnmem,"nfdetint"); gerepileall(av1,6, &det1,&piv,&pivprec,&pass,&v,&idprod); } } if (!cm) { avma = av; return gscalmat(gen_0,N); } return gerepileupto(av, idealmul(nf,idprod,det1)); } /* clean in place (destroy x) */ static void nfcleanmod(GEN nf, GEN x, long lim, GEN D) { long i; GEN c; D = lllint_ip(Q_primitive_part(D, &c), 4); if (c) D = gmul(D,c); for (i=1; i<=lim; i++) gel(x,i) = element_reduce(nf, gel(x,i), D); } GEN nfhermitemod(GEN nf, GEN x, GEN detmat) { long li, co, i, j, def, ldef, N; pari_sp av0=avma, av, lim; GEN d0, w, p1, d, u, v, A, I, J, di, unnf; nf = checknf(nf); N = degpol(nf[1]); check_ZKmodule(x, "nfhermitemod"); A = gel(x,1); I = gel(x,2); co = lg(A); if (co==1) return cgetg(1,t_MAT); li = lg(A[1]); unnf = gscalcol_i(gen_1,N); detmat = lllint_ip(Q_remove_denom(detmat, NULL), 100); av = avma; lim = stack_lim(av,2); A = matalgtobasis(nf, A); I = shallowcopy(I); def = co; ldef = (li>co)? li-co+1: 1; for (i=li-1; i>=ldef; i--) { def--; j=def; while (j>=1 && gcmp0(gcoeff(A,i,j))) j--; if (j==def) j--; else { lswap(A[j], A[def]); lswap(I[j], I[def]); } for ( ; j; j--) { GEN a, b, S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (gcmp0(b)) continue; S0 = gel(A,def); a = gel(S0,i); d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di); S = colcomb(nf, u,v, S0,T0); T = colcomb(nf, a,gneg(b), T0,S0); if (u != gen_0 && v != gen_0) /* already reduced otherwise */ nfcleanmod(nf, S, i, idealmul(nf,detmat,di)); nfcleanmod(nf, T, i, idealdiv(nf,detmat,w)); gel(A,def) = S; gel(A,j) = T; gel(I,def) = d; gel(I,j) = w; } if (low_stack(lim, stack_lim(av,2))) { if(DEBUGMEM>1) pari_warn(warnmem,"[1]: nfhermitemod, i = %ld", i); gerepileall(av,2, &A,&I); } } def--; d0 = detmat; A += def; A[0] = evaltyp(t_MAT)|evallg(li); I += def; I[0] = evaltyp(t_VEC)|evallg(li); for (i=li-1; i>=1; i--) { d = nfbezout(nf, gen_1,gcoeff(A,i,i), d0,gel(I,i), &u,&v,&w,&di); p1 = element_mulvec(nf,v,gel(A,i)); if (i > 1) { d0 = idealmul(nf,d0,di); nfcleanmod(nf, p1, i, d0); } gel(A,i) = p1; gel(p1,i) = unnf; gel(I,i) = d; } J = cgetg(li,t_VEC); gel(J,1) = gen_0; for (j=2; j=1; i--) { d = gel(I,i); for (j=i+1; j1) pari_warn(warnmem,"[2]: nfhermitemod, i = %ld", i); gerepileall(av,3, &A,&I,&J); } } return gerepilecopy(av0, mkvec2(A, I)); }