/* $Id: base5.c,v 1.84 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 2) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" static GEN _checkrnfeq(GEN x) { if (typ(x) == t_VEC) switch(lg(x)) { case 13: /* checkrnf(x); */ return gel(x,11); case 4: return x; } return NULL; } GEN checkrnfeq(GEN x) { x = _checkrnfeq(x); if (!x) pari_err(talker,"please apply rnfequation(,,1)"); return x; } GEN eltreltoabs(GEN rnfeq, GEN x) { long i, k, va; pari_sp av = avma; GEN polabs, teta, alpha, s; rnfeq = checkrnfeq(rnfeq); polabs= gel(rnfeq,1); alpha = lift_intern(gel(rnfeq,2)); k = itos(gel(rnfeq,3)); va = varn(polabs); if (varncmp(gvar(x), va) > 0) x = scalarpol(x,va); /* Mod(X - k alpha, polabs(X)), alpha root of the polynomial defining base */ teta = gadd(pol_x[va], gmulsg(-k,alpha)); s = gen_0; for (i=lg(x)-1; i>1; i--) { GEN c = gel(x,i); long tc = typ(c); switch(tc) { case t_POLMOD: c = gel(c,2); /* fall through */ case t_POL: c = RgX_RgXQ_compo(c, alpha, polabs); break; default: if (!is_const_t(tc)) pari_err(talker, "incorrect data in eltreltoabs"); } s = RgX_rem(gadd(c, gmul(teta,s)), polabs); } return gerepileupto(av, s); } #if 0 static GEN rnfmakematrices(GEN rnf) { long i, j, k, n, ru, vnf; GEN nf, pol, sym, ro, w, ronf, z, vecM, T; pol = gel(rnf,1); n = degpol(pol); sym = polsym(pol, n-1); ro = gel(rnf,6); w = gel(rnf,7); w = gel(w,1); nf = gel(rnf,10); vnf = varn(nf[1]); T = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) { GEN c = cgetg(n+1,t_COL); gel(T,j) = c; for (i=1; i<=n; i++) { GEN d = grem(gmul(gel(w,i),gel(w,j)), pol); gel(c,i) = lift_if_rational( quicktrace(d, sym) ); } } w = lift(w); ru = lg(ro)-1; ronf = gel(nf,6); vecM = cgetg(ru+1,t_VEC); for (k=1; k<=ru; k++) { GEN rok = gel(ro,k), M = cgetg(n+1,t_MAT); long l = lg(rok); gel(vecM,k) = M; for (j=1; j<=n; j++) { GEN a, c = cgetg(l,t_COL); gel(M,j) = c; a = gsubst(gel(w,j), vnf, gel(ronf,k)); for (i=1; i>1); gel(r,j) = get_roots(ro, r1j, 0); } for (; j<=r1+r2; j++) { ro = roots(gsubst(pol,v,gel(ro,j)), prec); gel(s,j) = mkvec2s(0, n); gel(r,j) = ro; } *pts = s; return r; } #else /* dummies */ static GEN rnfmakematrices(GEN rnf) { (void)rnf; return cgetg(1, t_VEC); } static GEN rnf_roots(GEN nf, GEN pol, long prec, GEN *pts) { (void)nf; (void)pol; (void)prec; *pts = cgetg(1,t_VEC); return cgetg(1, t_VEC); } #endif static GEN modulereltoabs(GEN rnf, GEN x) { GEN w = gel(x,1), I = gel(x,2), nf = gel(rnf,10), rnfeq = gel(rnf,11); GEN M, basnf, cobasnf, T = gel(nf,1), polabs = gel(rnfeq,1); long i, j, k, n = lg(w)-1, m = degpol(T); M = cgetg(n*m+1, t_VEC); basnf = lift_intern( gsubst(gel(nf,7), varn(T), gel(rnfeq,2)) ); basnf = Q_primitive_part(basnf, &cobasnf); /* remove denom. --> faster */ for (k=i=1; i<=n; i++) { GEN c0, om = gel(w,i), id = gel(I,i); om = Q_primitive_part(eltreltoabs(rnfeq, om), &c0); c0 = mul_content(c0, cobasnf); for (j=1; j<=m; j++) { GEN c, z = Q_primitive_part(gmul(basnf,gel(id,j)), &c); z = RgX_rem(gmul(om, RgX_rem(z,polabs)), polabs); c = mul_content(c, c0); if (c) z = gmul(c, z); gel(M,k++) = z; } } return M; } GEN hnfcenter_ip(GEN M) { long i, j, k, N = lg(M)-1; GEN a, Mj, Mk; for (j=N-1; j>0; j--) { Mj = gel(M,j); a = gel(Mj,j); if (cmpiu(a, 2) <= 0) continue; a = shifti(a, -1); for (k = j+1; k <= N; k++) { Mk = gel(M,k); if (cmpii(gel(Mk,j),a) > 0) for (i = 1; i <= j; i++) gel(Mk,i) = subii(gel(Mk,i), gel(Mj,i)); } } return M; } static GEN makenfabs(GEN rnf) { GEN M, d, rnfeq, pol, nf, NF = zerovec(9); long n; rnfeq = gel(rnf,11); pol = gel(rnfeq,1); nf = gel(rnf,10); M = modulereltoabs(rnf, gel(rnf,7)); n = lg(M)-1; M = RgXV_to_RgM(Q_remove_denom(M, &d), n); if (d) M = gdiv(hnfcenter_ip(hnfmodid(M, d)), d); else M = matid(n); gel(NF,1) = pol; gel(NF,3) = mulii(powiu(gel(nf,3), degpol(rnf[1])), idealnorm(nf, gel(rnf,3))); gel(NF,7) = RgM_to_RgXV(M,varn(pol)); gel(NF,8) = invmat(M); gel(NF,9) = get_mul_table(pol, gel(NF,7), gel(NF,8)); /* possibly wrong, but correct prime divisors [for primedec] */ gel(NF,4) = Q_denom(gel(NF,7)); return NF; } static GEN makenorms(GEN rnf) { GEN f = gel(rnf,4); return typ(f) == t_INT? gen_1: dethnf(f); } #define NFABS 1 #define NORMS 2 GEN check_and_build_nfabs(GEN rnf) { return check_and_build_obj(rnf, NFABS, &makenfabs); } GEN check_and_build_norms(GEN rnf) { return check_and_build_obj(rnf, NORMS, &makenorms); } GEN rnfinitalg(GEN nf, GEN pol, long prec) { pari_sp av = avma; long vpol; GEN rnf, delta, bas, D,d,f, B; if (typ(pol)!=t_POL) pari_err(notpoler,"rnfinitalg"); nf = checknf(nf); vpol = varn(pol); pol = fix_relative_pol(nf,pol,0); if (vpol >= varn(nf[1])) pari_err(talker,"main variable must be of higher priority in rnfinitalg"); bas = rnfallbase(nf,pol, &D,&d, &f); B = matbasistoalg(nf,gel(bas,1)); gel(bas,1) = lift_if_rational( RgM_to_RgXV(B,vpol) ); delta = mkvec2(D, d); rnf = cgetg(13, t_VEC); gel(rnf,1) = pol; gel(rnf,3) = delta; gel(rnf,4) = f; gel(rnf,6) = rnf_roots(nf, pol, prec, (GEN*)rnf+2); gel(rnf,7) = bas; gel(rnf,8) = lift_if_rational( invmat(B) ); gel(rnf,9) = cgetg(1,t_VEC); /* dummy */ gel(rnf,10) = nf; gel(rnf,11) = rnfequation2(nf,pol); gel(rnf,12) = gen_0; gel(rnf,5) = rnfmakematrices(rnf); return gerepilecopy(av, rnf); } GEN rnfelementreltoabs(GEN rnf,GEN x) { long i, lx, tx = typ(x); GEN z; switch(tx) { case t_VEC: case t_COL: case t_MAT: lx = lg(x); z = cgetg(lx,tx); for (i=1; i 3) pari_err(talker,"element is not in the base field in rnfelementdown"); z = gel(z,2); } return gerepilecopy(av, z); default: return gcopy(x); } } static GEN rnfid(long n, long m) { return matid_intern(n, col_ei(m,1), zerocol(m)); } /* x est exprime sur la base relative */ static GEN rnfprincipaltohermite(GEN rnf,GEN x) { pari_sp av = avma; GEN bas = gel(rnf,7), nf = gel(rnf,10); x = rnfbasistoalg(rnf,x); x = rnfalgtobasis(rnf, gmul(x, gmodulo(gel(bas,1), gel(rnf,1)))); settyp(x, t_MAT); return gerepileupto(av, nfhermite(nf, mkvec2(x, gel(bas,2)))); } GEN rnfidealhermite(GEN rnf, GEN x) { GEN z, nf, bas; checkrnf(rnf); nf = gel(rnf,10); switch(typ(x)) { case t_INT: case t_FRAC: bas = gel(rnf,7); z = cgetg(3,t_VEC); gel(z,1) = rnfid(degpol(rnf[1]), degpol(nf[1])); gel(z,2) = gmul(x, gel(bas,2)); return z; case t_VEC: if (lg(x) == 3 && typ(x[1]) == t_MAT) return nfhermite(nf, x); return rnfidealabstorel(rnf, x); case t_POLMOD: case t_POL: case t_COL: return rnfprincipaltohermite(rnf,x); } pari_err(typeer,"rnfidealhermite"); return NULL; /* not reached */ } GEN prodid(GEN nf, GEN I) { long i, l = lg(I); GEN z; if (l == 1) return matid(degpol(nf[1])); z = gel(I,1); for (i=2; i vector of 2 generators (relative polymods) */ GEN rnfidealtwoelement(GEN rnf, GEN x) { pari_sp av = avma; GEN y, z, NF; checkrnf(rnf); NF = check_and_build_nfabs(rnf); y = rnfidealreltoabs(rnf,x); y = algtobasis(NF, y); settyp(y, t_MAT); y = ideal_two_elt(NF, hnf(y)); z = rnfelementabstorel(rnf, gmul(gel(NF,7), gel(y,2))); return gerepilecopy(av, mkvec2(gel(y,1), z)); } GEN rnfidealmul(GEN rnf,GEN x,GEN y) /* x et y sous HNF relative uniquement */ { pari_sp av = avma; GEN z, nf, x1, x2, p1, p2; z = rnfidealtwoelement(rnf,y); nf = gel(rnf,10); x = rnfidealhermite(rnf,x); x1 = gmodulo(gmul(gmael(rnf,7,1), matbasistoalg(nf,gel(x,1))),gel(rnf,1)); x2 = gel(x,2); p1 = gmul(gel(z,1), gel(x,1)); p2 = rnfalgtobasis(rnf, gmul(gel(z,2), x1)); settyp(p2, t_MAT); z = mkvec2(shallowconcat(p1, p2), shallowconcat(x2, x2)); return gerepileupto(av, nfhermite(nf,z)); }