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

Annotation of OpenXM_contrib/pari/src/basemath/subgroup.c, Revision 1.1.1.1

1.1       maekawa     1: /* $Id: subgroup.c,v 1.1.1.1 1999/09/16 13:47:37 karim Exp $ */
                      2: #include "pari.h"
                      3: GEN hnf0(GEN x, long r);
                      4: void push_val(entree *ep, GEN a);
                      5: void pop_val(entree *ep);
                      6:
                      7: /* SUBGROUPS
                      8:  * Assume: G = Gp x I, with Gp a p-group and (|I|,p)=1, and I small.
                      9:  * Compute subgroups of I by recursive calls
                     10:  * Loop through subgroups Hp of Gp using Birkhoff's algorithm.
                     11:  * If (I is non trivial)
                     12:  *   lift Hp to G (mul by exponent of I)
                     13:  *   for each subgp of I, lift it to G (mult by exponent of Gp)
                     14:  *   consider the group generated by the two subgroups (concat)
                     15:  */
                     16: static long *powerlist, *mmu, *lam, *c, *maxc, *a, *maxa, **g, **maxg;
                     17: static GEN **H, subq, subqpart, hnfgroup;
                     18: static GEN BINMAT;
                     19: static long countsub, expoI;
                     20: static long *available, indexbound, lsubq, lsubqpart;
                     21: static char *gpch;
                     22: static entree *ep;
                     23: static void(*treatsub_fun)(GEN);
                     24: typedef struct slist {
                     25:   struct slist *next;
                     26:   long *data;
                     27: } slist;
                     28:
                     29: static slist *sublist;
                     30:
                     31: void
                     32: printtyp(long *typ)
                     33: {
                     34:   long i;
                     35:   for (i=1; i<=typ[0]; i++) fprintferr(" %ld ",typ[i]);
                     36:   fprintferr("\n");
                     37: }
                     38:
                     39: /* compute conjugate partition of typ */
                     40: static long*
                     41: conjugate(long *typ)
                     42: {
                     43:   long *t, i, k = typ[0], l, last;
                     44:
                     45:   if (!k) { t = new_chunk(1); t[0]=0; return t; }
                     46:   l = typ[1]; t = new_chunk(l+2);
                     47:   t[1] = k; last = k;
                     48:   for (i=2; i<=l; i++)
                     49:   {
                     50:     while (typ[last] < i) last--;
                     51:     t[i] = last;
                     52:   }
                     53:   t[i] = 0; t[0] = l;
                     54:   return t;
                     55: }
                     56:
                     57: static void
                     58: std_fun(GEN x)
                     59: {
                     60:   ep->value = (void*)x;
                     61:   lisseq(gpch); countsub++;
                     62: }
                     63:
                     64: void
                     65: addcell(GEN H)
                     66: {
                     67:   long *pt,i,j, k = 0, n = lg(H)-1;
                     68:   slist *cell = (slist*) gpmalloc(sizeof(slist) + n*(n+1)/2 * sizeof(long));
                     69:
                     70:   sublist->next = cell; cell->data = pt = (long*) (cell + 1);
                     71:   for (j=1; j<=n; j++)
                     72:     for(i=1; i<=j; i++) pt[k++] = itos(gcoeff(H,i,j));
                     73:   sublist = cell;
                     74: }
                     75:
                     76: static void
                     77: list_fun(GEN x)
                     78: {
                     79:   addcell(hnf(concatsp(hnfgroup,x))); countsub++;
                     80: }
                     81:
                     82: /* treat subgroup Hp (not in HNF, treatsub_fun should do it if desired) */
                     83: static void
                     84: treatsub(GEN Hp)
                     85: {
                     86:   long i;
                     87:   if (!subq) treatsub_fun(Hp);
                     88:   else
                     89:   { /* not a p group, add the trivial part */
                     90:     Hp = gmulsg(expoI,Hp); /* lift Hp to G */
                     91:     for (i=1; i<lsubqpart; i++)
                     92:       treatsub_fun(concatsp(Hp, (GEN)subqpart[i]));
                     93:   }
                     94: }
                     95:
                     96: /* assume t>0 and l>1 */
                     97: static void
                     98: dogroup()
                     99: {
                    100:   long av = avma,av1, e,i,j,k,r,n,t2,ind, t = mmu[0], l = lam[0];
                    101:
                    102:   t2 = (l==t)? t-1: t;
                    103:   n = t2 * l - (t2*(t2+1))/2; /* number of gamma_ij */
                    104:   for (i=1, r=t+1; ; i++)
                    105:   {
                    106:     if (available[i]) c[r++] = i;
                    107:     if (r > l) break;
                    108:   }
                    109:   if (DEBUGLEVEL>2) { fprintferr("    column selection:"); printtyp(c); }
                    110:   /* a/g and maxa/maxg access the same data indexed differently */
                    111:   for (ind=0,i=1; i<=t; ind+=(l-i),i++)
                    112:   {
                    113:     maxg[i] = maxa + (ind - (i+1)); /* only access maxg[i][i+1..l] */
                    114:     g[i] = a + (ind - (i+1));
                    115:     for (r=i+1; r<=l; r++)
                    116:       if (c[r] < c[i])             maxg[i][r] = powerlist[mmu[i]-mmu[r]-1];
                    117:       else if (lam[c[r]] < mmu[i]) maxg[i][r] = powerlist[lam[c[r]]-mmu[r]];
                    118:       else                         maxg[i][r] = powerlist[mmu[i]-mmu[r]];
                    119:   }
                    120:   av1=avma; a[n-1]=0; for (i=0; i<n-1; i++) a[i]=1;
                    121:   for(;;)
                    122:   {
                    123:     a[n-1]++;
                    124:     if (a[n-1] > maxa[n-1])
                    125:     {
                    126:       j=n-2; while (j>=0 && a[j]==maxa[j]) j--;
                    127:       if (j<0) { avma=av; return; }
                    128:       a[j]++; for (k=j+1; k<n; k++) a[k]=1;
                    129:     }
                    130:     for (i=1; i<=t; i++)
                    131:     {
                    132:       for (r=1; r<i; r++) affsi(0, H[i][c[r]]);
                    133:       affsi(powerlist[lam[c[r]]-mmu[r]], H[r][c[r]]);
                    134:       for (r=i+1; r<=l; r++)
                    135:       {
                    136:         if (c[r] < c[i])
                    137:           e = g[i][r]*powerlist[lam[c[r]]-mmu[i]+1];
                    138:         else
                    139:           if (lam[c[r]] < mmu[i]) e = g[i][r];
                    140:           else e = g[i][r]*powerlist[lam[c[r]]-mmu[i]];
                    141:         affsi(e, H[i][c[r]]);
                    142:       }
                    143:     }
                    144:     treatsub((GEN)H); avma=av1;
                    145:   }
                    146: }
                    147:
                    148: /* c[1],...,c[r-1] filled */
                    149: static void
                    150: loop(long r)
                    151: {
                    152:   long j;
                    153:
                    154:   if (r > mmu[0]) { dogroup(); return; }
                    155:
                    156:   if (r!=1 && (mmu[r-1] == mmu[r])) j = c[r-1]+1; else j = 1;
                    157:   for (  ; j<=maxc[r]; j++)
                    158:     if (available[j])
                    159:     {
                    160:       c[r] = j;  available[j] = 0;
                    161:       loop(r+1); available[j] = 1;
                    162:     }
                    163: }
                    164:
                    165: static void
                    166: dopsubtyp()
                    167: {
                    168:   long av = avma, i,r, l = lam[0], t = mmu[0];
                    169:
                    170:   if (!t)
                    171:   {
                    172:     GEN p1 = cgetg(2,t_MAT);
                    173:     p1[1] = (long)zerocol(l);
                    174:     treatsub(p1); avma=av; return;
                    175:   }
                    176:   if (l==1) /* imply t = 1 */
                    177:   {
                    178:     GEN p1 = gtomat(stoi(powerlist[lam[1]-mmu[1]]));
                    179:     treatsub(p1); avma=av; return;
                    180:   }
                    181:   c = new_chunk(l+1); c[0] = l;
                    182:   maxc = new_chunk(l+1);
                    183:   available = new_chunk(l+1);
                    184:   a  = new_chunk(l*(t+1));
                    185:   maxa=new_chunk(l*(t+1));
                    186:   g = (long**)new_chunk(t+1);
                    187:   maxg = (long**)new_chunk(t+1);
                    188:
                    189:   if (DEBUGLEVEL) { fprintferr("  subgroup:"); printtyp(mmu); }
                    190:   for (i=1; i<=t; i++)
                    191:   {
                    192:     for (r=1; r<=l; r++)
                    193:       if (mmu[i] > lam[r]) break;
                    194:     maxc[i] = r-1;
                    195:   }
                    196:   H = (GEN**)cgetg(t+1, t_MAT);
                    197:   for (i=1; i<=t; i++)
                    198:   {
                    199:     H[i] = (GEN*)cgetg(l+1, t_COL);
                    200:     for (r=1; r<=l; r++) H[i][r] = cgeti(3);
                    201:   }
                    202:   for (i=1; i<=l; i++) available[i]=1;
                    203:   for (i=1; i<=t; i++) c[i]=0;
                    204:   /* go through all column selections */
                    205:   loop(1); avma=av; return;
                    206: }
                    207:
                    208: static long
                    209: weight(long *typ)
                    210: {
                    211:   long i,w = 0;
                    212:   for (i=1; i<=typ[0]; i++) w += typ[i];
                    213:   return w;
                    214: }
                    215:
                    216: static long
                    217: dopsub(long p, long *gtyp, long *indexsubq)
                    218: {
                    219:   long w,i,j,k,n, wg, wmin = 0, count = 0;
                    220:
                    221:   if (DEBUGLEVEL) { fprintferr("\ngroup:"); printtyp(gtyp); }
                    222:   if (indexbound)
                    223:   {
                    224:     wg = weight(gtyp);
                    225:     wmin = (long) (wg - (log((double)indexbound) / log((double)p)));
                    226:     if (cmpis(gpuigs(stoi(p), wg - wmin), indexbound) > 0) wmin++;
                    227:   }
                    228:   lam = gtyp; n = lam[0]; mmu = new_chunk(n+1);
                    229:   mmu[1] = -1; for (i=2; i<=n; i++) mmu[i]=0;
                    230:   for(;;) /* go through all vectors mu_{i+1} <= mu_i <= lam_i */
                    231:   {
                    232:     mmu[1]++;
                    233:     if (mmu[1] > lam[1])
                    234:     {
                    235:       for (j=2; j<=n; j++)
                    236:         if (mmu[j] < lam[j] && mmu[j] < mmu[j-1]) break;
                    237:       if (j>n) return count;
                    238:       mmu[j]++; for (k=1; k<j; k++) mmu[k]=mmu[j];
                    239:     }
                    240:     for (j=1; j<=n; j++)
                    241:       if (!mmu[j]) break;
                    242:     mmu[0] = j-1; w = weight(mmu);
                    243:     if (w >= wmin)
                    244:     {
                    245:       GEN p1 = gun;
                    246:
                    247:       if (subq) /* G not a p-group */
                    248:       {
                    249:         if (indexbound)
                    250:         {
                    251:           long indexH = itos(gpuigs(stoi(p), wg - w));
                    252:           long bound = indexbound / indexH;
                    253:           subqpart = cgetg(lsubq, t_VEC);
                    254:           lsubqpart = 1;
                    255:           for (i=1; i<lsubq; i++)
                    256:             if (indexsubq[i] <= bound) subqpart[lsubqpart++] = subq[i];
                    257:         }
                    258:         else { subqpart = subq; lsubqpart = lsubq; }
                    259:       }
                    260:       if (DEBUGLEVEL)
                    261:       {
                    262:         long *lp = conjugate(lam);
                    263:         long *mp = conjugate(mmu);
                    264:
                    265:         if (DEBUGLEVEL > 3)
                    266:         {
                    267:           fprintferr("    lambda = "); printtyp(lam);
                    268:           fprintferr("    lambda' = "); printtyp(lp);
                    269:           fprintferr("    mu = "); printtyp(mmu);
                    270:           fprintferr("    mu' = "); printtyp(mp);
                    271:         }
                    272:         for (j=1; j<=mp[0]; j++)
                    273:         {
                    274:           p1 = mulii(p1, gpuigs(stoi(p), mp[j+1]*(lp[j]-mp[j])));
                    275:           p1 = mulii(p1, gcoeff(BINMAT, lp[j]-mp[j+1]+1, mp[j]-mp[j+1]+1));
                    276:         }
                    277:         fprintferr("  alpha_lambda(mu,p) = %Z\n",p1);
                    278:       }
                    279:       countsub = 0;
                    280:       dopsubtyp();
                    281:       count += countsub;
                    282:       if (DEBUGLEVEL)
                    283:       {
                    284:         fprintferr("  countsub = %ld\n", countsub);
                    285:         msgtimer("for this type");
                    286:         if (subq) p1 = mulis(p1,lsubqpart-1);
                    287:         if (cmpis(p1,countsub))
                    288:         {
                    289:           fprintferr("  alpha = %Z\n",p1);
                    290:           err(bugparier,"forsubgroup (alpha != countsub)");
                    291:         }
                    292:       }
                    293:     }
                    294:   }
                    295: }
                    296:
                    297: static GEN
                    298: expand_sub(GEN x, long n)
                    299: {
                    300:   long i,j, m = lg(x);
                    301:   GEN p = idmat(n-1), q,c;
                    302:
                    303:   for (i=1; i<m; i++)
                    304:   {
                    305:     q = (GEN)p[i]; c = (GEN)x[i];
                    306:     for (j=1; j<m; j++) q[j] = c[j];
                    307:     for (   ; j<n; j++) q[j] = zero;
                    308:   }
                    309:   return p;
                    310: }
                    311:
                    312: GEN matqpascal(long n, GEN q);
                    313:
                    314: static long
                    315: subgroup_engine(GEN cyc, long bound)
                    316: {
                    317:   long av=avma,i,j,k,imax,nbprim,count, n = lg(cyc);
                    318:   GEN gtyp,fa,junk,primlist,p,listgtyp,indexsubq = NULL;
                    319:   long oindexbound = indexbound;
                    320:   long oexpoI      = expoI;
                    321:   long *opowerlist = powerlist;
                    322:   GEN osubq        = subq;
                    323:   GEN oBINMAT      = BINMAT;
                    324:   long olsubq      = lsubq;
                    325:
                    326:   long *ommu=mmu, *olam=lam, *oc=c, *omaxc=maxc, *oa=a, *omaxa=maxa, **og=g, **omaxg=maxg;
                    327:   GEN **oH=H, osubqpart=subqpart;
                    328:   long ocountsub=countsub;
                    329:   long *oavailable=available, olsubqpart=lsubqpart;
                    330:
                    331:   if (typ(cyc) != t_VEC)
                    332:   {
                    333:     if (typ(cyc) != t_MAT) err(typeer,"forsubgroup");
                    334:     cyc = mattodiagonal(cyc);
                    335:   }
                    336:   for (i=1; i<n-1; i++)
                    337:     if (!divise((GEN)cyc[i], (GEN)cyc[i+1]))
                    338:       err(talker,"not a group in forsubgroup");
                    339:   if (n == 1 || gcmp1((GEN)cyc[1])) { treatsub(cyc); return 1; }
                    340:   if (!signe(cyc[1]))
                    341:     err(talker,"infinite group in forsubgroup");
                    342:   if (DEBUGLEVEL) timer2();
                    343:   indexbound = bound;
                    344:   fa = factor((GEN)cyc[1]); primlist = (GEN)fa[1];
                    345:   nbprim = lg(primlist);
                    346:   listgtyp = new_chunk(n); k = 0;
                    347:   for (i=1; i<nbprim; i++)
                    348:   {
                    349:     gtyp = new_chunk(n); p = (GEN)primlist[i];
                    350:     for (j=1; j<n; j++)
                    351:     {
                    352:       gtyp[j] = pvaluation((GEN)cyc[j], p, &junk);
                    353:       if (!gtyp[j]) break;
                    354:     }
                    355:     j--; gtyp[0] = j;
                    356:     if (j > k) { k = j; imax = i; }
                    357:     listgtyp[i] = (long)gtyp;
                    358:   }
                    359:   gtyp = (GEN)listgtyp[imax]; p = (GEN)primlist[imax];
                    360:   k = gtyp[1];
                    361:   powerlist = new_chunk(k+1); powerlist[0] = 1;
                    362:   powerlist[1] = itos(p);
                    363:   for (j=1; j<=k; j++) powerlist[j] = powerlist[1] * powerlist[j-1];
                    364:
                    365:   if (DEBUGLEVEL) BINMAT = matqpascal(gtyp[0]+1, p);
                    366:   if (nbprim == 2) subq = NULL;
                    367:   else
                    368:   { /* not a p-group */
                    369:     GEN cyc2 = dummycopy(cyc);
                    370:     GEN ohnfgroup = hnfgroup;
                    371:     for (i=1; i<n; i++)
                    372:     {
                    373:       cyc2[i] = ldivis((GEN)cyc2[i], powerlist[gtyp[i]]);
                    374:       if (gcmp1((GEN)cyc2[i])) break;
                    375:     }
                    376:     setlg(cyc2, i);
                    377:     if (is_bigint(cyc[1]))
                    378:       err(impl,"subgrouplist for large cyclic factors");
                    379:     expoI = itos((GEN)cyc2[1]);
                    380:     hnfgroup = diagonal(cyc2);
                    381:     subq = subgrouplist(cyc2, bound);
                    382:     hnfgroup = ohnfgroup;
                    383:     lsubq = lg(subq);
                    384:     for (i=1; i<lsubq; i++)
                    385:       subq[i] = (long)expand_sub((GEN)subq[i], n);
                    386:     if (indexbound)
                    387:     {
                    388:       indexsubq = new_chunk(lsubq);
                    389:       for (i=1; i<lsubq; i++)
                    390:         indexsubq[i] = itos(dethnf((GEN)subq[i]));
                    391:     }
                    392:     /* lift subgroups of I to G */
                    393:     for (i=1; i<lsubq; i++)
                    394:       subq[i] = lmulsg(powerlist[k],(GEN)subq[i]);
                    395:     if (DEBUGLEVEL>2)
                    396:     {
                    397:       fprintferr("(lifted) subgp of prime to %Z part:\n",p);
                    398:       outbeaut(subq);
                    399:     }
                    400:   }
                    401:   count = dopsub(powerlist[1],gtyp,indexsubq);
                    402:   if (DEBUGLEVEL) fprintferr("nb subgroup = %ld\n",count);
                    403:
                    404:   mmu=ommu; lam=olam; c=oc; maxc=omaxc; a=oa; maxa=omaxa; g=og; maxg=omaxg;
                    405:   H=oH; subqpart=osubqpart,
                    406:   countsub=ocountsub;
                    407:   available=oavailable; lsubqpart=olsubqpart;
                    408:
                    409:   indexbound = oindexbound;
                    410:   expoI    = oexpoI;
                    411:   powerlist = opowerlist;
                    412:   subq      = osubq;
                    413:   BINMAT    = oBINMAT;
                    414:   lsubq     = olsubq;
                    415:   avma=av; return count;
                    416: }
                    417:
                    418: void
                    419: forsubgroup(entree *oep, GEN cyc, long bound, char *och)
                    420: {
                    421:   entree *saveep = ep;
                    422:   char *savech = gpch;
                    423:   void(*savefun)(GEN) = treatsub_fun;
                    424:   long n, N = lg(cyc)-1;
                    425:
                    426:   treatsub_fun = std_fun;
                    427:   cyc = dummycopy(cyc);
                    428:   for (n = N; n > 1; n--) /* take care of trailing 1s */
                    429:     if (!gcmp1((GEN)cyc[n])) break;
                    430:   setlg(cyc, n+1);
                    431:   gpch = och;
                    432:   ep = oep;
                    433:   push_val(ep, gzero);
                    434:   (void)subgroup_engine(cyc,bound);
                    435:   pop_val(ep);
                    436:   treatsub_fun = savefun;
                    437:   gpch = savech;
                    438:   ep = saveep;
                    439: }
                    440:
                    441: GEN
                    442: subgrouplist(GEN cyc, long bound)
                    443: {
                    444:   void(*savefun)(GEN) = treatsub_fun;
                    445:   slist *olist = sublist, *list;
                    446:   long ii,i,j,k,nbsub,n, N = lg(cyc)-1, av = avma;
                    447:   GEN z,H;
                    448:   GEN ohnfgroup = hnfgroup;
                    449:
                    450:   sublist = list = (slist*) gpmalloc(sizeof(slist));
                    451:   treatsub_fun = list_fun;
                    452:   cyc = dummycopy(cyc);
                    453:   for (n = N; n > 1; n--) /* take care of trailing 1s */
                    454:     if (!gcmp1((GEN)cyc[n])) break;
                    455:   setlg(cyc, n+1);
                    456:   hnfgroup = diagonal(cyc);
                    457:   nbsub = subgroup_engine(cyc,bound);
                    458:   hnfgroup = ohnfgroup; avma = av;
                    459:   z = cgetg(nbsub+1,t_VEC); sublist = list;
                    460:   for (ii=1; ii<=nbsub; ii++)
                    461:   {
                    462:     list = sublist; sublist = list->next; free(list);
                    463:     H = cgetg(N+1,t_MAT); z[ii]=(long)H; k=0;
                    464:     for (j=1; j<=n; j++)
                    465:     {
                    466:       H[j] = lgetg(N+1, t_COL);
                    467:       for (i=1; i<=j; i++) coeff(H,i,j) = lstoi(sublist->data[k++]);
                    468:       for (   ; i<=N; i++) coeff(H,i,j) = zero;
                    469:     }
                    470:     for (   ; j<=N; j++)
                    471:     {
                    472:       H[j] = lgetg(N+1, t_COL);
                    473:       for (i=1; i<=N; i++) coeff(H,i,j) = (i==j)? un: zero;
                    474:     }
                    475:   }
                    476:   free(sublist); sublist = olist;
                    477:   treatsub_fun = savefun; return z;
                    478: }

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