Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - basemath - base3.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31041-bd73e9fcdd) Lines: 95.0 % 2159 2051
Test Date: 2026-07-22 22:45:42 Functions: 95.4 % 237 226
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2000  The PARI group.
       2              : 
       3              : This file is part of the PARI/GP package.
       4              : 
       5              : PARI/GP is free software; you can redistribute it and/or modify it under the
       6              : terms of the GNU General Public License as published by the Free Software
       7              : Foundation; either version 2 of the License, or (at your option) any later
       8              : version. It is distributed in the hope that it will be useful, but WITHOUT
       9              : ANY WARRANTY WHATSOEVER.
      10              : 
      11              : Check the License for details. You should have received a copy of it, along
      12              : with the package; see the file 'COPYING'. If not, write to the Free Software
      13              : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
      14              : 
      15              : /*******************************************************************/
      16              : /*                                                                 */
      17              : /*                       BASIC NF OPERATIONS                       */
      18              : /*                                                                 */
      19              : /*******************************************************************/
      20              : #include "pari.h"
      21              : #include "paripriv.h"
      22              : 
      23              : #define DEBUGLEVEL DEBUGLEVEL_nf
      24              : 
      25              : /*******************************************************************/
      26              : /*                                                                 */
      27              : /*                OPERATIONS OVER NUMBER FIELD ELEMENTS.           */
      28              : /*     represented as column vectors over the integral basis       */
      29              : /*                                                                 */
      30              : /*******************************************************************/
      31              : static GEN
      32     40374135 : get_tab(GEN nf, long *N)
      33              : {
      34     40374135 :   GEN tab = (typ(nf) == t_MAT)? nf: gel(nf,9);
      35     40374135 :   *N = nbrows(tab); return tab;
      36              : }
      37              : 
      38              : /* x != 0, y t_INT. Return x * y (not memory clean if x = 1) */
      39              : static GEN
      40   1145605780 : _mulii(GEN x, GEN y) {
      41   1844922526 :   return is_pm1(x)? (signe(x) < 0)? negi(y): y
      42   1844745720 :                   : mulii(x, y);
      43              : }
      44              : 
      45              : GEN
      46         5834 : tablemul_ei_ej(GEN M, long i, long j)
      47              : {
      48              :   long N;
      49         5834 :   GEN tab = get_tab(M, &N);
      50         5834 :   tab += (i-1)*N; return gel(tab,j);
      51              : }
      52              : 
      53              : /* Outputs x.ei, where ei is the i-th elt of the algebra basis.
      54              :  * x an RgV of correct length and arbitrary content (polynomials, scalars...).
      55              :  * M is the multiplication table ei ej = sum_k M_k^(i,j) ek */
      56              : GEN
      57         4158 : tablemul_ei(GEN M, GEN x, long i)
      58              : {
      59              :   long j, k, N;
      60              :   GEN v, tab;
      61              : 
      62         4158 :   if (i==1) return gcopy(x);
      63         4158 :   tab = get_tab(M, &N);
      64         4158 :   if (typ(x) != t_COL) { v = zerocol(N); gel(v,i) = gcopy(x); return v; }
      65         4158 :   tab += (i-1)*N; v = cgetg(N+1,t_COL);
      66              :   /* wi . x = [ sum_j tab[k,j] x[j] ]_k */
      67        27020 :   for (k=1; k<=N; k++)
      68              :   {
      69        22862 :     pari_sp av = avma;
      70        22862 :     GEN s = gen_0;
      71       165396 :     for (j=1; j<=N; j++)
      72              :     {
      73       142534 :       GEN c = gcoeff(tab,k,j);
      74       142534 :       if (!gequal0(c)) s = gadd(s, gmul(c, gel(x,j)));
      75              :     }
      76        22862 :     gel(v,k) = gc_upto(av,s);
      77              :   }
      78         4158 :   return v;
      79              : }
      80              : /* as tablemul_ei, assume x a ZV of correct length */
      81              : GEN
      82     24730079 : zk_ei_mul(GEN nf, GEN x, long i)
      83              : {
      84              :   long j, k, N;
      85              :   GEN v, tab;
      86              : 
      87     24730079 :   if (i==1) return ZC_copy(x);
      88     24730079 :   tab = get_tab(nf, &N); tab += (i-1)*N;
      89     24730227 :   v = cgetg(N+1,t_COL);
      90    174356999 :   for (k=1; k<=N; k++)
      91              :   {
      92    149630806 :     pari_sp av = avma;
      93    149630806 :     GEN s = gen_0;
      94   2237644121 :     for (j=1; j<=N; j++)
      95              :     {
      96   2088154613 :       GEN c = gcoeff(tab,k,j);
      97   2088154613 :       if (signe(c)) s = addii(s, _mulii(c, gel(x,j)));
      98              :     }
      99    149489508 :     gel(v,k) = gc_INT(av, s);
     100              :   }
     101     24726193 :   return v;
     102              : }
     103              : 
     104              : /* table of multiplication by wi in R[w1,..., wN] */
     105              : GEN
     106        40121 : ei_multable(GEN TAB, long i)
     107              : {
     108              :   long k,N;
     109        40121 :   GEN m, tab = get_tab(TAB, &N);
     110        40121 :   tab += (i-1)*N;
     111        40121 :   m = cgetg(N+1,t_MAT);
     112       158521 :   for (k=1; k<=N; k++) gel(m,k) = gel(tab,k);
     113        40121 :   return m;
     114              : }
     115              : 
     116              : GEN
     117     11379310 : zk_multable(GEN nf, GEN x)
     118              : {
     119     11379310 :   long i, l = lg(x);
     120     11379310 :   GEN mul = cgetg(l,t_MAT);
     121     11379292 :   gel(mul,1) = x; /* assume w_1 = 1 */
     122     35738886 :   for (i=2; i<l; i++) gel(mul,i) = zk_ei_mul(nf,x,i);
     123     11375708 :   return mul;
     124              : }
     125              : GEN
     126         2058 : multable(GEN M, GEN x)
     127              : {
     128              :   long i, N;
     129              :   GEN mul;
     130         2058 :   if (typ(x) == t_MAT) return x;
     131            0 :   M = get_tab(M, &N);
     132            0 :   if (typ(x) != t_COL) return scalarmat(x, N);
     133            0 :   mul = cgetg(N+1,t_MAT);
     134            0 :   gel(mul,1) = x; /* assume w_1 = 1 */
     135            0 :   for (i=2; i<=N; i++) gel(mul,i) = tablemul_ei(M,x,i);
     136            0 :   return mul;
     137              : }
     138              : 
     139              : /* x integral in nf; table of multiplication by x in ZK = Z[w1,..., wN].
     140              :  * Return a t_INT if x is scalar, and a ZM otherwise */
     141              : GEN
     142      5358550 : zk_scalar_or_multable(GEN nf, GEN x)
     143              : {
     144      5358550 :   long tx = typ(x);
     145      5358550 :   if (tx == t_MAT || tx == t_INT) return x;
     146      5192657 :   x = nf_to_scalar_or_basis(nf, x);
     147      5192642 :   return (typ(x) == t_COL)? zk_multable(nf, x): x;
     148              : }
     149              : 
     150              : GEN
     151        22497 : nftrace(GEN nf, GEN x)
     152              : {
     153        22497 :   pari_sp av = avma;
     154        22497 :   nf = checknf(nf);
     155        22497 :   x = nf_to_scalar_or_basis(nf, x);
     156        22479 :   x = (typ(x) == t_COL)? RgV_dotproduct(x, gel(nf_get_Tr(nf),1))
     157        22500 :                        : gmulgu(x, nf_get_degree(nf));
     158        22500 :   return gc_upto(av, x);
     159              : }
     160              : GEN
     161         1050 : rnfelttrace(GEN rnf, GEN x)
     162              : {
     163         1050 :   pari_sp av = avma;
     164         1050 :   checkrnf(rnf);
     165              :   /* avoid rnfabstorel special t_POL case misinterpretation */
     166         1043 :   if (typ(x) == t_POL && varn(x) == rnf_get_varn(rnf))
     167           63 :     x = gmodulo(x, rnf_get_pol(rnf));
     168         1043 :   x = rnfeltabstorel(rnf, x);
     169          728 :   x = (typ(x) == t_POLMOD)? rnfeltdown(rnf, gtrace(x))
     170          833 :                           : gmulgu(x, rnf_get_degree(rnf));
     171          833 :   return gc_upto(av, x);
     172              : }
     173              : 
     174              : static GEN
     175           35 : famatQ_to_famatZ(GEN fa)
     176              : {
     177           35 :   GEN E, F, Q, P = gel(fa,1);
     178           35 :   long i, j, l = lg(P);
     179           35 :   if (l == 1 || RgV_is_ZV(P)) return fa;
     180            7 :   Q = cgetg(2*l, t_COL);
     181            7 :   F = cgetg(2*l, t_COL); E = gel(fa, 2);
     182           35 :   for (i = j = 1; i < l; i++)
     183              :   {
     184           28 :     GEN p = gel(P,i);
     185           28 :     if (typ(p) == t_INT)
     186           14 :     { gel(Q, j) = p; gel(F, j) = gel(E, i); j++; }
     187              :     else
     188              :     {
     189           14 :       gel(Q, j) = gel(p,1); gel(F, j) = gel(E, i); j++;
     190           14 :       gel(Q, j) = gel(p,2); gel(F, j) = negi(gel(E, i)); j++;
     191              :     }
     192              :   }
     193            7 :   setlg(Q, j); setlg(F, j); return mkmat2(Q, F);
     194              : }
     195              : static GEN
     196           35 : famat_cba(GEN fa)
     197              : {
     198           35 :   GEN Q, F, P = gel(fa, 1), E = gel(fa, 2);
     199           35 :   long i, j, lQ, l = lg(P);
     200           35 :   if (l == 1) return fa;
     201           28 :   Q = ZV_cba(P); lQ = lg(Q); settyp(Q, t_COL);
     202           28 :   F = cgetg(lQ, t_COL);
     203           77 :   for (j = 1; j < lQ; j++)
     204              :   {
     205           49 :     GEN v = gen_0, q = gel(Q,j);
     206           49 :     if (!equali1(q))
     207          203 :       for (i = 1; i < l; i++)
     208              :       {
     209          161 :         long e = Z_pval(gel(P,i), q);
     210          161 :         if (e) v = addii(v, muliu(gel(E,i), e));
     211              :       }
     212           49 :     gel(F, j) = v;
     213              :   }
     214           28 :   return mkmat2(Q, F);
     215              : }
     216              : static long
     217           35 : famat_sign(GEN fa)
     218              : {
     219           35 :   GEN P = gel(fa,1), E = gel(fa,2);
     220           35 :   long i, l = lg(P), s = 1;
     221          126 :   for (i = 1; i < l; i++)
     222           91 :     if (signe(gel(P,i)) < 0 && mpodd(gel(E,i))) s = -s;
     223           35 :   return s;
     224              : }
     225              : static GEN
     226           35 : famat_abs(GEN fa)
     227              : {
     228           35 :   GEN Q, P = gel(fa,1);
     229              :   long i, l;
     230           35 :   Q = cgetg_copy(P, &l);
     231          126 :   for (i = 1; i < l; i++) gel(Q,i) = absi_shallow(gel(P,i));
     232           35 :   return mkmat2(Q, gel(fa,2));
     233              : }
     234              : 
     235              : /* assume nf is a genuine nf, fa a famat */
     236              : static GEN
     237           35 : famat_norm(GEN nf, GEN fa)
     238              : {
     239           35 :   pari_sp av = avma;
     240           35 :   GEN G, g = gel(fa,1);
     241              :   long i, l, s;
     242              : 
     243           35 :   G = cgetg_copy(g, &l);
     244          112 :   for (i = 1; i < l; i++) gel(G,i) = nfnorm(nf, gel(g,i));
     245           35 :   fa = mkmat2(G, gel(fa,2));
     246           35 :   fa = famatQ_to_famatZ(fa);
     247           35 :   s = famat_sign(fa);
     248           35 :   fa = famat_reduce(famat_abs(fa));
     249           35 :   fa = famat_cba(fa);
     250           35 :   g = factorback(fa);
     251           35 :   return gc_upto(av, s < 0? gneg(g): g);
     252              : }
     253              : GEN
     254       216424 : nfnorm(GEN nf, GEN x)
     255              : {
     256       216424 :   pari_sp av = avma;
     257              :   GEN c, den;
     258              :   long n;
     259       216424 :   nf = checknf(nf);
     260       216424 :   n = nf_get_degree(nf);
     261       216424 :   if (typ(x) == t_MAT) return famat_norm(nf, x);
     262       216389 :   x = nf_to_scalar_or_basis(nf, x);
     263       216386 :   if (typ(x)!=t_COL)
     264       123495 :     return gc_upto(av, gpowgs(x, n));
     265        92891 :   x = nf_to_scalar_or_alg(nf, Q_primitive_part(x, &c));
     266        92893 :   x = Q_remove_denom(x, &den);
     267        92893 :   x = ZX_resultant_all(nf_get_pol(nf), x, den, 0);
     268        92893 :   return gc_upto(av, c ? gmul(x, gpowgs(c, n)): x);
     269              : }
     270              : 
     271              : static GEN
     272          119 : to_RgX(GEN P, long vx)
     273              : {
     274          119 :   return varn(P) == vx ? P: scalarpol_shallow(P, vx);
     275              : }
     276              : 
     277              : GEN
     278          462 : rnfeltnorm(GEN rnf, GEN x)
     279              : {
     280          462 :   pari_sp av = avma;
     281              :   GEN nf, pol;
     282              :   long v;
     283          462 :   checkrnf(rnf);
     284          455 :   v = rnf_get_varn(rnf);
     285              :   /* avoid rnfabstorel special t_POL case misinterpretation */
     286          455 :   if (typ(x) == t_POL && varn(x) == v) x = gmodulo(x, rnf_get_pol(rnf));
     287          455 :   x = liftpol_shallow(rnfeltabstorel(rnf, x));
     288          245 :   nf = rnf_get_nf(rnf); pol = rnf_get_pol(rnf);
     289          490 :   x = (typ(x) == t_POL)
     290          119 :     ? rnfeltdown(rnf, nfX_resultant(nf,pol,to_RgX(x,v)))
     291          245 :     : gpowgs(x, rnf_get_degree(rnf));
     292          245 :   return gc_upto(av, x);
     293              : }
     294              : 
     295              : /* x + y in nf */
     296              : GEN
     297     14282389 : nfadd(GEN nf, GEN x, GEN y)
     298              : {
     299     14282389 :   pari_sp av = avma;
     300              :   GEN z;
     301              : 
     302     14282389 :   nf = checknf(nf);
     303     14282389 :   x = nf_to_scalar_or_basis(nf, x);
     304     14282389 :   y = nf_to_scalar_or_basis(nf, y);
     305     14282389 :   if (typ(x) != t_COL)
     306     11157281 :   { z = (typ(y) == t_COL)? RgC_Rg_add(y, x): gadd(x,y); }
     307              :   else
     308      3125108 :   { z = (typ(y) == t_COL)? RgC_add(x, y): RgC_Rg_add(x, y); }
     309     14282388 :   return gc_upto(av, z);
     310              : }
     311              : /* x - y in nf */
     312              : GEN
     313      1432749 : nfsub(GEN nf, GEN x, GEN y)
     314              : {
     315      1432749 :   pari_sp av = avma;
     316              :   GEN z;
     317              : 
     318      1432749 :   nf = checknf(nf);
     319      1432749 :   x = nf_to_scalar_or_basis(nf, x);
     320      1432749 :   y = nf_to_scalar_or_basis(nf, y);
     321      1432749 :   if (typ(x) != t_COL)
     322      1172514 :   { z = (typ(y) == t_COL)? Rg_RgC_sub(x,y): gsub(x,y); }
     323              :   else
     324       260235 :   { z = (typ(y) == t_COL)? RgC_sub(x,y): RgC_Rg_sub(x,y); }
     325      1432749 :   return gc_upto(av, z);
     326              : }
     327              : 
     328              : /* product of ZC x,y in (true) nf; ( sum_i x_i sum_j y_j m^{i,j}_k )_k */
     329              : static GEN
     330      8246987 : nfmuli_ZC(GEN nf, GEN x, GEN y)
     331              : {
     332              :   long i, j, k, N;
     333      8246987 :   GEN TAB = get_tab(nf, &N), v = cgetg(N+1,t_COL);
     334              : 
     335     41449441 :   for (k = 1; k <= N; k++)
     336              :   {
     337     33202541 :     pari_sp av = avma;
     338     33202541 :     GEN s, TABi = TAB;
     339     33202541 :     if (k == 1)
     340      8246981 :       s = mulii(gel(x,1),gel(y,1));
     341              :     else
     342     24955379 :       s = addii(mulii(gel(x,1),gel(y,k)),
     343     24955560 :                 mulii(gel(x,k),gel(y,1)));
     344    223282281 :     for (i=2; i<=N; i++)
     345              :     {
     346    190083531 :       GEN t, xi = gel(x,i);
     347    190083531 :       TABi += N;
     348    190083531 :       if (!signe(xi)) continue;
     349              : 
     350     94603131 :       t = NULL;
     351   1086783280 :       for (j=2; j<=N; j++)
     352              :       {
     353    992181897 :         GEN p1, c = gcoeff(TABi, k, j); /* m^{i,j}_k */
     354    992181897 :         if (!signe(c)) continue;
     355    294239916 :         p1 = _mulii(c, gel(y,j));
     356    294244088 :         t = t? addii(t, p1): p1;
     357              :       }
     358     94601383 :       if (t) s = addii(s, mulii(xi, t));
     359              :     }
     360     33198750 :     gel(v,k) = gc_INT(av,s);
     361              :   }
     362      8246900 :   return v;
     363              : }
     364              : static int
     365     54069715 : is_famat(GEN x) { return typ(x) == t_MAT && lg(x) == 3; }
     366              : /* product of x and y in nf */
     367              : GEN
     368     24580799 : nfmul(GEN nf, GEN x, GEN y)
     369              : {
     370              :   GEN z;
     371     24580799 :   pari_sp av = avma;
     372              : 
     373     24580799 :   if (x == y) return nfsqr(nf,x);
     374              : 
     375     23325801 :   nf = checknf(nf);
     376     23325801 :   if (is_famat(x) || is_famat(y)) return famat_mul(x, y);
     377     23325492 :   x = nf_to_scalar_or_basis(nf, x);
     378     23325492 :   y = nf_to_scalar_or_basis(nf, y);
     379     23325491 :   if (typ(x) != t_COL)
     380              :   {
     381     16514608 :     if (isintzero(x)) return gen_0;
     382     13758924 :     z = (typ(y) == t_COL)? RgC_Rg_mul(y, x): gmul(x,y); }
     383              :   else
     384              :   {
     385      6810883 :     if (typ(y) != t_COL)
     386              :     {
     387      1892794 :       if (isintzero(y)) return gen_0;
     388      1047814 :       z = RgC_Rg_mul(x, y);
     389              :     }
     390              :     else
     391              :     {
     392              :       GEN dx, dy;
     393      4918089 :       x = Q_remove_denom(x, &dx);
     394      4918090 :       y = Q_remove_denom(y, &dy);
     395      4918090 :       z = nfmuli_ZC(nf,x,y);
     396      4918089 :       dx = mul_denom(dx,dy);
     397      4918089 :       if (dx) z = ZC_Z_div(z, dx);
     398              :     }
     399              :   }
     400     19724821 :   return gc_upto(av, z);
     401              : }
     402              : /* square of ZC x in nf */
     403              : static GEN
     404      7349760 : nfsqri_ZC(GEN nf, GEN x)
     405              : {
     406              :   long i, j, k, N;
     407      7349760 :   GEN TAB = get_tab(nf, &N), v = cgetg(N+1,t_COL);
     408              : 
     409     39772681 :   for (k = 1; k <= N; k++)
     410              :   {
     411     32422942 :     pari_sp av = avma;
     412     32422942 :     GEN s, TABi = TAB;
     413     32422942 :     if (k == 1)
     414      7349964 :       s = sqri(gel(x,1));
     415              :     else
     416     25072978 :       s = shifti(mulii(gel(x,1),gel(x,k)), 1);
     417    256784431 :     for (i=2; i<=N; i++)
     418              :     {
     419    224381098 :       GEN p1, c, t, xi = gel(x,i);
     420    224381098 :       TABi += N;
     421    224381098 :       if (!signe(xi)) continue;
     422              : 
     423     80586862 :       c = gcoeff(TABi, k, i);
     424     80586862 :       t = signe(c)? _mulii(c,xi): NULL;
     425    679252466 :       for (j=i+1; j<=N; j++)
     426              :       {
     427    598667082 :         c = gcoeff(TABi, k, j);
     428    598667082 :         if (!signe(c)) continue;
     429    233968508 :         p1 = _mulii(c, shifti(gel(x,j),1));
     430    233974124 :         t = t? addii(t, p1): p1;
     431              :       }
     432     80585384 :       if (t) s = addii(s, mulii(xi, t));
     433              :     }
     434     32403333 :     gel(v,k) = gc_INT(av,s);
     435              :   }
     436      7349739 :   return v;
     437              : }
     438              : /* square of x in nf */
     439              : GEN
     440      6108660 : nfsqr(GEN nf, GEN x)
     441              : {
     442      6108660 :   pari_sp av = avma;
     443              :   GEN z;
     444              : 
     445      6108660 :   nf = checknf(nf);
     446      6108661 :   if (is_famat(x)) return famat_sqr(x);
     447      6108663 :   x = nf_to_scalar_or_basis(nf, x);
     448      6108663 :   if (typ(x) != t_COL) z = gsqr(x);
     449              :   else
     450              :   {
     451              :     GEN dx;
     452      2644099 :     x = Q_remove_denom(x, &dx);
     453      2644100 :     z = nfsqri_ZC(nf,x);
     454      2644092 :     if (dx) z = RgC_Rg_div(z, sqri(dx));
     455              :   }
     456      6108656 :   return gc_upto(av, z);
     457              : }
     458              : 
     459              : /* x a ZC, v a t_COL of ZC/Z */
     460              : GEN
     461       194459 : zkC_multable_mul(GEN v, GEN x)
     462              : {
     463       194459 :   long i, l = lg(v);
     464       194459 :   GEN y = cgetg(l, t_COL);
     465       761671 :   for (i = 1; i < l; i++)
     466              :   {
     467       567212 :     GEN c = gel(v,i);
     468       567212 :     if (typ(c)!=t_COL) {
     469            0 :       if (!isintzero(c)) c = ZC_Z_mul(gel(x,1), c);
     470              :     } else {
     471       567212 :       c = ZM_ZC_mul(x,c);
     472       567212 :       if (ZV_isscalar(c)) c = gel(c,1);
     473              :     }
     474       567212 :     gel(y,i) = c;
     475              :   }
     476       194459 :   return y;
     477              : }
     478              : 
     479              : GEN
     480        31375 : nfC_multable_mul(GEN v, GEN x)
     481              : {
     482        31375 :   long i, l = lg(v);
     483        31375 :   GEN y = cgetg(l, t_COL);
     484       210577 :   for (i = 1; i < l; i++)
     485              :   {
     486       179202 :     GEN c = gel(v,i);
     487       179202 :     if (typ(c)!=t_COL) {
     488       141601 :       if (!isintzero(c)) c = RgC_Rg_mul(gel(x,1), c);
     489              :     } else {
     490        37601 :       c = RgM_RgC_mul(x,c);
     491        37601 :       if (QV_isscalar(c)) c = gel(c,1);
     492              :     }
     493       179202 :     gel(y,i) = c;
     494              :   }
     495        31375 :   return y;
     496              : }
     497              : 
     498              : GEN
     499       114287 : nfC_nf_mul(GEN nf, GEN v, GEN x)
     500              : {
     501              :   long tx;
     502              :   GEN y;
     503              : 
     504       114287 :   x = nf_to_scalar_or_basis(nf, x);
     505       114287 :   tx = typ(x);
     506       114287 :   if (tx != t_COL)
     507              :   {
     508              :     long l, i;
     509        85240 :     if (tx == t_INT)
     510              :     {
     511        81419 :       long s = signe(x);
     512        81419 :       if (!s) return zerocol(lg(v)-1);
     513        76479 :       if (is_pm1(x)) return s > 0? leafcopy(v): RgC_neg(v);
     514              :     }
     515        27215 :     l = lg(v); y = cgetg(l, t_COL);
     516       199154 :     for (i=1; i < l; i++)
     517              :     {
     518       171939 :       GEN c = gel(v,i);
     519       171939 :       if (typ(c) != t_COL) c = gmul(c, x); else c = RgC_Rg_mul(c, x);
     520       171939 :       gel(y,i) = c;
     521              :     }
     522        27215 :     return y;
     523              :   }
     524              :   else
     525              :   {
     526              :     GEN dx;
     527        29047 :     x = zk_multable(nf, Q_remove_denom(x,&dx));
     528        29047 :     y = nfC_multable_mul(v, x);
     529        29047 :     return dx? RgC_Rg_div(y, dx): y;
     530              :   }
     531              : }
     532              : static GEN
     533         7300 : mulbytab(GEN M, GEN c)
     534         7300 : { return typ(c) == t_COL? RgM_RgC_mul(M,c): RgC_Rg_mul(gel(M,1), c); }
     535              : GEN
     536         2058 : tablemulvec(GEN M, GEN x, GEN v)
     537              : {
     538              :   long l, i;
     539              :   GEN y;
     540              : 
     541         2058 :   if (typ(x) == t_COL && RgV_isscalar(x))
     542              :   {
     543            0 :     x = gel(x,1);
     544            0 :     return typ(v) == t_POL? RgX_Rg_mul(v,x): RgV_Rg_mul(v,x);
     545              :   }
     546         2058 :   x = multable(M, x); /* multiplication table by x */
     547         2058 :   y = cgetg_copy(v, &l);
     548         2058 :   if (typ(v) == t_POL)
     549              :   {
     550         2058 :     y[1] = v[1];
     551         9358 :     for (i=2; i < l; i++) gel(y,i) = mulbytab(x, gel(v,i));
     552         2058 :     y = normalizepol(y);
     553              :   }
     554              :   else
     555              :   {
     556            0 :     for (i=1; i < l; i++) gel(y,i) = mulbytab(x, gel(v,i));
     557              :   }
     558         2058 :   return y;
     559              : }
     560              : 
     561              : GEN
     562      1330594 : zkmultable_capZ(GEN mx) { return Q_denom(zkmultable_inv(mx)); }
     563              : GEN
     564      1639928 : zkmultable_inv(GEN mx) { return ZM_gauss(mx, col_ei(lg(mx)-1,1)); }
     565              : /* nf a true nf, x a ZC */
     566              : GEN
     567       309335 : zk_inv(GEN nf, GEN x) { return zkmultable_inv(zk_multable(nf,x)); }
     568              : 
     569              : /* inverse of x in nf */
     570              : GEN
     571       188896 : nfinv(GEN nf, GEN x)
     572              : {
     573       188896 :   pari_sp av = avma;
     574              :   GEN z;
     575              : 
     576       188896 :   nf = checknf(nf);
     577       188896 :   if (is_famat(x)) return famat_inv(x);
     578       188896 :   x = nf_to_scalar_or_basis(nf, x);
     579       188896 :   if (typ(x) == t_COL)
     580              :   {
     581              :     GEN d;
     582       173232 :     x = Q_remove_denom(x, &d);
     583       173232 :     z = zk_inv(nf, x);
     584       173232 :     if (d) z = RgC_Rg_mul(z, d);
     585              :   }
     586              :   else
     587        15664 :     z = ginv(x);
     588       188896 :   return gc_upto(av, z);
     589              : }
     590              : 
     591              : /* quotient of x and y in nf */
     592              : GEN
     593        40151 : nfdiv(GEN nf, GEN x, GEN y)
     594              : {
     595        40151 :   pari_sp av = avma;
     596              :   GEN z;
     597              : 
     598        40151 :   nf = checknf(nf);
     599        40151 :   if (is_famat(x) || is_famat(y)) return famat_div(x,y);
     600        40060 :   y = nf_to_scalar_or_basis(nf, y);
     601        40060 :   if (typ(y) != t_COL)
     602              :   {
     603        19887 :     x = nf_to_scalar_or_basis(nf, x);
     604        19887 :     z = (typ(x) == t_COL)? RgC_Rg_div(x, y): gdiv(x,y);
     605              :   }
     606              :   else
     607              :   {
     608              :     GEN d;
     609        20173 :     y = Q_remove_denom(y, &d);
     610        20173 :     z = nfmul(nf, x, zk_inv(nf,y));
     611        20173 :     if (d) z = typ(z) == t_COL? RgC_Rg_mul(z, d): gmul(z, d);
     612              :   }
     613        40060 :   return gc_upto(av, z);
     614              : }
     615              : 
     616              : /* product of INTEGERS (t_INT or ZC) x and y in (true) nf */
     617              : GEN
     618      4817722 : nfmuli(GEN nf, GEN x, GEN y)
     619              : {
     620      4817722 :   if (typ(x) == t_INT) return (typ(y) == t_COL)? ZC_Z_mul(y, x): mulii(x,y);
     621      3584514 :   if (typ(y) == t_INT) return ZC_Z_mul(x, y);
     622      3328840 :   return nfmuli_ZC(nf, x, y);
     623              : }
     624              : GEN
     625      4705714 : nfsqri(GEN nf, GEN x)
     626      4705714 : { return (typ(x) == t_INT)? sqri(x): nfsqri_ZC(nf, x); }
     627              : 
     628              : /* both x and y are RgV */
     629              : GEN
     630            0 : tablemul(GEN TAB, GEN x, GEN y)
     631              : {
     632              :   long i, j, k, N;
     633              :   GEN s, v;
     634            0 :   if (typ(x) != t_COL) return gmul(x, y);
     635            0 :   if (typ(y) != t_COL) return gmul(y, x);
     636            0 :   N = lg(x)-1;
     637            0 :   v = cgetg(N+1,t_COL);
     638            0 :   for (k=1; k<=N; k++)
     639              :   {
     640            0 :     pari_sp av = avma;
     641            0 :     GEN TABi = TAB;
     642            0 :     if (k == 1)
     643            0 :       s = gmul(gel(x,1),gel(y,1));
     644              :     else
     645            0 :       s = gadd(gmul(gel(x,1),gel(y,k)),
     646            0 :                gmul(gel(x,k),gel(y,1)));
     647            0 :     for (i=2; i<=N; i++)
     648              :     {
     649            0 :       GEN t, xi = gel(x,i);
     650            0 :       TABi += N;
     651            0 :       if (gequal0(xi)) continue;
     652              : 
     653            0 :       t = NULL;
     654            0 :       for (j=2; j<=N; j++)
     655              :       {
     656            0 :         GEN p1, c = gcoeff(TABi, k, j); /* m^{i,j}_k */
     657            0 :         if (gequal0(c)) continue;
     658            0 :         p1 = gmul(c, gel(y,j));
     659            0 :         t = t? gadd(t, p1): p1;
     660              :       }
     661            0 :       if (t) s = gadd(s, gmul(xi, t));
     662              :     }
     663            0 :     gel(v,k) = gc_upto(av,s);
     664              :   }
     665            0 :   return v;
     666              : }
     667              : GEN
     668        10356 : tablesqr(GEN TAB, GEN x)
     669              : {
     670              :   long i, j, k, N;
     671              :   GEN s, v;
     672              : 
     673        10356 :   if (typ(x) != t_COL) return gsqr(x);
     674        10356 :   N = lg(x)-1;
     675        10356 :   v = cgetg(N+1,t_COL);
     676              : 
     677        83106 :   for (k=1; k<=N; k++)
     678              :   {
     679        72750 :     pari_sp av = avma;
     680        72750 :     GEN TABi = TAB;
     681        72750 :     if (k == 1)
     682        10356 :       s = gsqr(gel(x,1));
     683              :     else
     684        62394 :       s = gmul2n(gmul(gel(x,1),gel(x,k)), 1);
     685       558276 :     for (i=2; i<=N; i++)
     686              :     {
     687       485526 :       GEN p1, c, t, xi = gel(x,i);
     688       485526 :       TABi += N;
     689       485526 :       if (gequal0(xi)) continue;
     690              : 
     691       140138 :       c = gcoeff(TABi, k, i);
     692       140138 :       t = !gequal0(c)? gmul(c,xi): NULL;
     693       652832 :       for (j=i+1; j<=N; j++)
     694              :       {
     695       512694 :         c = gcoeff(TABi, k, j);
     696       512694 :         if (gequal0(c)) continue;
     697       248752 :         p1 = gmul(gmul2n(c,1), gel(x,j));
     698       248752 :         t = t? gadd(t, p1): p1;
     699              :       }
     700       140138 :       if (t) s = gadd(s, gmul(xi, t));
     701              :     }
     702        72750 :     gel(v,k) = gc_upto(av,s);
     703              :   }
     704        10356 :   return v;
     705              : }
     706              : 
     707              : static GEN
     708       398768 : _mul(void *data, GEN x, GEN y) { return nfmuli((GEN)data,x,y); }
     709              : static GEN
     710      1061744 : _sqr(void *data, GEN x) { return nfsqri((GEN)data,x); }
     711              : 
     712              : /* Compute z^n in nf, left-shift binary powering */
     713              : GEN
     714      1025577 : nfpow(GEN nf, GEN z, GEN n)
     715              : {
     716      1025577 :   pari_sp av = avma;
     717              :   long s;
     718              :   GEN x, cx;
     719              : 
     720      1025577 :   if (typ(n)!=t_INT) pari_err_TYPE("nfpow",n);
     721      1025577 :   nf = checknf(nf);
     722      1025576 :   s = signe(n); if (!s) return gen_1;
     723      1025576 :   if (is_famat(z)) return famat_pow(z, n);
     724       964935 :   x = nf_to_scalar_or_basis(nf, z);
     725       964942 :   if (typ(x) != t_COL) return powgi(x,n);
     726       838713 :   if (s < 0)
     727              :   { /* simplified nfinv */
     728              :     GEN d;
     729        46705 :     x = Q_remove_denom(x, &d);
     730        46705 :     x = zk_inv(nf, x);
     731        46705 :     x = primitive_part(x, &cx);
     732        46705 :     cx = mul_content(cx, d);
     733        46705 :     n = negi(n);
     734              :   }
     735              :   else
     736       792008 :     x = primitive_part(x, &cx);
     737       838691 :   x = gen_pow_i(x, n, (void*)nf, _sqr, _mul);
     738       838706 :   if (cx)
     739        48130 :     x = gc_upto(av, gmul(x, powgi(cx, n)));
     740              :   else
     741       790576 :     x = gc_GEN(av, x);
     742       838714 :   return x;
     743              : }
     744              : /* Compute z^n in nf, left-shift binary powering */
     745              : GEN
     746       370600 : nfpow_u(GEN nf, GEN z, ulong n)
     747              : {
     748       370600 :   pari_sp av = avma;
     749              :   GEN x, cx;
     750              : 
     751       370600 :   if (!n) return gen_1;
     752       370600 :   x = nf_to_scalar_or_basis(nf, z);
     753       370600 :   if (typ(x) != t_COL) return gpowgs(x,n);
     754       329777 :   x = primitive_part(x, &cx);
     755       329778 :   x = gen_powu_i(x, n, (void*)nf, _sqr, _mul);
     756       329777 :   if (cx)
     757              :   {
     758       113497 :     x = gmul(x, powgi(cx, utoipos(n)));
     759       113497 :     return gc_upto(av,x);
     760              :   }
     761       216280 :   return gc_GEN(av, x);
     762              : }
     763              : 
     764              : long
     765         2163 : nfissquare(GEN nf, GEN z, GEN *px)
     766              : {
     767         2163 :   pari_sp av = avma;
     768         2163 :   long v = fetch_var_higher();
     769              :   GEN R;
     770         2163 :   nf = checknf(nf);
     771         2163 :   if (nf_get_degree(nf) == 1)
     772              :   {
     773          210 :     z = algtobasis(nf, z);
     774          210 :     if (!issquareall(gel(z,1), px)) return gc_long(av, 0);
     775           21 :     if (px) *px = gc_upto(av, *px); else set_avma(av);
     776           21 :     return 1;
     777              :   }
     778         1953 :   z = nf_to_scalar_or_alg(nf, z);
     779         1953 :   R = nfroots(nf, deg2pol_shallow(gen_m1, gen_0, z, v));
     780         1953 :   delete_var(); if (lg(R) == 1) return gc_long(av, 0);
     781         1330 :   if (px) *px = gc_GEN(av, nf_to_scalar_or_basis(nf, gel(R,1)));
     782           14 :   else set_avma(av);
     783         1330 :   return 1;
     784              : }
     785              : 
     786              : long
     787        11702 : nfispower(GEN nf, GEN z, long n, GEN *px)
     788              : {
     789        11702 :   pari_sp av = avma;
     790        11702 :   long v = fetch_var_higher();
     791              :   GEN R;
     792        11702 :   nf = checknf(nf);
     793        11702 :   if (nf_get_degree(nf) == 1)
     794              :   {
     795          329 :     z = algtobasis(nf, z);
     796          329 :     if (!ispower(gel(z,1), stoi(n), px)) return gc_long(av, 0);
     797          147 :     if (px) *px = gc_upto(av, *px); else set_avma(av);
     798          147 :     return 1;
     799              :   }
     800        11373 :   if (n <= 0)
     801            0 :     pari_err_DOMAIN("nfeltispower","exponent","<=",gen_0,stoi(n));
     802        11373 :   z = nf_to_scalar_or_alg(nf, z);
     803        11373 :   if (n==1)
     804              :   {
     805            0 :     if (px) *px = gc_GEN(av, z);
     806            0 :     return 1;
     807              :   }
     808        11373 :   R = nfroots(nf, gsub(pol_xn(n, v), z));
     809        11373 :   delete_var(); if (lg(R) == 1) return gc_long(av, 0);
     810         3780 :   if (px) *px = gc_GEN(av, nf_to_scalar_or_basis(nf, gel(R,1)));
     811         3766 :   else set_avma(av);
     812         3780 :   return 1;
     813              : }
     814              : 
     815              : static GEN
     816           56 : idmulred(void *nf, GEN x, GEN y) { return idealmulred((GEN) nf, x, y); }
     817              : static GEN
     818          413 : idpowred(void *nf, GEN x, GEN n) { return idealpowred((GEN) nf, x, n); }
     819              : static GEN
     820        72020 : idmul(void *nf, GEN x, GEN y) { return idealmul((GEN) nf, x, y); }
     821              : static GEN
     822        87971 : idpow(void *nf, GEN x, GEN n) { return idealpow((GEN) nf, x, n); }
     823              : GEN
     824        94611 : idealfactorback(GEN nf, GEN L, GEN e, long red)
     825              : {
     826        94611 :   nf = checknf(nf);
     827        94611 :   if (red) return gen_factorback(L, e, (void*)nf, &idmulred, &idpowred, NULL);
     828        94254 :   if (!e && typ(L) == t_MAT && lg(L) == 3) { e = gel(L,2); L = gel(L,1); }
     829        94254 :   if (is_vec_t(typ(L)) && RgV_is_prV(L))
     830              :   { /* don't use gen_factorback since *= pr^v can be done more efficiently */
     831        73620 :     pari_sp av = avma;
     832        73620 :     long i, l = lg(L);
     833              :     GEN a;
     834        73620 :     if (!e) e = const_vec(l-1, gen_1);
     835        70757 :     else switch(typ(e))
     836              :     {
     837         7742 :       case t_VECSMALL: e = zv_to_ZV(e); break;
     838        63015 :       case t_VEC: case t_COL:
     839        63015 :         if (!RgV_is_ZV(e))
     840            0 :           pari_err_TYPE("factorback [not an exponent vector]", e);
     841        63015 :         break;
     842            0 :       default: pari_err_TYPE("idealfactorback", e);
     843              :     }
     844        73620 :     if (l != lg(e))
     845            0 :       pari_err_TYPE("factorback [not an exponent vector]", e);
     846        73620 :     if (l == 1 || ZV_equal0(e)) return gc_const(av, gen_1);
     847        23072 :     a = idealpow(nf, gel(L,1), gel(e,1));
     848       250469 :     for (i = 2; i < l; i++)
     849       227397 :       if (signe(gel(e,i))) a = idealmulpowprime(nf, a, gel(L,i), gel(e,i));
     850        23072 :     return gc_upto(av, a);
     851              :   }
     852        20634 :   return gen_factorback(L, e, (void*)nf, &idmul, &idpow, NULL);
     853              : }
     854              : static GEN
     855       350813 : eltmul(void *nf, GEN x, GEN y) { return nfmul((GEN) nf, x, y); }
     856              : static GEN
     857       499812 : eltpow(void *nf, GEN x, GEN n) { return nfpow((GEN) nf, x, n); }
     858              : GEN
     859       281075 : nffactorback(GEN nf, GEN L, GEN e)
     860       281075 : { return gen_factorback(L, e, (void*)checknf(nf), &eltmul, &eltpow, NULL); }
     861              : 
     862              : static GEN
     863       778543 : _nf_red(void *E, GEN x) { (void)E; return gcopy(x); }
     864              : 
     865              : static GEN
     866      3861892 : _nf_add(void *E, GEN x, GEN y) { return nfadd((GEN)E,x,y); }
     867              : 
     868              : static GEN
     869       204392 : _nf_neg(void *E, GEN x) { (void)E; return gneg(x); }
     870              : 
     871              : static GEN
     872      4502050 : _nf_mul(void *E, GEN x, GEN y) { return nfmul((GEN)E,x,y); }
     873              : 
     874              : static GEN
     875        13727 : _nf_inv(void *E, GEN x) { return nfinv((GEN)E,x); }
     876              : 
     877              : static GEN
     878         3353 : _nf_s(void *E, long x) { (void)E; return stoi(x); }
     879              : 
     880              : static const struct bb_field nf_field={_nf_red,_nf_add,_nf_mul,_nf_neg,
     881              :                                         _nf_inv,&gequal0,_nf_s };
     882              : 
     883        54830 : const struct bb_field *get_nf_field(void **E, GEN nf)
     884        54830 : { *E = (void*)nf; return &nf_field; }
     885              : 
     886              : GEN
     887           14 : nfM_det(GEN nf, GEN M)
     888              : {
     889              :   void *E;
     890           14 :   const struct bb_field *S = get_nf_field(&E, nf);
     891           14 :   return gen_det(M, E, S);
     892              : }
     893              : GEN
     894         3339 : nfM_inv(GEN nf, GEN M)
     895              : {
     896              :   void *E;
     897         3339 :   const struct bb_field *S = get_nf_field(&E, nf);
     898         3339 :   return gen_Gauss(M, matid(lg(M)-1), E, S);
     899              : }
     900              : 
     901              : GEN
     902            0 : nfM_ker(GEN nf, GEN M)
     903              : {
     904              :    void *E;
     905            0 :    const struct bb_field *S = get_nf_field(&E, nf);
     906            0 :    return gen_ker(M, 0, E, S);
     907              : }
     908              : 
     909              : GEN
     910         2948 : nfM_mul(GEN nf, GEN A, GEN B)
     911              : {
     912              :   void *E;
     913         2948 :   const struct bb_field *S = get_nf_field(&E, nf);
     914         2948 :   return gen_matmul(A, B, E, S);
     915              : }
     916              : GEN
     917        48529 : nfM_nfC_mul(GEN nf, GEN A, GEN B)
     918              : {
     919              :   void *E;
     920        48529 :   const struct bb_field *S = get_nf_field(&E, nf);
     921        48529 :   return gen_matcolmul(A, B, E, S);
     922              : }
     923              : 
     924              : /* valuation of integral x (ZV), with resp. to prime ideal pr */
     925              : long
     926     24763706 : ZC_nfvalrem(GEN x, GEN pr, GEN *newx)
     927              : {
     928     24763706 :   pari_sp av = avma;
     929              :   long i, v, l;
     930     24763706 :   GEN r, y, p = pr_get_p(pr), mul = pr_get_tau(pr);
     931              : 
     932              :   /* p inert */
     933     24763730 :   if (typ(mul) == t_INT) return newx? ZV_pvalrem(x, p, newx):ZV_pval(x, p);
     934     23761582 :   y = cgetg_copy(x, &l); /* will hold the new x */
     935     23761981 :   x = leafcopy(x);
     936     38519315 :   for(v=0;; v++)
     937              :   {
     938    146389090 :     for (i=1; i<l; i++)
     939              :     { /* is (x.b)[i] divisible by p ? */
     940    131626495 :       gel(y,i) = dvmdii(ZMrow_ZC_mul(mul,x,i),p,&r);
     941    131629783 :       if (r != gen_0) { if (newx) *newx = x; return v; }
     942              :     }
     943     14762595 :     swap(x, y);
     944     14762595 :     if (!newx && (v & 0xf) == 0xf) v += pr_get_e(pr) * ZV_pvalrem(x, p, &x);
     945     14762595 :     if (gc_needed(av,1))
     946              :     {
     947            0 :       if(DEBUGMEM>1) pari_warn(warnmem,"ZC_nfvalrem, v >= %ld", v);
     948            0 :       (void)gc_all(av, 2, &x, &y);
     949              :     }
     950              :   }
     951              : }
     952              : long
     953     20261500 : ZC_nfval(GEN x, GEN P)
     954     20261500 : { return ZC_nfvalrem(x, P, NULL); }
     955              : 
     956              : /* v_P(x) != 0, x a ZV. Simpler version of ZC_nfvalrem */
     957              : int
     958      1294475 : ZC_prdvd(GEN x, GEN P)
     959              : {
     960      1294475 :   pari_sp av = avma;
     961              :   long i, l;
     962      1294475 :   GEN p = pr_get_p(P), mul = pr_get_tau(P);
     963      1294492 :   if (typ(mul) == t_INT) return ZV_Z_dvd(x, p);
     964      1293925 :   l = lg(x);
     965      5204535 :   for (i=1; i<l; i++)
     966      4663341 :     if (!dvdii(ZMrow_ZC_mul(mul,x,i), p)) return gc_bool(av,0);
     967       541194 :   return gc_bool(av,1);
     968              : }
     969              : 
     970              : int
     971          357 : pr_equal(GEN P, GEN Q)
     972              : {
     973          357 :   GEN gQ, p = pr_get_p(P);
     974          357 :   long e = pr_get_e(P), f = pr_get_f(P), n;
     975          357 :   if (!equalii(p, pr_get_p(Q)) || e != pr_get_e(Q) || f != pr_get_f(Q))
     976          336 :     return 0;
     977           21 :   gQ = pr_get_gen(Q); n = lg(gQ)-1;
     978           21 :   if (2*e*f > n) return 1; /* room for only one such pr */
     979           14 :   return ZV_equal(pr_get_gen(P), gQ) || ZC_prdvd(gQ, P);
     980              : }
     981              : 
     982              : GEN
     983       422947 : famat_nfvalrem(GEN nf, GEN x, GEN pr, GEN *py)
     984              : {
     985       422947 :   pari_sp av = avma;
     986       422947 :   GEN P = gel(x,1), E = gel(x,2), V = gen_0, y = NULL;
     987       422947 :   long l = lg(P), simplify = 0, i;
     988       422947 :   if (py) { *py = gen_1; y = cgetg(l, t_COL); }
     989              : 
     990      2265071 :   for (i = 1; i < l; i++)
     991              :   {
     992      1842124 :     GEN e = gel(E,i);
     993              :     long v;
     994      1842124 :     if (!signe(e))
     995              :     {
     996            7 :       if (py) gel(y,i) = gen_1;
     997            7 :       simplify = 1; continue;
     998              :     }
     999      1842117 :     v = nfvalrem(nf, gel(P,i), pr, py? &gel(y,i): NULL);
    1000      1842117 :     if (v == LONG_MAX) { set_avma(av); if (py) *py = gen_0; return mkoo(); }
    1001      1842117 :     V = addmulii(V, stoi(v), e);
    1002              :   }
    1003       422947 :   if (!py) V = gc_INT(av, V);
    1004              :   else
    1005              :   {
    1006           56 :     y = mkmat2(y, gel(x,2));
    1007           56 :     if (simplify) y = famat_remove_trivial(y);
    1008           56 :     (void)gc_all(av, 2, &V, &y); *py = y;
    1009              :   }
    1010       422947 :   return V;
    1011              : }
    1012              : long
    1013      5614563 : nfval(GEN nf, GEN x, GEN pr)
    1014              : {
    1015      5614563 :   pari_sp av = avma;
    1016              :   long w, e;
    1017              :   GEN cx, p;
    1018              : 
    1019      5614563 :   if (gequal0(x)) return LONG_MAX;
    1020      5601723 :   nf = checknf(nf);
    1021      5601722 :   checkprid(pr);
    1022      5601713 :   p = pr_get_p(pr);
    1023      5601710 :   e = pr_get_e(pr);
    1024      5601707 :   x = nf_to_scalar_or_basis(nf, x);
    1025      5601664 :   if (typ(x) != t_COL) return e*Q_pval(x,p);
    1026      2377985 :   x = Q_primitive_part(x, &cx);
    1027      2377999 :   w = ZC_nfval(x,pr);
    1028      2377940 :   if (cx) w += e*Q_pval(cx,p);
    1029      2377941 :   return gc_long(av,w);
    1030              : }
    1031              : 
    1032              : /* want to write p^v = uniformizer^(e*v) * z^v, z coprime to pr */
    1033              : /* z := tau^e / p^(e-1), algebraic integer coprime to pr; return z^v */
    1034              : static GEN
    1035       973434 : powp(GEN nf, GEN pr, long v)
    1036              : {
    1037              :   GEN b, z;
    1038              :   long e;
    1039       973434 :   if (!v) return gen_1;
    1040       446824 :   b = pr_get_tau(pr);
    1041       446824 :   if (typ(b) == t_INT) return gen_1;
    1042       131299 :   e = pr_get_e(pr);
    1043       131299 :   z = gel(b,1);
    1044       131299 :   if (e != 1) z = gdiv(nfpow_u(nf, z, e), powiu(pr_get_p(pr),e-1));
    1045       131299 :   if (v < 0) { v = -v; z = nfinv(nf, z); }
    1046       131299 :   if (v != 1) z = nfpow_u(nf, z, v);
    1047       131299 :   return z;
    1048              : }
    1049              : long
    1050      3666399 : nfvalrem(GEN nf, GEN x, GEN pr, GEN *py)
    1051              : {
    1052      3666399 :   pari_sp av = avma;
    1053              :   long w, e;
    1054              :   GEN cx, p, t;
    1055              : 
    1056      3666399 :   if (!py) return nfval(nf,x,pr);
    1057      1810919 :   if (gequal0(x)) { *py = gen_0; return LONG_MAX; }
    1058      1810863 :   nf = checknf(nf);
    1059      1810861 :   checkprid(pr);
    1060      1810861 :   p = pr_get_p(pr);
    1061      1810859 :   e = pr_get_e(pr);
    1062      1810859 :   x = nf_to_scalar_or_basis(nf, x);
    1063      1810858 :   if (typ(x) != t_COL) {
    1064       557858 :     w = Q_pvalrem(x,p, py);
    1065       557858 :     if (!w) { *py = gc_GEN(av, x); return 0; }
    1066       349279 :     *py = gc_upto(av, gmul(powp(nf, pr, w), *py));
    1067       349279 :     return e*w;
    1068              :   }
    1069      1253000 :   x = Q_primitive_part(x, &cx);
    1070      1252994 :   w = ZC_nfvalrem(x,pr, py);
    1071      1252991 :   if (cx)
    1072              :   {
    1073       624155 :     long v = Q_pvalrem(cx,p, &t);
    1074       624155 :     *py = nfmul(nf, *py, gmul(powp(nf,pr,v), t));
    1075       624155 :     *py = gc_upto(av, *py);
    1076       624155 :     w += e*v;
    1077              :   }
    1078              :   else
    1079       628836 :     *py = gc_GEN(av, *py);
    1080      1253005 :   return w;
    1081              : }
    1082              : GEN
    1083        15015 : gpnfvalrem(GEN nf, GEN x, GEN pr, GEN *py)
    1084              : {
    1085              :   long v;
    1086        15015 :   if (is_famat(x)) return famat_nfvalrem(nf, x, pr, py);
    1087        15008 :   v = nfvalrem(nf,x,pr,py);
    1088        15008 :   return v == LONG_MAX? mkoo(): stoi(v);
    1089              : }
    1090              : 
    1091              : GEN
    1092       226047 : basistoalg(GEN nf, GEN x)
    1093              : {
    1094              :   GEN T;
    1095              : 
    1096       226047 :   nf = checknf(nf);
    1097       226047 :   switch(typ(x))
    1098              :   {
    1099       142578 :     case t_COL: {
    1100       142578 :       pari_sp av = avma; x = nf_to_scalar_or_alg(nf, x);
    1101       142571 :       return gc_GEN(av, mkpolmod(x, nf_get_pol(nf)));
    1102              :     }
    1103        45563 :     case t_POLMOD:
    1104        45563 :       T = nf_get_pol(nf);
    1105        45563 :       if (!RgX_equal_var(T,gel(x,1)))
    1106            0 :         pari_err_MODULUS("basistoalg", T,gel(x,1));
    1107        45563 :       return gcopy(x);
    1108         4865 :     case t_POL:
    1109         4865 :       T = nf_get_pol(nf);
    1110         4865 :       if (varn(T) != varn(x)) pari_err_VAR("basistoalg",x,T);
    1111         4858 :       retmkpolmod(RgX_rem(x, T), ZX_copy(T));
    1112        33041 :     case t_INT:
    1113              :     case t_FRAC:
    1114        33041 :       T = nf_get_pol(nf);
    1115        33041 :       retmkpolmod(gcopy(x), ZX_copy(T));
    1116            0 :     default:
    1117            0 :       pari_err_TYPE("basistoalg",x);
    1118              :       return NULL; /* LCOV_EXCL_LINE */
    1119              :   }
    1120              : }
    1121              : 
    1122              : /* true nf, x a t_POL */
    1123              : static GEN
    1124      3480123 : pol_to_scalar_or_basis(GEN nf, GEN x)
    1125              : {
    1126      3480123 :   GEN T = nf_get_pol(nf);
    1127      3480121 :   long l = lg(x);
    1128      3480121 :   if (varn(x) != varn(T)) pari_err_VAR("nf_to_scalar_or_basis", x,T);
    1129      3480016 :   if (l >= lg(T)) { x = RgX_rem(x, T); l = lg(x); }
    1130      3480016 :   if (l == 2) return gen_0;
    1131      3016749 :   if (l == 3)
    1132              :   {
    1133       677516 :     x = gel(x,2);
    1134       677516 :     if (!is_rational_t(typ(x))) pari_err_TYPE("nf_to_scalar_or_basis",x);
    1135       677509 :     return x;
    1136              :   }
    1137      2339233 :   return poltobasis(nf,x);
    1138              : }
    1139              : /* Assume nf is a genuine nf. */
    1140              : GEN
    1141    123900087 : nf_to_scalar_or_basis(GEN nf, GEN x)
    1142              : {
    1143    123900087 :   switch(typ(x))
    1144              :   {
    1145     71140589 :     case t_INT: case t_FRAC:
    1146     71140589 :       return x;
    1147       525473 :     case t_POLMOD:
    1148       525473 :       x = checknfelt_mod(nf,x,"nf_to_scalar_or_basis");
    1149       525342 :       switch(typ(x))
    1150              :       {
    1151        38605 :         case t_INT: case t_FRAC: return x;
    1152       486737 :         case t_POL: return pol_to_scalar_or_basis(nf,x);
    1153              :       }
    1154            0 :       break;
    1155      2993387 :     case t_POL: return pol_to_scalar_or_basis(nf,x);
    1156     49245339 :     case t_COL:
    1157     49245339 :       if (lg(x)-1 != nf_get_degree(nf)) break;
    1158     49245179 :       return QV_isscalar(x)? gel(x,1): x;
    1159              :   }
    1160           96 :   pari_err_TYPE("nf_to_scalar_or_basis",x);
    1161              :   return NULL; /* LCOV_EXCL_LINE */
    1162              : }
    1163              : /* Let x be a polynomial with coefficients in Q or nf. Return the same
    1164              :  * polynomial with coefficients expressed as vectors (on the integral basis).
    1165              :  * No consistency checks, not memory-clean. */
    1166              : GEN
    1167        33750 : RgX_to_nfX(GEN nf, GEN x)
    1168       258721 : { pari_APPLY_pol_normalized(nf_to_scalar_or_basis(nf, gel(x,i))); }
    1169              : 
    1170              : /* Assume nf is a genuine nf. */
    1171              : GEN
    1172      7169074 : nf_to_scalar_or_alg(GEN nf, GEN x)
    1173              : {
    1174      7169074 :   switch(typ(x))
    1175              :   {
    1176      1921555 :     case t_INT: case t_FRAC:
    1177      1921555 :       return x;
    1178        94689 :     case t_POLMOD:
    1179        94689 :       x = checknfelt_mod(nf,x,"nf_to_scalar_or_alg");
    1180        94689 :       if (typ(x) != t_POL) return x;
    1181              :       /* fall through */
    1182              :     case t_POL:
    1183              :     {
    1184       100443 :       GEN T = nf_get_pol(nf);
    1185       100443 :       long l = lg(x);
    1186       100443 :       if (varn(x) != varn(T)) pari_err_VAR("nf_to_scalar_or_alg", x,T);
    1187       100443 :       if (l >= lg(T)) { x = RgX_rem(x, T); l = lg(x); }
    1188       100443 :       if (l == 2) return gen_0;
    1189       100380 :       if (l == 3) return gel(x,2);
    1190        98665 :       return x;
    1191              :     }
    1192      5146091 :     case t_COL:
    1193              :     {
    1194              :       GEN dx;
    1195      5146091 :       if (lg(x)-1 != nf_get_degree(nf)) break;
    1196     10191007 :       if (QV_isscalar(x)) return gel(x,1);
    1197      5044743 :       x = Q_remove_denom(x, &dx);
    1198      5044797 :       x = RgV_RgC_mul(nf_get_zkprimpart(nf), x);
    1199      5044915 :       dx = mul_denom(dx, nf_get_zkden(nf));
    1200      5044898 :       return gdiv(x,dx);
    1201              :     }
    1202              :   }
    1203           54 :   pari_err_TYPE("nf_to_scalar_or_alg",x);
    1204              :   return NULL; /* LCOV_EXCL_LINE */
    1205              : }
    1206              : 
    1207              : /* Assume nf is a genuine nf. */
    1208              : GEN
    1209      2134874 : nf_to_scalar_or_polmod(GEN nf, GEN x)
    1210              : {
    1211      2134874 :   x = nf_to_scalar_or_alg(nf, x);
    1212      2134874 :   if (typ(x) == t_POL && varn(x) == nf_get_varn(nf))
    1213       281358 :     x = mkpolmod(x, nf_get_pol(nf));
    1214      2134874 :   return x;
    1215              : }
    1216              : 
    1217              : /* gmul(A, RgX_to_RgC(x)), A t_MAT of compatible dimensions */
    1218              : GEN
    1219         1365 : RgM_RgX_mul(GEN A, GEN x)
    1220              : {
    1221         1365 :   long i, l = lg(x)-1;
    1222              :   GEN z;
    1223         1365 :   if (l == 1) return zerocol(nbrows(A));
    1224         1351 :   z = gmul(gel(x,2), gel(A,1));
    1225         2555 :   for (i = 2; i < l; i++)
    1226         1204 :     if (!gequal0(gel(x,i+1))) z = gadd(z, gmul(gel(x,i+1), gel(A,i)));
    1227         1351 :   return z;
    1228              : }
    1229              : GEN
    1230     10291684 : ZM_ZX_mul(GEN A, GEN x)
    1231              : {
    1232     10291684 :   long i, l = lg(x)-1;
    1233              :   GEN z;
    1234     10291684 :   if (l == 1) return zerocol(nbrows(A));
    1235     10290354 :   z = ZC_Z_mul(gel(A,1), gel(x,2));
    1236     33522004 :   for (i = 2; i < l ; i++)
    1237     23239029 :     if (signe(gel(x,i+1))) z = ZC_add(z, ZC_Z_mul(gel(A,i), gel(x,i+1)));
    1238     10282975 :   return z;
    1239              : }
    1240              : /* x a t_POL, nf a genuine nf. No garbage collecting. No check.  */
    1241              : GEN
    1242      9652545 : poltobasis(GEN nf, GEN x)
    1243              : {
    1244      9652545 :   GEN d, T = nf_get_pol(nf);
    1245      9652519 :   if (varn(x) != varn(T)) pari_err_VAR( "poltobasis", x,T);
    1246      9652386 :   if (degpol(x) >= degpol(T)) x = RgX_rem(x,T);
    1247      9652435 :   x = Q_remove_denom(x, &d);
    1248      9652618 :   if (!RgX_is_ZX(x)) pari_err_TYPE("poltobasis",x);
    1249      9652563 :   x = ZM_ZX_mul(nf_get_invzk(nf), x);
    1250      9650390 :   if (d) x = RgC_Rg_div(x, d);
    1251      9650504 :   return x;
    1252              : }
    1253              : 
    1254              : GEN
    1255       975426 : algtobasis(GEN nf, GEN x)
    1256              : {
    1257              :   pari_sp av;
    1258              : 
    1259       975426 :   nf = checknf(nf);
    1260       975424 :   switch(typ(x))
    1261              :   {
    1262       153854 :     case t_POLMOD:
    1263       153854 :       if (!RgX_equal_var(nf_get_pol(nf),gel(x,1)))
    1264            7 :         pari_err_MODULUS("algtobasis", nf_get_pol(nf),gel(x,1));
    1265       153847 :       x = gel(x,2);
    1266       153847 :       switch(typ(x))
    1267              :       {
    1268        12635 :         case t_INT:
    1269        12635 :         case t_FRAC: return scalarcol(x, nf_get_degree(nf));
    1270       141212 :         case t_POL:
    1271       141212 :           av = avma;
    1272       141212 :           return gc_upto(av,poltobasis(nf,x));
    1273              :       }
    1274            0 :       break;
    1275              : 
    1276       252912 :     case t_POL:
    1277       252912 :       av = avma;
    1278       252912 :       return gc_upto(av,poltobasis(nf,x));
    1279              : 
    1280        85750 :     case t_COL:
    1281        85750 :       if (!RgV_is_QV(x)) pari_err_TYPE("nfalgtobasis",x);
    1282        85744 :       if (lg(x)-1 != nf_get_degree(nf)) pari_err_DIM("nfalgtobasis");
    1283        85744 :       return gcopy(x);
    1284              : 
    1285       482910 :     case t_INT:
    1286       482910 :     case t_FRAC: return scalarcol(x, nf_get_degree(nf));
    1287              :   }
    1288            0 :   pari_err_TYPE("algtobasis",x);
    1289              :   return NULL; /* LCOV_EXCL_LINE */
    1290              : }
    1291              : 
    1292              : GEN
    1293        61264 : rnfbasistoalg(GEN rnf,GEN x)
    1294              : {
    1295        61264 :   const char *f = "rnfbasistoalg";
    1296              :   long lx, i;
    1297        61264 :   pari_sp av = avma;
    1298              :   GEN z, nf, R, T;
    1299              : 
    1300        61264 :   checkrnf(rnf);
    1301        61264 :   nf = rnf_get_nf(rnf);
    1302        61264 :   T = nf_get_pol(nf);
    1303        61264 :   R = QXQX_to_mod_shallow(rnf_get_pol(rnf), T);
    1304        61264 :   switch(typ(x))
    1305              :   {
    1306          875 :     case t_COL:
    1307          875 :       z = cgetg_copy(x, &lx);
    1308         2597 :       for (i=1; i<lx; i++)
    1309              :       {
    1310         1778 :         GEN c = nf_to_scalar_or_alg(nf, gel(x,i));
    1311         1722 :         if (typ(c) == t_POL) c = mkpolmod(c,T);
    1312         1722 :         gel(z,i) = c;
    1313              :       }
    1314          819 :       z = RgV_RgC_mul(gel(rnf_get_zk(rnf),1), z);
    1315          735 :       return gc_upto(av, gmodulo(z,R));
    1316              : 
    1317        37555 :     case t_POLMOD:
    1318        37555 :       x = polmod_nffix(f, rnf, x, 0);
    1319        37282 :       if (typ(x) != t_POL) break;
    1320        17549 :       retmkpolmod(RgX_copy(x), RgX_copy(R));
    1321         1841 :     case t_POL:
    1322         1841 :       if (varn(x) == varn(T)) { RgX_check_QX(x,f); x = gmodulo(x,T); break; }
    1323         1596 :       if (varn(x) == varn(R))
    1324              :       {
    1325         1540 :         x = RgX_nffix(f,nf_get_pol(nf),x,0);
    1326         1540 :         return gmodulo(x, R);
    1327              :       }
    1328           56 :       pari_err_VAR(f, x,R);
    1329              :   }
    1330        40915 :   retmkpolmod(scalarpol(x, varn(R)), RgX_copy(R));
    1331              : }
    1332              : 
    1333              : GEN
    1334         3220 : matbasistoalg(GEN nf,GEN x)
    1335              : {
    1336              :   long i, j, li, lx;
    1337         3220 :   GEN z = cgetg_copy(x, &lx);
    1338              : 
    1339         3220 :   if (lx == 1) return z;
    1340         3213 :   switch(typ(x))
    1341              :   {
    1342           91 :     case t_VEC: case t_COL:
    1343          371 :       for (i=1; i<lx; i++) gel(z,i) = basistoalg(nf, gel(x,i));
    1344           91 :       return z;
    1345         3122 :     case t_MAT: break;
    1346            0 :     default: pari_err_TYPE("matbasistoalg",x);
    1347              :   }
    1348         3122 :   li = lgcols(x);
    1349        11018 :   for (j=1; j<lx; j++)
    1350              :   {
    1351         7896 :     GEN c = cgetg(li,t_COL), xj = gel(x,j);
    1352         7896 :     gel(z,j) = c;
    1353        33943 :     for (i=1; i<li; i++) gel(c,i) = basistoalg(nf, gel(xj,i));
    1354              :   }
    1355         3122 :   return z;
    1356              : }
    1357              : 
    1358              : GEN
    1359        33258 : matalgtobasis(GEN nf,GEN x)
    1360              : {
    1361              :   long i, j, li, lx;
    1362        33258 :   GEN z = cgetg_copy(x, &lx);
    1363              : 
    1364        33258 :   if (lx == 1) return z;
    1365        32789 :   switch(typ(x))
    1366              :   {
    1367        32782 :     case t_VEC: case t_COL:
    1368        86240 :       for (i=1; i<lx; i++) gel(z,i) = algtobasis(nf, gel(x,i));
    1369        32782 :       return z;
    1370            7 :     case t_MAT: break;
    1371            0 :     default: pari_err_TYPE("matalgtobasis",x);
    1372              :   }
    1373            7 :   li = lgcols(x);
    1374           14 :   for (j=1; j<lx; j++)
    1375              :   {
    1376            7 :     GEN c = cgetg(li,t_COL), xj = gel(x,j);
    1377            7 :     gel(z,j) = c;
    1378           21 :     for (i=1; i<li; i++) gel(c,i) = algtobasis(nf, gel(xj,i));
    1379              :   }
    1380            7 :   return z;
    1381              : }
    1382              : GEN
    1383         6800 : RgM_to_nfM(GEN nf,GEN x)
    1384              : {
    1385              :   long i, j, li, lx;
    1386         6800 :   GEN z = cgetg_copy(x, &lx);
    1387              : 
    1388         6800 :   if (lx == 1) return z;
    1389         6800 :   li = lgcols(x);
    1390        43755 :   for (j=1; j<lx; j++)
    1391              :   {
    1392        36955 :     GEN c = cgetg(li,t_COL), xj = gel(x,j);
    1393        36955 :     gel(z,j) = c;
    1394       228983 :     for (i=1; i<li; i++) gel(c,i) = nf_to_scalar_or_basis(nf, gel(xj,i));
    1395              :   }
    1396         6800 :   return z;
    1397              : }
    1398              : GEN
    1399       112896 : RgC_to_nfC(GEN nf, GEN x)
    1400       661480 : { pari_APPLY_type(t_COL, nf_to_scalar_or_basis(nf, gel(x,i))) }
    1401              : 
    1402              : /* x a t_POLMOD, supposedly in rnf = K[z]/(T), K = Q[y]/(Tnf) */
    1403              : GEN
    1404       181329 : polmod_nffix(const char *f, GEN rnf, GEN x, int lift)
    1405       181329 : { return polmod_nffix2(f, rnf_get_nfpol(rnf), rnf_get_pol(rnf), x,lift); }
    1406              : GEN
    1407       181420 : polmod_nffix2(const char *f, GEN T, GEN R, GEN x, int lift)
    1408              : {
    1409       181420 :   if (RgX_equal_var(gel(x,1), R))
    1410              :   {
    1411       149408 :     x = gel(x,2);
    1412       149408 :     if (typ(x) == t_POL && varn(x) == varn(R))
    1413              :     {
    1414       115887 :       x = RgX_nffix(f, T, x, lift);
    1415       115887 :       switch(lg(x))
    1416              :       {
    1417         5691 :         case 2: return gen_0;
    1418        18786 :         case 3: return gel(x,2);
    1419              :       }
    1420        91410 :       return x;
    1421              :     }
    1422              :   }
    1423        65533 :   return Rg_nffix(f, T, x, lift);
    1424              : }
    1425              : GEN
    1426         1428 : rnfalgtobasis(GEN rnf,GEN x)
    1427              : {
    1428         1428 :   const char *f = "rnfalgtobasis";
    1429         1428 :   pari_sp av = avma;
    1430              :   GEN T, R;
    1431              : 
    1432         1428 :   checkrnf(rnf);
    1433         1428 :   R = rnf_get_pol(rnf);
    1434         1428 :   T = rnf_get_nfpol(rnf);
    1435         1428 :   switch(typ(x))
    1436              :   {
    1437           98 :     case t_COL:
    1438           98 :       if (lg(x)-1 != rnf_get_degree(rnf)) pari_err_DIM(f);
    1439           49 :       x = RgV_nffix(f, T, x, 0);
    1440           42 :       return gc_GEN(av, x);
    1441              : 
    1442         1162 :     case t_POLMOD:
    1443         1162 :       x = polmod_nffix(f, rnf, x, 0);
    1444         1057 :       if (typ(x) != t_POL) break;
    1445          714 :       return gc_upto(av, RgM_RgX_mul(rnf_get_invzk(rnf), x));
    1446          112 :     case t_POL:
    1447          112 :       if (varn(x) == varn(T))
    1448              :       {
    1449           42 :         RgX_check_QX(x,f);
    1450           28 :         if (degpol(x) >= degpol(T)) x = RgX_rem(x,T);
    1451           28 :         x = mkpolmod(x,T); break;
    1452              :       }
    1453           70 :       x = RgX_nffix(f, T, x, 0);
    1454           56 :       if (degpol(x) >= degpol(R)) x = RgX_rem(x, R);
    1455           56 :       return gc_upto(av, RgM_RgX_mul(rnf_get_invzk(rnf), x));
    1456              :   }
    1457          427 :   return gc_upto(av, scalarcol(x, rnf_get_degree(rnf)));
    1458              : }
    1459              : 
    1460              : /* Given a and b in nf, gives an algebraic integer y in nf such that a-b.y
    1461              :  * is "small" */
    1462              : GEN
    1463          259 : nfdiveuc(GEN nf, GEN a, GEN b)
    1464              : {
    1465          259 :   pari_sp av = avma;
    1466          259 :   a = nfdiv(nf,a,b);
    1467          259 :   return gc_upto(av, ground(a));
    1468              : }
    1469              : 
    1470              : /* Given a and b in nf, gives a "small" algebraic integer r in nf
    1471              :  * of the form a-b.y */
    1472              : GEN
    1473          259 : nfmod(GEN nf, GEN a, GEN b)
    1474              : {
    1475          259 :   pari_sp av = avma;
    1476          259 :   GEN p1 = gneg_i(nfmul(nf,b,ground(nfdiv(nf,a,b))));
    1477          259 :   return gc_upto(av, nfadd(nf,a,p1));
    1478              : }
    1479              : 
    1480              : /* Given a and b in nf, gives a two-component vector [y,r] in nf such
    1481              :  * that r=a-b.y is "small". */
    1482              : GEN
    1483          259 : nfdivrem(GEN nf, GEN a, GEN b)
    1484              : {
    1485          259 :   pari_sp av = avma;
    1486          259 :   GEN p1,z, y = ground(nfdiv(nf,a,b));
    1487              : 
    1488          259 :   p1 = gneg_i(nfmul(nf,b,y));
    1489          259 :   z = cgetg(3,t_VEC);
    1490          259 :   gel(z,1) = gcopy(y);
    1491          259 :   gel(z,2) = nfadd(nf,a,p1); return gc_upto(av, z);
    1492              : }
    1493              : 
    1494              : /*************************************************************************/
    1495              : /**                                                                     **/
    1496              : /**                   LOGARITHMIC EMBEDDINGS                            **/
    1497              : /**                                                                     **/
    1498              : /*************************************************************************/
    1499              : 
    1500              : static int
    1501      4744911 : low_prec(GEN x)
    1502              : {
    1503      4744911 :   switch(typ(x))
    1504              :   {
    1505            0 :     case t_INT: return !signe(x);
    1506      4744911 :     case t_REAL: return !signe(x) || realprec(x) <= DEFAULTPREC;
    1507            0 :     default: return 0;
    1508              :   }
    1509              : }
    1510              : 
    1511              : static GEN
    1512        23449 : cxlog_1(GEN nf) { return zerocol(lg(nf_get_roots(nf))-1); }
    1513              : static GEN
    1514          541 : cxlog_m1(GEN nf, long prec)
    1515              : {
    1516          541 :   long i, l = lg(nf_get_roots(nf)), r1 = nf_get_r1(nf);
    1517          541 :   GEN v = cgetg(l, t_COL), p,  P;
    1518          541 :   p = mppi(prec); P = mkcomplex(gen_0, p);
    1519         1258 :   for (i = 1; i <= r1; i++) gel(v,i) = P; /* IPi*/
    1520          541 :   if (i < l) P = gmul2n(P,1);
    1521         1133 :   for (     ; i < l; i++) gel(v,i) = P; /* 2IPi */
    1522          541 :   return v;
    1523              : }
    1524              : static GEN
    1525      1768971 : ZC_cxlog(GEN nf, GEN x, long prec)
    1526              : {
    1527              :   long i, l, r1;
    1528              :   GEN v;
    1529      1768971 :   x = RgM_RgC_mul(nf_get_M(nf), Q_primpart(x));
    1530      1768974 :   l = lg(x); r1 = nf_get_r1(nf);
    1531      4496239 :   for (i = 1; i <= r1; i++)
    1532      2727265 :     if (low_prec(gel(x,i))) return NULL;
    1533      3572540 :   for (     ; i <  l;  i++)
    1534      1803567 :     if (low_prec(gnorm(gel(x,i)))) return NULL;
    1535      1768973 :   v = cgetg(l,t_COL);
    1536      4496238 :   for (i = 1; i <= r1; i++) gel(v,i) = glog(gel(x,i),prec);
    1537      3572539 :   for (     ; i <  l;  i++) gel(v,i) = gmul2n(glog(gel(x,i),prec),1);
    1538      1768974 :   return v;
    1539              : }
    1540              : static GEN
    1541       227519 : famat_cxlog(GEN nf, GEN fa, long prec)
    1542              : {
    1543       227519 :   GEN G, E, y = NULL;
    1544              :   long i, l;
    1545              : 
    1546       227519 :   if (typ(fa) != t_MAT) pari_err_TYPE("famat_cxlog",fa);
    1547       227519 :   if (lg(fa) == 1) return cxlog_1(nf);
    1548       227519 :   G = gel(fa,1);
    1549       227519 :   E = gel(fa,2); l = lg(E);
    1550      1133078 :   for (i = 1; i < l; i++)
    1551              :   {
    1552       905559 :     GEN t, e = gel(E,i), x = nf_to_scalar_or_basis(nf, gel(G,i));
    1553              :     /* multiplicative arch would be better (save logs), but exponents overflow
    1554              :      * [ could keep track of expo separately, but not worth it ] */
    1555       905559 :     switch(typ(x))
    1556              :     { /* ignore positive rationals */
    1557        16411 :       case t_FRAC: x = gel(x,1); /* fall through */
    1558       271095 :       case t_INT: if (signe(x) > 0) continue;
    1559           86 :         if (!mpodd(e)) continue;
    1560           30 :         t = cxlog_m1(nf, prec); /* we probably should not reach this line */
    1561           30 :         break;
    1562       634464 :       default: /* t_COL */
    1563       634464 :         t = ZC_cxlog(nf,x,prec); if (!t) return NULL;
    1564       634464 :         t = RgC_Rg_mul(t, e);
    1565              :     }
    1566       634494 :     y = y? RgV_add(y,t): t;
    1567              :   }
    1568       227519 :   return y ? y: cxlog_1(nf);
    1569              : }
    1570              : /* Archimedean components: [e_i Log( sigma_i(X) )], where X = primpart(x),
    1571              :  * and e_i = 1 (resp 2.) for i <= R1 (resp. > R1) */
    1572              : GEN
    1573      1363181 : nf_cxlog(GEN nf, GEN x, long prec)
    1574              : {
    1575      1363181 :   if (typ(x) == t_MAT) return famat_cxlog(nf,x,prec);
    1576      1135662 :   x = nf_to_scalar_or_basis(nf,x);
    1577      1135662 :   switch(typ(x))
    1578              :   {
    1579            0 :     case t_FRAC: x = gel(x,1); /* fall through */
    1580         1155 :     case t_INT:
    1581         1155 :       return signe(x) > 0? cxlog_1(nf): cxlog_m1(nf, prec);
    1582      1134507 :     default:
    1583      1134507 :       return ZC_cxlog(nf, x, prec);
    1584              :   }
    1585              : }
    1586              : GEN
    1587           97 : nfV_cxlog(GEN nf, GEN x, long prec)
    1588              : {
    1589              :   long i, l;
    1590           97 :   GEN v = cgetg_copy(x, &l);
    1591          167 :   for (i = 1; i < l; i++)
    1592           70 :     if (!(gel(v,i) = nf_cxlog(nf, gel(x,i), prec))) return NULL;
    1593           97 :   return v;
    1594              : }
    1595              : 
    1596              : static GEN
    1597        15820 : scalar_logembed(GEN nf, GEN u, GEN *emb)
    1598              : {
    1599              :   GEN v, logu;
    1600        15820 :   long i, s = signe(u), RU = lg(nf_get_roots(nf))-1, R1 = nf_get_r1(nf);
    1601              : 
    1602        15820 :   if (!s) pari_err_DOMAIN("nflogembed","argument","=",gen_0,u);
    1603        15820 :   v = cgetg(RU+1, t_COL); logu = logr_abs(u);
    1604        18977 :   for (i = 1; i <= R1; i++) gel(v,i) = logu;
    1605        15820 :   if (i <= RU)
    1606              :   {
    1607        14350 :     GEN logu2 = shiftr(logu,1);
    1608        55839 :     for (   ; i <= RU; i++) gel(v,i) = logu2;
    1609              :   }
    1610        15820 :   if (emb) *emb = const_col(RU, u);
    1611        15820 :   return v;
    1612              : }
    1613              : 
    1614              : static GEN
    1615         1309 : famat_logembed(GEN nf,GEN x,GEN *emb,long prec)
    1616              : {
    1617         1309 :   GEN A, M, T, a, t, g = gel(x,1), e = gel(x,2);
    1618         1309 :   long i, l = lg(e);
    1619              : 
    1620         1309 :   if (l == 1) return scalar_logembed(nf, real_1(prec), emb);
    1621         1309 :   A = NULL; T = emb? cgetg(l, t_COL): NULL;
    1622         1309 :   if (emb) *emb = M = mkmat2(T, e);
    1623        62132 :   for (i = 1; i < l; i++)
    1624              :   {
    1625        60823 :     a = nflogembed(nf, gel(g,i), &t, prec);
    1626        60823 :     if (!a) return NULL;
    1627        60823 :     a = RgC_Rg_mul(a, gel(e,i));
    1628        60823 :     A = A? RgC_add(A, a): a;
    1629        60823 :     if (emb) gel(T,i) = t;
    1630              :   }
    1631         1309 :   return A;
    1632              : }
    1633              : 
    1634              : /* Get archimedean components: [e_i log( | sigma_i(x) | )], with e_i = 1
    1635              :  * (resp 2.) for i <= R1 (resp. > R1) and set emb to the embeddings of x.
    1636              :  * Return NULL if precision problem */
    1637              : GEN
    1638       107642 : nflogembed(GEN nf, GEN x, GEN *emb, long prec)
    1639              : {
    1640              :   long i, l, r1;
    1641              :   GEN v, t;
    1642              : 
    1643       107642 :   if (typ(x) == t_MAT) return famat_logembed(nf,x,emb,prec);
    1644       106333 :   x = nf_to_scalar_or_basis(nf,x);
    1645       106333 :   if (typ(x) != t_COL) return scalar_logembed(nf, gtofp(x,prec), emb);
    1646        90513 :   x = RgM_RgC_mul(nf_get_M(nf), x);
    1647        90517 :   l = lg(x); r1 = nf_get_r1(nf); v = cgetg(l,t_COL);
    1648       134610 :   for (i = 1; i <= r1; i++)
    1649              :   {
    1650        44093 :     t = gabs(gel(x,i),prec); if (low_prec(t)) return NULL;
    1651        44093 :     gel(v,i) = glog(t,prec);
    1652              :   }
    1653       260505 :   for (   ; i < l; i++)
    1654              :   {
    1655       169988 :     t = gnorm(gel(x,i)); if (low_prec(t)) return NULL;
    1656       169988 :     gel(v,i) = glog(t,prec);
    1657              :   }
    1658        90517 :   if (emb) *emb = x;
    1659        90517 :   return v;
    1660              : }
    1661              : 
    1662              : /*************************************************************************/
    1663              : /**                                                                     **/
    1664              : /**                        REAL EMBEDDINGS                              **/
    1665              : /**                                                                     **/
    1666              : /*************************************************************************/
    1667              : static GEN
    1668       512131 : sarch_get_cyc(GEN sarch) { return gel(sarch,1); }
    1669              : static GEN
    1670      1863628 : sarch_get_archp(GEN sarch) { return gel(sarch,2); }
    1671              : static GEN
    1672       730425 : sarch_get_MI(GEN sarch) { return gel(sarch,3); }
    1673              : static GEN
    1674       730424 : sarch_get_lambda(GEN sarch) { return gel(sarch,4); }
    1675              : static GEN
    1676       730424 : sarch_get_F(GEN sarch) { return gel(sarch,5); }
    1677              : 
    1678              : /* true nf, x non-zero algebraic integer; return number of positive real roots
    1679              :  * of char_x */
    1680              : static long
    1681      1163999 : num_positive(GEN nf, GEN x)
    1682              : {
    1683      1163999 :   GEN T = nf_get_pol(nf), B, charx;
    1684      1163998 :   long dnf, vnf, N, r1 = nf_get_r1(nf);
    1685      1164000 :   x = nf_to_scalar_or_alg(nf, x);
    1686      1163998 :   if (typ(x) != t_POL) return (signe(x) < 0)? 0: degpol(T);
    1687              :   /* x not a scalar */
    1688      1158530 :   if (r1 == 1)
    1689              :   {
    1690        31402 :     long s = signe(ZX_resultant(T, Q_primpart(x)));
    1691        31402 :     return s > 0? 1: 0;
    1692              :   }
    1693      1127128 :   charx = ZXQ_charpoly(x, T, 0);
    1694      1127136 :   charx = ZX_radical(charx);
    1695      1127129 :   N = degpol(T) / degpol(charx);
    1696              :   /* real places are unramified ? */
    1697      1127128 :   if (N == 1 || ZX_sturm(charx) * N == r1)
    1698      1126518 :     return ZX_sturmpart(charx, mkvec2(gen_0,mkoo())) * N;
    1699              :   /* painful case, multiply by random square until primitive */
    1700          610 :   dnf = nf_get_degree(nf);
    1701          610 :   vnf = varn(T);
    1702          610 :   B = int2n(10);
    1703              :   for(;;)
    1704            0 :   {
    1705          610 :     GEN y = RgXQ_sqr(random_FpX(dnf, vnf, B), T);
    1706          610 :     y = RgXQ_mul(x, y, T);
    1707          610 :     charx = ZXQ_charpoly(y, T, 0);
    1708          610 :     if (ZX_is_squarefree(charx))
    1709          610 :       return ZX_sturmpart(charx, mkvec2(gen_0,mkoo()));
    1710              :   }
    1711              : }
    1712              : 
    1713              : /* x a QC: return sigma_k(x) where 1 <= k <= r1+r2; correct but inefficient
    1714              :  * if x in Q. M = nf_get_M(nf) */
    1715              : static GEN
    1716         2147 : nfembed_i(GEN M, GEN x, long k)
    1717              : {
    1718         2147 :   long i, l = lg(M);
    1719         2147 :   GEN z = gel(x,1);
    1720        24394 :   for (i = 2; i < l; i++) z = gadd(z, gmul(gcoeff(M,k,i), gel(x,i)));
    1721         2147 :   return z;
    1722              : }
    1723              : GEN
    1724            0 : nfembed(GEN nf, GEN x, long k)
    1725              : {
    1726            0 :   pari_sp av = avma;
    1727            0 :   nf = checknf(nf);
    1728            0 :   x = nf_to_scalar_or_basis(nf,x);
    1729            0 :   if (typ(x) != t_COL) return gc_GEN(av, x);
    1730            0 :   return gc_upto(av, nfembed_i(nf_get_M(nf),x,k));
    1731              : }
    1732              : 
    1733              : /* x a ZC */
    1734              : static GEN
    1735       104390 : zk_embed(GEN M, GEN x, long k)
    1736              : {
    1737       104390 :   long i, l = lg(x);
    1738              :   GEN z; /* times M[k,1], which is 1 */
    1739       104390 :   if (l == 2) return gel(x,1); /* K = Q */
    1740       104390 :   z = addir(gel(x,1), mulri(gcoeff(M,k,2), gel(x,2)));
    1741       154111 :   for (i = 3; i < l; i++) z = addrr(z, mulri(gcoeff(M,k,i), gel(x,i)));
    1742       104389 :   return z;
    1743              : }
    1744              : 
    1745              : /* check that signs[i..#signs] == s; signs = NULL encodes "totally positive" */
    1746              : static int
    1747        34237 : oksigns(long l, GEN signs, long i, long s)
    1748              : {
    1749        34237 :   if (!signs) return s == 0;
    1750        40492 :   for (; i < l; i++)
    1751        30493 :     if (signs[i] != s) return 0;
    1752         9999 :   return 1;
    1753              : }
    1754              : 
    1755              : /* true nf, x a ZC (primitive for efficiency) which is not a scalar */
    1756              : static int
    1757       105795 : nfchecksigns_i(GEN nf, GEN x, GEN signs, GEN archp)
    1758              : {
    1759       105795 :   long i, np, npc, l = lg(archp), r1 = nf_get_r1(nf);
    1760              :   GEN sarch;
    1761              : 
    1762       105795 :   if (r1 == 0) return 1;
    1763       105403 :   np = num_positive(nf, x);
    1764       105403 :   if (np == 0)  return oksigns(l, signs, 1, 1);
    1765        89833 :   if (np == r1) return oksigns(l, signs, 1, 0);
    1766        71166 :   sarch = nfarchstar(nf, NULL, identity_perm(r1));
    1767        80346 :   for (i = 1, npc = 0; i < l; i++)
    1768              :   {
    1769        80096 :     GEN xi = set_sign_mod_divisor(nf, vecsmall_ei(r1, archp[i]), gen_1, sarch);
    1770              :     long ni, s;
    1771        80095 :     xi = Q_primpart(xi);
    1772        80096 :     ni = num_positive(nf, nfmuli(nf,x,xi));
    1773        80096 :     s = ni < np? 0: 1;
    1774        80096 :     if (s != (signs? signs[i]: 0)) return 0;
    1775        34822 :     if (!s) npc++; /* found a positive root */
    1776        34822 :     if (npc == np)
    1777              :     { /* found all positive roots */
    1778        24979 :       if (!signs) return i == l-1;
    1779        18096 :       for (i++; i < l; i++)
    1780         8827 :         if (signs[i] != 1) return 0;
    1781         9269 :       return 1;
    1782              :     }
    1783         9843 :     if (i - npc == r1 - np)
    1784              :     { /* found all negative roots */
    1785          663 :       if (!signs) return 1;
    1786          719 :       for (i++; i < l; i++)
    1787           77 :         if (signs[i]) return 0;
    1788          642 :       return 1;
    1789              :     }
    1790              :   }
    1791          250 :   return 1;
    1792              : }
    1793              : static void
    1794         1220 : pl_convert(GEN pl, GEN *psigns, GEN *parchp)
    1795              : {
    1796         1220 :   long i, j, l = lg(pl);
    1797         1220 :   GEN signs = cgetg(l, t_VECSMALL);
    1798         1220 :   GEN archp = cgetg(l, t_VECSMALL);
    1799         3928 :   for (i = j = 1; i < l; i++)
    1800              :   {
    1801         2708 :     if (!pl[i]) continue;
    1802         1926 :     archp[j] = i;
    1803         1926 :     signs[j] = (pl[i] < 0)? 1: 0;
    1804         1926 :     j++;
    1805              :   }
    1806         1220 :   setlg(archp, j); *parchp = archp;
    1807         1220 :   setlg(signs, j); *psigns = signs;
    1808         1220 : }
    1809              : /* pl : requested signs for real embeddings, 0 = no sign constraint */
    1810              : int
    1811        14506 : nfchecksigns(GEN nf, GEN x, GEN pl)
    1812              : {
    1813        14506 :   pari_sp av = avma;
    1814              :   GEN signs, archp;
    1815        14506 :   nf = checknf(nf);
    1816        14506 :   x = nf_to_scalar_or_basis(nf,x);
    1817        14506 :   if (typ(x) != t_COL)
    1818              :   {
    1819        13286 :     long i, l = lg(pl), s = gsigne(x);
    1820        24332 :     for (i = 1; i < l; i++)
    1821        13349 :       if (pl[i] && pl[i] != s) return gc_bool(av,0);
    1822        10983 :     return gc_bool(av,1);
    1823              :   }
    1824         1220 :   pl_convert(pl, &signs, &archp);
    1825         1220 :   return gc_bool(av, nfchecksigns_i(nf, x, signs, archp));
    1826              : }
    1827              : 
    1828              : /* signs = NULL: totally positive, else sign[i] = 0 (+) or 1 (-) */
    1829              : static GEN
    1830       730426 : get_C(GEN lambda, long l, GEN signs)
    1831              : {
    1832              :   long i;
    1833              :   GEN C, mlambda;
    1834       730426 :   if (!signs) return const_vec(l-1, lambda);
    1835       700676 :   C = cgetg(l, t_COL); mlambda = gneg(lambda);
    1836      2716795 :   for (i = 1; i < l; i++) gel(C,i) = signs[i]? mlambda: lambda;
    1837       700675 :   return C;
    1838              : }
    1839              : /* signs = NULL: totally positive at archp.
    1840              :  * Assume that a t_COL x is not a scalar */
    1841              : static GEN
    1842       864208 : nfsetsigns(GEN nf, GEN signs, GEN x, GEN sarch)
    1843              : {
    1844       864208 :   long i, l = lg(sarch_get_archp(sarch));
    1845       864208 :   GEN ex = NULL;
    1846              :   /* Is signature already correct ? */
    1847       864208 :   if (typ(x) != t_COL)
    1848              :   {
    1849       759636 :     long s = gsigne(x);
    1850       759635 :     if (!s) i = 1;
    1851       759614 :     else if (!signs)
    1852         7399 :       i = (s < 0)? 1: l;
    1853              :     else
    1854              :     {
    1855       752215 :       s = s < 0? 1: 0;
    1856      1285944 :       for (i = 1; i < l; i++)
    1857      1194668 :         if (signs[i] != s) break;
    1858              :     }
    1859       759635 :     if (i < l) ex = const_col(l-1, x);
    1860              :   }
    1861              :   else
    1862              :   { /* inefficient if x scalar, wrong if x = 0 */
    1863       104572 :     pari_sp av = avma;
    1864       104572 :     GEN cex, M = nf_get_M(nf), archp = sarch_get_archp(sarch);
    1865       104575 :     GEN xp = Q_primitive_part(x,&cex);
    1866       104575 :     if (nfchecksigns_i(nf, xp, signs, archp)) set_avma(av);
    1867              :     else
    1868              :     {
    1869        69325 :       ex = cgetg(l,t_COL);
    1870       173714 :       for (i = 1; i < l; i++) gel(ex,i) = zk_embed(M,xp,archp[i]);
    1871        69324 :       if (cex) ex = RgC_Rg_mul(ex, cex); /* put back content */
    1872              :     }
    1873              :   }
    1874       864201 :   if (ex)
    1875              :   { /* If no, fix it */
    1876       730425 :     GEN MI = sarch_get_MI(sarch), F = sarch_get_F(sarch);
    1877       730424 :     GEN lambda = sarch_get_lambda(sarch);
    1878       730425 :     GEN t = RgC_sub(get_C(lambda, l, signs), ex);
    1879       730421 :     t = grndtoi(RgM_RgC_mul(MI,t), NULL);
    1880       730407 :     if (lg(F) != 1) t = ZM_ZC_mul(F, t);
    1881       730407 :     x = typ(x) == t_COL? RgC_add(t, x): RgC_Rg_add(t, x);
    1882              :   }
    1883       864180 :   return x;
    1884              : }
    1885              : /* - true nf
    1886              :  * - sarch = nfarchstar(nf, F);
    1887              :  * - x encodes a vector of signs at arch.archp: either a t_VECSMALL
    1888              :  *   (vector of signs as {0,1}-vector), NULL (totally positive at archp),
    1889              :  *   or a nonzero number field element (replaced by its signature at archp);
    1890              :  * - y is a nonzero number field element
    1891              :  * Return z = y (mod F) with signs(y, archp) = signs(x) (a {0,1}-vector).
    1892              :  * Not stack-clean */
    1893              : GEN
    1894       894852 : set_sign_mod_divisor(GEN nf, GEN x, GEN y, GEN sarch)
    1895              : {
    1896       894852 :   GEN archp = sarch_get_archp(sarch);
    1897       894851 :   if (lg(archp) == 1) return y;
    1898       861958 :   if (x && typ(x) != t_VECSMALL) x = nfsign_arch(nf, x, archp);
    1899       861958 :   return nfsetsigns(nf, x, nf_to_scalar_or_basis(nf,y), sarch);
    1900              : }
    1901              : 
    1902              : static GEN
    1903       480624 : setsigns_init(GEN nf, GEN archp, GEN F, GEN DATA)
    1904              : {
    1905       480624 :   GEN lambda, Mr = rowpermute(nf_get_M(nf), archp), MI = F? RgM_mul(Mr,F): Mr;
    1906       480635 :   lambda = gmul2n(matrixnorm(MI,DEFAULTPREC), -1);
    1907       480629 :   if (typ(lambda) != t_REAL) lambda = gmul(lambda, uutoQ(1001,1000));
    1908       480634 :   if (lg(archp) < lg(MI))
    1909              :   {
    1910        81853 :     GEN perm = gel(indexrank(MI), 2);
    1911        81852 :     if (!F) F = matid(nf_get_degree(nf));
    1912        81852 :     MI = vecpermute(MI, perm);
    1913        81852 :     F = vecpermute(F, perm);
    1914              :   }
    1915       480632 :   if (!F) F = cgetg(1,t_MAT);
    1916       480631 :   MI = RgM_inv(MI);
    1917       480635 :   return mkvec5(DATA, archp, MI, lambda, F);
    1918              : }
    1919              : /* F nonzero integral ideal in HNF (or NULL: Z_K), compute elements in 1+F
    1920              :  * whose sign matrix at archp is identity; archp in 'indices' format */
    1921              : GEN
    1922       658941 : nfarchstar(GEN nf, GEN F, GEN archp)
    1923              : {
    1924       658941 :   long nba = lg(archp) - 1;
    1925       658941 :   if (!nba) return mkvec2(cgetg(1,t_VEC), archp);
    1926       478387 :   if (F && equali1(gcoeff(F,1,1))) F = NULL;
    1927       478388 :   if (F) F = idealpseudored(F, nf_get_roundG(nf));
    1928       478379 :   return setsigns_init(nf, archp, F, const_vec(nba, gen_2));
    1929              : }
    1930              : 
    1931              : /*************************************************************************/
    1932              : /**                                                                     **/
    1933              : /**                         IDEALCHINESE                                **/
    1934              : /**                                                                     **/
    1935              : /*************************************************************************/
    1936              : static int
    1937         6218 : isprfact(GEN x)
    1938              : {
    1939              :   long i, l;
    1940              :   GEN L, E;
    1941         6218 :   if (typ(x) != t_MAT || lg(x) != 3) return 0;
    1942         6218 :   L = gel(x,1); l = lg(L);
    1943         6218 :   E = gel(x,2);
    1944        19015 :   for(i=1; i<l; i++)
    1945              :   {
    1946        12797 :     checkprid(gel(L,i));
    1947        12797 :     if (typ(gel(E,i)) != t_INT) return 0;
    1948              :   }
    1949         6218 :   return 1;
    1950              : }
    1951              : 
    1952              : /* initialize projectors mod pr[i]^e[i] for idealchinese */
    1953              : static GEN
    1954         6218 : pr_init(GEN nf, GEN fa, GEN w, GEN dw)
    1955              : {
    1956         6218 :   GEN U, E, F, FZ, L = gel(fa,1), E0 = gel(fa,2);
    1957         6218 :   long i, r = lg(L);
    1958              : 
    1959         6218 :   if (w && lg(w) != r) pari_err_TYPE("idealchinese", w);
    1960         6218 :   if (r == 1 && !dw) return cgetg(1,t_VEC);
    1961         6204 :   E = leafcopy(E0); /* do not destroy fa[2] */
    1962        19001 :   for (i = 1; i < r; i++)
    1963        12797 :     if (signe(gel(E,i)) < 0) gel(E,i) = gen_0;
    1964         6204 :   F = factorbackprime(nf, L, E);
    1965         6204 :   if (dw)
    1966              :   {
    1967          693 :     F = ZM_Z_mul(F, dw);
    1968         1596 :     for (i = 1; i < r; i++)
    1969              :     {
    1970          903 :       GEN pr = gel(L,i);
    1971          903 :       long e = itos(gel(E0,i)), v = idealval(nf, dw, pr);
    1972          903 :       if (e >= 0)
    1973          896 :         gel(E,i) = addiu(gel(E,i), v);
    1974            7 :       else if (v + e <= 0)
    1975            0 :         F = idealmulpowprime(nf, F, pr, stoi(-v)); /* coprime to pr */
    1976              :       else
    1977              :       {
    1978            7 :         F = idealmulpowprime(nf, F, pr, stoi(e));
    1979            7 :         gel(E,i) = stoi(v + e);
    1980              :       }
    1981              :     }
    1982              :   }
    1983         6204 :   U = cgetg(r, t_VEC);
    1984        19001 :   for (i = 1; i < r; i++)
    1985              :   {
    1986              :     GEN u;
    1987        12797 :     if (w && gequal0(gel(w,i))) u = gen_0; /* unused */
    1988              :     else
    1989              :     {
    1990        12720 :       GEN pr = gel(L,i), e = gel(E,i), t;
    1991        12720 :       t = idealdivpowprime(nf,F, pr, e);
    1992        12720 :       u = hnfmerge_get_1(t, idealpow(nf, pr, e));
    1993        12720 :       if (!u) pari_err_COPRIME("idealchinese", t,pr);
    1994              :     }
    1995        12797 :     gel(U,i) = u;
    1996              :   }
    1997         6204 :   FZ = gcoeff(F, 1, 1);
    1998         6204 :   F = idealpseudored(F, nf_get_roundG(nf));
    1999         6204 :   return mkvec2(mkvec2(F, FZ), U);
    2000              : }
    2001              : 
    2002              : static GEN
    2003         2996 : pl_normalize(GEN nf, GEN pl)
    2004              : {
    2005         2996 :   const char *fun = "idealchinese";
    2006         2996 :   if (lg(pl)-1 != nf_get_r1(nf)) pari_err_TYPE(fun,pl);
    2007         2996 :   switch(typ(pl))
    2008              :   {
    2009          707 :     case t_VEC: RgV_check_ZV(pl,fun); pl = ZV_to_zv(pl);
    2010              :       /* fall through */
    2011         2996 :     case t_VECSMALL: break;
    2012            0 :     default: pari_err_TYPE(fun,pl);
    2013              :   }
    2014         2996 :   return pl;
    2015              : }
    2016              : 
    2017              : static int
    2018        13274 : is_chineseinit(GEN x)
    2019              : {
    2020              :   GEN fa, pl;
    2021              :   long l;
    2022        13274 :   if (typ(x) != t_VEC || lg(x)!=3) return 0;
    2023        10712 :   fa = gel(x,1);
    2024        10712 :   pl = gel(x,2);
    2025        10712 :   if (typ(fa) != t_VEC || typ(pl) != t_VEC) return 0;
    2026         6568 :   l = lg(fa);
    2027         6568 :   if (l != 1)
    2028              :   {
    2029              :     GEN z;
    2030         6526 :     if (l != 3) return 0;
    2031         6526 :     z = gel(fa, 1);
    2032         6526 :     if (typ(z) != t_VEC || lg(z) != 3 || typ(gel(z,1)) != t_MAT
    2033         6519 :                         || typ(gel(z,2)) != t_INT
    2034         6519 :                         || typ(gel(fa,2)) != t_VEC)
    2035            7 :       return 0;
    2036              :   }
    2037         6561 :   l = lg(pl);
    2038         6561 :   if (l != 1)
    2039              :   {
    2040         1136 :     if (l != 6 || typ(gel(pl,3)) != t_MAT || typ(gel(pl,1)) != t_VECSMALL
    2041         1136 :                                           || typ(gel(pl,2)) != t_VECSMALL)
    2042            0 :       return 0;
    2043              :   }
    2044         6561 :   return 1;
    2045              : }
    2046              : 
    2047              : /* nf a true 'nf' */
    2048              : static GEN
    2049         6687 : chineseinit_i(GEN nf, GEN fa, GEN w, GEN dw)
    2050              : {
    2051         6687 :   const char *fun = "idealchineseinit";
    2052         6687 :   GEN archp = NULL, pl = NULL;
    2053         6687 :   switch(typ(fa))
    2054              :   {
    2055         2996 :     case t_VEC:
    2056         2996 :       if (is_chineseinit(fa))
    2057              :       {
    2058            0 :         if (dw) pari_err_DOMAIN(fun, "denom(y)", "!=", gen_1, w);
    2059            0 :         return fa;
    2060              :       }
    2061         2996 :       if (lg(fa) != 3) pari_err_TYPE(fun, fa);
    2062              :       /* of the form [x,s] */
    2063         2996 :       pl = pl_normalize(nf, gel(fa,2));
    2064         2996 :       fa = gel(fa,1);
    2065         2996 :       archp = vecsmall01_to_indices(pl);
    2066              :       /* keep pr_init, reset pl */
    2067         2996 :       if (is_chineseinit(fa)) { fa = gel(fa,1); break; }
    2068              :       /* fall through */
    2069              :     case t_MAT: /* factorization? */
    2070         6218 :       if (isprfact(fa)) { fa = pr_init(nf, fa, w, dw); break; }
    2071            0 :     default: pari_err_TYPE(fun,fa);
    2072              :   }
    2073              : 
    2074         6687 :   if (!pl) pl = cgetg(1,t_VEC);
    2075              :   else
    2076              :   {
    2077         2996 :     long r = lg(archp);
    2078         2996 :     if (r == 1) pl = cgetg(1, t_VEC);
    2079              :     else
    2080              :     {
    2081         2242 :       GEN F = (lg(fa) == 1)? NULL: gmael(fa,1,1), signs = cgetg(r, t_VECSMALL);
    2082              :       long i;
    2083         6234 :       for (i = 1; i < r; i++) signs[i] = (pl[archp[i]] < 0)? 1: 0;
    2084         2242 :       pl = setsigns_init(nf, archp, F, signs);
    2085              :     }
    2086              :   }
    2087         6687 :   return mkvec2(fa, pl);
    2088              : }
    2089              : 
    2090              : /* Given a prime ideal factorization x, possibly with 0 or negative exponents,
    2091              :  * and a vector w of elements of nf, gives b such that
    2092              :  * v_p(b-w_p)>=v_p(x) for all prime ideals p in the ideal factorization
    2093              :  * and v_p(b)>=0 for all other p, using the standard proof given in GTM 138. */
    2094              : GEN
    2095        12779 : idealchinese(GEN nf, GEN x0, GEN w)
    2096              : {
    2097        12779 :   const char *fun = "idealchinese";
    2098        12779 :   pari_sp av = avma;
    2099        12779 :   GEN x = x0, x1, x2, s, dw, F;
    2100              : 
    2101        12779 :   nf = checknf(nf);
    2102        12779 :   if (!w) return gc_GEN(av, chineseinit_i(nf,x,NULL,NULL));
    2103              : 
    2104         7282 :   if (typ(w) != t_VEC) pari_err_TYPE(fun,w);
    2105         7282 :   w = Q_remove_denom(matalgtobasis(nf,w), &dw);
    2106         7282 :   if (!is_chineseinit(x)) x = chineseinit_i(nf,x,w,dw);
    2107              :   /* x is a 'chineseinit' */
    2108         7282 :   x1 = gel(x,1); s = NULL;
    2109         7282 :   x2 = gel(x,2);
    2110         7282 :   if (lg(x1) == 1) { F = NULL; dw = NULL; }
    2111              :   else
    2112              :   {
    2113         7240 :     GEN  U = gel(x1,2), FZ;
    2114         7240 :     long i, r = lg(w);
    2115         7240 :     F = gmael(x1,1,1); FZ = gmael(x1,1,2);
    2116        23726 :     for (i=1; i<r; i++)
    2117        16486 :       if (!ZV_equal0(gel(w,i)))
    2118              :       {
    2119        12363 :         GEN t = nfmuli(nf, gel(U,i), gel(w,i));
    2120        12363 :         s = s? ZC_add(s,t): t;
    2121              :       }
    2122         7240 :     if (s)
    2123              :     {
    2124         7219 :       s = ZC_reducemodmatrix(s, F);
    2125         7219 :       if (dw && x == x0) /* input was a chineseinit */
    2126              :       {
    2127            7 :         dw = modii(dw, FZ);
    2128            7 :         s = FpC_Fp_mul(s, Fp_inv(dw, FZ), FZ);
    2129            7 :         dw = NULL;
    2130              :       }
    2131         7219 :       if (ZV_isscalar(s)) s = icopy(gel(s,1));
    2132              :     }
    2133              :   }
    2134         7282 :   if (lg(x2) != 1)
    2135              :   {
    2136         2249 :     s = nfsetsigns(nf, gel(x2,1), s? s: gen_0, x2);
    2137         2249 :     if (typ(s) == t_COL && QV_isscalar(s))
    2138              :     {
    2139          434 :       s = gel(s,1); if (!dw) s = gcopy(s);
    2140              :     }
    2141              :   }
    2142         5033 :   else if (!s) return gc_const(av, gen_0);
    2143         7233 :   return gc_upto(av, dw? gdiv(s, dw): s);
    2144              : }
    2145              : 
    2146              : /*************************************************************************/
    2147              : /**                                                                     **/
    2148              : /**                           (Z_K/I)^*                                 **/
    2149              : /**                                                                     **/
    2150              : /*************************************************************************/
    2151              : GEN
    2152         2996 : vecsmall01_to_indices(GEN v)
    2153              : {
    2154         2996 :   long i, k, l = lg(v);
    2155         2996 :   GEN p = new_chunk(l) + l;
    2156         8449 :   for (k=1, i=l-1; i; i--)
    2157         5453 :     if (v[i]) { *--p = i; k++; }
    2158         2996 :   *--p = _evallg(k) | evaltyp(t_VECSMALL);
    2159         2996 :   set_avma((pari_sp)p); return p;
    2160              : }
    2161              : GEN
    2162      1330886 : vec01_to_indices(GEN v)
    2163              : {
    2164              :   long i, k, l;
    2165              :   GEN p;
    2166              : 
    2167      1330886 :   switch (typ(v))
    2168              :   {
    2169      1271064 :    case t_VECSMALL: return v;
    2170        59822 :    case t_VEC: break;
    2171            0 :    default: pari_err_TYPE("vec01_to_indices",v);
    2172              :   }
    2173        59822 :   l = lg(v);
    2174        59822 :   p = new_chunk(l) + l;
    2175       180145 :   for (k=1, i=l-1; i; i--)
    2176       120323 :     if (signe(gel(v,i))) { *--p = i; k++; }
    2177        59822 :   *--p = _evallg(k) | evaltyp(t_VECSMALL);
    2178        59822 :   set_avma((pari_sp)p); return p;
    2179              : }
    2180              : GEN
    2181       143702 : indices_to_vec01(GEN p, long r)
    2182              : {
    2183       143702 :   long i, l = lg(p);
    2184       143702 :   GEN v = zerovec(r);
    2185       217823 :   for (i = 1; i < l; i++) gel(v, p[i]) = gen_1;
    2186       143702 :   return v;
    2187              : }
    2188              : 
    2189              : /* return (column) vector of R1 signatures of x (0 or 1) */
    2190              : GEN
    2191      1271064 : nfsign_arch(GEN nf, GEN x, GEN arch)
    2192              : {
    2193      1271064 :   GEN sarch, V, archp = vec01_to_indices(arch);
    2194      1271064 :   long i, s, np, npc, r1, n = lg(archp)-1;
    2195              :   pari_sp av;
    2196              : 
    2197      1271064 :   if (!n) return cgetg(1,t_VECSMALL);
    2198      1064821 :   if (typ(x) == t_MAT)
    2199              :   { /* factorisation */
    2200       337495 :     GEN g = gel(x,1), e = gel(x,2);
    2201       337495 :     long l = lg(g);
    2202       337495 :     V = zero_zv(n);
    2203       954127 :     for (i = 1; i < l; i++)
    2204       616630 :       if (mpodd(gel(e,i)))
    2205       504705 :         Flv_add_inplace(V, nfsign_arch(nf,gel(g,i),archp), 2);
    2206       337497 :     set_avma((pari_sp)V); return V;
    2207              :   }
    2208       727326 :   av = avma; V = cgetg(n+1,t_VECSMALL);
    2209       727326 :   x = nf_to_scalar_or_basis(nf, x);
    2210       727326 :   switch(typ(x))
    2211              :   {
    2212       202822 :     case t_INT:
    2213       202822 :       s = signe(x);
    2214       202822 :       if (!s) pari_err_DOMAIN("nfsign_arch","element","=",gen_0,x);
    2215       202822 :       set_avma(av); return const_vecsmall(n, (s < 0)? 1: 0);
    2216          644 :     case t_FRAC:
    2217          644 :       s = signe(gel(x,1));
    2218          644 :       set_avma(av); return const_vecsmall(n, (s < 0)? 1: 0);
    2219              :   }
    2220       523860 :   r1 = nf_get_r1(nf); x = Q_primpart(x); np = num_positive(nf, x);
    2221       523861 :   if (np == 0) { set_avma(av); return const_vecsmall(n, 1); }
    2222       461840 :   if (np == r1){ set_avma(av); return const_vecsmall(n, 0); }
    2223       315783 :   sarch = nfarchstar(nf, NULL, identity_perm(r1));
    2224       456010 :   for (i = 1, npc = 0; i <= n; i++)
    2225              :   {
    2226       454650 :     GEN xi = set_sign_mod_divisor(nf, vecsmall_ei(r1, archp[i]), gen_1, sarch);
    2227              :     long ni;
    2228       454643 :     xi = Q_primpart(xi);
    2229       454645 :     ni = num_positive(nf, nfmuli(nf,x,xi));
    2230       454650 :     V[i] = ni < np? 0: 1;
    2231       454650 :     if (!V[i]) npc++; /* found a positive root */
    2232       454650 :     if (npc == np)
    2233              :     { /* found all positive roots */
    2234       323307 :       for (i++; i <= n; i++) V[i] = 1;
    2235       178720 :       break;
    2236              :     }
    2237       275930 :     if (i - npc == r1 - np)
    2238              :     { /* found all negative roots */
    2239       212841 :       for (i++; i <= n; i++) V[i] = 0;
    2240       135703 :       break;
    2241              :     }
    2242              :   }
    2243       315783 :   set_avma((pari_sp)V); return V;
    2244              : }
    2245              : static void
    2246        37121 : chk_ind(const char *s, long i, long r1)
    2247              : {
    2248        37121 :   if (i <= 0) pari_err_DOMAIN(s, "index", "<=", gen_0, stoi(i));
    2249        37107 :   if (i > r1) pari_err_DOMAIN(s, "index", ">", utoi(r1), utoi(i));
    2250        37072 : }
    2251              : static GEN
    2252       129066 : parse_embed(GEN ind, long r, const char *f)
    2253              : {
    2254              :   long l, i;
    2255       129066 :   if (!ind) return identity_perm(r);
    2256        34755 :   switch(typ(ind))
    2257              :   {
    2258           70 :     case t_INT: ind = mkvecsmall(itos(ind)); break;
    2259           84 :     case t_VEC: case t_COL: ind = vec_to_vecsmall(ind); break;
    2260        34601 :     case t_VECSMALL: break;
    2261            0 :     default: pari_err_TYPE(f, ind);
    2262              :   }
    2263        34755 :   l = lg(ind);
    2264        71827 :   for (i = 1; i < l; i++) chk_ind(f, ind[i], r);
    2265        34706 :   return ind;
    2266              : }
    2267              : GEN
    2268       126175 : nfeltsign(GEN nf, GEN x, GEN ind0)
    2269              : {
    2270       126175 :   pari_sp av = avma;
    2271              :   long i, l;
    2272              :   GEN v, ind;
    2273       126175 :   nf = checknf(nf);
    2274       126175 :   ind = parse_embed(ind0, nf_get_r1(nf), "nfeltsign");
    2275       126154 :   l = lg(ind);
    2276       126154 :   if (is_rational_t(typ(x)))
    2277              :   { /* nfsign_arch would test this, but avoid converting t_VECSMALL -> t_VEC */
    2278              :     GEN s;
    2279        31913 :     switch(gsigne(x))
    2280              :     {
    2281        16625 :       case -1:s = gen_m1; break;
    2282        15281 :       case 1: s = gen_1; break;
    2283            7 :       default: s = gen_0; break;
    2284              :     }
    2285        31913 :     set_avma(av);
    2286        31913 :     return (ind0 && typ(ind0) == t_INT)? s: const_vec(l-1, s);
    2287              :   }
    2288        94241 :   v = nfsign_arch(nf, x, ind);
    2289        94241 :   if (ind0 && typ(ind0) == t_INT) { set_avma(av); return v[1]? gen_m1: gen_1; }
    2290        94227 :   settyp(v, t_VEC);
    2291       264264 :   for (i = 1; i < l; i++) gel(v,i) = v[i]? gen_m1: gen_1;
    2292        94227 :   return gc_upto(av, v);
    2293              : }
    2294              : 
    2295              : /* true nf */
    2296              : GEN
    2297          735 : nfeltembed_i(GEN *pnf, GEN x, GEN ind0, long prec0)
    2298              : {
    2299              :   long i, e, l, r1, r2, prec, prec1;
    2300          735 :   GEN v, ind, cx, nf = *pnf;
    2301          735 :   nf_get_sign(nf,&r1,&r2);
    2302          735 :   x = nf_to_scalar_or_basis(nf, x);
    2303          728 :   ind = parse_embed(ind0, r1+r2, "nfeltembed");
    2304          721 :   l = lg(ind);
    2305          721 :   if (typ(x) != t_COL)
    2306              :   {
    2307          224 :     if (!(ind0 && typ(ind0) == t_INT)) x = const_vec(l-1, x);
    2308          224 :     return x;
    2309              :   }
    2310          497 :   x = Q_primitive_part(x, &cx);
    2311          497 :   prec1 = prec0; e = gexpo(x);
    2312          497 :   if (e > 8) prec1 += nbits2extraprec(e);
    2313          497 :   prec = prec1;
    2314          497 :   if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf, prec);
    2315          497 :   v = cgetg(l, t_VEC);
    2316              :   for(;;)
    2317          138 :   {
    2318          635 :     GEN M = nf_get_M(nf);
    2319         2644 :     for (i = 1; i < l; i++)
    2320              :     {
    2321         2147 :       GEN t = nfembed_i(M, x, ind[i]);
    2322         2147 :       long e = gexpo(t);
    2323         2147 :       if (gequal0(t) || precision(t) < prec0
    2324         2147 :                      || (e < 0 && prec < prec1 + nbits2extraprec(-e)) ) break;
    2325         2009 :       if (cx) t = gmul(t, cx);
    2326         2009 :       gel(v,i) = t;
    2327              :     }
    2328          635 :     if (i == l) break;
    2329          138 :     prec = precdbl(prec);
    2330          138 :     if (DEBUGLEVEL>1) pari_warn(warnprec,"eltnfembed", prec);
    2331          138 :     *pnf = nf = nfnewprec_shallow(nf, prec);
    2332              :   }
    2333          497 :   if (ind0 && typ(ind0) == t_INT) v = gel(v,1);
    2334          497 :   return v;
    2335              : }
    2336              : GEN
    2337          735 : nfeltembed(GEN nf, GEN x, GEN ind0, long prec0)
    2338              : {
    2339          735 :   pari_sp av = avma; nf = checknf(nf);
    2340          735 :   return gc_GEN(av, nfeltembed_i(&nf, x, ind0, prec0));
    2341              : }
    2342              : 
    2343              : /* number of distinct roots of sigma(f) */
    2344              : GEN
    2345         2163 : nfpolsturm(GEN nf, GEN f, GEN ind0)
    2346              : {
    2347         2163 :   pari_sp av = avma;
    2348              :   long d, l, r1, single;
    2349              :   GEN ind, u, v, vr1, T, s, t;
    2350              : 
    2351         2163 :   nf = checknf(nf); T = nf_get_pol(nf); r1 = nf_get_r1(nf);
    2352         2163 :   ind = parse_embed(ind0, r1, "nfpolsturm");
    2353         2142 :   single = ind0 && typ(ind0) == t_INT;
    2354         2142 :   l = lg(ind);
    2355              : 
    2356         2142 :   if (gequal0(f)) pari_err_ROOTS0("nfpolsturm");
    2357         2135 :   if (typ(f) == t_POL && varn(f) != varn(T))
    2358              :   {
    2359         2114 :     f = RgX_nffix("nfpolsturm", T, f,1);
    2360         2114 :     if (lg(f) == 3) f = NULL;
    2361              :   }
    2362              :   else
    2363              :   {
    2364           21 :     (void)Rg_nffix("nfpolsturm", T, f, 0);
    2365           21 :     f = NULL;
    2366              :   }
    2367         2135 :   if (!f) { set_avma(av); return single? gen_0: zerovec(l-1); }
    2368         2114 :   d = degpol(f);
    2369         2114 :   if (d == 1) { set_avma(av); return single? gen_1: const_vec(l-1,gen_1); }
    2370              : 
    2371         2023 :   vr1 = const_vecsmall(l-1, 1);
    2372         2023 :   u = Q_primpart(f); s = ZV_to_zv(nfeltsign(nf, gel(u,d+2), ind));
    2373         2023 :   v = RgX_deriv(u); t = odd(d)? leafcopy(s): zv_neg(s);
    2374              :   for(;;)
    2375          301 :   {
    2376         2324 :     GEN r = RgX_neg( Q_primpart(RgX_pseudorem(u, v)) ), sr;
    2377         2324 :     long i, dr = degpol(r);
    2378         2324 :     if (dr < 0) break;
    2379         2324 :     sr = ZV_to_zv(nfeltsign(nf, gel(r,dr+2), ind));
    2380         5579 :     for (i = 1; i < l; i++)
    2381         3255 :       if (sr[i] != s[i]) { s[i] = sr[i], vr1[i]--; }
    2382         2324 :     if (odd(dr)) sr = zv_neg(sr);
    2383         5579 :     for (i = 1; i < l; i++)
    2384         3255 :       if (sr[i] != t[i]) { t[i] = sr[i], vr1[i]++; }
    2385         2324 :     if (!dr) break;
    2386          301 :     u = v; v = r;
    2387              :   }
    2388         2023 :   if (single) return gc_stoi(av,vr1[1]);
    2389         2016 :   return gc_upto(av, zv_to_ZV(vr1));
    2390              : }
    2391              : 
    2392              : /* True nf; return the vector of signs of x; the matrix of such if x is a vector
    2393              :  * of nf elements */
    2394              : GEN
    2395        53914 : nfsign(GEN nf, GEN x)
    2396              : {
    2397              :   long i, l;
    2398              :   GEN archp, S;
    2399              : 
    2400        53914 :   archp = identity_perm( nf_get_r1(nf) );
    2401        53914 :   if (typ(x) != t_VEC) return nfsign_arch(nf, x, archp);
    2402        45507 :   l = lg(x); S = cgetg(l, t_MAT);
    2403       196363 :   for (i=1; i<l; i++) gel(S,i) = nfsign_arch(nf, gel(x,i), archp);
    2404        45508 :   return S;
    2405              : }
    2406              : 
    2407              : /* x integral elt, A integral ideal in HNF; reduce x mod A */
    2408              : static GEN
    2409      8142385 : zk_modHNF(GEN x, GEN A)
    2410      8142385 : { return (typ(x) == t_COL)?  ZC_hnfrem(x, A): modii(x, gcoeff(A,1,1)); }
    2411              : 
    2412              : /* given an element x in Z_K and an integral ideal y in HNF, coprime with x,
    2413              :    outputs an element inverse of x modulo y */
    2414              : GEN
    2415          175 : nfinvmodideal(GEN nf, GEN x, GEN y)
    2416              : {
    2417          175 :   pari_sp av = avma;
    2418          175 :   GEN a, yZ = gcoeff(y,1,1);
    2419              : 
    2420          175 :   if (equali1(yZ)) return gen_0;
    2421          175 :   x = nf_to_scalar_or_basis(nf, x);
    2422          175 :   if (typ(x) == t_INT) return gc_upto(av, Fp_inv(x, yZ));
    2423              : 
    2424           79 :   a = hnfmerge_get_1(idealhnf_principal(nf,x), y);
    2425           79 :   if (!a) pari_err_INV("nfinvmodideal", x);
    2426           79 :   return gc_upto(av, zk_modHNF(nfdiv(nf,a,x), y));
    2427              : }
    2428              : 
    2429              : static GEN
    2430      2813417 : nfsqrmodideal(GEN nf, GEN x, GEN id)
    2431      2813417 : { return zk_modHNF(nfsqri(nf,x), id); }
    2432              : static GEN
    2433      7852469 : nfmulmodideal(GEN nf, GEN x, GEN y, GEN id)
    2434      7852469 : { return x? zk_modHNF(nfmuli(nf,x,y), id): y; }
    2435              : /* assume x integral, k integer, A in HNF */
    2436              : GEN
    2437      6490086 : nfpowmodideal(GEN nf,GEN x,GEN k,GEN A)
    2438              : {
    2439      6490086 :   long s = signe(k);
    2440              :   pari_sp av;
    2441              :   GEN y;
    2442              : 
    2443      6490086 :   if (!s) return gen_1;
    2444      6490086 :   av = avma;
    2445      6490086 :   x = nf_to_scalar_or_basis(nf, x);
    2446      6490343 :   if (typ(x) != t_COL) return Fp_pow(x, k, gcoeff(A,1,1));
    2447      2807149 :   if (s < 0) { k = negi(k); x = nfinvmodideal(nf, x,A); }
    2448      2807149 :   if (equali1(k)) return gc_upto(av, s > 0? zk_modHNF(x, A): x);
    2449      1274805 :   for(y = NULL;;)
    2450              :   {
    2451      4088438 :     if (mpodd(k)) y = nfmulmodideal(nf,y,x,A);
    2452      4088400 :     k = shifti(k,-1); if (!signe(k)) break;
    2453      2813078 :     x = nfsqrmodideal(nf,x,A);
    2454              :   }
    2455      1274799 :   return gc_upto(av, y);
    2456              : }
    2457              : 
    2458              : /* a * g^n mod id */
    2459              : static GEN
    2460      5090117 : nfmulpowmodideal(GEN nf, GEN a, GEN g, GEN n, GEN id)
    2461              : {
    2462      5090117 :   return nfmulmodideal(nf, a, nfpowmodideal(nf,g,n,id), id);
    2463              : }
    2464              : 
    2465              : /* assume (num(g[i]), id) = 1 for all i. Return prod g[i]^e[i] mod id.
    2466              :  * EX = multiple of exponent of (O_K/id)^* */
    2467              : GEN
    2468      2927839 : famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id, GEN EX)
    2469              : {
    2470      2927839 :   GEN EXo2, plus = NULL, minus = NULL, idZ = gcoeff(id,1,1);
    2471      2927839 :   long i, lx = lg(g);
    2472              : 
    2473      2927839 :   if (equali1(idZ)) return gen_1; /* id = Z_K */
    2474      2927393 :   EXo2 = (expi(EX) > 10)? shifti(EX,-1): NULL;
    2475      9193877 :   for (i = 1; i < lx; i++)
    2476              :   {
    2477      6266537 :     GEN h, n = centermodii(gel(e,i), EX, EXo2);
    2478      6266043 :     long sn = signe(n);
    2479      6266043 :     if (!sn) continue;
    2480              : 
    2481      4356312 :     h = nf_to_scalar_or_basis(nf, gel(g,i));
    2482      4356710 :     switch(typ(h))
    2483              :     {
    2484      2650305 :       case t_INT: break;
    2485            0 :       case t_FRAC:
    2486            0 :         h = Fp_div(gel(h,1), gel(h,2), idZ); break;
    2487      1706405 :       default:
    2488              :       {
    2489              :         GEN dh;
    2490      1706405 :         h = Q_remove_denom(h, &dh);
    2491      1706556 :         if (dh) h = FpC_Fp_mul(h, Fp_inv(dh,idZ), idZ);
    2492              :       }
    2493              :     }
    2494      4356769 :     if (sn > 0)
    2495      4354933 :       plus = nfmulpowmodideal(nf, plus, h, n, id);
    2496              :     else /* sn < 0 */
    2497         1836 :       minus = nfmulpowmodideal(nf, minus, h, negi(n), id);
    2498              :   }
    2499      2927340 :   if (minus) plus = nfmulmodideal(nf, plus, nfinvmodideal(nf,minus,id), id);
    2500      2927405 :   return plus? plus: gen_1;
    2501              : }
    2502              : 
    2503              : /* given 2 integral ideals x, y in HNF s.t x | y | x^2, compute (1+x)/(1+y) in
    2504              :  * the form [[cyc],[gen], U], where U := ux^-1 as a pair [ZM, denom(U)] */
    2505              : static GEN
    2506       275318 : zidealij(GEN x, GEN y)
    2507              : {
    2508       275318 :   GEN U, G, cyc, xp = gcoeff(x,1,1), xi = hnf_invscale(x, xp);
    2509              :   long j, N;
    2510              : 
    2511              :   /* x^(-1) y = relations between the 1 + x_i (HNF) */
    2512       275314 :   cyc = ZM_snf_group(ZM_Z_divexact(ZM_mul(xi, y), xp), &U, &G);
    2513       275309 :   N = lg(cyc); G = ZM_mul(x,G); settyp(G, t_VEC); /* new generators */
    2514       652063 :   for (j=1; j<N; j++)
    2515              :   {
    2516       376766 :     GEN c = gel(G,j);
    2517       376766 :     gel(c,1) = addiu(gel(c,1), 1); /* 1 + g_j */
    2518       376751 :     if (ZV_isscalar(c)) gel(G,j) = gel(c,1);
    2519              :   }
    2520       275297 :   return mkvec4(cyc, G, ZM_mul(U,xi), xp);
    2521              : }
    2522              : 
    2523              : /* lg(x) > 1, x + 1; shallow */
    2524              : static GEN
    2525       204721 : ZC_add1(GEN x)
    2526              : {
    2527       204721 :   long i, l = lg(x);
    2528       204721 :   GEN y = cgetg(l, t_COL);
    2529       471434 :   for (i = 2; i < l; i++) gel(y,i) = gel(x,i);
    2530       204724 :   gel(y,1) = addiu(gel(x,1), 1); return y;
    2531              : }
    2532              : /* lg(x) > 1, x - 1; shallow */
    2533              : static GEN
    2534        71777 : ZC_sub1(GEN x)
    2535              : {
    2536        71777 :   long i, l = lg(x);
    2537        71777 :   GEN y = cgetg(l, t_COL);
    2538       182047 :   for (i = 2; i < l; i++) gel(y,i) = gel(x,i);
    2539        71777 :   gel(y,1) = subiu(gel(x,1), 1); return y;
    2540              : }
    2541              : 
    2542              : /* x,y are t_INT or ZC */
    2543              : static GEN
    2544            0 : zkadd(GEN x, GEN y)
    2545              : {
    2546            0 :   long tx = typ(x);
    2547            0 :   if (tx == typ(y))
    2548            0 :     return tx == t_INT? addii(x,y): ZC_add(x,y);
    2549              :   else
    2550            0 :     return tx == t_INT? ZC_Z_add(y,x): ZC_Z_add(x,y);
    2551              : }
    2552              : /* x a t_INT or ZC, x+1; shallow */
    2553              : static GEN
    2554       301813 : zkadd1(GEN x)
    2555              : {
    2556       301813 :   long tx = typ(x);
    2557       301813 :   return tx == t_INT? addiu(x,1): ZC_add1(x);
    2558              : }
    2559              : /* x a t_INT or ZC, x-1; shallow */
    2560              : static GEN
    2561       301847 : zksub1(GEN x)
    2562              : {
    2563       301847 :   long tx = typ(x);
    2564       301847 :   return tx == t_INT? subiu(x,1): ZC_sub1(x);
    2565              : }
    2566              : /* x,y are t_INT or ZC; x - y */
    2567              : static GEN
    2568            0 : zksub(GEN x, GEN y)
    2569              : {
    2570            0 :   long tx = typ(x), ty = typ(y);
    2571            0 :   if (tx == ty)
    2572            0 :     return tx == t_INT? subii(x,y): ZC_sub(x,y);
    2573              :   else
    2574            0 :     return tx == t_INT? Z_ZC_sub(x,y): ZC_Z_sub(x,y);
    2575              : }
    2576              : /* x is t_INT or ZM (mult. map), y is t_INT or ZC; x * y */
    2577              : static GEN
    2578       301828 : zkmul(GEN x, GEN y)
    2579              : {
    2580       301828 :   long tx = typ(x), ty = typ(y);
    2581       301828 :   if (ty == t_INT)
    2582       230066 :     return tx == t_INT? mulii(x,y): ZC_Z_mul(gel(x,1),y);
    2583              :   else
    2584        71762 :     return tx == t_INT? ZC_Z_mul(y,x): ZM_ZC_mul(x,y);
    2585              : }
    2586              : 
    2587              : /* (U,V) = 1 coprime ideals. Want z = x mod U, = y mod V; namely
    2588              :  * z =vx + uy = v(x-y) + y, where u + v = 1, u in U, v in V.
    2589              :  * zkc = [v, UV], v a t_INT or ZM (mult. by v map), UV a ZM (ideal in HNF);
    2590              :  * shallow */
    2591              : GEN
    2592            0 : zkchinese(GEN zkc, GEN x, GEN y)
    2593              : {
    2594            0 :   GEN v = gel(zkc,1), UV = gel(zkc,2), z = zkadd(zkmul(v, zksub(x,y)), y);
    2595            0 :   return zk_modHNF(z, UV);
    2596              : }
    2597              : /* special case z = x mod U, = 1 mod V; shallow */
    2598              : GEN
    2599       301847 : zkchinese1(GEN zkc, GEN x)
    2600              : {
    2601       301847 :   GEN v = gel(zkc,1), UV = gel(zkc,2), z = zkadd1(zkmul(v, zksub1(x)));
    2602       301829 :   return (typ(z) == t_INT)? z: ZC_hnfrem(z, UV);
    2603              : }
    2604              : static GEN
    2605       270569 : zkVchinese1(GEN zkc, GEN v)
    2606              : {
    2607              :   long i, ly;
    2608       270569 :   GEN y = cgetg_copy(v, &ly);
    2609       572386 :   for (i=1; i<ly; i++) gel(y,i) = zkchinese1(zkc, gel(v,i));
    2610       270539 :   return y;
    2611              : }
    2612              : 
    2613              : /* prepare to solve z = x (mod A), z = y mod (B) [zkchinese or zkchinese1] */
    2614              : GEN
    2615       270320 : zkchineseinit(GEN nf, GEN A, GEN B, GEN AB)
    2616              : {
    2617       270320 :   GEN v = idealaddtoone_raw(nf, A, B);
    2618              :   long e;
    2619       270309 :   if ((e = gexpo(v)) > 5)
    2620              :   {
    2621        83351 :     GEN b = (typ(v) == t_COL)? v: scalarcol_shallow(v, nf_get_degree(nf));
    2622        83351 :     b= ZC_reducemodlll(b, AB);
    2623        83356 :     if (gexpo(b) < e) v = b;
    2624              :   }
    2625       270301 :   return mkvec2(zk_scalar_or_multable(nf,v), AB);
    2626              : }
    2627              : /* prepare to solve z = x (mod A), z = 1 mod (B)
    2628              :  * and then         z = 1 (mod A), z = y mod (B) [zkchinese1 twice] */
    2629              : static GEN
    2630          259 : zkchinese1init2(GEN nf, GEN A, GEN B, GEN AB)
    2631              : {
    2632          259 :   GEN zkc = zkchineseinit(nf, A, B, AB);
    2633          259 :   GEN mv = gel(zkc,1), mu;
    2634          259 :   if (typ(mv) == t_INT) return mkvec2(zkc, mkvec2(subui(1,mv),AB));
    2635           35 :   mu = RgM_Rg_add_shallow(ZM_neg(mv), gen_1);
    2636           35 :   return mkvec2(mkvec2(mv,AB), mkvec2(mu,AB));
    2637              : }
    2638              : 
    2639              : static GEN
    2640      2781910 : apply_U(GEN L, GEN a)
    2641              : {
    2642      2781910 :   GEN e, U = gel(L,3), dU = gel(L,4);
    2643      2781910 :   if (typ(a) == t_INT)
    2644       973942 :     e = ZC_Z_mul(gel(U,1), subiu(a, 1));
    2645              :   else
    2646              :   { /* t_COL */
    2647      1807968 :     GEN t = shallowcopy(a);
    2648      1808012 :     gel(t,1) = subiu(gel(t,1), 1); /* t = a - 1 */
    2649      1807921 :     e = ZM_ZC_mul(U, t);
    2650              :   }
    2651      2781839 :   return gdiv(e, dU);
    2652              : }
    2653              : 
    2654              : /* true nf; vectors of [[cyc],[g],U.X^-1]. Assume k > 1. */
    2655              : static GEN
    2656       194100 : principal_units(GEN nf, GEN pr, long k, GEN prk)
    2657              : {
    2658              :   GEN list, prb;
    2659       194100 :   ulong mask = quadratic_prec_mask(k);
    2660       194100 :   long a = 1;
    2661              : 
    2662       194100 :   prb = pr_hnf(nf,pr);
    2663       194100 :   list = vectrunc_init(k);
    2664       469414 :   while (mask > 1)
    2665              :   {
    2666       275321 :     GEN pra = prb;
    2667       275321 :     long b = a << 1;
    2668              : 
    2669       275321 :     if (mask & 1) b--;
    2670       275321 :     mask >>= 1;
    2671              :     /* compute 1 + pr^a / 1 + pr^b, 2a <= b */
    2672       275321 :     prb = (b >= k)? prk: idealpows(nf,pr,b);
    2673       275320 :     vectrunc_append(list, zidealij(pra, prb));
    2674       275316 :     a = b;
    2675              :   }
    2676       194093 :   return list;
    2677              : }
    2678              : /* a = 1 mod (pr) return log(a) on local-gens of 1+pr/1+pr^k */
    2679              : static GEN
    2680      1686163 : log_prk1(GEN nf, GEN a, long nh, GEN L2, GEN prk)
    2681              : {
    2682      1686163 :   GEN y = cgetg(nh+1, t_COL);
    2683      1686170 :   long j, iy, c = lg(L2)-1;
    2684      4467990 :   for (j = iy = 1; j <= c; j++)
    2685              :   {
    2686      2781902 :     GEN L = gel(L2,j), cyc = gel(L,1), gen = gel(L,2), E = apply_U(L,a);
    2687      2781874 :     long i, nc = lg(cyc)-1;
    2688      2781874 :     int last = (j == c);
    2689      7111992 :     for (i = 1; i <= nc; i++, iy++)
    2690              :     {
    2691      4330172 :       GEN t, e = gel(E,i);
    2692      4330172 :       if (typ(e) != t_INT) pari_err_COPRIME("zlog_prk1", a, prk);
    2693      4330165 :       t = Fp_neg(e, gel(cyc,i));
    2694      4330020 :       gel(y,iy) = negi(t);
    2695      4330104 :       if (!last && signe(t)) a = nfmulpowmodideal(nf, a, gel(gen,i), t, prk);
    2696              :     }
    2697              :   }
    2698      1686088 :   return y;
    2699              : }
    2700              : /* true nf */
    2701              : static GEN
    2702        69957 : principal_units_relations(GEN nf, GEN L2, GEN prk, long nh)
    2703              : {
    2704        69957 :   GEN h = cgetg(nh+1,t_MAT);
    2705        69957 :   long ih, j, c = lg(L2)-1;
    2706       221141 :   for (j = ih = 1; j <= c; j++)
    2707              :   {
    2708       151184 :     GEN L = gel(L2,j), F = gel(L,1), G = gel(L,2);
    2709       151184 :     long k, lG = lg(G);
    2710       358918 :     for (k = 1; k < lG; k++,ih++)
    2711              :     { /* log(g^f) mod pr^e */
    2712       207734 :       GEN a = nfpowmodideal(nf,gel(G,k),gel(F,k),prk);
    2713       207734 :       gel(h,ih) = ZC_neg(log_prk1(nf, a, nh, L2, prk));
    2714       207734 :       gcoeff(h,ih,ih) = gel(F,k);
    2715              :     }
    2716              :   }
    2717        69957 :   return h;
    2718              : }
    2719              : /* true nf; k > 1; multiplicative group (1 + pr) / (1 + pr^k) */
    2720              : static GEN
    2721       194091 : idealprincipalunits_i(GEN nf, GEN pr, long k, GEN *pU)
    2722              : {
    2723       194091 :   GEN cyc, gen, L2, prk = idealpows(nf, pr, k);
    2724              : 
    2725       194100 :   L2 = principal_units(nf, pr, k, prk);
    2726       194099 :   if (k == 2)
    2727              :   {
    2728       124143 :     GEN L = gel(L2,1);
    2729       124143 :     cyc = gel(L,1);
    2730       124143 :     gen = gel(L,2);
    2731       124143 :     if (pU) *pU = matid(lg(gen)-1);
    2732              :   }
    2733              :   else
    2734              :   {
    2735        69956 :     long c = lg(L2), j;
    2736        69956 :     GEN EX, h, Ui, vg = cgetg(c, t_VEC);
    2737       221141 :     for (j = 1; j < c; j++) gel(vg, j) = gmael(L2,j,2);
    2738        69957 :     vg = shallowconcat1(vg);
    2739        69957 :     h = principal_units_relations(nf, L2, prk, lg(vg)-1);
    2740        69958 :     h = ZM_hnfall_i(h, NULL, 0);
    2741        69956 :     cyc = ZM_snf_group(h, pU, &Ui);
    2742        69956 :     c = lg(Ui); gen = cgetg(c, t_VEC); EX = cyc_get_expo(cyc);
    2743       228835 :     for (j = 1; j < c; j++)
    2744       158877 :       gel(gen,j) = famat_to_nf_modideal_coprime(nf, vg, gel(Ui,j), prk, EX);
    2745              :   }
    2746       194102 :   return mkvec4(cyc, gen, prk, L2);
    2747              : }
    2748              : GEN
    2749          196 : idealprincipalunits(GEN nf, GEN pr, long k)
    2750              : {
    2751              :   pari_sp av;
    2752              :   GEN v;
    2753          196 :   nf = checknf(nf);
    2754          196 :   if (k == 1) { checkprid(pr); retmkvec3(gen_1,cgetg(1,t_VEC),cgetg(1,t_VEC)); }
    2755          189 :   av = avma; v = idealprincipalunits_i(nf, pr, k, NULL);
    2756          189 :   return gc_GEN(av, mkvec3(powiu(pr_norm(pr), k-1), gel(v,1), gel(v,2)));
    2757              : }
    2758              : 
    2759              : /* true nf; given an ideal pr^k dividing an integral ideal x (in HNF form)
    2760              :  * compute an 'sprk', the structure of G = (Z_K/pr^k)^* [ x = NULL for x=pr^k ]
    2761              :  * Return a vector with at least 4 components [cyc],[gen],[HNF pr^k,pr,k],ff,
    2762              :  * where
    2763              :  * cyc : type of G as abelian group (SNF)
    2764              :  * gen : generators of G, coprime to x
    2765              :  * pr^k: in HNF
    2766              :  * ff  : data for log_g in (Z_K/pr)^*
    2767              :  * Two extra components are present iff k > 1: L2, U
    2768              :  * L2  : list of data structures to compute local DL in (Z_K/pr)^*,
    2769              :  *       and 1 + pr^a/ 1 + pr^b for various a < b <= min(2a, k)
    2770              :  * U   : base change matrices to convert a vector of local DL to DL wrt gen
    2771              :  * If MOD is not NULL, initialize G / G^MOD instead */
    2772              : static GEN
    2773       465698 : sprkinit(GEN nf, GEN pr, long k, GEN x, GEN MOD)
    2774              : {
    2775       465698 :   GEN T, p, Ld, modpr, cyc, gen, g, g0, A, prk, U, L2, ord0 = NULL;
    2776       465698 :   long f = pr_get_f(pr);
    2777              : 
    2778       465698 :   if(DEBUGLEVEL>3) err_printf("treating pr^%ld, pr = %Ps\n",k,pr);
    2779       465698 :   modpr = nf_to_Fq_init(nf, &pr,&T,&p);
    2780       465716 :   if (MOD)
    2781              :   {
    2782       418025 :     GEN o = subiu(powiu(p,f), 1), d = gcdii(o, MOD), fa = Z_factor(d);
    2783       418000 :     ord0 = mkvec2(o, fa); /* true order, factorization of order in G/G^MOD */
    2784       417991 :     Ld = gel(fa,1);
    2785       417991 :     if (lg(Ld) > 1 && equaliu(gel(Ld,1),2)) Ld = vecslice(Ld,2,lg(Ld)-1);
    2786              :   }
    2787              :   /* (Z_K / pr)^* */
    2788       465689 :   if (f == 1)
    2789              :   {
    2790       375732 :     g0 = g = MOD? pgener_Fp_local(p, Ld): pgener_Fp(p);
    2791       375754 :     if (!ord0) ord0 = get_arith_ZZM(subiu(p,1));
    2792              :   }
    2793              :   else
    2794              :   {
    2795        89957 :     g0 = g = MOD? gener_FpXQ_local(T, p, Ld): gener_FpXQ(T,p, &ord0);
    2796        89957 :     g = Fq_to_nf(g, modpr);
    2797        89956 :     if (typ(g) == t_POL) g = poltobasis(nf, g);
    2798              :   }
    2799       465712 :   A = gel(ord0, 1); /* Norm(pr)-1 */
    2800              :   /* If MOD != NULL, d = gcd(A, MOD): g^(A/d) has order d */
    2801       465712 :   if (k == 1)
    2802              :   {
    2803       271809 :     cyc = mkvec(A);
    2804       271808 :     gen = mkvec(g);
    2805       271803 :     prk = pr_hnf(nf,pr);
    2806       271816 :     L2 = U = NULL;
    2807              :   }
    2808              :   else
    2809              :   { /* local-gens of (1 + pr)/(1 + pr^k) = SNF-gens * U */
    2810              :     GEN AB, B, u, v, w;
    2811              :     long j, l;
    2812       193903 :     w = idealprincipalunits_i(nf, pr, k, &U);
    2813              :     /* incorporate (Z_K/pr)^*, order A coprime to B = expo(1+pr/1+pr^k)*/
    2814       193913 :     cyc = leafcopy(gel(w,1)); B = cyc_get_expo(cyc); AB = mulii(A,B);
    2815       193901 :     gen = leafcopy(gel(w,2));
    2816       193895 :     prk = gel(w,3);
    2817       193895 :     g = nfpowmodideal(nf, g, B, prk);
    2818       193909 :     g0 = Fq_pow(g0, modii(B,A), T, p); /* update primitive root */
    2819       193900 :     L2 = mkvec3(A, g, gel(w,4));
    2820       193908 :     gel(cyc,1) = AB;
    2821       193908 :     gel(gen,1) = nfmulmodideal(nf, gel(gen,1), g, prk);
    2822       193905 :     u = mulii(Fp_inv(A,B), A);
    2823       193894 :     v = subui(1, u); l = lg(U);
    2824       570064 :     for (j = 1; j < l; j++) gcoeff(U,1,j) = Fp_mul(u, gcoeff(U,1,j), AB);
    2825       193899 :     U = mkvec2(Rg_col_ei(v, lg(gen)-1, 1), U);
    2826              :   }
    2827              :   /* local-gens of (Z_K/pr^k)^* = SNF-gens * U */
    2828       465718 :   if (x)
    2829              :   {
    2830       270065 :     GEN uv = zkchineseinit(nf, idealmulpowprime(nf,x,pr,utoineg(k)), prk, x);
    2831       270052 :     gen = zkVchinese1(uv, gen);
    2832              :   }
    2833       465676 :   return mkvecn(U? 6: 4, cyc, gen, prk, mkvec3(modpr,g0,ord0), L2, U);
    2834              : }
    2835              : GEN
    2836      4570942 : sprk_get_cyc(GEN s) { return gel(s,1); }
    2837              : GEN
    2838      2143762 : sprk_get_expo(GEN s) { return cyc_get_expo(sprk_get_cyc(s)); }
    2839              : GEN
    2840       370358 : sprk_get_gen(GEN s) { return gel(s,2); }
    2841              : GEN
    2842      5630544 : sprk_get_prk(GEN s) { return gel(s,3); }
    2843              : GEN
    2844      3041832 : sprk_get_ff(GEN s) { return gel(s,4); }
    2845              : GEN
    2846      2820300 : sprk_get_pr(GEN s) { GEN ff = gel(s,4); return modpr_get_pr(gel(ff,1)); }
    2847              : /* L2 to 1 + pr / 1 + pr^k */
    2848              : static GEN
    2849      1552255 : sprk_get_L2(GEN s) { return gmael(s,5,3); }
    2850              : /* lift to nf of primitive root of k(pr) */
    2851              : static GEN
    2852       318214 : sprk_get_gnf(GEN s) { return gmael(s,5,2); }
    2853              : /* A = Npr-1, <g> = (Z_K/pr)^*, L2 to 1 + pr / 1 + pr^k */
    2854              : void
    2855            0 : sprk_get_AgL2(GEN s, GEN *A, GEN *g, GEN *L2)
    2856            0 : { GEN v = gel(s,5); *A = gel(v,1); *g = gel(v,2); *L2 = gel(v,3); }
    2857              : void
    2858      1532126 : sprk_get_U2(GEN s, GEN *U1, GEN *U2)
    2859      1532126 : { GEN v = gel(s,6); *U1 = gel(v,1); *U2 = gel(v,2); }
    2860              : static int
    2861      3041831 : sprk_is_prime(GEN s) { return lg(s) == 5; }
    2862              : 
    2863              : GEN
    2864      2143566 : famat_zlog_pr(GEN nf, GEN g, GEN e, GEN sprk, GEN mod)
    2865              : {
    2866      2143566 :   GEN x, expo = sprk_get_expo(sprk);
    2867      2143565 :   if (mod) expo = gcdii(expo,mod);
    2868      2143554 :   x = famat_makecoprime(nf, g, e, sprk_get_pr(sprk), sprk_get_prk(sprk), expo);
    2869      2143558 :   return log_prk(nf, x, sprk, mod);
    2870              : }
    2871              : /* famat_zlog_pr assuming (g,sprk.pr) = 1 */
    2872              : static GEN
    2873          196 : famat_zlog_pr_coprime(GEN nf, GEN g, GEN e, GEN sprk, GEN MOD)
    2874              : {
    2875          196 :   GEN x = famat_to_nf_modideal_coprime(nf, g, e, sprk_get_prk(sprk),
    2876              :                                        sprk_get_expo(sprk));
    2877          196 :   return log_prk(nf, x, sprk, MOD);
    2878              : }
    2879              : 
    2880              : /* o t_INT, O = [ord,fa] format for multiple of o (for Fq_log);
    2881              :  * return o in [ord,fa] format */
    2882              : static GEN
    2883       739833 : order_update(GEN o, GEN O)
    2884              : {
    2885       739833 :   GEN p = gmael(O,2,1), z = o, P, E;
    2886       739833 :   long i, j, l = lg(p);
    2887       739833 :   P = cgetg(l, t_COL);
    2888       739828 :   E = cgetg(l, t_COL);
    2889       797033 :   for (i = j = 1; i < l; i++)
    2890              :   {
    2891       797033 :     long v = Z_pvalrem(z, gel(p,i), &z);
    2892       796982 :     if (v)
    2893              :     {
    2894       783888 :       gel(P,j) = gel(p,i);
    2895       783888 :       gel(E,j) = utoipos(v); j++;
    2896       783900 :       if (is_pm1(z)) break;
    2897              :     }
    2898              :   }
    2899       739790 :   setlg(P, j);
    2900       739787 :   setlg(E, j); return mkvec2(o, mkmat2(P,E));
    2901              : }
    2902              : 
    2903              : /* a in Z_K (t_COL or t_INT), pr prime ideal, sprk = sprkinit(nf,pr,k,x),
    2904              :  * mod positive t_INT or NULL (meaning mod=0).
    2905              :  * return log(a) modulo mod on SNF-generators of (Z_K/pr^k)^* */
    2906              : GEN
    2907      3124427 : log_prk(GEN nf, GEN a, GEN sprk, GEN mod)
    2908              : {
    2909              :   GEN e, prk, g, U1, U2, y, ff, O, o, oN, gN,  N, T, p, modpr, pr, cyc;
    2910              : 
    2911      3124427 :   if (typ(a) == t_MAT) return famat_zlog_pr(nf, gel(a,1), gel(a,2), sprk, mod);
    2912      3041820 :   N = NULL;
    2913      3041820 :   ff = sprk_get_ff(sprk);
    2914      3041827 :   pr = gel(ff,1); /* modpr */
    2915      3041827 :   g = gN = gel(ff,2);
    2916      3041827 :   O = gel(ff,3); /* order of g = |Fq^*|, in [ord, fa] format */
    2917      3041827 :   o = oN = gel(O,1); /* order as a t_INT */
    2918      3041827 :   prk = sprk_get_prk(sprk);
    2919      3041848 :   modpr = nf_to_Fq_init(nf, &pr, &T, &p);
    2920      3041841 :   if (mod)
    2921              :   {
    2922      2523120 :     GEN d = gcdii(o,mod);
    2923      2522906 :     if (!equalii(o, d))
    2924              :     {
    2925       947441 :       N = diviiexact(o,d); /* > 1, coprime to p */
    2926       947378 :       a = nfpowmodideal(nf, a, N, prk);
    2927       947558 :       oN = d; /* order of g^N mod pr */
    2928              :     }
    2929              :   }
    2930      3041690 :   if (equali1(oN))
    2931       684764 :     e = gen_0;
    2932              :   else
    2933              :   {
    2934      2356957 :     if (N) { O = order_update(oN, O); gN = Fq_pow(g, N, T, p); }
    2935      2356960 :     e = Fq_log(nf_to_Fq(nf,a,modpr), gN, O, T, p);
    2936              :   }
    2937              :   /* 0 <= e < oN is correct modulo oN */
    2938      3041848 :   if (sprk_is_prime(sprk)) return mkcol(e); /* k = 1 */
    2939              : 
    2940      1087196 :   sprk_get_U2(sprk, &U1,&U2);
    2941      1087278 :   cyc = sprk_get_cyc(sprk);
    2942      1087282 :   if (mod)
    2943              :   {
    2944       663686 :     cyc = ZV_snf_gcd(cyc, mod);
    2945       663673 :     if (signe(remii(mod,p))) return ZV_ZV_mod(ZC_Z_mul(U1,e), cyc);
    2946              :   }
    2947      1033549 :   if (signe(e))
    2948              :   {
    2949       318214 :     GEN E = N? mulii(e, N): e;
    2950       318214 :     a = nfmulpowmodideal(nf, a, sprk_get_gnf(sprk), Fp_neg(E, o), prk);
    2951              :   }
    2952              :   /* a = 1 mod pr */
    2953      1033549 :   y = log_prk1(nf, a, lg(U2)-1, sprk_get_L2(sprk), prk);
    2954      1033581 :   if (N)
    2955              :   { /* from DL(a^N) to DL(a) */
    2956       152175 :     GEN E = gel(sprk_get_cyc(sprk), 1), q = powiu(p, Z_pval(E, p));
    2957       152176 :     y = ZC_Z_mul(y, Fp_inv(N, q));
    2958              :   }
    2959      1033581 :   y = ZC_lincomb(gen_1, e, ZM_ZC_mul(U2,y), U1);
    2960      1033588 :   return ZV_ZV_mod(y, cyc);
    2961              : }
    2962              : /* true nf */
    2963              : GEN
    2964        95417 : log_prk_init(GEN nf, GEN pr, long k, GEN MOD)
    2965        95417 : { return sprkinit(nf,pr,k,NULL,MOD);}
    2966              : GEN
    2967          497 : veclog_prk(GEN nf, GEN v, GEN sprk)
    2968              : {
    2969          497 :   long l = lg(v), i;
    2970          497 :   GEN w = cgetg(l, t_MAT);
    2971         1232 :   for (i = 1; i < l; i++) gel(w,i) = log_prk(nf, gel(v,i), sprk, NULL);
    2972          497 :   return w;
    2973              : }
    2974              : 
    2975              : static GEN
    2976      1424660 : famat_zlog(GEN nf, GEN fa, GEN sgn, zlog_S *S)
    2977              : {
    2978      1424660 :   long i, l0, l = lg(S->U);
    2979      1424660 :   GEN g = gel(fa,1), e = gel(fa,2), y = cgetg(l, t_COL);
    2980      1424661 :   l0 = lg(S->sprk); /* = l (trivial arch. part), or l-1 */
    2981      3065925 :   for (i=1; i < l0; i++) gel(y,i) = famat_zlog_pr(nf, g, e, gel(S->sprk,i), S->mod);
    2982      1424657 :   if (l0 != l)
    2983              :   {
    2984       233420 :     if (!sgn) sgn = nfsign_arch(nf, fa, S->archp);
    2985       233420 :     gel(y,l0) = Flc_to_ZC(sgn);
    2986              :   }
    2987      1424657 :   return y;
    2988              : }
    2989              : 
    2990              : /* assume that cyclic factors are normalized, in particular != [1] */
    2991              : static GEN
    2992       270376 : split_U(GEN U, GEN Sprk)
    2993              : {
    2994       270376 :   long t = 0, k, n, l = lg(Sprk);
    2995       270376 :   GEN vU = cgetg(l+1, t_VEC);
    2996       639946 :   for (k = 1; k < l; k++)
    2997              :   {
    2998       369574 :     n = lg(sprk_get_cyc(gel(Sprk,k))) - 1; /* > 0 */
    2999       369575 :     gel(vU,k) = vecslice(U, t+1, t+n);
    3000       369578 :     t += n;
    3001              :   }
    3002              :   /* t+1 .. lg(U)-1 */
    3003       270372 :   n = lg(U) - t - 1; /* can be 0 */
    3004       270372 :   if (!n) setlg(vU,l); else gel(vU,l) = vecslice(U, t+1, t+n);
    3005       270380 :   return vU;
    3006              : }
    3007              : 
    3008              : static void
    3009      2157256 : init_zlog_mod(zlog_S *S, GEN bid, GEN mod)
    3010              : {
    3011      2157256 :   GEN fa2 = bid_get_fact2(bid), MOD = bid_get_MOD(bid);
    3012      2157256 :   S->U = bid_get_U(bid);
    3013      2157253 :   S->hU = lg(bid_get_cyc(bid))-1;
    3014      2157250 :   S->archp = bid_get_archp(bid);
    3015      2157250 :   S->sprk = bid_get_sprk(bid);
    3016      2157249 :   S->bid = bid;
    3017      2157249 :   if (MOD) mod = mod? gcdii(mod, MOD): MOD;
    3018      2157161 :   S->mod = mod;
    3019      2157161 :   S->P = gel(fa2,1);
    3020      2157161 :   S->k = gel(fa2,2);
    3021      2157161 :   S->no2 = lg(S->P) == lg(gel(bid_get_fact(bid),1));
    3022      2157173 : }
    3023              : void
    3024       395953 : init_zlog(zlog_S *S, GEN bid)
    3025              : {
    3026       395953 :   return init_zlog_mod(S, bid, NULL);
    3027              : }
    3028              : 
    3029              : /* a a t_FRAC/t_INT, reduce mod bid */
    3030              : static GEN
    3031           14 : Q_mod_bid(GEN bid, GEN a)
    3032              : {
    3033           14 :   GEN xZ = gcoeff(bid_get_ideal(bid),1,1);
    3034           14 :   GEN b = Rg_to_Fp(a, xZ);
    3035           14 :   if (gsigne(a) < 0) b = subii(b, xZ);
    3036           14 :   return signe(b)? b: xZ;
    3037              : }
    3038              : /* Return decomposition of a on the CRT generators blocks attached to the
    3039              :  * S->sprk and sarch; sgn = sign(a, S->arch), NULL if unknown */
    3040              : static GEN
    3041       495227 : zlog(GEN nf, GEN a, GEN sgn, zlog_S *S)
    3042              : {
    3043              :   long k, l;
    3044              :   GEN y;
    3045       495227 :   a = nf_to_scalar_or_basis(nf, a);
    3046       495220 :   switch(typ(a))
    3047              :   {
    3048       184968 :     case t_INT: break;
    3049           14 :     case t_FRAC: a = Q_mod_bid(S->bid, a); break;
    3050       310238 :     default: /* case t_COL: */
    3051              :     {
    3052              :       GEN den;
    3053       310238 :       a = Q_remove_denom(a, &den);
    3054       310251 :       if (den)
    3055              :       {
    3056           84 :         a = mkmat2(mkcol2(a, den), mkcol2(gen_1, gen_m1));
    3057           84 :         return famat_zlog(nf, a, sgn, S);
    3058              :       }
    3059              :     }
    3060              :   }
    3061       495144 :   if (sgn)
    3062       400812 :     sgn = (lg(sgn) == 1)? NULL: leafcopy(sgn);
    3063              :   else
    3064        94332 :     sgn = (lg(S->archp) == 1)? NULL: nfsign_arch(nf, a, S->archp);
    3065       495141 :   l = lg(S->sprk);
    3066       495141 :   y = cgetg(sgn? l+1: l, t_COL);
    3067      1350393 :   for (k = 1; k < l; k++)
    3068              :   {
    3069       855295 :     GEN sprk = gel(S->sprk,k);
    3070       855295 :     gel(y,k) = log_prk(nf, a, sprk, S->mod);
    3071              :   }
    3072       495098 :   if (sgn) gel(y,l) = Flc_to_ZC(sgn);
    3073       495103 :   return y;
    3074              : }
    3075              : 
    3076              : /* true nf */
    3077              : GEN
    3078        72247 : pr_basis_perm(GEN nf, GEN pr)
    3079              : {
    3080        72247 :   long f = pr_get_f(pr);
    3081              :   GEN perm;
    3082        72247 :   if (f == nf_get_degree(nf)) return identity_perm(f);
    3083        62167 :   perm = cgetg(f+1, t_VECSMALL);
    3084        62167 :   perm[1] = 1;
    3085        62167 :   if (f > 1)
    3086              :   {
    3087         3248 :     GEN H = pr_hnf(nf,pr);
    3088              :     long i, k;
    3089        11480 :     for (i = k = 2; k <= f; i++)
    3090         8232 :       if (!equali1(gcoeff(H,i,i))) perm[k++] = i;
    3091              :   }
    3092        62167 :   return perm;
    3093              : }
    3094              : 
    3095              : /* \sum U[i]*y[i], U[i] ZM, y[i] ZC. We allow lg(y) > lg(U). */
    3096              : static GEN
    3097      1919860 : ZMV_ZCV_mul(GEN U, GEN y)
    3098              : {
    3099      1919860 :   long i, l = lg(U);
    3100      1919860 :   GEN z = NULL;
    3101      1919860 :   if (l == 1) return cgetg(1,t_COL);
    3102      4915472 :   for (i = 1; i < l; i++)
    3103              :   {
    3104      2995722 :     GEN u = ZM_ZC_mul(gel(U,i), gel(y,i));
    3105      2995678 :     z = z? ZC_add(z, u): u;
    3106              :   }
    3107      1919750 :   return z;
    3108              : }
    3109              : /* A * (x[1], ..., x[d] */
    3110              : static GEN
    3111          518 : ZM_ZMV_mul(GEN A, GEN x)
    3112         1057 : { pari_APPLY_same(ZM_mul(A,gel(x,i))); }
    3113              : 
    3114              : /* a = 1 mod pr, sprk mod pr^e, e >= 1 */
    3115              : static GEN
    3116       444864 : sprk_log_prk1_2(GEN nf, GEN a, GEN sprk)
    3117              : {
    3118       444864 :   GEN U1, U2, y, L2 = sprk_get_L2(sprk);
    3119       444865 :   sprk_get_U2(sprk, &U1,&U2);
    3120       444865 :   y = ZM_ZC_mul(U2, log_prk1(nf, a, lg(U2)-1, L2, sprk_get_prk(sprk)));
    3121       444859 :   return ZV_ZV_mod(y, sprk_get_cyc(sprk));
    3122              : }
    3123              : /* true nf; assume e >= 2 */
    3124              : GEN
    3125       145845 : sprk_log_gen_pr2(GEN nf, GEN sprk, long e)
    3126              : {
    3127       145845 :   GEN M, G, pr = sprk_get_pr(sprk);
    3128              :   long i, l;
    3129       145845 :   if (e == 2)
    3130              :   {
    3131        73850 :     GEN L2 = sprk_get_L2(sprk), L = gel(L2,1);
    3132        73850 :     G = gel(L,2); l = lg(G);
    3133              :   }
    3134              :   else
    3135              :   {
    3136        71995 :     GEN perm = pr_basis_perm(nf,pr), PI = nfpow_u(nf, pr_get_gen(pr), e-1);
    3137        71995 :     l = lg(perm);
    3138        71995 :     G = cgetg(l, t_VEC);
    3139        71995 :     if (typ(PI) == t_INT)
    3140              :     { /* zk_ei_mul doesn't allow t_INT */
    3141        10073 :       long N = nf_get_degree(nf);
    3142        10073 :       gel(G,1) = addiu(PI,1);
    3143        13076 :       for (i = 2; i < l; i++)
    3144              :       {
    3145         3003 :         GEN z = col_ei(N, 1);
    3146         3003 :         gel(G,i) = z; gel(z, perm[i]) = PI;
    3147              :       }
    3148              :     }
    3149              :     else
    3150              :     {
    3151        61922 :       gel(G,1) = nfadd(nf, gen_1, PI);
    3152        69041 :       for (i = 2; i < l; i++)
    3153         7119 :         gel(G,i) = nfadd(nf, gen_1, zk_ei_mul(nf, PI, perm[i]));
    3154              :     }
    3155              :   }
    3156       145845 :   M = cgetg(l, t_MAT);
    3157       314819 :   for (i = 1; i < l; i++) gel(M,i) = sprk_log_prk1_2(nf, gel(G,i), sprk);
    3158       145827 :   return M;
    3159              : }
    3160              : /* Log on bid.gen of generators of P_{1,I pr^{e-1}} / P_{1,I pr^e} (I,pr) = 1,
    3161              :  * defined implicitly via CRT. 'ind' is the index of pr in modulus
    3162              :  * factorization; true nf */
    3163              : GEN
    3164       484277 : log_gen_pr(zlog_S *S, long ind, GEN nf, long e)
    3165              : {
    3166       484277 :   GEN Uind = gel(S->U, ind);
    3167       484277 :   if (e == 1) retmkmat( gel(Uind,1) );
    3168       143127 :   return ZM_mul(Uind, sprk_log_gen_pr2(nf, gel(S->sprk,ind), e));
    3169              : }
    3170              : /* true nf */
    3171              : GEN
    3172         2037 : sprk_log_gen_pr(GEN nf, GEN sprk, long e)
    3173              : {
    3174         2037 :   if (e == 1)
    3175              :   {
    3176            0 :     long n = lg(sprk_get_cyc(sprk))-1;
    3177            0 :     retmkmat(col_ei(n, 1));
    3178              :   }
    3179         2037 :   return sprk_log_gen_pr2(nf, sprk, e);
    3180              : }
    3181              : /* a = 1 mod pr */
    3182              : GEN
    3183       275872 : sprk_log_prk1(GEN nf, GEN a, GEN sprk)
    3184              : {
    3185       275872 :   if (lg(sprk) == 5) return mkcol(gen_0); /* mod pr */
    3186       275872 :   return sprk_log_prk1_2(nf, a, sprk);
    3187              : }
    3188              : /* Log on bid.gen of generator of P_{1,f} / P_{1,f v[index]}
    3189              :  * v = vector of r1 real places */
    3190              : GEN
    3191       111991 : log_gen_arch(zlog_S *S, long index) { return gel(veclast(S->U), index); }
    3192              : 
    3193              : /* compute bid.clgp: [h,cyc] or [h,cyc,gen] */
    3194              : static GEN
    3195       271392 : bid_grp(GEN nf, GEN U, GEN cyc, GEN g, GEN F, GEN sarch)
    3196              : {
    3197       271392 :   GEN G, h = ZV_prod(cyc);
    3198              :   long c;
    3199       271416 :   if (!U) return mkvec2(h,cyc);
    3200       271059 :   c = lg(U);
    3201       271059 :   G = cgetg(c,t_VEC);
    3202       271065 :   if (c > 1)
    3203              :   {
    3204       240974 :     GEN U0, Uoo, EX = cyc_get_expo(cyc); /* exponent of bid */
    3205       240973 :     long i, hU = nbrows(U), nba = lg(sarch_get_cyc(sarch))-1; /* #f_oo */
    3206       240981 :     if (!nba) { U0 = U; Uoo = NULL; }
    3207        90583 :     else if (nba == hU) { U0 = NULL; Uoo = U; }
    3208              :     else
    3209              :     {
    3210        81441 :       U0 = rowslice(U, 1, hU-nba);
    3211        81444 :       Uoo = rowslice(U, hU-nba+1, hU);
    3212              :     }
    3213       771488 :     for (i = 1; i < c; i++)
    3214              :     {
    3215       530510 :       GEN t = gen_1;
    3216       530510 :       if (U0) t = famat_to_nf_modideal_coprime(nf, g, gel(U0,i), F, EX);
    3217       530510 :       if (Uoo) t = set_sign_mod_divisor(nf, ZV_to_Flv(gel(Uoo,i),2), t, sarch);
    3218       530507 :       gel(G,i) = t;
    3219              :     }
    3220              :   }
    3221       271069 :   return mkvec3(h, cyc, G);
    3222              : }
    3223              : 
    3224              : /* remove prime ideals of norm 2 with exponent 1 from factorization */
    3225              : static GEN
    3226       271767 : famat_strip2(GEN fa)
    3227              : {
    3228       271767 :   GEN P = gel(fa,1), E = gel(fa,2), Q, F;
    3229       271767 :   long l = lg(P), i, j;
    3230       271767 :   Q = cgetg(l, t_COL);
    3231       271764 :   F = cgetg(l, t_COL);
    3232       681394 :   for (i = j = 1; i < l; i++)
    3233              :   {
    3234       409624 :     GEN pr = gel(P,i), e = gel(E,i);
    3235       409624 :     if (!absequaliu(pr_get_p(pr), 2) || itou(e) != 1 || pr_get_f(pr) != 1)
    3236              :     {
    3237       370984 :       gel(Q,j) = pr;
    3238       370984 :       gel(F,j) = e; j++;
    3239              :     }
    3240              :   }
    3241       271770 :   setlg(Q,j);
    3242       271769 :   setlg(F,j); return mkmat2(Q,F);
    3243              : }
    3244              : static int
    3245       134104 : checkarchp(GEN v, long r1)
    3246              : {
    3247       134104 :   long i, l = lg(v);
    3248       134104 :   pari_sp av = avma;
    3249              :   GEN p;
    3250       134104 :   if (l == 1) return 1;
    3251        47167 :   if (l == 2) return v[1] > 0 && v[1] <= r1;
    3252        22016 :   p = zero_zv(r1);
    3253        66147 :   for (i = 1; i < l; i++)
    3254              :   {
    3255        44161 :     long j = v[i];
    3256        44161 :     if (j <= 0 || j > r1 || p[j]) return gc_long(av, 0);
    3257        44126 :     p[j] = 1;
    3258              :   }
    3259        21986 :   return gc_long(av, 1);
    3260              : }
    3261              : 
    3262              : /* True nf. Put ideal to form [[ideal,arch]] and set fa and fa2 to its
    3263              :  * factorization, archp to the indices of arch places */
    3264              : GEN
    3265       271761 : check_mod_factored(GEN nf, GEN ideal, GEN *fa_, GEN *fa2_, GEN *archp_, GEN MOD)
    3266              : {
    3267              :   GEN arch, x, fa, fa2, archp;
    3268              :   long R1;
    3269              : 
    3270       271761 :   R1 = nf_get_r1(nf);
    3271       271763 :   if (typ(ideal) == t_VEC && lg(ideal) == 3)
    3272              :   {
    3273       191560 :     arch = gel(ideal,2);
    3274       191560 :     ideal= gel(ideal,1);
    3275       191560 :     switch(typ(arch))
    3276              :     {
    3277        57456 :       case t_VEC:
    3278        57456 :         if (lg(arch) != R1+1)
    3279            7 :           pari_err_TYPE("Idealstar [incorrect archimedean component]",arch);
    3280        57449 :         archp = vec01_to_indices(arch);
    3281        57449 :         break;
    3282       134104 :       case t_VECSMALL:
    3283       134104 :         if (!checkarchp(arch, R1))
    3284           35 :           pari_err_TYPE("Idealstar [incorrect archimedean component]",arch);
    3285       134071 :         archp = arch;
    3286       134071 :         arch = indices_to_vec01(archp, R1);
    3287       134069 :         break;
    3288            0 :       default:
    3289            0 :         pari_err_TYPE("Idealstar [incorrect archimedean component]",arch);
    3290              :         return NULL;/*LCOV_EXCL_LINE*/
    3291              :     }
    3292              :   }
    3293              :   else
    3294              :   {
    3295        80203 :     arch = zerovec(R1);
    3296        80195 :     archp = cgetg(1, t_VECSMALL);
    3297              :   }
    3298       271718 :   if (MOD)
    3299              :   {
    3300       227086 :     if (typ(MOD) != t_INT) pari_err_TYPE("bnrinit [incorrect cycmod]", MOD);
    3301       227086 :     if (mpodd(MOD) && lg(archp) != 1)
    3302          231 :       MOD = shifti(MOD, 1); /* ensure elements of G^MOD are >> 0 */
    3303              :   }
    3304       271714 :   if (is_nf_factor(ideal))
    3305              :   {
    3306        53172 :     fa = ideal;
    3307        53172 :     x = factorbackprime(nf, gel(fa,1), gel(fa,2));
    3308              :   }
    3309              :   else
    3310              :   {
    3311       218544 :     fa = idealfactor(nf, ideal);
    3312       218551 :     x = ideal;
    3313              :   }
    3314       271723 :   if (typ(x) != t_MAT) x = idealhnf_shallow(nf, x);
    3315       271711 :   if (lg(x) == 1) pari_err_DOMAIN("Idealstar", "ideal","=",gen_0,x);
    3316       271711 :   if (typ(gcoeff(x,1,1)) != t_INT)
    3317            7 :     pari_err_DOMAIN("Idealstar","denominator(ideal)", "!=",gen_1,x);
    3318              : 
    3319       271704 :   fa2 = famat_strip2(fa);
    3320       271704 :   if (fa_ != NULL) *fa_ = fa;
    3321       271704 :   if (fa2_ != NULL) *fa2_ = fa2;
    3322       271704 :   if (fa2_ != NULL) *archp_ = archp;
    3323       271704 :   return mkvec2(x, arch);
    3324              : }
    3325              : 
    3326              : /* True nf. Compute [[ideal,arch], [h,[cyc],[gen]], idealfact, [liste], U]
    3327              :    flag may include nf_GEN | nf_INIT */
    3328              : static GEN
    3329       271114 : Idealstarmod_i(GEN nf, GEN ideal, long flag, GEN MOD)
    3330              : {
    3331              :   long i, nbp;
    3332       271114 :   GEN y, cyc, U, u1 = NULL, fa, fa2, sprk, x_arch, x, arch, archp, E, P, sarch, gen;
    3333              : 
    3334       271114 :   x_arch = check_mod_factored(nf, ideal, &fa, &fa2, &archp, MOD);
    3335       271063 :   x = gel(x_arch, 1);
    3336       271063 :   arch = gel(x_arch, 2);
    3337              : 
    3338       271063 :   sarch = nfarchstar(nf, x, archp);
    3339       271061 :   P = gel(fa2,1);
    3340       271061 :   E = gel(fa2,2);
    3341       271061 :   nbp = lg(P)-1;
    3342       271061 :   sprk = cgetg(nbp+1,t_VEC);
    3343       271070 :   if (nbp)
    3344              :   {
    3345       231793 :     GEN t = (lg(gel(fa,1))==2)? NULL: x; /* beware fa != fa2 */
    3346       231793 :     cyc = cgetg(nbp+2,t_VEC);
    3347       231786 :     gen = cgetg(nbp+1,t_VEC);
    3348       602084 :     for (i = 1; i <= nbp; i++)
    3349              :     {
    3350       370285 :       GEN L = sprkinit(nf, gel(P,i), itou(gel(E,i)), t, MOD);
    3351       370298 :       gel(sprk,i) = L;
    3352       370298 :       gel(cyc,i) = sprk_get_cyc(L);
    3353              :       /* true gens are congruent to those mod x AND positive at archp */
    3354       370296 :       gel(gen,i) = sprk_get_gen(L);
    3355              :     }
    3356       231799 :     gel(cyc,i) = sarch_get_cyc(sarch);
    3357       231799 :     cyc = shallowconcat1(cyc);
    3358       231799 :     gen = shallowconcat1(gen);
    3359       231803 :     cyc = ZV_snf_group(cyc, &U, (flag & nf_GEN)? &u1: NULL);
    3360              :   }
    3361              :   else
    3362              :   {
    3363        39277 :     cyc = sarch_get_cyc(sarch);
    3364        39277 :     gen = cgetg(1,t_VEC);
    3365        39276 :     U = matid(lg(cyc)-1);
    3366        39275 :     if (flag & nf_GEN) u1 = U;
    3367              :   }
    3368       271052 :   if (MOD) cyc = ZV_snf_gcd(cyc, MOD);
    3369       271035 :   y = bid_grp(nf, u1, cyc, gen, x, sarch);
    3370       271070 :   if (!(flag & nf_INIT)) return y;
    3371       270272 :   U = split_U(U, sprk);
    3372       540539 :   return mkvec5(mkvec2(x, arch), y, mkvec2(fa,fa2),
    3373       270269 :                 MOD? mkvec3(sprk, sarch, MOD): mkvec2(sprk, sarch),
    3374              :                 U);
    3375              : }
    3376              : 
    3377              : static long
    3378           63 : idealHNF_norm_pval(GEN x, GEN p)
    3379              : {
    3380           63 :   long i, v = 0, l = lg(x);
    3381          175 :   for (i = 1; i < l; i++) v += Z_pval(gcoeff(x,i,i), p);
    3382           63 :   return v;
    3383              : }
    3384              : static long
    3385           63 : sprk_get_k(GEN sprk)
    3386              : {
    3387              :   GEN pr, prk;
    3388           63 :   if (sprk_is_prime(sprk)) return 1;
    3389           63 :   pr = sprk_get_pr(sprk);
    3390           63 :   prk = sprk_get_prk(sprk);
    3391           63 :   return idealHNF_norm_pval(prk, pr_get_p(pr)) / pr_get_f(pr);
    3392              : }
    3393              : /* true nf, L a sprk */
    3394              : GEN
    3395           63 : sprk_to_bid(GEN nf, GEN L, long flag)
    3396              : {
    3397           63 :   GEN y, cyc, U, u1 = NULL, fa, fa2, arch, sarch, gen, sprk;
    3398              : 
    3399           63 :   arch = zerovec(nf_get_r1(nf));
    3400           63 :   fa = to_famat_shallow(sprk_get_pr(L), utoipos(sprk_get_k(L)));
    3401           63 :   sarch = nfarchstar(nf, NULL, cgetg(1, t_VECSMALL));
    3402           63 :   fa2 = famat_strip2(fa);
    3403           63 :   sprk = mkvec(L);
    3404           63 :   cyc = shallowconcat(sprk_get_cyc(L), sarch_get_cyc(sarch));
    3405           63 :   gen = sprk_get_gen(L);
    3406           63 :   cyc = ZV_snf_group(cyc, &U, (flag & nf_GEN)? &u1: NULL);
    3407           63 :   y = bid_grp(nf, u1, cyc, gen, NULL, sarch);
    3408           63 :   if (!(flag & nf_INIT)) return y;
    3409           63 :   return mkvec5(mkvec2(sprk_get_prk(L), arch), y, mkvec2(fa,fa2),
    3410              :                 mkvec2(sprk, sarch), split_U(U, sprk));
    3411              : }
    3412              : GEN
    3413       270833 : Idealstarmod(GEN nf, GEN ideal, long flag, GEN MOD)
    3414              : {
    3415       270833 :   pari_sp av = avma;
    3416       270833 :   nf = nf? checknf(nf): nfinit(pol_x(0), DEFAULTPREC);
    3417       270841 :   return gc_GEN(av, Idealstarmod_i(nf, ideal, flag, MOD));
    3418              : }
    3419              : GEN
    3420          938 : Idealstar(GEN nf, GEN ideal, long flag) { return Idealstarmod(nf, ideal, flag, NULL); }
    3421              : GEN
    3422          273 : Idealstarprk(GEN nf, GEN pr, long k, long flag)
    3423              : {
    3424          273 :   pari_sp av = avma;
    3425          273 :   GEN z = Idealstarmod_i(nf, mkmat2(mkcol(pr),mkcols(k)), flag, NULL);
    3426          273 :   return gc_GEN(av, z);
    3427              : }
    3428              : 
    3429              : /* FIXME: obsolete */
    3430              : GEN
    3431            0 : zidealstarinitgen(GEN nf, GEN ideal)
    3432            0 : { return Idealstar(nf,ideal, nf_INIT|nf_GEN); }
    3433              : GEN
    3434            0 : zidealstarinit(GEN nf, GEN ideal)
    3435            0 : { return Idealstar(nf,ideal, nf_INIT); }
    3436              : GEN
    3437            0 : zidealstar(GEN nf, GEN ideal)
    3438            0 : { return Idealstar(nf,ideal, nf_GEN); }
    3439              : 
    3440              : GEN
    3441          112 : idealstarmod(GEN nf, GEN ideal, long flag, GEN MOD)
    3442              : {
    3443          112 :   switch(flag)
    3444              :   {
    3445            0 :     case 0: return Idealstarmod(nf,ideal, nf_GEN, MOD);
    3446           98 :     case 1: return Idealstarmod(nf,ideal, nf_INIT, MOD);
    3447           14 :     case 2: return Idealstarmod(nf,ideal, nf_INIT|nf_GEN, MOD);
    3448            0 :     default: pari_err_FLAG("idealstar");
    3449              :   }
    3450              :   return NULL; /* LCOV_EXCL_LINE */
    3451              : }
    3452              : GEN
    3453            0 : idealstar0(GEN nf, GEN ideal,long flag) { return idealstarmod(nf, ideal, flag, NULL); }
    3454              : 
    3455              : GEN
    3456      2321590 : ZV_snf_gcd(GEN x, GEN mod)
    3457      5501777 : { pari_APPLY_same(gcdii(gel(x,i), mod)); }
    3458              : 
    3459              : /* assume a true bnf and bid */
    3460              : GEN
    3461       239957 : ideallog_units0(GEN bnf, GEN bid, GEN MOD)
    3462              : {
    3463       239957 :   GEN nf = bnf_get_nf(bnf), D, y, C, cyc;
    3464       239956 :   long j, lU = lg(bnf_get_logfu(bnf)); /* r1+r2 */
    3465              :   zlog_S S;
    3466       239956 :   init_zlog_mod(&S, bid, MOD);
    3467       239935 :   if (!S.hU) return zeromat(0,lU);
    3468       239935 :   cyc = bid_get_cyc(bid);
    3469       239932 :   D = nfsign_fu(bnf, bid_get_archp(bid));
    3470       239950 :   y = cgetg(lU, t_MAT);
    3471       239947 :   if ((C = bnf_build_cheapfu(bnf)))
    3472       400767 :   { for (j = 1; j < lU; j++) gel(y,j) = zlog(nf, gel(C,j), gel(D,j), &S); }
    3473              :   else
    3474              :   {
    3475           49 :     long i, l = lg(S.U), l0 = lg(S.sprk);
    3476              :     GEN X, U;
    3477           49 :     if (!(C = bnf_compactfu_mat(bnf))) bnf_build_units(bnf); /* error */
    3478           49 :     X = gel(C,1); U = gel(C,2);
    3479          147 :     for (j = 1; j < lU; j++) gel(y,j) = cgetg(l, t_COL);
    3480          126 :     for (i = 1; i < l0; i++)
    3481              :     {
    3482           77 :       GEN sprk = gel(S.sprk, i);
    3483           77 :       GEN Xi = sunits_makecoprime(X, sprk_get_pr(sprk), sprk_get_prk(sprk));
    3484          231 :       for (j = 1; j < lU; j++)
    3485          154 :         gcoeff(y,i,j) = famat_zlog_pr_coprime(nf, Xi, gel(U,j), sprk, MOD);
    3486              :     }
    3487           49 :     if (l0 != l)
    3488           56 :       for (j = 1; j < lU; j++) gcoeff(y,l0,j) = Flc_to_ZC(gel(D,j));
    3489              :   }
    3490       239946 :   y = vec_prepend(y, zlog(nf, bnf_get_tuU(bnf), nfsign_tu(bnf, S.archp), &S));
    3491       640818 :   for (j = 1; j <= lU; j++)
    3492       400889 :     gel(y,j) = ZV_ZV_mod(ZMV_ZCV_mul(S.U, gel(y,j)), cyc);
    3493       239929 :   return y;
    3494              : }
    3495              : GEN
    3496           84 : ideallog_units(GEN bnf, GEN bid)
    3497           84 : { return ideallog_units0(bnf, bid, NULL); }
    3498              : GEN
    3499          518 : log_prk_units(GEN nf, GEN D, GEN sprk)
    3500              : {
    3501          518 :   GEN L, Ltu = log_prk(nf, gel(D,1), sprk, NULL);
    3502          518 :   D = gel(D,2);
    3503          518 :   if (lg(D) != 3 || typ(gel(D,2)) != t_MAT) L = veclog_prk(nf, D, sprk);
    3504              :   else
    3505              :   {
    3506           21 :     GEN X = gel(D,1), U = gel(D,2);
    3507           21 :     long j, lU = lg(U);
    3508           21 :     X = sunits_makecoprime(X, sprk_get_pr(sprk), sprk_get_prk(sprk));
    3509           21 :     L = cgetg(lU, t_MAT);
    3510           63 :     for (j = 1; j < lU; j++)
    3511           42 :       gel(L,j) = famat_zlog_pr_coprime(nf, X, gel(U,j), sprk, NULL);
    3512              :   }
    3513          518 :   return vec_prepend(L, Ltu);
    3514              : }
    3515              : 
    3516              : static GEN
    3517      1521357 : ideallog_i(GEN nf, GEN x, zlog_S *S)
    3518              : {
    3519      1521357 :   pari_sp av = avma;
    3520              :   GEN y;
    3521      1521357 :   if (!S->hU) return cgetg(1, t_COL);
    3522      1518991 :   if (typ(x) == t_MAT)
    3523      1424575 :     y = famat_zlog(nf, x, NULL, S);
    3524              :   else
    3525        94416 :     y = zlog(nf, x, NULL, S);
    3526      1518984 :   y = ZMV_ZCV_mul(S->U, y);
    3527      1518986 :   return gc_upto(av, ZV_ZV_mod(y, bid_get_cyc(S->bid)));
    3528              : }
    3529              : GEN
    3530      1528039 : ideallogmod(GEN nf, GEN x, GEN bid, GEN mod)
    3531              : {
    3532              :   zlog_S S;
    3533      1528039 :   if (!nf)
    3534              :   {
    3535         6671 :     if (mod) pari_err_IMPL("Zideallogmod");
    3536         6671 :     return Zideallog(bid, x);
    3537              :   }
    3538      1521368 :   checkbid(bid); init_zlog_mod(&S, bid, mod);
    3539      1521358 :   return ideallog_i(checknf(nf), x, &S);
    3540              : }
    3541              : GEN
    3542        13769 : ideallog(GEN nf, GEN x, GEN bid) { return ideallogmod(nf, x, bid, NULL); }
    3543              : 
    3544              : /*************************************************************************/
    3545              : /**                                                                     **/
    3546              : /**               JOIN BID STRUCTURES, IDEAL LISTS                      **/
    3547              : /**                                                                     **/
    3548              : /*************************************************************************/
    3549              : /* bid1, bid2: for coprime modules m1 and m2 (without arch. part).
    3550              :  * Output: bid for m1 m2 */
    3551              : static GEN
    3552          469 : join_bid(GEN nf, GEN bid1, GEN bid2)
    3553              : {
    3554          469 :   pari_sp av = avma;
    3555              :   long nbgen, l1,l2;
    3556              :   GEN I1,I2, G1,G2, sprk1,sprk2, cyc1,cyc2, sarch;
    3557          469 :   GEN sprk, fa,fa2, U, cyc, y, u1 = NULL, x, gen;
    3558              : 
    3559          469 :   I1 = bid_get_ideal(bid1);
    3560          469 :   I2 = bid_get_ideal(bid2);
    3561          469 :   if (gequal1(gcoeff(I1,1,1))) return bid2; /* frequent trivial case */
    3562          259 :   G1 = bid_get_grp(bid1);
    3563          259 :   G2 = bid_get_grp(bid2);
    3564          259 :   x = idealmul(nf, I1,I2);
    3565          259 :   fa = famat_mul_shallow(bid_get_fact(bid1), bid_get_fact(bid2));
    3566          259 :   fa2= famat_mul_shallow(bid_get_fact2(bid1), bid_get_fact2(bid2));
    3567          259 :   sprk1 = bid_get_sprk(bid1);
    3568          259 :   sprk2 = bid_get_sprk(bid2);
    3569          259 :   sprk = shallowconcat(sprk1, sprk2);
    3570              : 
    3571          259 :   cyc1 = abgrp_get_cyc(G1); l1 = lg(cyc1);
    3572          259 :   cyc2 = abgrp_get_cyc(G2); l2 = lg(cyc2);
    3573          259 :   gen = (lg(G1)>3 && lg(G2)>3)? gen_1: NULL;
    3574          259 :   nbgen = l1+l2-2;
    3575          259 :   cyc = ZV_snf_group(shallowconcat(cyc1,cyc2), &U, gen? &u1: NULL);
    3576          259 :   if (nbgen)
    3577              :   {
    3578          259 :     GEN U1 = bid_get_U(bid1), U2 = bid_get_U(bid2);
    3579            0 :     U1 = l1==1? const_vec(lg(sprk1), cgetg(1,t_MAT))
    3580          259 :               : ZM_ZMV_mul(vecslice(U, 1, l1-1),   U1);
    3581            0 :     U2 = l2==1? const_vec(lg(sprk2), cgetg(1,t_MAT))
    3582          259 :               : ZM_ZMV_mul(vecslice(U, l1, nbgen), U2);
    3583          259 :     U = shallowconcat(U1, U2);
    3584              :   }
    3585              :   else
    3586            0 :     U = const_vec(lg(sprk), cgetg(1,t_MAT));
    3587              : 
    3588          259 :   if (gen)
    3589              :   {
    3590          259 :     GEN uv = zkchinese1init2(nf, I2, I1, x);
    3591          518 :     gen = shallowconcat(zkVchinese1(gel(uv,1), abgrp_get_gen(G1)),
    3592          259 :                         zkVchinese1(gel(uv,2), abgrp_get_gen(G2)));
    3593              :   }
    3594          259 :   sarch = bid_get_sarch(bid1); /* trivial */
    3595          259 :   y = bid_grp(nf, u1, cyc, gen, x, sarch);
    3596          259 :   x = mkvec2(x, bid_get_arch(bid1));
    3597          259 :   y = mkvec5(x, y, mkvec2(fa, fa2), mkvec2(sprk, sarch), U);
    3598          259 :   return gc_GEN(av,y);
    3599              : }
    3600              : 
    3601              : typedef struct _ideal_data {
    3602              :   GEN nf, emb, L, pr, prL, sgnU, archp;
    3603              : } ideal_data;
    3604              : 
    3605              : /* z <- ( z | f(v[i])_{i=1..#v} ) */
    3606              : static void
    3607       758573 : concat_join(GEN *pz, GEN v, GEN (*f)(ideal_data*,GEN), ideal_data *data)
    3608              : {
    3609       758573 :   long i, nz, lv = lg(v);
    3610              :   GEN z, Z;
    3611       758573 :   if (lv == 1) return;
    3612       223047 :   z = *pz; nz = lg(z)-1;
    3613       223047 :   *pz = Z = cgetg(lv + nz, typ(z));
    3614       371674 :   for (i = 1; i <=nz; i++) gel(Z,i) = gel(z,i);
    3615       223338 :   Z += nz;
    3616       492113 :   for (i = 1; i < lv; i++) gel(Z,i) = f(data, gel(v,i));
    3617              : }
    3618              : static GEN
    3619          469 : join_idealinit(ideal_data *D, GEN x)
    3620          469 : { return join_bid(D->nf, x, D->prL); }
    3621              : static GEN
    3622       268509 : join_ideal(ideal_data *D, GEN x)
    3623       268509 : { return idealmulpowprime(D->nf, x, D->pr, D->L); }
    3624              : static GEN
    3625          448 : join_unit(ideal_data *D, GEN x)
    3626              : {
    3627          448 :   GEN bid = join_idealinit(D, gel(x,1)), u = gel(x,2), v = mkvec(D->emb);
    3628          448 :   if (lg(u) != 1) v = shallowconcat(u, v);
    3629          448 :   return mkvec2(bid, v);
    3630              : }
    3631              : 
    3632              : GEN
    3633           49 : log_prk_units_init(GEN bnf)
    3634              : {
    3635           49 :   GEN U = bnf_has_fu(bnf);
    3636           49 :   if (U) U = matalgtobasis(bnf_get_nf(bnf), U);
    3637           21 :   else if (!(U = bnf_compactfu_mat(bnf))) (void)bnf_build_units(bnf);
    3638           49 :   return mkvec2(bnf_get_tuU(bnf), U);
    3639              : }
    3640              : /*  flag & nf_GEN : generators, otherwise no
    3641              :  *  flag &2 : units, otherwise no
    3642              :  *  flag &4 : ideals in HNF, otherwise bid
    3643              :  *  flag &8 : omit ideals which cannot be conductors (pr^1 with Npr=2) */
    3644              : static GEN
    3645        11333 : Ideallist(GEN bnf, ulong bound, long flag)
    3646              : {
    3647        11333 :   const long do_units = flag & 2, big_id = !(flag & 4), cond = flag & 8;
    3648        11333 :   const long istar_flag = (flag & nf_GEN) | nf_INIT;
    3649              :   pari_sp av;
    3650              :   long i, j;
    3651        11333 :   GEN nf, z, p, fa, id, BOUND, U, empty = cgetg(1,t_VEC);
    3652              :   forprime_t S;
    3653              :   ideal_data ID;
    3654              :   GEN (*join_z)(ideal_data*, GEN);
    3655              : 
    3656        11333 :   if (do_units)
    3657              :   {
    3658           21 :     bnf = checkbnf(bnf);
    3659           21 :     nf = bnf_get_nf(bnf);
    3660           21 :     join_z = &join_unit;
    3661              :   }
    3662              :   else
    3663              :   {
    3664        11312 :     nf = checknf(bnf);
    3665        11312 :     join_z = big_id? &join_idealinit: &join_ideal;
    3666              :   }
    3667        11333 :   if ((long)bound <= 0) return empty;
    3668        11333 :   id = matid(nf_get_degree(nf));
    3669        11333 :   if (big_id) id = Idealstar(nf,id, istar_flag);
    3670              : 
    3671              :   /* z[i] will contain all "objects" of norm i. Depending on flag, this means
    3672              :    * an ideal, a bid, or a couple [bid, log(units)]. Such objects are stored
    3673              :    * in vectors, computed one primary component at a time; join_z
    3674              :    * reconstructs the global object */
    3675        11333 :   BOUND = utoipos(bound);
    3676        11333 :   z = const_vec(bound, empty);
    3677        11333 :   U = do_units? log_prk_units_init(bnf): NULL;
    3678        11333 :   gel(z,1) = mkvec(U? mkvec2(id, empty): id);
    3679        11333 :   ID.nf = nf;
    3680              : 
    3681        11333 :   p = cgetipos(3);
    3682        11333 :   u_forprime_init(&S, 2, bound);
    3683        11333 :   av = avma;
    3684        92940 :   while ((p[2] = u_forprime_next(&S)))
    3685              :   {
    3686        81616 :     if (DEBUGLEVEL>1) err_printf("%ld ",p[2]);
    3687        81616 :     fa = idealprimedec_limit_norm(nf, p, BOUND);
    3688       163121 :     for (j = 1; j < lg(fa); j++)
    3689              :     {
    3690        81514 :       GEN pr = gel(fa,j), z2 = leafcopy(z);
    3691        81515 :       ulong Q, q = upr_norm(pr);
    3692              :       long l;
    3693        81515 :       ID.pr = ID.prL = pr;
    3694        81515 :       if (cond && q == 2) { l = 2; Q = 4; } else { l = 1; Q = q; }
    3695       184549 :       for (; Q <= bound; l++, Q *= q) /* add pr^l */
    3696              :       {
    3697              :         ulong iQ;
    3698       103046 :         ID.L = utoipos(l);
    3699       103045 :         if (big_id) {
    3700          210 :           ID.prL = Idealstarprk(nf, pr, l, istar_flag);
    3701          210 :           if (U)
    3702          189 :             ID.emb = Q == 2? empty
    3703          189 :                            : log_prk_units(nf, U, gel(bid_get_sprk(ID.prL),1));
    3704              :         }
    3705       861608 :         for (iQ = Q,i = 1; iQ <= bound; iQ += Q,i++)
    3706       758574 :           concat_join(&gel(z,iQ), gel(z2,i), join_z, &ID);
    3707              :       }
    3708              :     }
    3709        81607 :     if (gc_needed(av,1))
    3710              :     {
    3711           18 :       if(DEBUGMEM>1) pari_warn(warnmem,"Ideallist");
    3712           18 :       z = gc_GEN(av, z);
    3713              :     }
    3714              :   }
    3715        11333 :   return z;
    3716              : }
    3717              : GEN
    3718           63 : gideallist(GEN bnf, GEN B, long flag)
    3719              : {
    3720           63 :   pari_sp av = avma;
    3721           63 :   if (typ(B) != t_INT)
    3722              :   {
    3723            0 :     B = gfloor(B);
    3724            0 :     if (typ(B) != t_INT) pari_err_TYPE("ideallist", B);
    3725            0 :     if (signe(B) < 0) B = gen_0;
    3726              :   }
    3727           63 :   if (signe(B) < 0)
    3728              :   {
    3729           28 :     if (flag != 4) pari_err_IMPL("ideallist with bid for single norm");
    3730           28 :     return gc_GEN(av, ideals_by_norm(checknf(bnf), absi(B)));
    3731              :   }
    3732           35 :   if (flag < 0 || flag > 15) pari_err_FLAG("ideallist");
    3733           35 :   return gc_GEN(av, Ideallist(bnf, itou(B), flag));
    3734              : }
    3735              : GEN
    3736        11298 : ideallist0(GEN bnf, long bound, long flag)
    3737              : {
    3738        11298 :   pari_sp av = avma;
    3739        11298 :   if (flag < 0 || flag > 15) pari_err_FLAG("ideallist");
    3740        11298 :   return gc_GEN(av, Ideallist(bnf, bound, flag));
    3741              : }
    3742              : GEN
    3743        10563 : ideallist(GEN bnf,long bound) { return ideallist0(bnf,bound,4); }
    3744              : 
    3745              : /* bid = for module m (without arch. part), arch = archimedean part.
    3746              :  * Output: bid for [m,arch] */
    3747              : static GEN
    3748           42 : join_bid_arch(GEN nf, GEN bid, GEN archp)
    3749              : {
    3750           42 :   pari_sp av = avma;
    3751              :   GEN G, U;
    3752           42 :   GEN sprk, cyc, y, u1 = NULL, x, sarch, gen;
    3753              : 
    3754           42 :   checkbid(bid);
    3755           42 :   G = bid_get_grp(bid);
    3756           42 :   x = bid_get_ideal(bid);
    3757           42 :   sarch = nfarchstar(nf, bid_get_ideal(bid), archp);
    3758           42 :   sprk = bid_get_sprk(bid);
    3759              : 
    3760           42 :   gen = (lg(G)>3)? gel(G,3): NULL;
    3761           42 :   cyc = diagonal_shallow(shallowconcat(gel(G,2), sarch_get_cyc(sarch)));
    3762           42 :   cyc = ZM_snf_group(cyc, &U, gen? &u1: NULL);
    3763           42 :   y = bid_grp(nf, u1, cyc, gen, x, sarch);
    3764           42 :   U = split_U(U, sprk);
    3765           42 :   y = mkvec5(mkvec2(x, archp), y, gel(bid,3), mkvec2(sprk, sarch), U);
    3766           42 :   return gc_GEN(av,y);
    3767              : }
    3768              : static GEN
    3769           42 : join_arch(ideal_data *D, GEN x) {
    3770           42 :   return join_bid_arch(D->nf, x, D->archp);
    3771              : }
    3772              : static GEN
    3773           14 : join_archunit(ideal_data *D, GEN x) {
    3774           14 :   GEN bid = join_arch(D, gel(x,1)), u = gel(x,2), v = mkvec(D->emb);
    3775           14 :   if (lg(u) != 1) v = shallowconcat(u, v);
    3776           14 :   return mkvec2(bid, v);
    3777              : }
    3778              : 
    3779              : /* L from ideallist, add archimedean part */
    3780              : GEN
    3781           14 : ideallistarch(GEN bnf, GEN L, GEN arch)
    3782              : {
    3783              :   pari_sp av;
    3784           14 :   long i, j, l = lg(L), lz;
    3785              :   GEN v, z, V, nf;
    3786              :   ideal_data ID;
    3787              :   GEN (*join_z)(ideal_data*, GEN);
    3788              : 
    3789           14 :   if (typ(L) != t_VEC) pari_err_TYPE("ideallistarch",L);
    3790           14 :   if (l == 1) return cgetg(1,t_VEC);
    3791           14 :   z = gel(L,1);
    3792           14 :   if (typ(z) != t_VEC) pari_err_TYPE("ideallistarch",z);
    3793           14 :   z = gel(z,1); /* either a bid or [bid,U] */
    3794           14 :   ID.archp = vec01_to_indices(arch);
    3795           14 :   if (lg(z) == 3)
    3796              :   { /* [bid,U]: do units */
    3797            7 :     bnf = checkbnf(bnf); nf = bnf_get_nf(bnf);
    3798            7 :     if (typ(z) != t_VEC) pari_err_TYPE("ideallistarch",z);
    3799            7 :     ID.emb = zm_to_ZM( rowpermute(nfsign_units(bnf,NULL,1), ID.archp) );
    3800            7 :     join_z = &join_archunit;
    3801              :   }
    3802              :   else
    3803              :   {
    3804            7 :     join_z = &join_arch;
    3805            7 :     nf = checknf(bnf);
    3806              :   }
    3807           14 :   ID.nf = nf;
    3808           14 :   av = avma; V = cgetg(l, t_VEC);
    3809           63 :   for (i = 1; i < l; i++)
    3810              :   {
    3811           49 :     z = gel(L,i); lz = lg(z);
    3812           49 :     gel(V,i) = v = cgetg(lz,t_VEC);
    3813           91 :     for (j=1; j<lz; j++) gel(v,j) = join_z(&ID, gel(z,j));
    3814              :   }
    3815           14 :   return gc_GEN(av,V);
    3816              : }
        

Generated by: LCOV version 2.0-1