1 #include "defs.h"
2 
3 extern char inf0[],inf1[],inf2[],inf3[],inf4[],outf0[],outf1[],outf2[],outfd[],
4              inf[],act,ch1,crel,cfm,gap;
5 extern short  mv,mm,facexp,tails,stage,depth,no,mng,mcl,
6        prime,exp,nng,class,*rpf,*rpb,**pcb,dim,onng,*spv,**spm,
7        rel[],wt[],d1[],d2[],*pcptr[],sd1[],sd2[],swt[],
8        dpth[],mspace[],*vec[],**mat[],cp[];
9 extern int rsp,msp,ptrsp,wsp;
10 short  **intg,**cintg,cbno,ngens,maxm,maxv,matcl,
11        **extno,**subno,chsdim=0,chpdim,exp1;
12 int    orsp,optrsp,rspk;
13 long   inf3offset,inf4offset;
14 char   norm;
15 FILE *ip,*ipm,*op;
16 
17 /* General comments on programs nqrun (and nqmrun).
18    See file Info.5 for format of ip/op files, and meaning of variables
19    exp,prime,facexp,no,class,depth.
20    Definiton of i is [d1[i],d2[i]] or d1[i]^prime if equal.
21    wt[i] and dpth[i] are weights and depths.
22    sd1,sd2 and swt are used to recall defs and weights of the calculation
23    in a Sylow intersection.
24    rel is array used to hold all pcp definitons, and some other material.
25    The front and back are used at times, using pointers rpf, rpb.
26    rsp is remaining space.
27    powptr and comptr point to power and commutator relations.
28    nng is no of new generators introduced so far.
29    onng is the value of nng at the end of stage 1 (see below), which is the
30    dimension of Hom-P(FM,M).
31    norm is set 1 when act=1 and g is in N(P).
32    separately. ipm similarly for inf4.
33    stage=0,1 or 2 for H^2 and 3 or 4 for H^1. For H^2, stage=0 when computing
34    Frattini module (FM), =1 when computing Hom-P(FM,M) and =2 thereafter.
35    For H^1 stage=3 initially and 4 when computation of H^1 begins.
36    In general tails=1 when new gens are being introduced (as tails), and the
37    strings for relns in the new gens are stored at the back of rel.
38    When act is true, intg and cintg are used to point to the expressions for
39    the generators of the Sylow intersection Q and their conjugates, resp., as
40    words in the gens of P. These are stored at the back of rel.
41    subno and extno point to strings which sre the generators of the groups
42    M2a and M2b, as described in Info.5. These are also stored at the back of rel
43 */
44 
45 int
nqprog(void)46 nqprog (void)
47 { short i,c,**p,**q,*r,ct,oexp; char adn;
48   if (cfm)
49 /* Calculate Frattini module only  */
50   { tails=1; stage=0; strcpy(outf1,outf0);
51     ip=fopen(inf1,"r"); fscanf(ip,"%hd",&prime); fclose(ip);
52     setpinv(); calcfm(0); return(0);
53   }
54   if (rdmats()== -1) return(-1);
55 /* If act, then we will first compute H^i(Q,M), using same algorithm as for
56    H^i(P,M). First we remember the amount of space and ptrspace we had before
57    we started.
58 */
59   if (act)
60   { orsp=rsp; optrsp=ptrsp; adn=0; ip=fopen(inf3,"r");
61     if (ip==0)
62     { if (gap==0) printf("Warning. File %s is not present.\n",inf3);}
63     else
64     { ipm=fopen(inf4,"r");
65       if (ipm==0)
66       { fprintf(stderr,"Cannot open file %s.\n",inf4); return(-1); }
67       while ((i=getc(ipm))!='\n');
68       inf3offset=ftell(ip); inf4offset=ftell(ipm);
69       fclose(ip);  fclose(ipm);
70     }
71   }
72   while (1)
73 /* If act=0 we do this only once. If act=1, each iteration in this loop
74    corresponds to the action of one element g.
75 */
76   { norm=0;
77     if (act)
78     { oexp=exp;
79       if (ip==0) i=1; else if ((i=intmats())== -1) return(-1);
80       if (i==1)
81       { if (adn==0)
82 /* if adn=0 at this stage, there are no elements acting, so full group must
83    be input, in case crel is true
84 */
85         {strcpy(inf1,inf0); stage=2; if (ingp(1)== -1) return(-1); onng=nng;}
86         else exp=oexp;
87         break;
88       }
89       adn=1;
90     }
91 /* Again we remember amount of space. If act is true, we will be storing some
92    data in the back of the array rel, which will no longer be needed after
93    H^i(Q,M) has been computed. rspk is recalled at end of subroutine spact.
94 */
95     if (norm) { inf3offset=ftell(ip); fclose(ip);}
96     rspk=rsp;
97     if (ch1==0)
98     { if (norm)
99       { ip=fopen(inf0,"r");
100         if (ip==0)
101         { fprintf(stderr,"Cannot open file %s.\n",inf0); return(-1); }
102         fscanf(ip,"%hd%hd%hd",&prime,&exp,&facexp);
103         for (i=1;i<=2;i++) while ((c=getc(ip))!='\n');
104         exp1= -1; ct=0;
105         while (ct<=facexp)
106         { exp1++; if (exp1==exp) break; fscanf(ip,"%hd",&ct);}
107         fclose(ip);
108       }
109       else
110       { tails=1; stage=0; strcpy(outf1,outf0);
111         if (calcfm(matcl)== -1) return(-1);
112         exp+=nng;
113       }
114       if (act)
115 /* Rearrange pointers intg, cintg in ptrsp, now we know how many new
116    ones need to be computed.
117 */
118       { p=pcptr+ptrsp-exp1-1; q=p-exp1; ptrsp-=(2*exp1);
119         for (i=1;i<=facexp;i++) { p[i]=intg[i]; q[i]=cintg[i]; }
120         intg=p; cintg=q;
121       }
122     }
123     if (norm) {tails=0; stage= ch1 ? 4 : 2; }
124     else
125     { tails=0; stage= ch1 ? 3 : 1;
126       if (spact()== -1) return(-1);
127       if (act==0)
128       { if (ch1==0)
129         { subno=extno-onng;
130           for (i=1;i<=onng;i++) subno[i]=0;
131         }
132         break;
133       }
134     }
135     i=intact();
136     if (i == -1) return(-1);
137     if (i == 2) break;
138 /* This ends the computation for the action of the current g. The next few
139    lines prepare for the next g (if any).
140 */
141     rsp=orsp; ptrsp=optrsp;
142     ip=fopen(outf2,"r");
143     if (ip==0) { fprintf(stderr,"Cannot open %s.\n",outf2); return(-1); }
144     fscanf(ip,"%hd%hd%hd",&prime,&dim,&ngens);
145     for (i=1;i<=ngens;i++) readmat(mat[i]);
146     fclose(ip);
147   }
148   if (gap)
149   { op=fopen(outfd,"w");
150     if (ch1) fprintf(op,"COHOMOLO.CoDim1 := %d;\n",nng);
151     else fprintf(op,"COHOMOLO.CoDim2 := %d;\n",chpdim-chsdim);
152     fclose(op);
153     printf("Present dimension of cohomology group is  ");
154     if (ch1) printf("%d\n",nng);
155     else printf("%d\n",chpdim-chsdim);
156   }
157   else
158   { fprintf(stderr,"Present dimension of cohomology group is  ");
159     if (ch1) fprintf(stderr,"%d\n",nng);
160     else fprintf(stderr,"%d\n",chpdim-chsdim);
161   }
162   if ((ch1 && nng==0) || (ch1==0 && chpdim==chsdim)) return(2);
163   if (crel) if (comprels()== -1) return(-1);
164   return(0);
165 }
166 
167 int
rdmats(void)168 rdmats (void)
169 /* reads matrices of generators of P  and set up matrix pointers.*/
170 { short i;
171   int quot;
172   if (act) ip=fopen(outf2,"r"); else  ip=fopen(inf2,"r");
173   if (ip==0)
174   { fprintf(stderr,"Cannot open ");
175     if (act) fprintf(stderr,"%s\n",outf2);
176     else fprintf(stderr,"%s\n",inf2);
177     return(-1);
178   }
179   fscanf(ip,"%hd%hd%hd",&prime,&dim,&ngens);
180   if (act==0) fscanf(ip,"%hd",&matcl);
181   setpinv();
182   quot=msp/dim; if (quot>mv) quot=mv; maxv=quot;
183   for (i=0;i<maxv;i++) vec[i]=mspace-1+i*dim;
184   maxm=maxv/dim; if (maxm>=mm) maxm=mm-1;
185   for (i=0;i<=maxm;i++) mat[i]=vec-1+i*dim;
186   spm=mat[0]; spv=spm[1];
187   if (maxm<ngens)
188   { fprintf(stderr,"Not enough mat space. Increase MSP (of MV or MM).\n");
189     return(-1);
190   }
191   if (act==0)
192   { for (i=1;i<=dim;i++) fscanf(ip,"%hd",swt+i);
193     for (i=1;i<=dim;i++) fscanf(ip,"%hd",sd1+i);
194     for (i=1;i<=dim;i++) fscanf(ip,"%hd",sd2+i);
195   }
196   for (i=1;i<=ngens;i++) readmat(mat[i]);
197   fclose(ip);
198   return(0);
199 }
200 
201 int
intmats(void)202 intmats (void)
203 /* When act=1, reads in gens for the action, computes their matrices,
204    and makes a base change for this action if necesary.
205 */
206 { short i,j,k,*p,l,ct,**swop,cbno2,**cbm,**newmat;
207   ip=fopen(inf3,"r"); fseek(ip,inf3offset,0);
208 retry:
209   fscanf(ip,"%hd",&exp);
210 /* if exp=0, the corresponding dcrep matrix must be skipped */
211   if (exp==0)
212   { ipm=fopen(inf4,"r"); fseek(ipm,inf4offset,0);
213     for (i=1;i<=dim*dim;i++) fscanf(ipm,"%hd",&j);
214     inf4offset=ftell(ipm); fclose(ipm);
215     goto retry;
216   }
217   if (exp== -1) {fclose(ip); return(1);}
218   norm= exp==ngens;
219   facexp=exp; no=exp-1;
220   for (i=1;i<=exp;i++) fscanf(ip,"%hd",wt+i);
221   class=1;
222   for (i=1;i<=exp;i++) if (wt[i]>class) class=wt[i];
223   ct= ch1 ? exp+dim+mng : exp;
224   cintg=pcptr+ptrsp-1-ct; intg=cintg-ct; ptrsp-=(2*ct);
225   rpb=rel+rsp-1; ct=0;
226   if (norm)
227   { for (i=1;i<=exp;i++) if (wt[i]==1)
228     { rpb-=3; intg[i]=rpb+1; *(rpb+1)=2; *(rpb+2)=i; *(rpb+3)=1; }
229   }
230   else for (i=1;i<=exp;i++)
231   { if (wt[i]==1)
232     { ct++; fscanf(ip,"%hd",&l); p=rpb-l; intg[i]=p; *p=l; *cp=0;
233       while (++p<=rpb)
234       { fscanf(ip,"%hd",p); k= *p; p++; fscanf(ip,"%hd",p);
235         for (j=1;j<= *p;j++) cp[++(*cp)]=k;
236       }
237       rpb-=(l+1); prod(cp,mat[ct+ngens]);
238     }
239     while (getc(ip)!='\n');
240   }
241   for (i=1;i<=exp;i++)
242   { if (wt[i]==1)
243     { fscanf(ip,"%hd",&l); p=rpb-l; cintg[i]=p; *p=l;
244       while (++p<=rpb) fscanf(ip,"%hd",p); rpb-=(l+1);
245     }
246     while (getc(ip)!='\n');
247   }
248   rsp=rpb-rel+1;
249   if (norm) return(0);
250   if (maxm<ngens+ct || maxm<2*exp+3)
251   { printf("Not enough mat space. Increase MSP (of MV or MM).\n");
252     return(-1);
253   }
254   for (i=1;i<=ct;i++) {swop=mat[i]; mat[i]=mat[i+ngens]; mat[i+ngens]=swop; }
255   ngens=ct; cbno=2*exp+1; cbm=mat[cbno];
256 /* mat[cbno] is the action base change matrix */
257   if (cbdef(1,ct,cbno,sd1,sd2,swt,&matcl))
258   printf("No action base change.\n"); else
259   { /* printf("Action base change matrix:\n");
260     for (i=1;i<=dim;i++)
261     { for (j=1;j<=dim;j++) printf("%3d",cbm[i][j]); printf("\n"); } */
262     cbno2=cbno+2; inv(cbm,mat[cbno+1]); newmat=mat[cbno2];
263     *cp=3; cp[1]=cbno; cp[3]=cbno+1;
264     for (i=1;i<=ct;i++)
265     { cp[2]=i; prod(cp,newmat);
266       mat[cbno2]=mat[i]; mat[i]=newmat; newmat=mat[cbno2];
267     }
268   }
269   return(0);
270 }
271 
272 int
calcfm(int steps)273 calcfm (int steps)
274 /* Computes the Frattini extension to depth steps. steps=0 computes complete
275    Frattini extension, but this is only used for testing.
276    At each stage, the NQA is applied to the group computed so far.
277 */
278 { short i,j,k,l,d,cl,st,dp,bd,ed; char inp;
279   printf("Computing Frattini module to depth %d.\n",steps);
280   st=1; depth= -1; inp= act ? 0 : 1;
281 /* if inp=0, initial input is from inf3 (which is already open as ip);
282    After first step, input is always from inf1
283 */
284   while (depth!=steps)
285   { if (ingp(inp) == -1) {fprintf(stderr,"Input error.\n"); return(-1); }
286     if (steps>0 && depth>=steps) break;
287     depth++; bd=exp+1;
288     for (dp=depth-1;dp>=0;dp--)
289     { ed=bd-1;
290       if (dp!=0) { i=ed-1; while (dpth[i]==dp) i--; bd=i+1; }
291       if (class+1>=mcl)
292       { fprintf(stderr,"class too big. Increase MCL.\n"); return(-1); }
293       for (cl=class+1;cl>=2;cl--)
294       { for (i=1;i<=facexp;i++)
295         { if (dp==0) bd=i+1;
296           for (j=bd;j<=ed;j++)
297           if (wt[i]==1 && wt[j]==(cl-1)) if (intgen(j,i)== -1) return(-1);
298         }
299         if (dp==0) for (i=1;i<=facexp;i++) if (wt[i]==cl-1)
300            if (intgen(i,i) == -1) return(-1);
301         for (i=2;i<=facexp;i++) if (wt[i]>1)
302         { if (dp==0) bd=i+1;
303           for (j=bd;j<=ed;j++) if (wt[i]+wt[j]==cl)
304           { k=d1[i]; l=d2[i];
305             if (assoc(j,k,l)) if (subrel(j,i)== -1) return(-1);
306           }
307         }
308         for (i=1;i<=facexp;i++) for (j=i+1;j<=facexp;j++)
309         { if (dp==0) bd=j+1;
310           for (k=bd;k<=ed;k++) if (wt[i]+wt[j]+wt[k]==cl && assoc(k,j,i))
311           { if ((l=prnrel())== 0) goto nextcl; if (l== -1) return(-1);}
312         }
313         for (i=1;i<=facexp;i++)
314         { if (dp==0) bd=i;
315           for (j=bd;j<=ed;j++) if (wt[i]+wt[j]+1==cl)
316           { if (assoc(j,i,i))
317             { if ((l=prnrel())== 0) goto nextcl; if (l== -1) return(-1);}
318             if (j!=i && j<=facexp  && assoc(j,j,i))
319             { if ((l=prnrel())== 0) goto nextcl;  if (l== -1) return(-1);}
320           }
321         }
322 nextcl:;
323       }
324       if (nng==0) break;
325     }
326     if (nng==0)
327     { printf("Frattini Module Complete.\n");
328       printf("Final order at depth %d was:  %d ^ %d.\n",depth-1,prime,exp);
329       fflush(stdout);
330       break;
331     }
332     outgp();
333     printf("Order of group at depth %d is:  %d ^ %d\n",depth,prime,exp+nng);
334     printf("Wasted space=%d.\n\n",wsp);
335     fflush(stdout);
336     if (st==1)
337     { strcpy(inf1,outf1);
338       if (act)
339       { inp=1; exp1=exp+nng; inf3offset=ftell(ip); fclose(ip);}
340     }
341     st++;
342   }
343   printf("Space used, used ptrspace=%d,%d.\n",(int)(rsp-(rpb-rpf)),(int)(pcb-pcptr));
344   fflush(stdout);
345   return(0);
346 }
347