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