=================================================================== RCS file: /home/cvs/OpenXM_contrib/pari-2.2/src/basemath/Attic/subgroup.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -p -r1.1 -r1.2 --- OpenXM_contrib/pari-2.2/src/basemath/Attic/subgroup.c 2001/10/02 11:17:05 1.1 +++ OpenXM_contrib/pari-2.2/src/basemath/Attic/subgroup.c 2002/09/11 07:26:52 1.2 @@ -1,4 +1,4 @@ -/* $Id: subgroup.c,v 1.1 2001/10/02 11:17:05 noro Exp $ +/* $Id: subgroup.c,v 1.2 2002/09/11 07:26:52 noro Exp $ Copyright (C) 2000 The PARI group. @@ -18,35 +18,62 @@ extern GEN hnf0(GEN x, long r); void push_val(entree *ep, GEN a); void pop_val(entree *ep); +typedef struct { + entree *ep; + char *s; +} expr_t; + +typedef struct slist { + struct slist *next; + long *data; +} slist; + +typedef struct { + GEN hnfgroup; + GEN listKer; + ulong count; + slist *list; +} sublist_t; + +/* MAX: [G:H] <= bound, EXACT: [G:H] = bound, TYPE: type(H) = bound */ +enum { b_NONE, b_MAX, b_EXACT, b_TYPE }; + /* SUBGROUPS - * Assume: G = Gp x I, with Gp a p-group and (|I|,p)=1, and I small. + * G = Gp x I, with Gp a p-Sylow (I assumed small). * Compute subgroups of I by recursive calls * Loop through subgroups Hp of Gp using Birkhoff's algorithm. * If (I is non trivial) * lift Hp to G (mul by exponent of I) * for each subgp of I, lift it to G (mult by exponent of Gp) * consider the group generated by the two subgroups (concat) - */ -static long *powerlist, *mmu, *lam, *c, *maxc, *a, *maxa, **g, **maxg; -static GEN **H, subq, subqpart, hnfgroup; -static GEN BINMAT; -static long countsub, expoI; -static long *available, indexbound, lsubq, lsubqpart; -static char *gpch; -static entree *ep; -static void(*treatsub_fun)(GEN); -typedef struct slist { - struct slist *next; - long *data; -} slist; + * + * type(H) = mu --> H = Z/p^mu[1] x ... x Z/p^mu[len(mu)] */ +typedef struct subgp_iter { + long *M, *L; /* mu = p-subgroup type, lambda = p-group type */ + long *powlist; /* [i] = p^i, i = 0.. */ + long *c, *maxc, *a, *maxa, **g, **maxg; + long *available; + GEN **H; /* p-subgroup of type mu, in matrix form */ + GEN cyc; /* cyclic factors of G */ + GEN subq;/* subgrouplist(I) */ + GEN subqpart; /* J in subq s.t [I:J][Gp:Hp] <= indexbound */ + GEN bound; /* if != NULL, impose a "bound" on [G:H] (see boundtype) */ + int boundtype; + long countsub; /* number of subgroups of type M (so far) */ + long count; /* number of p-subgroups so far [updated when M completed] */ + GEN expoI; /* exponent of I */ + void(*fun)(struct subgp_iter *, GEN); /* applied to each subgroup */ + void *fundata; /* for fun */ +} subgp_iter; -static slist *sublist; +#define len(x) (x)[0] +#define setlen(x,l) len(x)=(l) -void -printtyp(long *typ) +void +printtyp(const long *typ) { - long i; - for (i=1; i<=typ[0]; i++) fprintferr(" %ld ",typ[i]); + long i, l = len(typ); + for (i=1; i<=l; i++) fprintferr(" %ld ",typ[i]); fprintferr("\n"); } @@ -54,9 +81,9 @@ printtyp(long *typ) static long* conjugate(long *typ) { - long *t, i, k = typ[0], l, last; + long *t, i, k = len(typ), l, last; - if (!k) { t = new_chunk(1); t[0]=0; return t; } + if (!k) { t = new_chunk(1); setlen(t,0); return t; } l = typ[1]; t = new_chunk(l+2); t[1] = k; last = k; for (i=2; i<=l; i++) @@ -64,60 +91,87 @@ conjugate(long *typ) while (typ[last] < i) last--; t[i] = last; } - t[i] = 0; t[0] = l; + t[i] = 0; setlen(t,l); return t; } - +/* --- subgp_iter 'fun' associated to forsubgroup -------------- */ static void -std_fun(GEN x) +std_fun(subgp_iter *T, GEN x) { - ep->value = (void*)x; - lisseq(gpch); countsub++; + expr_t *E = (expr_t *)T->fundata; + E->ep->value = (void*)x; + (void)lisseq(E->s); T->countsub++; } - -void -addcell(GEN H) +/* ----subgp_iter 'fun' associated to subgrouplist ------------- */ +static void +addcell(sublist_t *S, GEN H) { long *pt,i,j, k = 0, n = lg(H)-1; slist *cell = (slist*) gpmalloc(sizeof(slist) + n*(n+1)/2 * sizeof(long)); - sublist->next = cell; cell->data = pt = (long*) (cell + 1); + S->list->next = cell; cell->data = pt = (long*) (cell + 1); for (j=1; j<=n; j++) for(i=1; i<=j; i++) pt[k++] = itos(gcoeff(H,i,j)); - sublist = cell; + S->list = cell; + S->count++; } +extern int hnfdivide(GEN A, GEN B); + +/* 1 if h^(-1)*list[i] integral for some i, 0 otherwise */ +static int +hnflistdivise(GEN list,GEN h) +{ + long i, n = lg(list); + for (i=1; ifundata; + GEN H = hnf(concatsp(S->hnfgroup,x)); + if (S->listKer && hnflistdivise(S->listKer, H)) return; /* test conductor */ + addcell(S, H); T->countsub++; } +/* -------------------------------------------------------------- */ -/* treat subgroup Hp (not in HNF, treatsub_fun should do it if desired) */ +/* treat subgroup Hp (not in HNF, T->fun should do it if desired) */ static void -treatsub(GEN Hp) +treatsub(subgp_iter *T, GEN H) { long i; - if (!subq) treatsub_fun(Hp); + if (!T->subq) T->fun(T, H); else { /* not a p group, add the trivial part */ - Hp = gmulsg(expoI,Hp); /* lift Hp to G */ - for (i=1; iexpoI, H); /* lift H to G */ + long l = lg(T->subqpart); + for (i=1; ifun(T, concatsp(Hp, (GEN)T->subqpart[i])); } } /* assume t>0 and l>1 */ static void -dogroup(void) +dogroup(subgp_iter *T) { - long av = avma,av1, e,i,j,k,r,n,t2,ind, t = mmu[0], l = lam[0]; + const long *powlist = T->powlist; + long *M = T->M; + long *L = T->L; + long *c = T->c; + long *a = T->a, *maxa = T->maxa; + long **g = T->g, **maxg = T->maxg; + GEN **H = T->H; + gpmem_t av = avma; + long e,i,j,k,r,n,t2,ind, t = len(M), l = len(L); t2 = (l==t)? t-1: t; n = t2 * l - (t2*(t2+1))/2; /* number of gamma_ij */ for (i=1, r=t+1; ; i++) { - if (available[i]) c[r++] = i; + if (T->available[i]) c[r++] = i; if (r > l) break; } if (DEBUGLEVEL>2) { fprintferr(" column selection:"); printtyp(c); } @@ -127,187 +181,232 @@ dogroup(void) maxg[i] = maxa + (ind - (i+1)); /* only access maxg[i][i+1..l] */ g[i] = a + (ind - (i+1)); for (r=i+1; r<=l; r++) - if (c[r] < c[i]) maxg[i][r] = powerlist[mmu[i]-mmu[r]-1]; - else if (lam[c[r]] < mmu[i]) maxg[i][r] = powerlist[lam[c[r]]-mmu[r]]; - else maxg[i][r] = powerlist[mmu[i]-mmu[r]]; + if (c[r] < c[i]) maxg[i][r] = powlist[M[i]-M[r]-1]; + else if (L[c[r]] < M[i]) maxg[i][r] = powlist[L[c[r]]-M[r]]; + else maxg[i][r] = powlist[M[i]-M[r]]; } - av1=avma; a[n-1]=0; for (i=0; i maxa[n-1]) { j=n-2; while (j>=0 && a[j]==maxa[j]) j--; - if (j<0) { avma=av; return; } + if (j < 0) { avma = av; return; } + a[j]++; for (k=j+1; kc[1],...,T->c[r-1] filled */ static void -loop(long r) +loop(subgp_iter *T, long r) { long j; - if (r > mmu[0]) { dogroup(); return; } + if (r > len(T->M)) { dogroup(T); return; } - if (r!=1 && (mmu[r-1] == mmu[r])) j = c[r-1]+1; else j = 1; - for ( ; j<=maxc[r]; j++) - if (available[j]) + if (r!=1 && (T->M[r-1] == T->M[r])) j = T->c[r-1]+1; else j = 1; + for ( ; j<=T->maxc[r]; j++) + if (T->available[j]) { - c[r] = j; available[j] = 0; - loop(r+1); available[j] = 1; + T->c[r] = j; T->available[j] = 0; + loop(T, r+1); T->available[j] = 1; } } static void -dopsubtyp(void) +dopsubtyp(subgp_iter *T) { - long av = avma, i,r, l = lam[0], t = mmu[0]; + gpmem_t av = avma; + long i,r, l = len(T->L), t = len(T->M); if (!t) { GEN p1 = cgetg(2,t_MAT); - p1[1] = (long)zerocol(l); - treatsub(p1); avma=av; return; + p1[1] = (long)zerocol(l); + treatsub(T, p1); avma = av; return; } if (l==1) /* imply t = 1 */ { - GEN p1 = gtomat(stoi(powerlist[lam[1]-mmu[1]])); - treatsub(p1); avma=av; return; + GEN p1 = gtomat(stoi(T->powlist[T->L[1]-T->M[1]])); + treatsub(T, p1); avma = av; return; } - c = new_chunk(l+1); c[0] = l; - maxc = new_chunk(l+1); - available = new_chunk(l+1); - a = new_chunk(l*(t+1)); - maxa=new_chunk(l*(t+1)); - g = (long**)new_chunk(t+1); - maxg = (long**)new_chunk(t+1); + T->c = new_chunk(l+1); setlen(T->c, l); + T->maxc = new_chunk(l+1); + T->available = new_chunk(l+1); + T->a = new_chunk(l*(t+1)); + T->maxa= new_chunk(l*(t+1)); + T->g = (long**)new_chunk(t+1); + T->maxg = (long**)new_chunk(t+1); - if (DEBUGLEVEL) { fprintferr(" subgroup:"); printtyp(mmu); } + if (DEBUGLEVEL) { fprintferr(" subgroup:"); printtyp(T->M); } for (i=1; i<=t; i++) { for (r=1; r<=l; r++) - if (mmu[i] > lam[r]) break; - maxc[i] = r-1; + if (T->M[i] > T->L[r]) break; + T->maxc[i] = r-1; } - H = (GEN**)cgetg(t+1, t_MAT); + T->H = (GEN**)cgetg(t+1, t_MAT); for (i=1; i<=t; i++) { - H[i] = (GEN*)cgetg(l+1, t_COL); - for (r=1; r<=l; r++) H[i][r] = cgeti(3); + T->H[i] = (GEN*)cgetg(l+1, t_COL); + for (r=1; r<=l; r++) T->H[i][r] = cgeti(3); } - for (i=1; i<=l; i++) available[i]=1; - for (i=1; i<=t; i++) c[i]=0; + for (i=1; i<=l; i++) T->available[i]=1; + for (i=1; i<=t; i++) T->c[i]=0; /* go through all column selections */ - loop(1); avma=av; return; + loop(T, 1); avma = av; return; } static long weight(long *typ) { - long i,w = 0; - for (i=1; i<=typ[0]; i++) w += typ[i]; + long i, l = len(typ), w = 0; + for (i=1; i<=l; i++) w += typ[i]; return w; } -static long -dopsub(long p, long *gtyp, long *indexsubq) +static void +dopsub(subgp_iter *T, GEN p, GEN indexsubq) { - long w,i,j,k,n, wg = 0, wmin = 0, count = 0; + long *M, *L = T->L; + long w,i,j,k, wG = weight(L), wmin = 0, wmax = wG, n = len(L); - if (DEBUGLEVEL) { fprintferr("\ngroup:"); printtyp(gtyp); } - if (indexbound) + if (DEBUGLEVEL) { fprintferr("\ngroup:"); printtyp(L); } + T->count = 0; + switch(T->boundtype) { - wg = weight(gtyp); - wmin = (long) (wg - (log((double)indexbound) / log((double)p))); - if (cmpis(gpuigs(stoi(p), wg - wmin), indexbound) > 0) wmin++; + case b_MAX: /* upper bound */ + wmin = (long) (wG - (log(gtodouble(T->bound)) / log(gtodouble(p)))); + if (cmpii(gpowgs(p, wG - wmin), T->bound) > 0) wmin++; + break; + case b_EXACT: /* exact value */ + wmin = wmax = wG - ggval(T->bound, p); + break; } - lam = gtyp; n = lam[0]; mmu = new_chunk(n+1); - mmu[1] = -1; for (i=2; i<=n; i++) mmu[i]=0; + T->M = M = new_chunk(n+1); + M[1] = -1; for (i=2; i<=n; i++) M[i]=0; for(;;) /* go through all vectors mu_{i+1} <= mu_i <= lam_i */ { - mmu[1]++; - if (mmu[1] > lam[1]) + M[1]++; + if (M[1] > L[1]) { for (j=2; j<=n; j++) - if (mmu[j] < lam[j] && mmu[j] < mmu[j-1]) break; - if (j>n) return count; - mmu[j]++; for (k=1; k n) return; + + M[j]++; for (k=1; k= wmin) - { + if (!M[j]) break; + setlen(M, j-1); w = weight(M); + if (w >= wmin && w <= wmax) + { GEN p1 = gun; - if (subq) /* G not a p-group */ + if (T->subq) /* G not a p-group */ { - if (indexbound) + if (T->bound) { - long indexH = itos(gpuigs(stoi(p), wg - w)); - long bound = indexbound / indexH; - subqpart = cgetg(lsubq, t_VEC); - lsubqpart = 1; - for (i=1; ibound, indexH); + long k, l = lg(T->subq); + T->subqpart = cgetg(l, t_VEC); + k = 1; + for (i=1; isubqpart[k++] = T->subq[i]; + setlg(T->subqpart, k); } - else { subqpart = subq; lsubqpart = lsubq; } + else T->subqpart = T->subq; } if (DEBUGLEVEL) { - long *lp = conjugate(lam); - long *mp = conjugate(mmu); + long *Lp = conjugate(L); + long *Mp = conjugate(M); + GEN BINMAT = matqpascal(len(L)+1, p); if (DEBUGLEVEL > 3) { - fprintferr(" lambda = "); printtyp(lam); - fprintferr(" lambda'= "); printtyp(lp); - fprintferr(" mu = "); printtyp(mmu); - fprintferr(" mu'= "); printtyp(mp); + fprintferr(" lambda = "); printtyp(L); + fprintferr(" lambda'= "); printtyp(Lp); + fprintferr(" mu = "); printtyp(M); + fprintferr(" mu'= "); printtyp(Mp); } - for (j=1; j<=mp[0]; j++) + for (j=1; j<=len(Mp); j++) { - p1 = mulii(p1, gpuigs(stoi(p), mp[j+1]*(lp[j]-mp[j]))); - p1 = mulii(p1, gcoeff(BINMAT, lp[j]-mp[j+1]+1, mp[j]-mp[j+1]+1)); + p1 = mulii(p1, gpuigs(p, Mp[j+1]*(Lp[j]-Mp[j]))); + p1 = mulii(p1, gcoeff(BINMAT, Lp[j]-Mp[j+1]+1, Mp[j]-Mp[j+1]+1)); } fprintferr(" alpha_lambda(mu,p) = %Z\n",p1); } - countsub = 0; - dopsubtyp(); - count += countsub; + T->countsub = 0; + + dopsubtyp(T); + + T->count += T->countsub; if (DEBUGLEVEL) { - fprintferr(" countsub = %ld\n", countsub); + fprintferr(" countsub = %ld\n", T->countsub); msgtimer("for this type"); - if (subq) p1 = mulis(p1,lsubqpart-1); - if (cmpis(p1,countsub)) + if (T->fun != list_fun || !((sublist_t*)(T->fundata))->listKer) { - fprintferr(" alpha = %Z\n",p1); - err(bugparier,"forsubgroup (alpha != countsub)"); + if (T->subq) p1 = mulis(p1,lg(T->subqpart)-1); + if (cmpis(p1,T->countsub)) + { + fprintferr(" alpha = %Z\n",p1); + err(bugparier,"forsubgroup (alpha != countsub)"); + } } } } } } +void +parse_bound(subgp_iter *T) +{ + GEN b, B = T->bound; + if (!B) { T->boundtype = b_NONE; return; } + switch(typ(B)) + { + case t_INT: /* upper bound */ + T->boundtype = b_MAX; + break; + case t_VEC: /* exact value */ + b = (GEN)B[1]; + if (lg(B) != 2 || typ(b) != t_INT) err(typeer,"subgroup"); + T->boundtype = b_EXACT; + T->bound = b; + break; + case t_COL: /* exact type */ + if (lg(B) > len(T->L)+1) err(typeer,"subgroup"); + err(impl,"exact type in subgrouplist"); + T->boundtype = b_TYPE; + break; + default: err(typeer,"subgroup"); + } + if (signe(T->bound) <= 0) + err(talker,"subgroup: index bound must be positive"); +} + static GEN expand_sub(GEN x, long n) { @@ -324,25 +423,31 @@ expand_sub(GEN x, long n) } extern GEN matqpascal(long n, GEN q); +static GEN subgrouplist_i(GEN cyc, GEN bound, GEN expoI, GEN listKer); -static long -subgroup_engine(GEN cyc, long bound) +static GEN +init_powlist(long k, long p) { - long av=avma,i,j,k,imax,nbprim,count, n = lg(cyc); - GEN gtyp,fa,junk,primlist,p,listgtyp,indexsubq = NULL; - long oindexbound = indexbound; - long oexpoI = expoI; - long *opowerlist = powerlist; - GEN osubq = subq; - GEN oBINMAT = BINMAT; - long olsubq = lsubq; + GEN z = new_chunk(k+1); + long i; + z[0] = 1; z[1] = (long)p; + for (i=1; i<=k; i++) + { + GEN t = muluu(p, z[i-1]); + z[i] = itos(t); + } + return z; +} - long *ommu=mmu, *olam=lam, *oc=c, *omaxc=maxc, *oa=a, *omaxa=maxa, **og=g, **omaxg=maxg; - GEN **oH=H, osubqpart=subqpart; - long ocountsub=countsub; - long *oavailable=available, olsubqpart=lsubqpart; - - if (typ(cyc) != t_VEC) +static void +subgroup_engine(subgp_iter *T) +{ + gpmem_t av = avma; + GEN B,L,fa,junk,primlist,p,listL,indexsubq = NULL; + GEN cyc = T->cyc; + long i,j,k,imax,nbprim, n = lg(cyc); + + if (typ(cyc) != t_VEC) { if (typ(cyc) != t_MAT) err(typeer,"forsubgroup"); cyc = mattodiagonal(cyc); @@ -350,87 +455,84 @@ subgroup_engine(GEN cyc, long bound) for (i=1; ifun(T, cyc); return; } if (!signe(cyc[1])) err(talker,"infinite group in forsubgroup"); - if (DEBUGLEVEL) timer2(); - indexbound = bound; + if (DEBUGLEVEL) (void)timer2(); fa = factor((GEN)cyc[1]); primlist = (GEN)fa[1]; nbprim = lg(primlist); - listgtyp = new_chunk(n); imax = k = 0; + listL = new_chunk(n); imax = k = 0; for (i=1; i k) { k = j; imax = i; } - listgtyp[i] = (long)gtyp; + listL[i] = (long)L; } - gtyp = (GEN)listgtyp[imax]; p = (GEN)primlist[imax]; - k = gtyp[1]; - powerlist = new_chunk(k+1); powerlist[0] = 1; - powerlist[1] = itos(p); - for (j=1; j<=k; j++) powerlist[j] = powerlist[1] * powerlist[j-1]; + L = (GEN)listL[imax]; p = (GEN)primlist[imax]; + k = L[1]; + T->L = L; + T->powlist = init_powlist(k, itos(p)); + B = T->bound; + parse_bound(T); - if (DEBUGLEVEL) BINMAT = matqpascal(gtyp[0]+1, p); - if (nbprim == 2) subq = NULL; + if (nbprim == 2) + { + T->subq = NULL; + if (T->boundtype == b_EXACT) + { + (void)pvaluation(T->bound,p,&B); + if (!gcmp1(B)) { avma = av; return; } + } + } else { /* not a p-group */ - GEN cyc2 = dummycopy(cyc); - GEN ohnfgroup = hnfgroup; + GEN cycI = dummycopy(cyc); + long lsubq; for (i=1; ipowlist[L[i]]); + if (gcmp1((GEN)cycI[i])) break; } - setlg(cyc2, i); - if (is_bigint(cyc[1])) - err(impl,"subgrouplist for large cyclic factors"); - expoI = itos((GEN)cyc2[1]); - hnfgroup = diagonal(cyc2); - subq = subgrouplist(cyc2, bound); - hnfgroup = ohnfgroup; - lsubq = lg(subq); - for (i=1; iboundtype == b_EXACT) { - indexsubq = new_chunk(lsubq); + (void)pvaluation(T->bound,p,&B); + B = _vec(B); + } + T->expoI = (GEN)cycI[1]; + T->subq = subgrouplist_i(cycI, B, T->expoI, NULL); + + lsubq = lg(T->subq); + for (i=1; isubq[i] = (long)expand_sub((GEN)T->subq[i], n); + if (T->bound) + { + indexsubq = cgetg(lsubq,t_VEC); for (i=1; isubq[i]); } /* lift subgroups of I to G */ - for (i=1; isubq[i] = lmulsg(T->powlist[k],(GEN)T->subq[i]); if (DEBUGLEVEL>2) { fprintferr("(lifted) subgp of prime to %Z part:\n",p); - outbeaut(subq); + outbeaut(T->subq); } } - count = dopsub(powerlist[1],gtyp,indexsubq); - if (DEBUGLEVEL) fprintferr("nb subgroup = %ld\n",count); - - mmu=ommu; lam=olam; c=oc; maxc=omaxc; a=oa; maxa=omaxa; g=og; maxg=omaxg; - H=oH; subqpart=osubqpart, - countsub=ocountsub; - available=oavailable; lsubqpart=olsubqpart; - - indexbound = oindexbound; - expoI = oexpoI; - powerlist = opowerlist; - subq = osubq; - BINMAT = oBINMAT; - lsubq = olsubq; - avma=av; return count; + dopsub(T, p,indexsubq); + if (DEBUGLEVEL) fprintferr("nb subgroup = %ld\n",T->count); + avma = av; } static GEN -get_snf(GEN x) +get_snf(GEN x, long *N) { GEN cyc; long n; @@ -439,11 +541,12 @@ get_snf(GEN x) case t_MAT: if (!isdiagonal(x)) return NULL; cyc = mattodiagonal_i(x); break; - case t_VEC: + case t_VEC: if (lg(x) == 4 && typ(x[2]) == t_VEC) x = (GEN)x[2]; case t_COL: cyc = dummycopy(x); break; default: return NULL; } - for (n = lg(cyc)-1; n > 1; n--) /* take care of trailing 1s */ + *N = lg(cyc)-1; + for (n = *N; n > 0; n--) /* take care of trailing 1s */ { GEN c = (GEN)cyc[n]; if (typ(c) != t_INT) return NULL; @@ -459,43 +562,56 @@ get_snf(GEN x) } void -forsubgroup(entree *oep, GEN cyc, long bound, char *och) +forsubgroup(entree *ep, GEN cyc, GEN bound, char *ch) { - entree *saveep = ep; - char *savech = gpch; - void(*savefun)(GEN) = treatsub_fun; + subgp_iter T; + expr_t E; + long N; - treatsub_fun = std_fun; - cyc = get_snf(cyc); + T.fun = &std_fun; + cyc = get_snf(cyc,&N); if (!cyc) err(typeer,"forsubgroup"); - gpch = och; - ep = oep; + T.bound = bound; + T.cyc = cyc; + E.s = ch; + E.ep= ep; T.fundata = (void*)&E; push_val(ep, gzero); - (void)subgroup_engine(cyc,bound); + + subgroup_engine(&T); + pop_val(ep); - treatsub_fun = savefun; - gpch = savech; - ep = saveep; } -GEN -subgrouplist(GEN cyc, long bound) +static GEN +subgrouplist_i(GEN cyc, GEN bound, GEN expoI, GEN listKer) { - void(*savefun)(GEN) = treatsub_fun; - slist *olist = sublist, *list; - long ii,i,j,k,nbsub,n, N = lg(cyc)-1, av = avma; + gpmem_t av = avma; + subgp_iter T; + sublist_t S; + slist *list, *sublist; + long ii,i,j,k,nbsub,n,N; GEN z,H; - GEN ohnfgroup = hnfgroup; - sublist = list = (slist*) gpmalloc(sizeof(slist)); - treatsub_fun = list_fun; - cyc = get_snf(cyc); + cyc = get_snf(cyc, &N); if (!cyc) err(typeer,"subgrouplist"); - n = lg(cyc)-1; - hnfgroup = diagonal(cyc); - nbsub = subgroup_engine(cyc,bound); - hnfgroup = ohnfgroup; avma = av; - z = cgetg(nbsub+1,t_VEC); sublist = list; + n = lg(cyc)-1; /* not necessarily = N */ + + S.list = sublist = (slist*) gpmalloc(sizeof(slist)); + S.hnfgroup = diagonal(cyc); + S.listKer = listKer; + S.count = 0; + T.fun = &list_fun; + T.fundata = (void*)&S; + + T.cyc = cyc; + T.bound = bound; + T.expoI = expoI; + + subgroup_engine(&T); + + nbsub = S.count; + avma = av; + z = cgetg(nbsub+1,t_VEC); for (ii=1; ii<=nbsub; ii++) { list = sublist; sublist = list->next; free(list); @@ -512,6 +628,17 @@ subgrouplist(GEN cyc, long bound) for (i=1; i<=N; i++) coeff(H,i,j) = (i==j)? un: zero; } } - free(sublist); sublist = olist; - treatsub_fun = savefun; return z; + free(sublist); return z; +} + +GEN +subgrouplist(GEN cyc, GEN bound) +{ + return subgrouplist_i(cyc,bound,NULL,NULL); +} + +GEN +subgroupcondlist(GEN cyc, GEN bound, GEN listKer) +{ + return subgrouplist_i(cyc,bound,NULL,listKer); }