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>