Beispiel #1
0
/* return the factorization of the square-free polynomial x.
   The coeffs of x are in Z_nf and its leading term is a rational integer.
   deg(x) > 1, deg(nfpol) > 1
   If fl = 1, return only the roots of x in nf
   If fl = 2, as fl=1 if pol splits, [] otherwise */
static GEN
nfsqff(GEN nf, GEN pol, long fl)
{
  long n, nbf, dpol = degpol(pol);
  GEN pr, C0, polbase, init_fa = NULL;
  GEN N2, rep, polmod, polred, lt, nfpol = gel(nf,1);
  nfcmbf_t T;
  nflift_t L;
  pari_timer ti, ti_tot;

  if (DEBUGLEVEL>2) { TIMERstart(&ti); TIMERstart(&ti_tot); }
  n = degpol(nfpol);
  polbase = unifpol(nf, pol, t_COL);
  if (typ(polbase) != t_POL) pari_err(typeer, "nfsqff");
  polmod  = lift_intern( unifpol(nf, pol, t_POLMOD) );
  if (dpol == 1) return mkvec(QXQX_normalize(polmod, nfpol));
  /* heuristic */
  if (dpol*3 < n) 
  {
    GEN z, t;
    long i;
    if (DEBUGLEVEL>2) fprintferr("Using Trager's method\n");
    z = (GEN)polfnf(polmod, nfpol)[1];
    if (fl) {
      long l = lg(z);
      for (i = 1; i < l; i++)
      {
        t = gel(z,i); if (degpol(t) > 1) break;
        gel(z,i) = gneg(gdiv(gel(t,2), gel(t,3)));
      }
      setlg(z, i);
      if (fl == 2 && i != l) return cgetg(1,t_VEC);
    }
    return z;
  }

  nbf = nf_pick_prime(5, nf, polbase, fl, &lt, &init_fa, &pr, &L.Tp);
  if (fl == 2 && nbf < dpol) return cgetg(1,t_VEC);
  if (nbf <= 1)
  {
    if (!fl) return mkvec(QXQX_normalize(polmod, nfpol)); /* irreducible */
    if (!nbf) return cgetg(1,t_VEC); /* no root */
  }

  if (DEBUGLEVEL>2) {
    msgTIMER(&ti, "choice of a prime ideal");
    fprintferr("Prime ideal chosen: %Z\n", pr);
  }

  pol = simplify_i(lift(polmod));
  L.tozk = gel(nf,8);
  L.topow= Q_remove_denom(gel(nf,7), &L.topowden);
  T.ZC = L2_bound(nf, L.tozk, &(T.dn));
  T.Br = nf_root_bounds(pol, nf); if (lt) T.Br = gmul(T.Br, lt);

  if (fl) C0 = normlp(T.Br, 2, n);
  else    C0 = nf_factor_bound(nf, polbase); /* bound for T_2(Q_i), Q | P */
  T.bound = mulrr(T.ZC, C0); /* bound for |Q_i|^2 in Z^n on chosen Z-basis */

  N2 = mulsr(dpol*dpol, normlp(T.Br, 4, n)); /* bound for T_2(lt * S_2) */
  T.BS_2 = mulrr(T.ZC, N2); /* bound for |S_2|^2 on chosen Z-basis */

  if (DEBUGLEVEL>2) {
    msgTIMER(&ti, "bound computation");
    fprintferr("  1) T_2 bound for %s: %Z\n", fl?"root":"factor", C0);
    fprintferr("  2) Conversion from T_2 --> | |^2 bound : %Z\n", T.ZC);
    fprintferr("  3) Final bound: %Z\n", T.bound);
  }

  L.p = gel(pr,1);
  if (L.Tp && degpol(L.Tp) == 1) L.Tp = NULL;
  bestlift_init(0, nf, pr, T.bound, &L);
  if (DEBUGLEVEL>2) TIMERstart(&ti);
  polred = ZqX_normalize(polbase, lt, &L); /* monic */

  if (fl) {
    GEN z = nf_DDF_roots(pol, polred, nfpol, lt, init_fa, nbf, fl, &L);
    if (lg(z) == 1) return cgetg(1, t_VEC);
    return z;
  }

  {
    pari_sp av = avma;
    if (L.Tp)
      rep = FqX_split_all(init_fa, L.Tp, L.p);
    else
    {
      long d;
      rep = cgetg(dpol + 1, t_VEC); gel(rep,1) = FpX_red(polred,L.p);
      d = FpX_split_Berlekamp((GEN*)(rep + 1), L.p);
      setlg(rep, d + 1);
    }
    T.fact  = gerepilecopy(av, sort_vecpol(rep, &cmp_pol));
  }
  if (DEBUGLEVEL>2) msgTIMER(&ti, "splitting mod %Z", pr);
  T.pr = pr;
  T.L  = &L;
  T.polbase = polbase;
  T.pol   = pol;
  T.nf    = nf;
  T.hint  = 1; /* useless */

  rep = nf_combine_factors(&T, polred, L.p, L.k, dpol-1);
  if (DEBUGLEVEL>2)
    fprintferr("Total Time: %ld\n===========\n", TIMER(&ti_tot));
  return rep;
}
Beispiel #2
0
/* return the factorization of x in nf */
GEN
nffactor(GEN nf,GEN pol)
{
  GEN A,g,y,p1,T, rep = cgetg(3, t_MAT);
  long l, j, dA;
  pari_sp av = avma;
  pari_timer ti;

  if (DEBUGLEVEL>2) { TIMERstart(&ti); fprintferr("\nEntering nffactor:\n"); }
  nf = checknf(nf); T = gel(nf,1);
  if (typ(pol) != t_POL) pari_err(notpoler,"nffactor");
  if (varncmp(varn(pol), varn(T)) >= 0)
    pari_err(talker,"polynomial variable must have highest priority in nffactor");

  A = fix_relative_pol(nf,pol,0);
  dA = degpol(A);
  if (dA <= 0) {
    avma = (pari_sp)(rep + 3);
    return dA == 0? trivfact(): zerofact(varn(pol));
  }
  A = Q_primpart( QXQX_normalize(A, T) );
  if (dA == 1) {
    GEN c;
    A = gerepilecopy(av, A); c = gel(A,2);
    if (typ(c) == t_POL && degpol(c) > 0) gel(A,2) = mkpolmod(c, gcopy(T));
    gel(rep,1) = mkcol(A);
    gel(rep,2) = mkcol(gen_1); return rep;
  }
  if (degpol(T) == 1)
    return gerepileupto(av, factpol(Q_primpart(simplify(pol)), 0));

  A = Q_primpart( lift_intern(A) );
  g = nfgcd(A, derivpol(A), T, gel(nf,4));

  A = QXQX_normalize(A, T);
  A = Q_primpart(A);
  if (DEBUGLEVEL>2) msgTIMER(&ti, "squarefree test");

  if (degpol(g))
  { /* not squarefree */
    pari_sp av1;
    GEN ex;
    g = QXQX_normalize(g, T);
    A = RgXQX_div(A,g, T);

    y = nfsqff(nf,A,0); av1 = avma;
    l = lg(y);
    ex=(GEN)gpmalloc(l * sizeof(long));
    for (j=l-1; j>=1; j--)
    {
      GEN fact = lift(gel(y,j)), quo = g, q;
      long e = 0;
      for(e = 1;; e++)
      {
        q = RgXQX_divrem(quo,fact,T, ONLY_DIVIDES);
        if (!q) break;
        quo = q;
      }
      ex[j] = e;
    }
    avma = av1; y = gerepileupto(av, RgXQXV_to_mod(y,T));
    p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) gel(p1,j) = utoipos(ex[j]);
    free(ex);
  }
  else
  {
    y = gerepileupto(av, RgXQXV_to_mod(nfsqff(nf,A,0), T));
    l = lg(y);
    p1 = cgetg(l, t_COL); for (j=l-1; j>=1; j--) gel(p1,j) = gen_1;
  }
  if (DEBUGLEVEL>3)
    fprintferr("number of factor(s) found: %ld\n", lg(y)-1);
  gel(rep,1) = y;
  gel(rep,2) = p1; return sort_factor(rep, cmp_pol);
}
Beispiel #3
0
static GEN
nf_LLL_cmbf(nfcmbf_t *T, GEN p, long k, long rec)
{
  nflift_t *L = T->L;
  GEN pk = L->pk, PRK = L->prk, PRKinv = L->iprk, GSmin = L->GSmin;
  GEN Tpk = L->Tpk;

  GEN famod = T->fact, nf = T->nf, ZC = T->ZC, Br = T->Br;
  GEN Pbase = T->polbase, P = T->pol, dn = T->dn;
  GEN nfT = gel(nf,1);
  GEN Btra;
  long dnf = degpol(nfT), dP = degpol(P);

  double BitPerFactor = 0.5; /* nb bits / modular factor */
  long i, C, tmax, n0;
  GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO;
  double Bhigh;
  pari_sp av, av2, lim;
  long ti_LLL = 0, ti_CF = 0;
  pari_timer ti2, TI;

  lP = absi(leading_term(P));
  if (is_pm1(lP)) lP = NULL;

  n0 = lg(famod) - 1;
 /* Lattice: (S PRK), small vector (vS vP). To find k bound for the image,
  * write S = S1 q + S0, P = P1 q + P0
  * |S1 vS + P1 vP|^2 <= Bhigh for all (vS,vP) assoc. to true factors */
  Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2, dnf)));
  Bhigh = get_Bhigh(n0, dnf);
  C = (long)ceil(sqrt(Bhigh/n0)) + 1; /* C^2 n0 ~ Bhigh */
  Bnorm = dbltor( n0 * C * C + Bhigh );
  ZERO = zeromat(n0, dnf);

  av = avma; lim = stack_lim(av, 1);
  TT = cgetg(n0+1, t_VEC);
  Tra  = cgetg(n0+1, t_MAT);
  for (i=1; i<=n0; i++) TT[i] = 0;
  CM_L = gscalsmat(C, n0);
  /* tmax = current number of traces used (and computed so far) */
  for(tmax = 0;; tmax++)
  {
    long a, b, bmin, bgood, delta, tnew = tmax + 1, r = lg(CM_L)-1;
    GEN oldCM_L, M_L, q, S1, P1, VV;
    int first = 1;

    /* bound for f . S_k(genuine factor) = ZC * bound for T_2(S_tnew) */
    Btra = mulrr(ZC, mulsr(dP*dP, normlp(Br, 2*tnew, dnf)));
    bmin = logint(ceil_safe(sqrtr(Btra)), gen_2, NULL);
    if (DEBUGLEVEL>2)
      fprintferr("\nLLL_cmbf: %ld potential factors (tmax = %ld, bmin = %ld)\n",
                 r, tmax, bmin);

    /* compute Newton sums (possibly relifting first) */
    if (gcmp(GSmin, Btra) < 0)
    {
      nflift_t L1;
      GEN polred;

      bestlift_init(k<<1, nf, T->pr, Btra, &L1);
      polred = ZqX_normalize(Pbase, lP, &L1);
      k      = L1.k;
      pk     = L1.pk;
      PRK    = L1.prk;
      PRKinv = L1.iprk;
      GSmin  = L1.GSmin;
      Tpk    = L1.Tpk;
      famod = hensel_lift_fact(polred, famod, Tpk, p, pk, k);
      for (i=1; i<=n0; i++) TT[i] = 0;
    }
    for (i=1; i<=n0; i++)
    {
      GEN h, lPpow = lP? gpowgs(lP, tnew): NULL;
      GEN z = polsym_gen(gel(famod,i), gel(TT,i), tnew, Tpk, pk);
      gel(TT,i) = z;
      h = gel(z,tnew+1);
      /* make Newton sums integral */
      lPpow = mul_content(lPpow, dn);
      if (lPpow) h = FpX_red(gmul(h,lPpow), pk);
      gel(Tra,i) = nf_bestlift(h, NULL, L); /* S_tnew(famod) */
    }

    /* compute truncation parameter */
    if (DEBUGLEVEL>2) { TIMERstart(&ti2); TIMERstart(&TI); }
    oldCM_L = CM_L;
    av2 = avma;
    b = delta = 0; /* -Wall */
AGAIN:
    M_L = Q_div_to_int(CM_L, utoipos(C));
    VV = get_V(Tra, M_L, PRK, PRKinv, pk, &a);
    if (first)
    { /* initialize lattice, using few p-adic digits for traces */
      bgood = (long)(a - max(32, BitPerFactor * r));
      b = max(bmin, bgood);
      delta = a - b;
    }
    else
    { /* add more p-adic digits and continue reduction */
      if (a < b) b = a;
      b = max(b-delta, bmin);
      if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */
    }

    /* restart with truncated entries */
    q = int2n(b);
    P1 = gdivround(PRK, q);
    S1 = gdivround(Tra, q);
    T2 = gsub(gmul(S1, M_L), gmul(P1, VV));
    m = vconcat( CM_L, T2 );
    if (first)
    {
      first = 0;
      m = shallowconcat( m, vconcat(ZERO, P1) );
      /*     [ C M_L   0  ]
       * m = [            ]   square matrix
       *     [  T2'   PRK ]   T2' = Tra * M_L  truncated
       */
    }
    CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL);
    if (DEBUGLEVEL>2)
      fprintferr("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n",
                 a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, TIMER(&TI));
    if (!CM_L) { list = mkcol(QXQX_normalize(P,nfT)); break; }
    if (b > bmin)
    {
      CM_L = gerepilecopy(av2, CM_L);
      goto AGAIN;
    }
    if (DEBUGLEVEL>2) msgTIMER(&ti2, "for this trace");

    i = lg(CM_L) - 1;
    if (i == r && gequal(CM_L, oldCM_L))
    {
      CM_L = oldCM_L;
      avma = av2; continue;
    }

    if (i <= r && i*rec < n0)
    {
      pari_timer ti;
      if (DEBUGLEVEL>2) TIMERstart(&ti);
      list = nf_chk_factors(T, P, Q_div_to_int(CM_L,utoipos(C)), famod, pk);
      if (DEBUGLEVEL>2) ti_CF += TIMER(&ti);
      if (list) break;
      CM_L = gerepilecopy(av2, CM_L);
    }
    if (low_stack(lim, stack_lim(av,1)))
    {
      if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf");
      gerepileall(av, Tpk? 9: 8,
                      &CM_L,&TT,&Tra,&famod,&pk,&GSmin,&PRK,&PRKinv,&Tpk);
    }
  }
  if (DEBUGLEVEL>2)
    fprintferr("* Time LLL: %ld\n* Time Check Factor: %ld\n",ti_LLL,ti_CF);
  return list;
}
Beispiel #4
0
static long
nf_pick_prime(long ct, GEN nf, GEN polbase, long fl,
              GEN *lt, GEN *Fa, GEN *pr, GEN *Tp)
{
  GEN nfpol = gel(nf,1), dk, bad;
  long maxf, n = degpol(nfpol), dpol = degpol(polbase), nbf = 0;
  byteptr pt = diffptr;
  ulong pp = 0;

  *lt  = leading_term(polbase); /* t_INT */
  if (gcmp1(*lt)) *lt = NULL;
  dk = absi(gel(nf,3));
  bad = mulii(dk,gel(nf,4)); if (*lt) bad = mulii(bad, *lt);

  /* FIXME: slow factorization of large polynomials over large Fq */
  maxf = 1;
  if (ct > 1) {
    if (dpol > 100) /* tough */
    {
      if (n >= 20) maxf = 4;
    }
    else
    {
      if (n >= 15) maxf = 4;
    }
  }
  
  for (ct = 5;;)
  {
    GEN aT, apr, ap, modpr, red;
    long anbf;
    pari_timer ti_pr;

    GEN list, r = NULL, fa = NULL;
    pari_sp av2 = avma;
    if (DEBUGLEVEL>3) TIMERstart(&ti_pr);
    for (;;)
    {
      NEXT_PRIME_VIADIFF_CHECK(pp, pt);
      if (! umodiu(bad,pp)) continue;
      ap = utoipos(pp);
      list = (GEN)FpX_factor(nfpol, ap)[1];
      if (maxf == 1)
      { /* deg.1 factors are best */
        r = gel(list,1);
        if (degpol(r) == 1) break;
      }
      else
      { /* otherwise, pick factor of largish degree */
        long i, dr;
        for (i = lg(list)-1; i > 0; i--)
        {
          r = gel(list,i); dr = degpol(r);
          if (dr <= maxf) break;
        }
        if (i > 0) break;
      }
      avma = av2;
    }
    apr = primedec_apply_kummer(nf,r,1,ap);

    modpr = zk_to_ff_init(nf,&apr,&aT,&ap);
    red = modprX(polbase, nf, modpr);
    if (!aT)
    { /* degree 1 */
      red = ZX_to_Flx(red, pp);
      if (!Flx_is_squarefree(red, pp)) { avma = av2; continue; }
      anbf = fl? Flx_nbroots(red, pp): Flx_nbfact(red, pp);
    }
    else
    {
      GEN q;
      if (!FqX_is_squarefree(red,aT,ap)) { avma = av2; continue; }
      q = gpowgs(ap, degpol(aT));
      anbf = fl? FqX_split_deg1(&fa, red, q, aT, ap)
               : FqX_split_by_degree(&fa, red, q, aT, ap);
    }
    if (fl == 2 && anbf < dpol) return anbf;
    if (anbf <= 1)
    {
      if (!fl) return anbf; /* irreducible */
      if (!anbf) return 0; /* no root */
    }

    if (!nbf || anbf < nbf
             || (anbf == nbf && cmpii(gel(apr,4), gel(*pr,4)) > 0))
    {
      nbf = anbf;
      *pr = apr;
      *Tp = aT;
      *Fa = fa;
    }
    else avma = av2;
    if (DEBUGLEVEL>3)
      fprintferr("%3ld %s at prime\n  %Z\nTime: %ld\n",
                 anbf, fl?"roots": "factors", apr, TIMER(&ti_pr));
    if (--ct <= 0) return nbf;
  }
}
Beispiel #5
0
static GEN
bnflog_i(GEN bnf, GEN ell)
{
  long prec0, prec;
  GEN nf, US, vdegS, S, T, M, CLp, CLt, Ftilde, vtG, ellk;
  GEN D, Ap, cycAp, bnfS;
  long i, j, lS, lvAp;

  checkbnf(bnf);
  nf = checknf(bnf);
  S = idealprimedec(nf, ell);
  bnfS = bnfsunit0(bnf, S, nf_GENMAT, LOWDEFAULTPREC); /* S-units */
  US = leafcopy(gel(bnfS,1));
  prec0 = maxss(30, vtilde_prec(nf, US, ell));
  US = shallowconcat(bnf_get_fu(bnf), US);
  settyp(US, t_COL);
  T = padicfact(nf, S, prec0);
  lS = lg(S); Ftilde = cgetg(lS, t_VECSMALL);
  for (j = 1; j < lS; j++) Ftilde[j] = ftilde(nf, gel(S,j), gel(T,j));
  CLp = CL_prime(bnf, ell, S);
  cycAp = gel(CLp,1);
  Ap = gel(CLp,2);
  for(;;)
  {
    CLt = CL_tilde(nf, US, ell, T, Ftilde, &vtG, prec0);
    if (CLt) break;
    prec0 <<= 1;
    T = padicfact(nf, S, prec0);
  }
  prec = ellexpo(cycAp, ell) + ellexpo(CLt,ell) + 1;
  if (prec == 1) return mkvec3(cgetg(1,t_VEC), cgetg(1,t_VEC), cgetg(1,t_VEC));

  vdegS = get_vdegS(Ftilde, ell, prec0);
  ellk = powiu(ell, prec);
  lvAp = lg(Ap);
  if (lvAp > 1)
  {
    GEN Kcyc = bnf_get_cyc(bnf);
    GEN C = zeromatcopy(lvAp-1, lS-1);
    GEN Rell = gel(CLp,3), Uell = gel(CLp,4), ordS = gel(CLp,5);
    for (i = 1; i < lvAp; i++)
    {
      GEN a, b, bi, A = gel(Ap,i), d = gel(cycAp,i);
      bi = isprincipal(bnf, A);
      a = vecmodii(ZC_Z_mul(bi,d), Kcyc);
      /* a in subgroup generated by S = Rell; hence b integral */
      b = hnf_invimage(Rell, a);
      b = vecmodii(ZM_ZC_mul(Uell, ZC_neg(b)), ordS);
      A = mkvec2(A, cgetg(1,t_MAT));
      A = idealpowred(nf, A, d);
      /* find a principal representative of A_i^cycA_i up to elements of S */
      a = isprincipalfact(bnf,gel(A,1),S,b,nf_GENMAT|nf_FORCE);
      if (!gequal0(gel(a,1))) pari_err_BUG("bnflog");
      a = famat_mul_shallow(gel(A,2), gel(a,2)); /* principal part */
      if (lg(a) == 1) continue;
      for (j = 1; j < lS; j++)
        gcoeff(C,i,j) = vtilde(nf, a, gel(T,j), gel(vdegS,j), ell, prec0);
    }
    C = gmod(gneg(C),ellk);
    C = shallowtrans(C);
    M = mkmat2(mkcol2(diagonal_shallow(cycAp), C), mkcol2(gen_0, vtG));
    M = shallowmatconcat(M); /* relation matrix */
  }
  else
    M = vtG;
  M = ZM_hnfmodid(M, ellk);
  D = matsnf0(M, 4);
  if (lg(D) == 1 || !dvdii(gel(D,1), ellk))
    pari_err_BUG("bnflog [missing Z_l component]");
  D = vecslice(D,2,lg(D)-1);
  return mkvec3(D, CLt, ellsylow(cycAp, ell));
}
Beispiel #6
0
//==============================================================================
// MAIN
int main( int argc, char* argv[] )
{
    // spatial dimension
    const unsigned    dim = SPACEDIM; 

    typedef base::solver::Eigen3           Solver;
    
    // Check input arguments
    if ( argc != 2 ) {
        std::cerr << "Usage: " << argv[0] << " input.dat\n"
                  << "(Compiled for dim=" << dim << ")\n\n";
        return -1;
    }
    
    // read name of input file
    const std::string   inputFile = boost::lexical_cast<std::string>( argv[1] );
    const InputNucleus<dim> ui( inputFile );

    // Simulation attributes
    const bool simplex = false;
    const bool stokesStabil = false;
    typedef mat::hypel::NeoHookeanCompressible Material;
    typedef TypesAndAttributes<dim,simplex>    TA;

    // basic attributes of the computation
    base::auxi::BoundingBox<dim> bbox( ui.bbmin, ui.bbmax );
    
    TA::Mesh mesh;
    generateMesh( mesh, ui );

    // Creates a list of <Element,faceNo> pairs
    base::mesh::MeshBoundary meshBoundary;
    meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() );

    TA::BoundaryMesh boundaryMesh;
    base::mesh::generateBoundaryMesh( meshBoundary.begin(),
                                      meshBoundary.end(),
                                      mesh, boundaryMesh );


    // mesh size (all equal, more or less)
    const double h = base::mesh::Size<TA::Mesh::Element>::apply( mesh.elementPtr(0) );

    //--------------------------------------------------------------------------
    typedef base::cut::LevelSet<dim> LevelSet;
    std::vector<LevelSet> levelSetNucleus, levelSetMembrane;
    base::cut::analyticLevelSet( mesh,
                                 base::cut::Sphere<dim>( ui.RN, ui.centerN ),
                                 true, levelSetNucleus );
    base::cut::analyticLevelSet( mesh,
                                 base::cut::Sphere<dim>( ui.RM, ui.centerM ),
                                 true, levelSetMembrane );

    //--------------------------------------------------------------------------
    // make cut cell structures
    std::vector<TA::Cell> cellsNucleus, cellsMembrane, cellsCS;
    base::cut::generateCutCells( mesh, levelSetNucleus,  cellsNucleus );
    base::cut::generateCutCells( mesh, levelSetMembrane, cellsMembrane );
    
    {
        cellsCS = cellsNucleus;
        std::for_each( cellsCS.begin(), cellsCS.end(),
                       boost::bind( &TA::Cell::reverse, _1 ) );

        base::cut::generateCutCells( mesh, levelSetMembrane, cellsCS,
                                     base::cut::INTERSECT );
    }

    // intersection with the box boundary
    std::vector<TA::SurfCell> surfaceCells;
    base::cut::generateCutCells( boundaryMesh, levelSetMembrane, surfaceCells );

    // Elastic material
    Material material( mat::Lame::lambda( ui.E, ui.nu),
                       mat::Lame::mu(     ui.E, ui.nu ) );

    // Solid and fluid handlers
    typedef Solid<TA::Mesh, Material>                        Solid;
    typedef Fluid<TA::Mesh, stokesStabil>                    Fluid;
    typedef SolidFluidInterface<TA::SurfaceMesh,Solid,Fluid> SFI;
    typedef FluidFluidInterface<TA::SurfaceMesh,Fluid>       FFI;
    
    Solid nucleus(      mesh, material );
    Fluid gel(          mesh, ui.viscosityGel, ui.alpha );
    Fluid cytoSkeleton( mesh, ui.viscosityCS,  ui.alpha );

    // find geometry association for the dofs
    std::vector<std::pair<std::size_t,TA::VecDim> > doFLocationD, doFLocationU;
    base::dof::associateLocation( nucleus.getDisplacement(), doFLocationD );
    base::dof::associateLocation( gel.getVelocity(),       doFLocationU );

    // Quadrature along a surface
    TA::CutQuadrature     cutQuadratureNucleus( cellsNucleus,  true  ); 
    TA::CutQuadrature     cutQuadratureGel(     cellsMembrane, false );
    TA::CutQuadrature     cutQuadratureCS(      cellsCS,       true  );
    TA::SurfaceQuadrature surfaceQuadrature;
    TA::SurfCutQuadrature surfaceCutQuadrature( surfaceCells, true );

    //--------------------------------------------------------------------------
    // Run a zero-th step in order to write the data before computation
    // (store the previously enclosed volume)
    double prevVolumeN, initialVolumeCS;
    {
        std::cout << 0 << "  " << 0. << "  0  " << std::flush;

        writeVTKFile( "nucleus", 0, mesh,
                      nucleus.getDisplacement(),
                      cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(),
                      gel.getVelocity(),          gel.getPressure(),
                      levelSetNucleus, levelSetMembrane,  ui.dt );

        // for surface field
        TA::SurfaceMesh membrane, envelope;
        base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsMembrane, membrane );
        base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsNucleus,  envelope );

        writeSurfaceVTKFile( "membrane", 0, membrane );
        writeSurfaceVTKFile( "envelope", 0, envelope );
            
        surfaceFeatures( boundaryMesh, membrane, envelope,
                         surfaceQuadrature, surfaceCutQuadrature, std::cout );
        std::cout << std::endl;

        // store the contained volume
        prevVolumeN     = surf::enclosedVolume( envelope, surfaceQuadrature );
        initialVolumeCS =
            surf::enclosedVolume( membrane, surfaceQuadrature ) +
            surf::enclosedVolume( boundaryMesh, surfaceCutQuadrature );
    }

    //--------------------------------------------------------------------------
    // * Loop over time steps *
    //--------------------------------------------------------------------------
    const double supportThreshold = std::numeric_limits<double>::min();
    for ( unsigned step = 0; step < ui.numLoadSteps; step++ ) {
        
        // for surface field
        TA::SurfaceMesh membrane, envelope;
        base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsMembrane, membrane );
        base::cut::generateSurfaceMesh<TA::Mesh,TA::Cell>( mesh, cellsNucleus,  envelope );

        // Interface handler
        SFI envelopeHandler( envelope,
                             nucleus.getDisplacement(),
                             cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(),
                             ui.viscosityCS );
        
        FFI membraneHandler( membrane,
                             cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(),
                             gel.getVelocity(), gel.getPressure(),
                             cellsMembrane, 
                             ui.viscosityCS, ui.viscosityGel, ui.sigma );

        std::cout << step+1 << "  " << (step+1) * ui.dt << "  " << std::flush;

        //----------------------------------------------------------------------
        // 0) Solve Lagrangian problem
        
        // compute supports
        std::vector<double> supportsD, supportsUCS, supportsPCS, supportsUGel, supportsPGel;
        base::cut::supportComputation( mesh, nucleus.getDisplacement(),
                                       cutQuadratureNucleus, supportsD );
        base::cut::supportComputation( mesh, cytoSkeleton.getVelocity(),
                                       cutQuadratureCS, supportsUCS );
        base::cut::supportComputation( mesh, cytoSkeleton.getPressure(),
                                       cutQuadratureCS, supportsPCS );
        base::cut::supportComputation( mesh, gel.getVelocity(),
                                       cutQuadratureGel, supportsUGel );
        base::cut::supportComputation( mesh, gel.getPressure(),
                                       cutQuadratureGel, supportsPGel );

        // Hard-wired Dirichlet constraints (fluid BC)
        {
            // apply to outer material = gel
            base::dof::constrainBoundary<Fluid::FEBasisU>(
                meshBoundary.begin(),
                meshBoundary.end(),
                mesh, gel.getVelocity(),
                boost::bind( &dirichletBC<dim,Fluid::DoFU>,
                             _1, _2, ui.ubar, bbox, ui.bc ) );

            // in case of boundary intersections, apply to cytoskeleton
            base::dof::constrainBoundary<Fluid::FEBasisU>(
                meshBoundary.begin(),
                meshBoundary.end(),
                mesh, cytoSkeleton.getVelocity(),
                boost::bind( &dirichletBC<dim,Fluid::DoFU>,
                             _1, _2, ui.ubar, bbox, ui.bc ) );

            // Fix first pressure dof in case of closed cavity flow
            if ( ui.bc == CAVITY ) {
                Fluid::Pressure::DoFPtrIter pIter = gel.getPressure().doFsBegin();
                (*pIter) -> constrainValue( 0, 0.0 );
            }
        }
    
        // Basis stabilisation
        base::cut::stabiliseBasis( mesh, nucleus.getDisplacement(),  supportsD,    doFLocationD );
        base::cut::stabiliseBasis( mesh, cytoSkeleton.getVelocity(), supportsUCS,  doFLocationU );
        base::cut::stabiliseBasis( mesh, cytoSkeleton.getPressure(), supportsPCS,  doFLocationD );
        base::cut::stabiliseBasis( mesh, gel.getVelocity(),          supportsUGel, doFLocationU );
        base::cut::stabiliseBasis( mesh, gel.getPressure(),          supportsPGel, doFLocationD );
        
        // number DoFs 
        const std::size_t activeDoFsD = 
            base::dof::numberDoFsConsecutively( nucleus.getDisplacement().doFsBegin(),
                                                nucleus.getDisplacement().doFsEnd() );
        const std::size_t activeDoFsUCS = 
            base::dof::numberDoFsConsecutively( cytoSkeleton.getVelocity().doFsBegin(),
                                                cytoSkeleton.getVelocity().doFsEnd(),
                                                activeDoFsD );
        const std::size_t activeDoFsPCS = 
            base::dof::numberDoFsConsecutively( cytoSkeleton.getPressure().doFsBegin(),
                                                cytoSkeleton.getPressure().doFsEnd(),
                                                activeDoFsD + activeDoFsUCS );
        const std::size_t activeDoFsUGel = 
            base::dof::numberDoFsConsecutively( gel.getVelocity().doFsBegin(),
                                                gel.getVelocity().doFsEnd(),
                                                activeDoFsD + activeDoFsUCS + activeDoFsPCS );
        const std::size_t activeDoFsPGel = 
            base::dof::numberDoFsConsecutively( gel.getPressure().doFsBegin(),
                                                gel.getPressure().doFsEnd(),
                                                activeDoFsD + activeDoFsUCS + activeDoFsPCS +
                                                activeDoFsUGel );


        // start from 0 for the increments, set rest to zero too
        base::dof::clearDoFs( nucleus.getDisplacement() );
        base::dof::clearDoFs( cytoSkeleton.getPressure() );
        base::dof::clearDoFs( cytoSkeleton.getVelocity() );
        base::dof::clearDoFs( gel.getPressure() );
        base::dof::clearDoFs( gel.getVelocity() );

        //----------------------------------------------------------------------
        // Nonlinear iterations
        unsigned iter = 0;
        for ( ; iter < ui.maxIter; iter++ ) {

            // Create a solver object
            Solver solver( activeDoFsD + activeDoFsUCS + activeDoFsPCS +
                           activeDoFsUGel + activeDoFsPGel );

            // register to solver
            nucleus.registerInSolver(      solver );
            cytoSkeleton.registerInSolver( solver );
            gel.registerInSolver(          solver );
            membraneHandler.registerInSolver(     solver );
            envelopeHandler.registerInSolver(     solver );

            // Compute as(d,dd) and Da(d,dd)[Delta d]
            nucleus.assembleBulk( cutQuadratureNucleus, solver, iter );

            // Body force
            nucleus.bodyForce( cutQuadratureNucleus, solver,
                               boost::bind( unitForce<0,dim>, _1, ui.forceValue ) );

            // Computate af(u,p; du,dp)
            cytoSkeleton.assembleBulk( cutQuadratureCS,  solver );
            gel.assembleBulk(          cutQuadratureGel, solver );

            // Penalty terms for int_Gamma (dot(d) - u) (E delta d - mu delta u) ds
            envelopeHandler.assemblePenaltyTerms( surfaceQuadrature, solver, ui.penaltyFac, ui.dt );
            membraneHandler.assemblePenaltyTerms( surfaceQuadrature, solver, ui.penaltyFac );

            // Boundary energy terms (beta = 0)  [ -int_Gamma (...) ds ]
            envelopeHandler.assembleEnergyTerms( surfaceQuadrature, solver, ui.dt );
            membraneHandler.assembleEnergyTerms( surfaceQuadrature, solver );

            // surface tension
            membraneHandler.surfaceTension( surfaceQuadrature, solver );
            

            // Finalise assembly
            solver.finishAssembly();

            // norm of residual
            const double conv1 = solver.norm(0, activeDoFsD) / ui.E;

            if ( isnan( conv1 ) ) return 1;
            
            if ( ( iter > 0 )  and ( conv1 < ui.tolerance ) ) {
                std::cout << "schon" << std::endl;
                break;
            }

            // Solve
#ifdef LOAD_PARDISO
            solver.pardisoLUSolve();
#else

#ifdef LOAD_UMFPACK
            solver.umfPackLUSolve();
#else
            solver.superLUSolve();
            //solver.biCGStabSolve();
#endif
            
#endif
            // distribute results back to dofs
            base::dof::addToDoFsFromSolver( solver, nucleus.getDisplacement() ); //<>
            base::dof::setDoFsFromSolver(   solver, cytoSkeleton.getVelocity() );
            base::dof::setDoFsFromSolver(   solver, cytoSkeleton.getPressure() );
            base::dof::setDoFsFromSolver(   solver, gel.getVelocity() );
            base::dof::setDoFsFromSolver(   solver, gel.getPressure() );

            const double conv2 = solver.norm(0, activeDoFsD);

            if ( conv2 < ui.tolerance ) break;
            
        } // finish non-linear iteration
        std::cout << iter << "  " << std::flush;

        // write a vtk file
        writeVTKFile( "nucleus", step+1, mesh,
                      nucleus.getDisplacement(),
                      cytoSkeleton.getVelocity(), cytoSkeleton.getPressure(),
                      gel.getVelocity(),          gel.getPressure(),
                      levelSetNucleus, levelSetMembrane, ui.dt );
        writeSurfaceVTKFile( "membrane", step+1, membrane );
        writeSurfaceVTKFile( "envelope", step+1, envelope );

        //----------------------------------------------------------------------
        // 1) Pass Data to complementary domain of solid
        {
            const double extL = h; // extrapolation length

            // pass extrapolated solution to inactive DoFs
            extrapolateToFictitious( mesh, nucleus.getDisplacement(),
                                     extL, doFLocationD, levelSetNucleus, bbox );
        }

        //----------------------------------------------------------------------
        // 2) Geometry update
        // a) Nucleus
        {
            // get shape features
            const double volumeN = surf::enclosedVolume( envelope, surfaceQuadrature );
            const TA::VecDim momentN =
                surf::enclosedVolumeMoment( envelope, surfaceQuadrature );
            const TA::VecDim centroidN = momentN / volumeN;

            const double factorN = std::pow( prevVolumeN / volumeN,
                                            1./static_cast<double>( dim ) );
     
            // Move with velocity solution
            moveSurface( mesh, cytoSkeleton.getVelocity(),
                         envelope, ui.dt, factorN, centroidN );

            // compute new level set for envelope of nucleus
            base::cut::bruteForce( mesh, envelope, true, levelSetNucleus );

            // update the cut cell structure
            base::cut::generateCutCells( mesh, levelSetNucleus, cellsNucleus );


            // store the contained volume
            prevVolumeN = surf::enclosedVolume( envelope, surfaceQuadrature );
        }

        // b) CS
        {
            // get shape features
            const double volumeCS =
                surf::enclosedVolume( membrane,  surfaceQuadrature ) +
                surf::enclosedVolume( boundaryMesh, surfaceCutQuadrature );
            const TA::VecDim momentCS =
                surf::enclosedVolumeMoment( membrane, surfaceQuadrature ) +
                surf::enclosedVolumeMoment( boundaryMesh, surfaceCutQuadrature );
            const TA::VecDim centroidCS = momentCS / volumeCS;

            // Move with velocity solution
            moveSurface( mesh, gel.getVelocity(), membrane, ui.dt, 1.0, centroidCS );
            // rescale in order to preserve initial volume
            rescaleSurface( membrane, initialVolumeCS, volumeCS, centroidCS );

            // compute new level set for membrane
            base::cut::bruteForce( mesh, membrane, true, levelSetMembrane );

            // update the cut cell structure
            base::cut::generateCutCells( mesh, levelSetMembrane, cellsMembrane );
            base::cut::generateCutCells( boundaryMesh, levelSetMembrane, surfaceCells );
        }

        // new structure for cytoskeleton
        {
            cellsCS = cellsNucleus;
            std::for_each( cellsCS.begin(), cellsCS.end(),
                           boost::bind( &TA::Cell::reverse, _1 ) );
            
            base::cut::generateCutCells( mesh, levelSetMembrane, cellsCS,
                                         base::cut::INTERSECT );
        }


        //----------------------------------------------------------------------
        // 3) advect data
        {
            base::cut::supportComputation( mesh, nucleus.getDisplacement(),
                                           cutQuadratureNucleus, supportsD ); 
        
            // Find the location of the DoFs in the previous configuration
            std::vector<std::pair<std::size_t,TA::VecDim> > previousDoFLocation;
            findPreviousDoFLocations( mesh, nucleus.getDisplacement(), supportsD, 
                                      doFLocationD, previousDoFLocation, bbox, 
                                      supportThreshold, ui.findTolerance, 10 );
            
            // add previous solution to current solution: u_{n+1} = \Delta u + u_n
            {
                Solid::Displacement::DoFPtrIter dIter = nucleus.getDisplacement().doFsBegin();
                Solid::Displacement::DoFPtrIter dEnd  = nucleus.getDisplacement().doFsEnd();
                for ( ; dIter != dEnd; ++dIter ) {
                    for ( unsigned d = 0; d < dim; d++ ) {
                        const double prevU  = (*dIter) -> getHistoryValue<1>( d );
                        const double deltaU = (*dIter) -> getHistoryValue<0>( d );
                        const double currU = prevU + deltaU;
                        (*dIter) -> setValue( d, currU );
                    }
                }
            }
        
            // advect displacement field from previous to new location
            advectField( mesh, nucleus.getDisplacement(), previousDoFLocation, supportsD, 
                         supportThreshold );
        }

        //----------------------------------------------------------------------
        // push history
        base::dof::pushHistory( nucleus.getDisplacement() );

        // remove the linear constraints used in the stabilisation process
        base::dof::clearConstraints( nucleus.getDisplacement() );
        base::dof::clearConstraints( cytoSkeleton.getVelocity()     );
        base::dof::clearConstraints( cytoSkeleton.getPressure()     );
        base::dof::clearConstraints( gel.getVelocity()     );
        base::dof::clearConstraints( gel.getPressure()     );

        surfaceFeatures( boundaryMesh, membrane, envelope,
                         surfaceQuadrature, surfaceCutQuadrature, std::cout );
        std::cout << std::endl;

    } // end load-steps

    return 0;
}
engine_RawRingElementArrayOrNull rawRoots(const RingElement *p, long prec,
                                          int unique) {
  const Ring *R = p->get_ring();
  const PolynomialRing *P = R->cast_to_PolynomialRing();
  if (P == 0) {
    ERROR("expected a polynomial ring");
    return NULL;
  }
  const int n = P->n_vars();
  if (n != 1) {
    ERROR("expected a univariate polynomial ring");
    return NULL;
  }
  const Ring *K = P->getCoefficients();
  int degree = 0;
  for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
    degree = max(degree, abs(*(t->monom)));
  }
  if (prec == -1) {
    prec = (K->get_precision() == 0 ? 53 : K->get_precision());
  }

  engine_RawRingElementArrayOrNull result = nullptr;

  /* Start PARI computations. */
  pari_CATCH(e_STACK) {
#ifdef NDEBUG
    /*
     * Every time the stack is changed PARI writes a message to the file pari_errfile
     * which by default is /dev/stderr. To avoid showing this message to the user we
     * redirect to /dev/null before the PARI's stack is modified.
     */
    FILE *tmp, *dev_null = fopen("/dev/null", "w");
    if (dev_null != NULL) {
      tmp = pari_errfile;
      pari_errfile = dev_null;
    }
#endif
  allocatemem(0); // passing 0 will double the current stack size.
#ifdef NDEBUG
    /*
     * We set pari_errfile back to the default value just in case PARI crashes.
     */
    if (dev_null != NULL) {
      pari_errfile = tmp;
      fclose(dev_null);
    }
#endif
  } pari_RETRY {
    const pari_sp av = avma;

    GEN q = cgetg(2 + degree + 1, t_POL);
    setsigne(q, 1);
    setvarn(q, 0);
    for (int i = 0; i < degree + 1; ++i) {
      gel(q, 2 + i) = gen_0;
    }

    switch (K->ringID()) {
    case M2::ring_ZZ:
    ZZ_GMP:
      for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
        gel(q, 2 + abs(*(t->monom))) =
            mpz_get_GEN(reinterpret_cast<const mpz_ptr>(t->coeff.poly_val));
      }
      break;
    case M2::ring_QQ:
      for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
        gel(q, 2 + abs(*(t->monom))) =
            mpq_get_GEN(reinterpret_cast<const mpq_ptr>(t->coeff.poly_val));
      }
      break;
    case M2::ring_RR:
      pari_CATCH(e_OVERFLOW) {
        ERROR("coefficient is NaN or Infinity");
        avma = av;
        return NULL;
      }
      pari_TRY {
        for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
          gel(q, 2 + abs(*(t->monom))) =
              dbltor(*reinterpret_cast<double *>(t->coeff.poly_val));
        }
      }
      pari_ENDCATCH
      break;
    case M2::ring_CC:
      pari_CATCH(e_OVERFLOW) {
        ERROR("coefficient is NaN or Infinity");
        avma = av;
        return NULL;
      }
      pari_TRY {
        for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
          GEN z = cgetg(3, t_COMPLEX);
          gel(z, 1) = dbltor(reinterpret_cast<complex *>(t->coeff.poly_val)->re);
          gel(z, 2) = dbltor(reinterpret_cast<complex *>(t->coeff.poly_val)->im);
          gel(q, 2 + abs(*(t->monom))) = z;
        }
      }
      pari_ENDCATCH
      break;
    case M2::ring_RRR:
      for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
        gel(q, 2 + abs(*(t->monom))) =
            mpfr_get_GEN(reinterpret_cast<const mpfr_ptr>(t->coeff.poly_val));
      }
      break;
    case M2::ring_CCC:
      for (Nterm *t = p->get_value(); t != NULL; t = t->next) {
        gel(q, 2 + abs(*(t->monom))) =
            mpc_get_GEN(reinterpret_cast<const mpc_ptr>(t->coeff.poly_val));
      }
      break;
    case M2::ring_old:
      if (K->is_ZZ()) {
        goto ZZ_GMP;
      }
    default:
      ERROR("expected coefficient ring of the form ZZ, QQ, RR or CC");
      return NULL;
    }

    if (unique) {
      q = RgX_div(q, RgX_gcd_simple(q, RgX_deriv(q)));
    }

    GEN roots = cleanroots(q, nbits2prec(prec));

    const size_t num_roots = lg(roots) - 1;
    result = getmemarraytype(engine_RawRingElementArray, num_roots);
    result->len = static_cast<int>(num_roots);

    ring_elem m2_root;
    if (prec <= 53) {
      const RingCC *CC = dynamic_cast<const RingCC *>(IM2_Ring_CCC(prec));

      for (int i = 0; i < num_roots; ++i) {
        const pari_sp av2 = avma;

        GEN pari_root = gel(roots, 1 + i);
        const complex root = {rtodbl(greal(pari_root)),
                              rtodbl(gimag(pari_root))};
        CC->ring().to_ring_elem(m2_root, root);
        result->array[i] = RingElement::make_raw(CC, m2_root);

        avma = av2;
      }
    } else {
      const RingCCC *CCC = dynamic_cast<const RingCCC *>(IM2_Ring_CCC(prec));

      for (int i = 0; i < num_roots; ++i) {
        const pari_sp av2 = avma;

        mpc_t root;
        auto root1 = reinterpret_cast<mpfc_t*>(&root);
        pari_mpc_init_set_GEN(root, gel(roots, 1 + i), GMP_RNDN);
        //        CCC->ring().to_ring_elem(m2_root, **reinterpret_cast<mpfc_t*>(&root));
        CCC->ring().to_ring_elem(m2_root, **root1);
        result->array[i] = RingElement::make_raw(CCC, m2_root);

        avma = av2;
      }
    }

    /* End PARI computations. */
    avma = av;
  }
  pari_ENDCATCH

  return result;
}
Beispiel #8
0
/* v_ell(  exponent(D) ) */
static long
ellexpo(GEN D, GEN ell) { return lg(D) == 1? 0: Z_pval(gel(D,1), ell); }
Beispiel #9
0
/* d = requested degree for subfield. Return DATA, valid for given pol, S and d
 * If DATA != NULL, translate pol [ --> pol(X+1) ] and update DATA
 * 1: polynomial pol
 * 2: p^e (for Hensel lifts) such that p^e > max(M),
 * 3: Hensel lift to precision p^e of DATA[4]
 * 4: roots of pol in F_(p^S->lcm),
 * 5: number of polynomial changes (translations)
 * 6: Bezout coefficients associated to the S->ff[i]
 * 7: Hadamard bound for coefficients of h(x) such that g o h = 0 mod pol.
 * 8: bound M for polynomials defining subfields x PD->den
 * 9: *[i] = interpolation polynomial for S->ff[i] [= 1 on the first root
      S->firstroot[i], 0 on the others] */
static void
compute_data(blockdata *B)
{
  GEN ffL, roo, pe, p1, p2, fk, fhk, MM, maxroot, pol;
  primedata *S = B->S;
  GEN p = S->p, T = S->T, ff = S->ff, DATA = B->DATA;
  long i, j, l, e, N, lff = lg(ff);

  if (DEBUGLEVEL>1) fprintferr("Entering compute_data()\n\n");
  pol = B->PD->pol; N = degpol(pol);
  roo = B->PD->roo;
  if (DATA) /* update (translate) an existing DATA */
  {
    GEN Xm1 = gsub(pol_x[varn(pol)], gen_1);
    GEN TR = addis(gel(DATA,5), 1);
    GEN mTR = negi(TR), interp, bezoutC;

    gel(DATA,5) = TR;
    pol = translate_pol(gel(DATA,1), gen_m1);
    l = lg(roo); p1 = cgetg(l, t_VEC);
    for (i=1; i<l; i++) gel(p1,i) = gadd(TR, gel(roo,i));
    roo = p1;

    fk = gel(DATA,4); l = lg(fk);
    for (i=1; i<l; i++) gel(fk,i) = gsub(Xm1, gel(fk,i));

    bezoutC = gel(DATA,6); l = lg(bezoutC);
    interp  = gel(DATA,9);
    for (i=1; i<l; i++)
    {
      if (degpol(interp[i]) > 0) /* do not turn pol_1[0] into gen_1 */
      {
        p1 = translate_pol(gel(interp,i), gen_m1);
        gel(interp,i) = FpXX_red(p1, p);
      }
      if (degpol(bezoutC[i]) > 0)
      {
        p1 = translate_pol(gel(bezoutC,i), gen_m1);
        gel(bezoutC,i) = FpXX_red(p1, p);
      }
    }
    ff = cgetg(lff, t_VEC); /* copy, don't overwrite! */
    for (i=1; i<lff; i++)
      gel(ff,i) = FpX_red(translate_pol((GEN)S->ff[i], mTR), p);
  }
  else
  {
    DATA = cgetg(10,t_VEC);
    fk = S->fk;
    gel(DATA,5) = gen_0;
    gel(DATA,6) = shallowcopy(S->bezoutC);
    gel(DATA,9) = shallowcopy(S->interp);
  }
  gel(DATA,1) = pol;
  MM = gmul2n(bound_for_coeff(B->d, roo, &maxroot), 1);
  gel(DATA,8) = MM;
  e = logint(shifti(vecmax(MM),20), p, &pe); /* overlift 2^20 [for d-1 test] */
  gel(DATA,2) = pe;
  gel(DATA,4) = roots_from_deg1(fk);

  /* compute fhk = hensel_lift_fact(pol,fk,T,p,pe,e) in 2 steps
   * 1) lift in Zp to precision p^e */
  ffL = hensel_lift_fact(pol, ff, NULL, p, pe, e);
  fhk = NULL;
  for (l=i=1; i<lff; i++)
  { /* 2) lift factorization of ff[i] in Qp[X] / T */
    GEN F, L = gel(ffL,i);
    long di = degpol(L);
    F = cgetg(di+1, t_VEC);
    for (j=1; j<=di; j++) F[j] = fk[l++];
    L = hensel_lift_fact(L, F, T, p, pe, e);
    fhk = fhk? shallowconcat(fhk, L): L;
  }
  gel(DATA,3) = roots_from_deg1(fhk);

  p1 = mulsr(N, gsqrt(gpowgs(utoipos(N-1),N-1),DEFAULTPREC));
  p2 = gpowgs(maxroot, B->size + N*(N-1)/2);
  p1 = gdiv(gmul(p1,p2), gsqrt(B->PD->dis,DEFAULTPREC));
  gel(DATA,7) = mulii(shifti(ceil_safe(p1), 1), B->PD->den);

  if (DEBUGLEVEL>1) {
    fprintferr("f = %Z\n",DATA[1]);
    fprintferr("p = %Z, lift to p^%ld\n", p, e);
    fprintferr("2 * Hadamard bound * ind = %Z\n",DATA[7]);
    fprintferr("2 * M = %Z\n",DATA[8]);
  }
  if (B->DATA) {
    DATA = gclone(DATA);
    if (isclone(B->DATA)) gunclone(B->DATA);
  }
  B->DATA = DATA;
}
Beispiel #10
0
static GEN
init_traces(GEN ff, GEN T, GEN p)
{
  long N = degpol(T),i,j,k, r = lg(ff);
  GEN Frob = FpXQ_matrix_pow(FpXQ_pow(pol_x[varn(T)],p, T,p), N,N, T,p);
  GEN y,p1,p2,Trk,pow,pow1;

  k = degpol(ff[r-1]); /* largest degree in modular factorization */
  pow = cgetg(k+1, t_VEC);
  gel(pow,1) = gen_0; /* dummy */
  gel(pow,2) = Frob;
  pow1= cgetg(k+1, t_VEC); /* 1st line */
  for (i=3; i<=k; i++)
    gel(pow,i) = FpM_mul(gel(pow,i-1), Frob, p);
  gel(pow1,1) = gen_0; /* dummy */
  for (i=2; i<=k; i++)
  {
    p1 = cgetg(N+1, t_VEC);
    gel(pow1,i) = p1; p2 = gel(pow,i);
    for (j=1; j<=N; j++) gel(p1,j) = gcoeff(p2,1,j);
  }
  
  /* Trk[i] = line 1 of x -> x + x^p + ... + x^{p^(i-1)} */
  Trk = pow; /* re-use (destroy) pow */
  gel(Trk,1) = vec_ei(N,1);
  for (i=2; i<=k; i++)
    gel(Trk,i) = gadd(gel(Trk,i-1), gel(pow1,i));
  y = cgetg(r, t_VEC);
  for (i=1; i<r; i++) y[i] = Trk[degpol(ff[i])];
  return y;
}
Beispiel #11
0
static GEN
print_block_system(blockdata *B, GEN Y, GEN SB)
{
  long i, j, l, ll, lp, u, v, ns, r = lg(Y), N = B->N;
  long *k, *n, **e, *t;
  GEN D, De, Z, cyperm, perm, VOID = cgetg(1, t_VECSMALL);

  if (DEBUGLEVEL>5) fprintferr("Y = %Z\n",Y);
  n = new_chunk(N+1);
  D = cget1(N+1, t_VEC);
  t = new_chunk(r+1);
  k = new_chunk(r+1);
  Z = cgetg(r+1, t_VEC);
  for (ns=0,i=1; i<r; i++)
  {
    GEN Yi = gel(Y,i);
    long ki = 0, si = lg(Yi)-1;

    for (j=1; j<=si; j++) { n[j] = lg(Yi[j])-1; ki += n[j]; }
    ki /= B->size;
    De = cgetg(ki+1,t_VEC);
    for (j=1; j<=ki; j++) gel(De,j) = VOID;
    for (j=1; j<=si; j++)
    {
      GEN cy = gel(Yi,j);
      for (l=1,lp=0; l<=n[j]; l++)
      {
        lp++; if (lp > ki) lp = 1;
        gel(De,lp) = vecsmall_append(gel(De,lp), cy[l]);
      }
    }
    append(D, De);
    if (si>1 && ki>1)
    {
      GEN p1 = cgetg(si,t_VEC);
      for (j=2; j<=si; j++) p1[j-1] = Yi[j];
      ns++;
      t[ns] = si-1;
      k[ns] = ki-1;
      gel(Z,ns) = p1;
    }
  }
  if (DEBUGLEVEL>2) fprintferr("\nns = %ld\n",ns);
  if (!ns) return test_block(B, SB, D);

  setlg(Z, ns+1);
  e = (long**)new_chunk(ns+1);
  for (i=1; i<=ns; i++)
  {
    e[i] = new_chunk(t[i]+1);
    for (j=1; j<=t[i]; j++) e[i][j] = 0;
  }
  cyperm= cgetg(N+1,t_VECSMALL);
  perm  = cgetg(N+1,t_VECSMALL); i = ns;
  do
  {
    pari_sp av = avma;
    for (u=1; u<=N; u++) perm[u] = u;
    for (u=1; u<=ns; u++)
      for (v=1; v<=t[u]; v++)
	perm_mul_i(perm, cycle_power_to_perm(cyperm, gmael(Z,u,v), e[u][v]));
    SB = test_block(B, SB, im_block_by_perm(D,perm));
    avma = av;

    /* i = 1..ns, j = 1..t[i], e[i][j] loop through 0..k[i].
     * TODO: flatten to 1-dimensional loop */
    if (++e[ns][t[ns]] > k[ns])
    {
      j = t[ns]-1;
      while (j>=1 && e[ns][j] == k[ns]) j--;
      if (j >= 1) { e[ns][j]++; for (l=j+1; l<=t[ns]; l++) e[ns][l] = 0; }
      else
      {
	i = ns-1;
	while (i>=1)
	{
	  j = t[i];
	  while (j>=1 && e[i][j] == k[i]) j--;
	  if (j<1) i--;
          else
	  {
	    e[i][j]++;
	    for (l=j+1; l<=t[i]; l++) e[i][l] = 0;
	    for (ll=i+1; ll<=ns; ll++)
              for (l=1; l<=t[ll]; l++) e[ll][l] = 0;
            break;
	  }
	}
      }
    }
  }
  while (i > 0);
  return SB;
}
Beispiel #12
0
/* Computation of potential block systems of given size d associated to a
 * rational prime p: give a row vector of row vectors containing the
 * potential block systems of imprimitivity; a potential block system is a
 * vector of row vectors (enumeration of the roots). */
static GEN
calc_block(blockdata *B, GEN Z, GEN Y, GEN SB)
{
  long r = lg(Z), lK, i, j, t, tp, T, u, nn, lnon, lY;
  GEN K, n, non, pn, pnon, e, Yp, Zp, Zpp;
  pari_sp av0 = avma;

  if (DEBUGLEVEL>3)
  {
    fprintferr("lg(Z) = %ld, lg(Y) = %ld\n", r,lg(Y));
    if (DEBUGLEVEL > 5)
    {
      fprintferr("Z = %Z\n",Z);
      fprintferr("Y = %Z\n",Y);
    }
  }
  lnon = min(BIL, r);
  e    = new_chunk(BIL);
  n    = new_chunk(r);
  non  = new_chunk(lnon);
  pnon = new_chunk(lnon);
  pn   = new_chunk(lnon);

  Zp   = cgetg(lnon,t_VEC);
  Zpp  = cgetg(lnon,t_VEC); nn = 0;
  for (i=1; i<r; i++) { n[i] = lg(Z[i])-1; nn += n[i]; }
  lY = lg(Y); Yp = cgetg(lY+1,t_VEC);
  for (j=1; j<lY; j++) Yp[j] = Y[j];

  {
    pari_sp av = avma;
    long k = nn / B->size;
    for (j = 1; j < r; j++) 
      if (n[j] % k) break;
    if (j == r)
    {
      gel(Yp,lY) = Z;
      SB = print_block_system(B, Yp, SB);
      avma = av;
    }
  }
  gel(Yp,lY) = Zp;

  K = divisors(utoipos(n[1])); lK = lg(K);
  for (i=1; i<lK; i++)
  {
    long ngcd = n[1], k = itos(gel(K,i)), dk = B->size*k, lpn = 0;
    for (j=2; j<r; j++)
      if (n[j]%k == 0)
      {
        if (++lpn >= BIL) pari_err(talker,"overflow in calc_block");
        pn[lpn] = n[j]; pnon[lpn] = j;
        ngcd = cgcd(ngcd, n[j]);
      }
    if (dk % ngcd) continue;
    T = 1<<lpn;
    if (lpn == r-2)
    {
      T--; /* done already above --> print_block_system */
      if (!T) continue;
    }

    if (dk == n[1])
    { /* empty subset, t = 0. Split out for clarity */
      Zp[1] = Z[1]; setlg(Zp, 2);
      for (u=1,j=2; j<r; j++) Zpp[u++] = Z[j];
      setlg(Zpp, u);
      SB = calc_block(B, Zpp, Yp, SB);
    }

    for (t = 1; t < T; t++)
    { /* loop through all non-empty subsets of [1..lpn] */
      for (nn=n[1],tp=t, u=1; u<=lpn; u++,tp>>=1)
      {
        if (tp&1) { nn += pn[u]; e[u] = 1; } else e[u] = 0;
      }
      if (dk != nn) continue;

      for (j=1; j<r; j++) non[j]=0;
      Zp[1] = Z[1];
      for (u=2,j=1; j<=lpn; j++)
        if (e[j]) { Zp[u] = Z[pnon[j]]; non[pnon[j]] = 1; u++; }
      setlg(Zp, u);
      for (u=1,j=2; j<r; j++)
        if (!non[j]) Zpp[u++] = Z[j];
      setlg(Zpp, u);
      SB = calc_block(B, Zpp, Yp, SB);
    }
  }
  avma = av0; return SB;
}
Beispiel #13
0
static long
group_ident_i(GEN G, GEN S)
{
  long n = group_order(G);
  long s;
  GEN F,p,e;
  if (n==1) return 1;
  if (!S) S = group_elts(G,group_domain(G));
  s = groupelts_sumorders(S);/*This is used as a hash value*/
  F = factoru(n);
  p = gel(F,1);
  e = gel(F,2);
  switch(lg(p)-1)
  {
  case 1:/*prime power*/
    switch (e[1])
    {
    case 1: /* p */
      return 1;
    case 2: /* p^2 */
      return (s == 1 - p[1] + n*p[1])? 2: 1; /* pxp || p^2 */
    case 3: /* p^3 */
      {
        GEN H = group_abelianSNF(G, S);
        if (H) /*G is abelian*/
        {
          long l = lg(H)-1;
          return (l==3)?5: l; /*pxpxp || p^3 or p^2xp*/
        } /*G is not abelian*/
        if (p[1] == 2)
          return (s == 19)? 3: 4; /*D8 || Q8*/
        else
        {
          long q = p[1]*p[1];
          q *= q;
          return (s == q - p[1] + 1)?3 :4; /* pxp:p || p^2:p */
        }
      }
    }
    break;
  case 2:
    switch(e[1]+e[2])
    {
    case 2: /*pq*/
      return (p[2]%p[1]!=1)?1:1+group_isabelian(G); /*pq || pq or p:q*/
    case 3:
      if (p[1]==2 && e[1]==2) /* 4p */
      {
        long q = p[2], q2 = q*q, pmq2 = (q%4 == 1 || q==3);
        if (s==3+5*q+3*q2) return 1; /* 2p.2 */
        if (s==11-11*q+11*q2) return 2; /* 4p */
        if (s==3+q+3*q2) return 3+pmq2; /* D4p */
        if (s==7-7*q+7*q2) return 4+pmq2; /* 2px2 */
        return 3; /*A4 or p:4 */
      }
      else if (p[1]==2 && e[1]==1) /*2p^2*/
      {
        long q = p[2], q2 = q*q, q3 = q*q2, q4 = q*q3;
        if (s==1-q+3*q2-q3+q4) return 1; /* p^2:2 */
        if (s==3-3*q+3*q2-3*q3+3*q4) return 2; /* 2p^2 */
        if (s==1+q-2*q2+3*q3) return 3; /* D2pxp */
        if (s==1-q+2*q2+q3) return 4; /* p:2+p:2 */
        return 5;   /* 2pxp */
      }
      else if (p[1]==3 && e[1]==2) /*9p, p>3*/
      {
        long q= p[2], q2 = q*q, p3 = (q%3 == 1), p9 = (q%9 == 1);
        if (s==7+47*q+7*q2) return 1; /* 3p.3 */
        if (s==61-61*q+61*q2) return 1+p3; /* 9p */
        if (s==1+59*q+q2) return 3; /* p:9 */
        if (s==7+11*q+7*q2) return 3+p9; /* p:3x3 */
        return 2+2*p3+p9; /* 3^2xp */
      }
      break;
    }
  case 3:
    switch(e[1]+e[2]+e[3])
    {
    case 3: /*pqr*/
      if (p[1]==2)  /*2qr*/
      {
        long q = p[2],q2 = q*q, qc = 1-q+q2, qd = 1+q+q2;
        long r = p[3],r2 = r*r, rc = 1-r+r2, rd = 1+r+r2;
        long pmq = (r%q==1)? 2: 0;
        if (pmq && s==3*r*(q2-q)+rd) return 1; /* r:2q */
        if (pmq && s==3*(r2+(q2-q-1)*r+1)) return 2; /* r:qx2 */
        if (s==qd*rc) return 1+pmq; /* D2qxr */
        if (s==rd*qc) return 2+pmq; /* D2rxq */
        if (s==3*qc*rc) return 4+pmq; /* 2qr */
        return 3+pmq; /* q:2+r:2 */
      }
      break;
    }
  }
  {
    const long tab[]={
    24, 173, 301, 99, 125, 113, 101, 97, 85, 161, 133, 189, 67, 87, 73, 105, -1,
    36, 255, 671, 265, 219, 427, 243, 147, 275, 115, 127, 121, 159, 111, 175,
       -1,
    40, 391, 903, 263, 311, 291, 271, 227, 207, 483, 399, 567, 163, 187, 315,
       -1,
    56, 697, 1849, 585, 557, 529, 413, 385, 989, 817, 1161, 351, 357, 645, -1,
    60, 945, 721, 561, 1617, 211, 497, 337, 373, 651, 581, 693, 501, 1029, -1,
    75, 3647, 271, 847, -1,
    84, 647, 935, 1935, 1295, 1071, 3311, 451, 699, 595, 1333, 469, 1099, 1419,
        987, 2107, -1,
    88, 1573, 4773, 1397, 1353, 1309, 953, 909, 2553, 2109, 2997, 865, 1665, -1,
    90, 1659, 1891, 1371, 3843, 775, 1407, 735, 903, 615, 1575, -1,
    104, 2143, 6751, 991, 1935, 1883, 1831, 1307, 1255, 3611, 2983, 4239, 731,
         1203, 2355, -1,
    105, 1785, 6321, -1,
    126, 1533, 2037, 3397, 3477, 2749, 7869, 777, 937, 721, 1281, 1425, 2881,
         1369, 1849, 1201, 3225, -1,
      -1};
      long i;
      const long *t;
      for(t=tab;*t!=-1;t++)
      {
        if (t[0]==n)
        {
          for(i=1; t[i] != -1; i++)
            if (t[i]==s) return i;
          return -1;
        }
        while (*t>=0) t++;
      }
  }
  {
    const long tab[]={
      16, 1710031, 550075, 70099, 70075, 870059, 110059, 30079, 30071, 30063,
470131, 70155, 70107, 110115, 310307, -1,
      32, 6830063, 150323, 1830171, /*230171*/0, 230227, 30283, 30251, 30203,
/*70267*/0, 70219, 110227, /*230171*/0, /*70187*/0, /*70187*/0, 110155,
3430123, 430123, 30191, 30175, 30159, 1110387, 150563, 150387, 230323, 230411,
230299, 70619, 70467, 70355, /*70379*/0, /*70379*/0, /*70267*/0, 70291, 70555,
70331, 1750291, 230291, 430275, 70411, 70363, 70315, 110331, 30371, 30323,
950819, 150995, 150643, 230691, 30747, 30635, 632451, -1,
      48, 430156, 11970124, 10219, 430324, 110324, 30396, 30444, 30348, 230300,
110300, 230396, /*70396*/0, /*70396*/0, 70540, 30412, 30364, 30380, 30332,
70492, 3850300, 490396, 490300, 6090236, 770236, 210316, 210284, 210252, 30299,
30371, 30363, 110299, 70311, 110271, 70588, 230732, 70876, 110636, 30868,
30628, 30596, 30644, 150684, 70828, 3290524, 490620, 490428, 770460, 30627,
70571, 10643, 151740, 2171228, -1,
      54, 10256, 16410120, 70292, 610232, 10373, 10292, 10616, 70517, 5610228,
210309, 210228, 250448, 70616, 11696, 2370552, -1,
      /*64*/
      72, 110307, 26230195, 210272, 30523, 110631, 30739, 70575, 30683,
14030351, 1830403, 1830299, 770346, 110586, 10750330, 10620, 210420, 71223,
9150663, 30426, 30858, 30978, 30954, 31074, 30762, 210452, 210538, 770634,
210730, 490626, 210722, 31018, 111234, 31450, 71106, 31322, 5750594, 750682,
750506, 10346, 10826, 10490, 70620, 11124, 10716, 30786, 31746, 210636, 491202,
72402, 3751122, -1,
      80, 430250, 35910186, 110282, 430530, 110530, 30650, 30730, 30570,
230482, 110482, 230642, /*70642*/0, /*70642*/0, 70882, 30666, 30586, 30618,
30538, 70786, 11550450, 1470594, 1470450, 18270354, 2310354, 630474, 630426,
630378, 110562, 30562, 110722, 30722, 70546, 30546, 30946, 70962, 231202,
71442, 111042, 31426, 31026, 30978, 31058, 151106, 71346, 9870786, 1470930,
1470642, 2310690, 10467, 71266, 152866, 6511842, -1,
      81,49210121, 6730319, 250427, 250319, 16450238, 610238, 70454, 70346,
70400, 70319, 5650670, 250994, 250670, 610589, 2412452, -1,
      /*96*/
      100, 30393, 57310217, 10481, 30693, 36470341, 630408, 30968, 13310392,
210416, 10576, 11256, 10856, 11096, 630648, 31768, 8470616, -1,
      108, 30552, 60170280, 610359, 30984, 38290440, 210660, 1830540, 30849,
30660, 31308, 211137, 20570532, 770721, 770532, 70769, 11636, 11813, 610647,
70647, 250674, 70674, 70890, 211092, 1830852, 31389, 31092, 32388, 211965,
13090836, 491133, 490836, 751080, 211416, 33576, 8691288, 70904, 11048, 71720,
13688, 12344, 251538, 751608, 212280, 36600, 5532024,-1,
      112, 430344, 73530248, 430736, 110736, 30904, 31016, 30792, 230664,
110664, 230888, 0/*70888*/, 0/*70888*/, 71224, 30920, 30808, 30856, 30744,
71080, 23650600, 3010792, 3010600, 37410472, 4730472, 1290632, 1290568,
1290504, 71336, 231672, 72008, 111448, 31984, 31424, 31360, 31472, 151528,
71864, 20211048, 3011240, 3010856, 4730920, 30643, 153992, 13332456,-1,
      120,2310456, 770488, 110648, 63210360, 30763, 210552, 30712, 31256,
31240, 31336, 31400, 31496, 31480, 31096, 630498, 210808, 770968, 211128,
490904, 211064, 630744, 2310888, 631032, 1470840, 630984, 31128, 111368, 31608,
71224, 31464, 33810648, 4410744, 4410552, 11211, 31263, 11416, 210858, 11290,
11090, 211032, 31352, 32600, 630738, 491864, 1471704, 72664, 22051224, -1,
      -1};
    long i;
    const long *t;
    GEN Z = groupelts_center(S), L = group_subgroups(G);
    long scenter = groupelts_sumorders(Z), svecgroup = vecgroup_sumorders(L);
    long u = svecgroup+10000*scenter; /*This is used as a hash value*/

    for(t=tab; *t!=-1; t++)
    {
      if (t[0]==n)
      {
        for(i=1; t[i] != -1; i++)
          if (t[i]==u) return i;
        switch(n)
        {
        case 32:
          switch(u)
          {
          case 230171:
            {
              const long good[]={2,0}, bad[]={4,5,0};
              return indexgroupcentre(G,Z,good,bad)? 4: 12;
            }
          case 70267:
            if (s==135) return 9;
            return 32;
          case 70187:
            {
              const long good[]={8,0}, bad[]={7,9,0};
              return indexgroupcentre(G,Z,good,bad)? 13: 14;
            }
          case 70379:
            {
              const long good[]={4,0},bad[]={0};
              return indexgroupsubgroup(L,8,good,bad)? 31: 30;
            }
          }
          break;
        case 48: case 80:
          {
            const long good[]={5,8,0},bad[]={6,7,0};
            return indexgroupcentre(G,Z,good,bad)? 12: 13;
          }
        case 112:
          {
            const long good[]={7,4,0},bad[]={5,6,0};
            return indexgroupcentre(G,Z,good,bad)? 11: 12;
          }
        }
        return -1;
      }
      while (*t!=-1) t++;
    }
    {
      const long tab[]={ 64, 1270001, /*4270003*/0, /*4270003*/0, 8190072,
 6430073, 6670445, 5550446, 8190278, 7070279, 6350071, 5230072, 8110154,
 /*5870155*/0, /*5870155*/0, /*4270042*/0, /*4270042*/0, 7710246, 7390277,
 6750037, 8032377, 8670266, 6750397, 11390022, 7710267, 7070277, /*3630046*/0,
 /*3630046*/0, 3630057, 4830196, 4830207, 4671808, 9070697, 6670700, 8750094,
 6990091, 6350111, 5870115, 6671599, 5711601, 5551702, 5871512, 6351709,
 5391711, /*3630046*/0, 3630047, 4111467, /*4430156*/0, /*4430156*/0, 3790166,
 /*2510026*/0, /*2510026*/0, 4470028, 4150300, 3830030, 13470021, 20350065,
 10910041, 16514365, /*12190433*/0, 34110271, /*16514475*/0, 15230465,
 /*10910433*/0, 9630041, 13470233, /*16514475*/0, 20834696, /*10910433*/0,
 13954343, /*12190433*/0, 19553542, 13474377, 25790466, 15870467, 18914476,
 14110477, /*14590443*/0, 13310443, 11550043, /*14590443*/0, 10270043, 8990002,
 8990546, 8990646, 8993647, 8356896, 13310905, 13310915, 12039018, 16990866,
 12670888, 15071116, 11551217, 12038218, 16031739, 12512740, 12353138, 12993048,
 15391849, 11872850, 12993551, 12353851, 8991446, 8991447, 8354830, 9951566,
 9951666, 8674709, 9317039, 8031897, 8030187, 7713641, 7714641, 7074743,
 9236585, 9236415, 9236586, 10990821, 9879066, 8751833, 9873399, 8751766,
 10990754, 8593054, 8593087, 6830446, 6833546, 17472434, 13953445, 14432313,
 16352544, 12833555, 13313423, 15635143, 13234877, 13874853, 12755287, 17870919,
 14190949, 13075209, 11955310, 10835253, 9715354, 11312124, 10193135, 11074927,
 12197529, 9957664, 11074970, 12196539, 9956674, 9958907, 10439497, 9479551,
 9554015, 8433958, 9553915, 8434058, 8918081, 7798421, 10110856, 10110756,
 9476648, 8991757, 8991857, 8356682, 10994275, 8750435, 8590474, 9230510,
 10355254, 8115355, 13556790, 15790679, 11310691, 12275539, 14035061, 11795172,
 8750465, 7474472, 8750475, 8114920, 6110196, 6111806, 5951808, 10191819,
 9238364, 8271841, 8590736, 9390959, 8432079, 25470255, 41792701, 25470275,
 20355344, 27233751, 18593673, 19717567, 23394762, 17312707, 19717633, 46115277,
 31557088, 22917189, 24677288, 24039835, 24676366, 16032362, 17793529, 17153269,
 38432486, 21153763, 23393635, 16037076, 27710971, 27074338, 20995174, 23396204,
 20193482, 17157790, 19550231, 14751475, 17153832, 19070249, 16038080, 33391110,
 25875097, 22197835, 22195018, 21070221, 24590112, 18999456, 15952565, 18356361,
 17237769, 18359003, 15951169, 14832955, 16110295, 18350268, 21392354, 22030301,
 18353365, 15955257, 13550032, 18430405, 18434015, 17150260, 17154128, 27234036,
 23710639, 20194057, 21157900, 24198470, 20679613, 21158141, 22435065, 21318520,
 20197076, 67390501, 83715011, 51070497, 54590283, 58915129, 50275230, 52035340,
 263870051, -1,
      -1};
      long i;
      const long *t;
      GEN V=vecgroup_idxlist(L,32);
      long idxlist=vecsmall_pack(V,10,9967);
      long w=10000*svecgroup+idxlist; /*This is used as a hash value*/
      for(t=tab; *t!=-1; t++)
      {
        if (t[0]==n)
        {
          for(i=1; t[i] != -1; i++)
            if (t[i]==w) return i;
          switch(n)
          {
          case 64:
            switch(w)
            {
            case 4270003:
              return (scenter==439)? 2: 3;
            case 5870155:
              {
                const long good[]={8,9,0},bad[]={7,0};
                return indexgroupcentre(G,Z,good,bad)? 13: 14;
              }
            case 4270042:
              {
                const long good[]={13,0},bad[]={14,0};
                return indexgroupcentre(G,Z,good,bad)? 15: 16;
              }
            case 4430156:
              {
                const long good[]={18,20,0},bad[]={19,0};
                return indexgroupcentre(G,Z,good,bad)? 47: 48;
              }
            case 2510026:
              return scenter==1367? 50: 51;
            case 12190433:
              return scenter==47? 59: 70;
            case 16514475:
              {
                const long good[]={22,24,28,0},bad[]={23,25,27,30,0};
                return indexgroupcentre(G,Z,good,bad)? 61: 66;
              }
            case 10910433:
              {
                const long good[]={23,31,0},bad[]={25,26,29,30,33,0};
                return indexgroupcentre(G,Z,good,bad)? 63: 68;
              }
            case 14590443:
              {
                const long good[]={28,33,0},bad[]={30,34,0};
                return indexgroupcentre(G,Z,good,bad)? 77: 80;
              }
            case 3630046:
              {
                const long good[]={3,0},bad[]={12,16,0};
                if (scenter==695) return 26;
                return indexgroupcentre(G,Z,good,bad)? 27: 44;
              }
            }
            break;
          }
          return -1;
        }
        while (*t!=-1) t++;
      }
    }
    {
      const long tab[]={ 96, 316010002, 252010002, 707020000, 676160124,
    676170124, 87180027, 988190278, 892200028, 876030110, 876040110, 876120110,
    215111237, 503062153, 972141052, 972131052, 455091156, 167101154, 620160033,
    620170033, 908031033, 908121033, 908041033, 199101564, 7130153, 7140153,
    812150123, 247051165, 487091566, 812151024, 391071276, 103081274, 247111377,
    988180195, 892190205, 924190197, 828200207, 103050134, 679020464, 295091075,
    199070145, 391060235, 103101076, 7080146, 135111157, 295020044, 684030223,
    684040223, 908050274, 135060255, 7070285, 812080286, 71092475, 876102476,
    908112287, 684120223, 748130243, 748140243, 620150254, 492160043, 492170043,
    764180045, 700190477, 636200047, 963110003, 779050031, 935100032, 799110033,
    819210003, 791260032, 246270050, 723330003, 987340003, 651360031, 623380033,
    647263930, 839351534, 455321350, 178211335, 791244031, 322256848, 189340236,
    130316409, 599331360, 743244548, 935295937, 551333907, 189222029, 274255883,
    525275609, 82306043, 610289391, 82315641, 82307025, 647262487, 839353950,
    0/*455322385*/, 0/*455322385*/, 178233588, 791245051, 322256982, 130307015,
    658286619, 983297004, 983297037, 599333858, 631365165, 631376165, 535386399,
    66408676, 354390966, 871428265, 775411064, 631376407, 535386309, 114430028,
    823441008, 314398920, 74437993, 831420054, 42405827, 90439425, 799440830,
    847426805, 767410275, 815440314, 863429143, 487360134, 487371044, 66211564,
    66231664, 871295713, 66231764, 679242567, 125228724, 210253894, 18306803,
    546288536, 162390938, 919437378, 871401018, 162255761, 967304398, 967313318,
    413274329, 498283470, 498288163, 29345108, 967401139, 727449579, 679411219,
    775352619, 583261276, 919295225, 66312839, 423381047, 2437470, 759424560,
    711448550, 770222372, 109272382, 551210244, 258222592, 551230264, 295242430,
    647254411, 199262266, 482272602, 871283751, 423293752, 519303751, 519312662,
    71320222, 167332232, 226340245, 327352266, 167360274, 167372584, 103382587,
    647392595, 455406162, 263412616, 327428742, 487438955, 295440098, 358290331,
    622253358, 886280358, 322410312, 754400322, 394443122, 282440313, 354423123,
    522430323, 726220349, 990273529, 470450359, 742460359, 522470032, 198470031,
    282480353, 290490033, 274500353, 414470000, 614490000, 605473864, 664459790,
    723464091, 893482714, 675465704, 845486215, 184493728, 653478045, 941489155,
    605501588, 925482982, 264492577, 589502601, 312450472, 371466994, 285450492,
    989464902, 578470486, 770489139, 994490497, 546500507, 604460529, 65270050,
    684510049, 468510050, 134510562, 831510052, -1
        -1};
      long i;
      const long *t;
      GEN V=vecgroup_idxlist(L,48);
      long idx48=vecsmall_pack(V,10,9967);
      long idx32=vecgroup_idxlist(L,32)[1];
      long w=1000000*(svecgroup%997)+10000*idx32+idx48;
      /*This is used as a hash value*/
      for(t=tab; *t!=-1; t++)
      {
        if (t[0]==n)
        {
          for(i=1; t[i] != -1; i++)
            if (t[i]==w) return i;
          switch(n)
          {
          case 96:
            switch(w)
            {
            case 455322385:
              {
                const long good[]={37,40,0},bad[]={34,41,0};
                return indexgroupcentre(G,Z,good,bad)? 96: 97;
              }
            }
            break;
          }
          return -1;
        }
        while (*t!=-1) t++;
      }
    }
  }
  return 0;
}