[BACK]Return to subgroup.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / basemath

Annotation of OpenXM_contrib/pari-2.2/src/basemath/subgroup.c, Revision 1.2

1.2     ! noro        1: /* $Id: subgroup.c,v 1.25 2002/04/19 20:13:01 karim Exp $
1.1       noro        2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: #include "pari.h"
                     17: extern GEN hnf0(GEN x, long r);
                     18: void push_val(entree *ep, GEN a);
                     19: void pop_val(entree *ep);
                     20:
1.2     ! noro       21: typedef struct {
        !            22:   entree *ep;
        !            23:   char *s;
        !            24: } expr_t;
        !            25:
        !            26: typedef struct slist {
        !            27:   struct slist *next;
        !            28:   long *data;
        !            29: } slist;
        !            30:
        !            31: typedef struct {
        !            32:   GEN hnfgroup;
        !            33:   GEN listKer;
        !            34:   ulong count;
        !            35:   slist *list;
        !            36: } sublist_t;
        !            37:
        !            38: /* MAX: [G:H] <= bound, EXACT: [G:H] = bound, TYPE: type(H) = bound */
        !            39: enum { b_NONE, b_MAX, b_EXACT, b_TYPE };
        !            40:
1.1       noro       41: /* SUBGROUPS
1.2     ! noro       42:  * G = Gp x I, with Gp a p-Sylow (I assumed small).
1.1       noro       43:  * Compute subgroups of I by recursive calls
                     44:  * Loop through subgroups Hp of Gp using Birkhoff's algorithm.
                     45:  * If (I is non trivial)
                     46:  *   lift Hp to G (mul by exponent of I)
                     47:  *   for each subgp of I, lift it to G (mult by exponent of Gp)
                     48:  *   consider the group generated by the two subgroups (concat)
1.2     ! noro       49:  *
        !            50:  * type(H) = mu --> H = Z/p^mu[1] x ... x Z/p^mu[len(mu)] */
        !            51: typedef struct subgp_iter {
        !            52:   long *M, *L; /* mu = p-subgroup type, lambda = p-group type */
        !            53:   long *powlist; /* [i] = p^i, i = 0.. */
        !            54:   long *c, *maxc, *a, *maxa, **g, **maxg;
        !            55:   long *available;
        !            56:   GEN **H; /* p-subgroup of type mu, in matrix form */
        !            57:   GEN cyc; /* cyclic factors of G */
        !            58:   GEN subq;/* subgrouplist(I) */
        !            59:   GEN subqpart; /* J in subq s.t [I:J][Gp:Hp] <= indexbound */
        !            60:   GEN bound; /* if != NULL, impose a "bound" on [G:H] (see boundtype) */
        !            61:   int boundtype;
        !            62:   long countsub; /* number of subgroups of type M (so far) */
        !            63:   long count; /* number of p-subgroups so far [updated when M completed] */
        !            64:   GEN expoI; /* exponent of I */
        !            65:   void(*fun)(struct subgp_iter *, GEN); /* applied to each subgroup */
        !            66:   void *fundata; /* for fun */
        !            67: } subgp_iter;
1.1       noro       68:
1.2     ! noro       69: #define len(x)      (x)[0]
        !            70: #define setlen(x,l) len(x)=(l)
1.1       noro       71:
1.2     ! noro       72: void
        !            73: printtyp(const long *typ)
1.1       noro       74: {
1.2     ! noro       75:   long i, l = len(typ);
        !            76:   for (i=1; i<=l; i++) fprintferr(" %ld ",typ[i]);
1.1       noro       77:   fprintferr("\n");
                     78: }
                     79:
                     80: /* compute conjugate partition of typ */
                     81: static long*
                     82: conjugate(long *typ)
                     83: {
1.2     ! noro       84:   long *t, i, k = len(typ), l, last;
1.1       noro       85:
1.2     ! noro       86:   if (!k) { t = new_chunk(1); setlen(t,0); return t; }
1.1       noro       87:   l = typ[1]; t = new_chunk(l+2);
                     88:   t[1] = k; last = k;
                     89:   for (i=2; i<=l; i++)
                     90:   {
                     91:     while (typ[last] < i) last--;
                     92:     t[i] = last;
                     93:   }
1.2     ! noro       94:   t[i] = 0; setlen(t,l);
1.1       noro       95:   return t;
                     96: }
1.2     ! noro       97: /* --- subgp_iter 'fun' associated to forsubgroup -------------- */
1.1       noro       98: static void
1.2     ! noro       99: std_fun(subgp_iter *T, GEN x)
1.1       noro      100: {
1.2     ! noro      101:   expr_t *E = (expr_t *)T->fundata;
        !           102:   E->ep->value = (void*)x;
        !           103:   (void)lisseq(E->s); T->countsub++;
1.1       noro      104: }
1.2     ! noro      105: /* ----subgp_iter 'fun' associated to subgrouplist ------------- */
        !           106: static void
        !           107: addcell(sublist_t *S, GEN H)
1.1       noro      108: {
                    109:   long *pt,i,j, k = 0, n = lg(H)-1;
                    110:   slist *cell = (slist*) gpmalloc(sizeof(slist) + n*(n+1)/2 * sizeof(long));
                    111:
1.2     ! noro      112:   S->list->next = cell; cell->data = pt = (long*) (cell + 1);
1.1       noro      113:   for (j=1; j<=n; j++)
                    114:     for(i=1; i<=j; i++) pt[k++] = itos(gcoeff(H,i,j));
1.2     ! noro      115:   S->list = cell;
        !           116:   S->count++;
        !           117: }
        !           118:
        !           119: extern int hnfdivide(GEN A, GEN B);
        !           120:
        !           121: /* 1 if h^(-1)*list[i] integral for some i, 0 otherwise */
        !           122: static int
        !           123: hnflistdivise(GEN list,GEN h)
        !           124: {
        !           125:   long i, n = lg(list);
        !           126:   for (i=1; i<n; i++)
        !           127:     if (hnfdivide(h, (GEN)list[i])) break;
        !           128:   return i < n;
1.1       noro      129: }
                    130:
                    131: static void
1.2     ! noro      132: list_fun(subgp_iter *T, GEN x)
1.1       noro      133: {
1.2     ! noro      134:   sublist_t *S = (sublist_t*)T->fundata;
        !           135:   GEN H = hnf(concatsp(S->hnfgroup,x));
        !           136:   if (S->listKer && hnflistdivise(S->listKer, H)) return; /* test conductor */
        !           137:   addcell(S, H); T->countsub++;
1.1       noro      138: }
1.2     ! noro      139: /* -------------------------------------------------------------- */
1.1       noro      140:
1.2     ! noro      141: /* treat subgroup Hp (not in HNF, T->fun should do it if desired) */
1.1       noro      142: static void
1.2     ! noro      143: treatsub(subgp_iter *T, GEN H)
1.1       noro      144: {
                    145:   long i;
1.2     ! noro      146:   if (!T->subq) T->fun(T, H);
1.1       noro      147:   else
                    148:   { /* not a p group, add the trivial part */
1.2     ! noro      149:     GEN Hp = gmul(T->expoI, H); /* lift H to G */
        !           150:     long l = lg(T->subqpart);
        !           151:     for (i=1; i<l; i++)
        !           152:       T->fun(T, concatsp(Hp, (GEN)T->subqpart[i]));
1.1       noro      153:   }
                    154: }
                    155:
                    156: /* assume t>0 and l>1 */
                    157: static void
1.2     ! noro      158: dogroup(subgp_iter *T)
1.1       noro      159: {
1.2     ! noro      160:   const long *powlist = T->powlist;
        !           161:   long *M = T->M;
        !           162:   long *L = T->L;
        !           163:   long *c = T->c;
        !           164:   long  *a = T->a,  *maxa = T->maxa;
        !           165:   long **g = T->g, **maxg = T->maxg;
        !           166:   GEN **H = T->H;
        !           167:   gpmem_t av = avma;
        !           168:   long e,i,j,k,r,n,t2,ind, t = len(M), l = len(L);
1.1       noro      169:
                    170:   t2 = (l==t)? t-1: t;
                    171:   n = t2 * l - (t2*(t2+1))/2; /* number of gamma_ij */
                    172:   for (i=1, r=t+1; ; i++)
                    173:   {
1.2     ! noro      174:     if (T->available[i]) c[r++] = i;
1.1       noro      175:     if (r > l) break;
                    176:   }
                    177:   if (DEBUGLEVEL>2) { fprintferr("    column selection:"); printtyp(c); }
                    178:   /* a/g and maxa/maxg access the same data indexed differently */
                    179:   for (ind=0,i=1; i<=t; ind+=(l-i),i++)
                    180:   {
                    181:     maxg[i] = maxa + (ind - (i+1)); /* only access maxg[i][i+1..l] */
                    182:     g[i] = a + (ind - (i+1));
                    183:     for (r=i+1; r<=l; r++)
1.2     ! noro      184:       if (c[r] < c[i])         maxg[i][r] = powlist[M[i]-M[r]-1];
        !           185:       else if (L[c[r]] < M[i]) maxg[i][r] = powlist[L[c[r]]-M[r]];
        !           186:       else                     maxg[i][r] = powlist[M[i]-M[r]];
1.1       noro      187:   }
1.2     ! noro      188:   av = avma; a[n-1]=0; for (i=0; i<n-1; i++) a[i]=1;
1.1       noro      189:   for(;;)
                    190:   {
                    191:     a[n-1]++;
                    192:     if (a[n-1] > maxa[n-1])
                    193:     {
                    194:       j=n-2; while (j>=0 && a[j]==maxa[j]) j--;
1.2     ! noro      195:       if (j < 0) { avma = av; return; }
        !           196:
1.1       noro      197:       a[j]++; for (k=j+1; k<n; k++) a[k]=1;
                    198:     }
                    199:     for (i=1; i<=t; i++)
                    200:     {
                    201:       for (r=1; r<i; r++) affsi(0, H[i][c[r]]);
1.2     ! noro      202:       affsi(powlist[L[c[r]] - M[r]], H[r][c[r]]);
1.1       noro      203:       for (r=i+1; r<=l; r++)
                    204:       {
1.2     ! noro      205:         if (c[r] < c[i])
        !           206:           e = g[i][r] * powlist[L[c[r]] - M[i]+1];
1.1       noro      207:         else
1.2     ! noro      208:           if (L[c[r]] < M[i]) e = g[i][r];
        !           209:           else e = g[i][r] * powlist[L[c[r]] - M[i]];
1.1       noro      210:         affsi(e, H[i][c[r]]);
                    211:       }
                    212:     }
1.2     ! noro      213:     treatsub(T, (GEN)H); avma = av;
1.1       noro      214:   }
                    215: }
                    216:
1.2     ! noro      217: /* T->c[1],...,T->c[r-1] filled */
1.1       noro      218: static void
1.2     ! noro      219: loop(subgp_iter *T, long r)
1.1       noro      220: {
                    221:   long j;
                    222:
1.2     ! noro      223:   if (r > len(T->M)) { dogroup(T); return; }
1.1       noro      224:
1.2     ! noro      225:   if (r!=1 && (T->M[r-1] == T->M[r])) j = T->c[r-1]+1; else j = 1;
        !           226:   for (  ; j<=T->maxc[r]; j++)
        !           227:     if (T->available[j])
1.1       noro      228:     {
1.2     ! noro      229:       T->c[r] = j;  T->available[j] = 0;
        !           230:       loop(T, r+1); T->available[j] = 1;
1.1       noro      231:     }
                    232: }
                    233:
                    234: static void
1.2     ! noro      235: dopsubtyp(subgp_iter *T)
1.1       noro      236: {
1.2     ! noro      237:   gpmem_t av = avma;
        !           238:   long i,r, l = len(T->L), t = len(T->M);
1.1       noro      239:
                    240:   if (!t)
                    241:   {
                    242:     GEN p1 = cgetg(2,t_MAT);
1.2     ! noro      243:     p1[1] = (long)zerocol(l);
        !           244:     treatsub(T, p1); avma = av; return;
1.1       noro      245:   }
                    246:   if (l==1) /* imply t = 1 */
                    247:   {
1.2     ! noro      248:     GEN p1 = gtomat(stoi(T->powlist[T->L[1]-T->M[1]]));
        !           249:     treatsub(T, p1); avma = av; return;
1.1       noro      250:   }
1.2     ! noro      251:   T->c         = new_chunk(l+1); setlen(T->c, l);
        !           252:   T->maxc      = new_chunk(l+1);
        !           253:   T->available = new_chunk(l+1);
        !           254:   T->a   = new_chunk(l*(t+1));
        !           255:   T->maxa= new_chunk(l*(t+1));
        !           256:   T->g    = (long**)new_chunk(t+1);
        !           257:   T->maxg = (long**)new_chunk(t+1);
1.1       noro      258:
1.2     ! noro      259:   if (DEBUGLEVEL) { fprintferr("  subgroup:"); printtyp(T->M); }
1.1       noro      260:   for (i=1; i<=t; i++)
                    261:   {
                    262:     for (r=1; r<=l; r++)
1.2     ! noro      263:       if (T->M[i] > T->L[r]) break;
        !           264:     T->maxc[i] = r-1;
1.1       noro      265:   }
1.2     ! noro      266:   T->H = (GEN**)cgetg(t+1, t_MAT);
1.1       noro      267:   for (i=1; i<=t; i++)
                    268:   {
1.2     ! noro      269:     T->H[i] = (GEN*)cgetg(l+1, t_COL);
        !           270:     for (r=1; r<=l; r++) T->H[i][r] = cgeti(3);
1.1       noro      271:   }
1.2     ! noro      272:   for (i=1; i<=l; i++) T->available[i]=1;
        !           273:   for (i=1; i<=t; i++) T->c[i]=0;
1.1       noro      274:   /* go through all column selections */
1.2     ! noro      275:   loop(T, 1); avma = av; return;
1.1       noro      276: }
                    277:
                    278: static long
                    279: weight(long *typ)
                    280: {
1.2     ! noro      281:   long i, l = len(typ), w = 0;
        !           282:   for (i=1; i<=l; i++) w += typ[i];
1.1       noro      283:   return w;
                    284: }
                    285:
1.2     ! noro      286: static void
        !           287: dopsub(subgp_iter *T, GEN p, GEN indexsubq)
1.1       noro      288: {
1.2     ! noro      289:   long *M, *L = T->L;
        !           290:   long w,i,j,k, wG = weight(L), wmin = 0, wmax = wG, n = len(L);
1.1       noro      291:
1.2     ! noro      292:   if (DEBUGLEVEL) { fprintferr("\ngroup:"); printtyp(L); }
        !           293:   T->count = 0;
        !           294:   switch(T->boundtype)
        !           295:   {
        !           296:   case b_MAX: /* upper bound */
        !           297:     wmin = (long) (wG - (log(gtodouble(T->bound)) / log(gtodouble(p))));
        !           298:     if (cmpii(gpowgs(p, wG - wmin), T->bound) > 0) wmin++;
        !           299:     break;
        !           300:   case b_EXACT: /* exact value */
        !           301:     wmin = wmax = wG - ggval(T->bound, p);
        !           302:     break;
1.1       noro      303:   }
1.2     ! noro      304:   T->M = M = new_chunk(n+1);
        !           305:   M[1] = -1; for (i=2; i<=n; i++) M[i]=0;
1.1       noro      306:   for(;;) /* go through all vectors mu_{i+1} <= mu_i <= lam_i */
                    307:   {
1.2     ! noro      308:     M[1]++;
        !           309:     if (M[1] > L[1])
1.1       noro      310:     {
                    311:       for (j=2; j<=n; j++)
1.2     ! noro      312:         if (M[j] < L[j] && M[j] < M[j-1]) break;
        !           313:       if (j > n) return;
        !           314:
        !           315:       M[j]++; for (k=1; k<j; k++) M[k]=M[j];
1.1       noro      316:     }
                    317:     for (j=1; j<=n; j++)
1.2     ! noro      318:       if (!M[j]) break;
        !           319:     setlen(M, j-1); w = weight(M);
        !           320:     if (w >= wmin && w <= wmax)
        !           321:     {
1.1       noro      322:       GEN p1 = gun;
                    323:
1.2     ! noro      324:       if (T->subq) /* G not a p-group */
1.1       noro      325:       {
1.2     ! noro      326:         if (T->bound)
1.1       noro      327:         {
1.2     ! noro      328:           GEN indexH = gpowgs(p, wG - w);
        !           329:           GEN B = divii(T->bound, indexH);
        !           330:           long k, l = lg(T->subq);
        !           331:           T->subqpart = cgetg(l, t_VEC);
        !           332:           k = 1;
        !           333:           for (i=1; i<l; i++)
        !           334:             if (cmpii((GEN)indexsubq[i], B) <= 0)
        !           335:               T->subqpart[k++] = T->subq[i];
        !           336:           setlg(T->subqpart, k);
1.1       noro      337:         }
1.2     ! noro      338:         else T->subqpart = T->subq;
1.1       noro      339:       }
                    340:       if (DEBUGLEVEL)
                    341:       {
1.2     ! noro      342:         long *Lp = conjugate(L);
        !           343:         long *Mp = conjugate(M);
        !           344:         GEN BINMAT = matqpascal(len(L)+1, p);
1.1       noro      345:
                    346:         if (DEBUGLEVEL > 3)
                    347:         {
1.2     ! noro      348:           fprintferr("    lambda = "); printtyp(L);
        !           349:           fprintferr("    lambda'= "); printtyp(Lp);
        !           350:           fprintferr("    mu = "); printtyp(M);
        !           351:           fprintferr("    mu'= "); printtyp(Mp);
1.1       noro      352:         }
1.2     ! noro      353:         for (j=1; j<=len(Mp); j++)
1.1       noro      354:         {
1.2     ! noro      355:           p1 = mulii(p1, gpuigs(p, Mp[j+1]*(Lp[j]-Mp[j])));
        !           356:           p1 = mulii(p1, gcoeff(BINMAT, Lp[j]-Mp[j+1]+1, Mp[j]-Mp[j+1]+1));
1.1       noro      357:         }
                    358:         fprintferr("  alpha_lambda(mu,p) = %Z\n",p1);
                    359:       }
1.2     ! noro      360:       T->countsub = 0;
        !           361:
        !           362:       dopsubtyp(T);
        !           363:
        !           364:       T->count += T->countsub;
1.1       noro      365:       if (DEBUGLEVEL)
                    366:       {
1.2     ! noro      367:         fprintferr("  countsub = %ld\n", T->countsub);
1.1       noro      368:         msgtimer("for this type");
1.2     ! noro      369:         if (T->fun != list_fun || !((sublist_t*)(T->fundata))->listKer)
1.1       noro      370:         {
1.2     ! noro      371:           if (T->subq) p1 = mulis(p1,lg(T->subqpart)-1);
        !           372:           if (cmpis(p1,T->countsub))
        !           373:           {
        !           374:             fprintferr("  alpha = %Z\n",p1);
        !           375:             err(bugparier,"forsubgroup (alpha != countsub)");
        !           376:           }
1.1       noro      377:         }
                    378:       }
                    379:     }
                    380:   }
                    381: }
                    382:
1.2     ! noro      383: void
        !           384: parse_bound(subgp_iter *T)
        !           385: {
        !           386:   GEN b, B = T->bound;
        !           387:   if (!B) { T->boundtype = b_NONE; return; }
        !           388:   switch(typ(B))
        !           389:   {
        !           390:   case t_INT: /* upper bound */
        !           391:     T->boundtype = b_MAX;
        !           392:     break;
        !           393:   case t_VEC: /* exact value */
        !           394:     b = (GEN)B[1];
        !           395:     if (lg(B) != 2 || typ(b) != t_INT) err(typeer,"subgroup");
        !           396:     T->boundtype = b_EXACT;
        !           397:     T->bound = b;
        !           398:     break;
        !           399:   case t_COL: /* exact type */
        !           400:     if (lg(B) > len(T->L)+1) err(typeer,"subgroup");
        !           401:     err(impl,"exact type in subgrouplist");
        !           402:     T->boundtype = b_TYPE;
        !           403:     break;
        !           404:   default: err(typeer,"subgroup");
        !           405:   }
        !           406:   if (signe(T->bound) <= 0)
        !           407:     err(talker,"subgroup: index bound must be positive");
        !           408: }
        !           409:
1.1       noro      410: static GEN
                    411: expand_sub(GEN x, long n)
                    412: {
                    413:   long i,j, m = lg(x);
                    414:   GEN p = idmat(n-1), q,c;
                    415:
                    416:   for (i=1; i<m; i++)
                    417:   {
                    418:     q = (GEN)p[i]; c = (GEN)x[i];
                    419:     for (j=1; j<m; j++) q[j] = c[j];
                    420:     for (   ; j<n; j++) q[j] = zero;
                    421:   }
                    422:   return p;
                    423: }
                    424:
                    425: extern GEN matqpascal(long n, GEN q);
1.2     ! noro      426: static GEN subgrouplist_i(GEN cyc, GEN bound, GEN expoI, GEN listKer);
        !           427:
        !           428: static GEN
        !           429: init_powlist(long k, long p)
        !           430: {
        !           431:   GEN z = new_chunk(k+1);
        !           432:   long i;
        !           433:   z[0] = 1; z[1] = (long)p;
        !           434:   for (i=1; i<=k; i++)
        !           435:   {
        !           436:     GEN t = muluu(p, z[i-1]);
        !           437:     z[i] = itos(t);
        !           438:   }
        !           439:   return z;
        !           440: }
1.1       noro      441:
1.2     ! noro      442: static void
        !           443: subgroup_engine(subgp_iter *T)
1.1       noro      444: {
1.2     ! noro      445:   gpmem_t av = avma;
        !           446:   GEN B,L,fa,junk,primlist,p,listL,indexsubq = NULL;
        !           447:   GEN cyc = T->cyc;
        !           448:   long i,j,k,imax,nbprim, n = lg(cyc);
        !           449:
        !           450:   if (typ(cyc) != t_VEC)
1.1       noro      451:   {
                    452:     if (typ(cyc) != t_MAT) err(typeer,"forsubgroup");
                    453:     cyc = mattodiagonal(cyc);
                    454:   }
                    455:   for (i=1; i<n-1; i++)
                    456:     if (!divise((GEN)cyc[i], (GEN)cyc[i+1]))
                    457:       err(talker,"not a group in forsubgroup");
1.2     ! noro      458:   if (n == 1) { T->fun(T, cyc); return; }
1.1       noro      459:   if (!signe(cyc[1]))
                    460:     err(talker,"infinite group in forsubgroup");
1.2     ! noro      461:   if (DEBUGLEVEL) (void)timer2();
1.1       noro      462:   fa = factor((GEN)cyc[1]); primlist = (GEN)fa[1];
                    463:   nbprim = lg(primlist);
1.2     ! noro      464:   listL = new_chunk(n); imax = k = 0;
1.1       noro      465:   for (i=1; i<nbprim; i++)
                    466:   {
1.2     ! noro      467:     L = new_chunk(n); p = (GEN)primlist[i];
1.1       noro      468:     for (j=1; j<n; j++)
                    469:     {
1.2     ! noro      470:       L[j] = pvaluation((GEN)cyc[j], p, &junk);
        !           471:       if (!L[j]) break;
1.1       noro      472:     }
1.2     ! noro      473:     j--; setlen(L, j);
1.1       noro      474:     if (j > k) { k = j; imax = i; }
1.2     ! noro      475:     listL[i] = (long)L;
1.1       noro      476:   }
1.2     ! noro      477:   L = (GEN)listL[imax]; p = (GEN)primlist[imax];
        !           478:   k = L[1];
        !           479:   T->L = L;
        !           480:   T->powlist = init_powlist(k, itos(p));
        !           481:   B = T->bound;
        !           482:   parse_bound(T);
1.1       noro      483:
1.2     ! noro      484:   if (nbprim == 2)
        !           485:   {
        !           486:     T->subq = NULL;
        !           487:     if (T->boundtype == b_EXACT)
        !           488:     {
        !           489:       (void)pvaluation(T->bound,p,&B);
        !           490:       if (!gcmp1(B)) { avma = av; return; }
        !           491:     }
        !           492:   }
1.1       noro      493:   else
                    494:   { /* not a p-group */
1.2     ! noro      495:     GEN cycI = dummycopy(cyc);
        !           496:     long lsubq;
1.1       noro      497:     for (i=1; i<n; i++)
                    498:     {
1.2     ! noro      499:       cycI[i] = ldivis((GEN)cycI[i], T->powlist[L[i]]);
        !           500:       if (gcmp1((GEN)cycI[i])) break;
1.1       noro      501:     }
1.2     ! noro      502:     setlg(cycI, i); /* cyclic factors of I */
        !           503:     if (T->boundtype == b_EXACT)
1.1       noro      504:     {
1.2     ! noro      505:       (void)pvaluation(T->bound,p,&B);
        !           506:       B = _vec(B);
        !           507:     }
        !           508:     T->expoI = (GEN)cycI[1];
        !           509:     T->subq = subgrouplist_i(cycI, B, T->expoI, NULL);
        !           510:
        !           511:     lsubq = lg(T->subq);
        !           512:     for (i=1; i<lsubq; i++)
        !           513:       T->subq[i] = (long)expand_sub((GEN)T->subq[i], n);
        !           514:     if (T->bound)
        !           515:     {
        !           516:       indexsubq = cgetg(lsubq,t_VEC);
1.1       noro      517:       for (i=1; i<lsubq; i++)
1.2     ! noro      518:         indexsubq[i] = (long)dethnf_i((GEN)T->subq[i]);
1.1       noro      519:     }
                    520:     /* lift subgroups of I to G */
1.2     ! noro      521:     for (i=1; i<lsubq; i++)
        !           522:       T->subq[i] = lmulsg(T->powlist[k],(GEN)T->subq[i]);
1.1       noro      523:     if (DEBUGLEVEL>2)
                    524:     {
                    525:       fprintferr("(lifted) subgp of prime to %Z part:\n",p);
1.2     ! noro      526:       outbeaut(T->subq);
1.1       noro      527:     }
                    528:   }
1.2     ! noro      529:   dopsub(T, p,indexsubq);
        !           530:   if (DEBUGLEVEL) fprintferr("nb subgroup = %ld\n",T->count);
        !           531:   avma = av;
1.1       noro      532: }
                    533:
                    534: static GEN
1.2     ! noro      535: get_snf(GEN x, long *N)
1.1       noro      536: {
                    537:   GEN cyc;
                    538:   long n;
                    539:   switch(typ(x))
                    540:   {
                    541:     case t_MAT:
                    542:       if (!isdiagonal(x)) return NULL;
                    543:       cyc = mattodiagonal_i(x); break;
1.2     ! noro      544:     case t_VEC: if (lg(x) == 4 && typ(x[2]) == t_VEC) x = (GEN)x[2];
1.1       noro      545:     case t_COL: cyc = dummycopy(x); break;
                    546:     default: return NULL;
                    547:   }
1.2     ! noro      548:   *N = lg(cyc)-1;
        !           549:   for (n = *N; n > 0; n--) /* take care of trailing 1s */
1.1       noro      550:   {
                    551:     GEN c = (GEN)cyc[n];
                    552:     if (typ(c) != t_INT) return NULL;
                    553:     if (!gcmp1(c)) break;
                    554:   }
                    555:   setlg(cyc, n+1);
                    556:   for ( ; n > 0; n--)
                    557:   {
                    558:     GEN c = (GEN)cyc[n];
                    559:     if (typ(c) != t_INT) return NULL;
                    560:   }
                    561:   return cyc;
                    562: }
                    563:
                    564: void
1.2     ! noro      565: forsubgroup(entree *ep, GEN cyc, GEN bound, char *ch)
1.1       noro      566: {
1.2     ! noro      567:   subgp_iter T;
        !           568:   expr_t E;
        !           569:   long N;
1.1       noro      570:
1.2     ! noro      571:   T.fun = &std_fun;
        !           572:   cyc = get_snf(cyc,&N);
1.1       noro      573:   if (!cyc) err(typeer,"forsubgroup");
1.2     ! noro      574:   T.bound = bound;
        !           575:   T.cyc = cyc;
        !           576:   E.s = ch;
        !           577:   E.ep= ep; T.fundata = (void*)&E;
1.1       noro      578:   push_val(ep, gzero);
1.2     ! noro      579:
        !           580:   subgroup_engine(&T);
        !           581:
1.1       noro      582:   pop_val(ep);
                    583: }
                    584:
1.2     ! noro      585: static GEN
        !           586: subgrouplist_i(GEN cyc, GEN bound, GEN expoI, GEN listKer)
1.1       noro      587: {
1.2     ! noro      588:   gpmem_t av = avma;
        !           589:   subgp_iter T;
        !           590:   sublist_t S;
        !           591:   slist *list, *sublist;
        !           592:   long ii,i,j,k,nbsub,n,N;
1.1       noro      593:   GEN z,H;
                    594:
1.2     ! noro      595:   cyc = get_snf(cyc, &N);
1.1       noro      596:   if (!cyc) err(typeer,"subgrouplist");
1.2     ! noro      597:   n = lg(cyc)-1; /* not necessarily = N */
        !           598:
        !           599:   S.list = sublist = (slist*) gpmalloc(sizeof(slist));
        !           600:   S.hnfgroup = diagonal(cyc);
        !           601:   S.listKer = listKer;
        !           602:   S.count = 0;
        !           603:   T.fun = &list_fun;
        !           604:   T.fundata = (void*)&S;
        !           605:
        !           606:   T.cyc = cyc;
        !           607:   T.bound = bound;
        !           608:   T.expoI = expoI;
        !           609:
        !           610:   subgroup_engine(&T);
        !           611:
        !           612:   nbsub = S.count;
        !           613:   avma = av;
        !           614:   z = cgetg(nbsub+1,t_VEC);
1.1       noro      615:   for (ii=1; ii<=nbsub; ii++)
                    616:   {
                    617:     list = sublist; sublist = list->next; free(list);
                    618:     H = cgetg(N+1,t_MAT); z[ii]=(long)H; k=0;
                    619:     for (j=1; j<=n; j++)
                    620:     {
                    621:       H[j] = lgetg(N+1, t_COL);
                    622:       for (i=1; i<=j; i++) coeff(H,i,j) = lstoi(sublist->data[k++]);
                    623:       for (   ; i<=N; i++) coeff(H,i,j) = zero;
                    624:     }
                    625:     for (   ; j<=N; j++)
                    626:     {
                    627:       H[j] = lgetg(N+1, t_COL);
                    628:       for (i=1; i<=N; i++) coeff(H,i,j) = (i==j)? un: zero;
                    629:     }
                    630:   }
1.2     ! noro      631:   free(sublist); return z;
        !           632: }
        !           633:
        !           634: GEN
        !           635: subgrouplist(GEN cyc, GEN bound)
        !           636: {
        !           637:   return subgrouplist_i(cyc,bound,NULL,NULL);
        !           638: }
        !           639:
        !           640: GEN
        !           641: subgroupcondlist(GEN cyc, GEN bound, GEN listKer)
        !           642: {
        !           643:   return subgrouplist_i(cyc,bound,NULL,listKer);
1.1       noro      644: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>