1 #include "defs.h"
2 
3 extern char inf0[],inf1[],inf4[],outf0[],outf1[],outf2[],outcopy[],
4              act,ch1,norm;
5 extern int  intexp,facexp,stage,mcl,
6        prime,exp,nng,*rpf,*rpb,*eexpnt,*enexpnt,**pcb,dim,onng,**npcb,
7        rel[],expnt[],nexpnt[],pinv[],wt[],
8        d1[],d2[],*pcptr[],**powptr[],**comptr[],sd1[],sd2[],swt[],
9        dpth[],**mat[],cp[],**intg,**cintg,cbno,
10        ngens,maxm,matcl,**extno,**subno,chsdim,chpdim,exp1;
11 extern int rsp,ptrsp,rspk,marg;
12 extern long inf3offset,inf4offset;
13 int *wf,*wc,**inteno,intcpd,inng,*nsd1,*nsd2,intfe,**npcb2;
14 extern FILE *ip,*ipm,*op;
15 FILE *ipcopy,*opcopy;
16 
17 int
spact(void)18 spact (void)
19 /* Computes cohomology group H^i(P,M) or H^i(Q,M) */
20 { int i,j,k,l,m,n,ie,ct,cl,fg,wi,wj,*p,*q,*r,*nrpf,*v1,*v2,
21   **swop,homcl,c;
22   char inp;
23   inp= (ch1 && act) ? 0 : 1;
24 /* inp as in calcfm in case ch1 */
25   if (ingp(inp) == -1) return(-1);
26   if (ch1 && act) { inf3offset=ftell(ip); fclose(ip);}
27   ct=ngens; j=exp;
28   for (i=1;i<=dim;i++)
29   { j++; wt[j]=swt[i]; d1[j]=(sd1[i]>0) ? sd1[i]+exp : 0; d2[j]=sd2[i]; }
30   printf("Computing matrices.\n");
31 /* Matrices for all pcp gens of P or Q are now computed */
32   if (maxm<2*facexp)
33   { fprintf(stderr,"Not enough mat space. Increase MSP (of MV or MM).\n");
34     return(-1);
35   }
36   for (i=facexp;i>=1;i--) if (wt[i]==1)
37   { if (i>ct)
38     { swop=mat[i]; mat[i]=mat[ct]; mat[ct]=swop;
39       for (j=1;j<=dim;j++) if (d2[exp+j]==ct) d2[exp+j]=i;
40     }
41     inv(mat[i],mat[facexp+i]); ct--;
42   }
43   if (ct!=0) {fprintf(stderr,"No of pgens wrong.\n"); return(-1); }
44   for (i=2;i<=facexp;i++) if (wt[i]>1)
45   { p= (d1[i]==d2[i]) ? *powptr[d1[i]] : *(comptr[d1[i]]+d2[i]);
46     q=p+ *p-2; *cp=0;
47     while (--q>p)
48     { k= *(q+1); for (j=1;j<=k;j++) cp[++(*cp)]= *q+facexp; q--; }
49     if (d1[i]==d2[i]) for (j=1;j<=prime;j++) cp[++(*cp)]=d1[i];
50     else
51     { cp[++(*cp)]=d1[i]+facexp; cp[++(*cp)]=d2[i]+facexp;
52       cp[++(*cp)]=d1[i]; cp[++(*cp)]=d2[i];
53     }
54     prod(cp,mat[i]); inv(mat[i],mat[i+facexp]);
55   }
56   if (act==0)
57   { op=fopen(outf2,"w");
58     fprintf(op,"%3d%3d%3d\n",prime,dim,facexp);
59     for (i=1;i<=facexp;i++) printmat(mat[i]);
60     fclose(op);
61   }
62 
63 
64   printf("Computing full pcp.\n");
65 /* pcp of P or Q in dual action on module is computed from the matrices. */
66   v1=mat[facexp+1][1]; v2=mat[facexp+1][2];
67   for (i=1;i<=dim;i++) v1[i]=0; ie=exp;
68   for (i=1;i<=dim;i++)
69   { if (i>1) v1[i-1]=0; v1[i]=1; ie++;
70     for (j=1;j<=facexp;j++) if (comm(v1,v2,mat[j]))
71     { *(comptr[ie]+j)=rpf+1; nrpf=rpf+2; l=0;
72       for (k=1;k<=dim;k++) if ((m=v2[k])!=0)
73       { *(nrpf++)=k+exp; *(nrpf++)=m; l+=2; }
74       *(rpf+1)=l; m= *(nrpf-2);
75       if (d1[m]==ie && d2[m]==j) *rpf=m; else *rpf=0; rpf=nrpf;
76     }
77   }
78   if (ch1==0)
79   { printf("Computing P-homs.\n"); fflush(stdout); homcl=0;
80 /* Hom-P(FM,M) will now be computed  as dual of tensor product, using NQA */
81     if (matcl+1>=mcl)
82     { fprintf(stderr,"Class too big. Increase MCL.\n"); return(-1); }
83     for (cl=matcl+1;cl>1;cl--)
84     { printf("cl=%d.\n",cl);
85       for (fg=facexp+1;dpth[fg]==1 && fg<=exp;fg++) for (i=exp+1;i<=exp+dim;i++)
86       if (wt[i]+1==cl)
87       { if (intgen(i,fg)== -1) return(-1);
88         if ((k=wt[i]+wt[fg])>homcl)
89         { homcl=k;
90           if (homcl+1>=mcl)
91           { fprintf(stderr,"Class too big. Increase MCL.\n"); return(-1); }
92         }
93       }
94       while (fg<=exp)
95       { for (i=exp+1;i<=exp+dim;i++) if (wt[i]+dpth[fg]==cl)
96         { if  (dpth[d1[fg]]==dpth[fg]-1)
97           { if (assoc(i,d1[fg],d2[fg]))
98             if (subrel(i,fg)== -1) return(-1);
99           }
100           else if (intgen(i,fg)== -1) return(-1);
101           if ((k=wt[i]+wt[fg])>homcl)
102           { homcl=k;
103             if (homcl+1>=mcl)
104             { fprintf(stderr,"Class too big. Increase MCL.\n"); return(-1); }
105           }
106         }
107         fg++;
108       }
109       for (i=1;i<=facexp;i++)
110       { wi=wt[i];
111         for (j=facexp+1;j<=exp;j++)
112         { wj=dpth[j]; if (wi+wj>=cl) break;
113           for (k=exp+1;k<=exp+dim;k++) if (wi+wj+wt[k]==cl) if (assoc(k,j,i))
114           { if ((l=prnrel())==0) goto nextcl; if (l== -1) return(-1); }
115         }
116       }
117  nextcl:;
118     }
119     bgc(); rsp=rpb-rel+1;
120     printf("Computing extensions. nng,homcl=%d,%d\n",nng,homcl); fflush(stdout);
121     stage=2; onng=nng; chpdim=0; chsdim=0; extno=pcptr+ptrsp-onng-1;
122     for (i=1;i<=nng;i++) extno[i]=0;
123   }
124   else
125   { stage=4; printf("Computing first cohomology group.\n"); homcl=matcl;
126     if (homcl+1>=mcl)
127     { fprintf(stderr,"Class too big. Increase MCL.\n"); return(-1); }
128   }
129 
130 /* H^2 or H^1 will now be computed */
131   for (cl=homcl+1;cl>=2;cl--)
132   { printf("cl=%d\n",cl);
133     if (cl<=matcl+1)
134     { for (i=1;i<=facexp;i++) if (wt[i]==1) for (j=exp+1;j<=exp+dim;j++)
135       if (wt[j]+1==cl) if (intgen(j,i)== -1) return(-1);
136       for (i=1;i<=facexp;i++)
137       { wi=wt[i];
138         if (wi>1) for (j=exp+1;j<=exp+dim;j++)
139         if (wi+wt[j]==cl) if (assoc(j,d1[i],d2[i]))
140         if (subrel(j,i)== -1) return(-1);
141       }
142     }
143     for (i=1;i<=facexp;i++) for (j=i;j<=facexp;j++) for (k=exp+1;k<=exp+dim;k++)
144     if ((i==j && wt[i]+1+wt[k]==cl) || (i!=j && wt[i]+wt[j]+wt[k]==cl))
145     if (assoc(k,j,i))
146     if (ch1)
147     { if ((l=prnrel())==0) goto ncl; if (l== -1) return(-1); }
148     else
149     { l=prnrel(); if (l== -1) return(-1); if (l>1) nchg(); }
150 ncl:;
151   }
152   if (ch1) printf("Cohomology grp has dim %d\n",nng);
153 /* We now no longer need the data for Q in the back of rel. */
154   rpb=rel+rspk-1;
155   if (act) { if (ch1) onng=nng; else unlink(outf1); }
156   else
157   { if (stage>2) {onng=nng; strcpy(outf1,outf0);}
158     outgp();
159     if (ch1)
160     { ipcopy=fopen(outf1,"r"); opcopy=fopen(outcopy,"w");
161       while ((c=getc(ipcopy))!= -1) putc(c,opcopy);
162       fclose(ipcopy); fclose(opcopy);
163     }
164   }
165   return(0);
166 }
167 
168 int
nchg(void)169 nchg (void)
170 /* We have a new generator for H^2. This is put into echelon form with the
171    existing generators, and stored.
172 */
173 { int l,m,n,len,*p,*q,*v1,*r,*r1;
174   for (m=1;m<=onng;m++) if ((n=nexpnt[m])!=0)
175   { if (n<0) {n+=prime; nexpnt[m]=n;}
176     if ((p=extno[m])!=0)
177     { expand(p,rpf,onng); p=rpf; n=prime-n; q=p+onng; v1=nexpnt+1;
178       while (++p<=q) {*v1+= (n* *p); *v1%=prime; v1++;}
179     }
180   }
181   for (m=1;m<=onng;m++) if ((n=nexpnt[m])!=0)
182   { n=pinv[n]; p=nexpnt+m-1; q=nexpnt+onng;
183     while (++p<=q) {*p *=n; *p%=prime; }
184     chpdim++; printf("chpdim=%2d,    bno=%2d\n",chpdim,m);
185     for (l=1;l<=onng;l++) if ((p=extno[l])!=0)
186     { r=rpb-onng; expand(p,r,onng);
187       if ((n=r[m])!=0)
188       { n=prime-n; r1=r; q=r+onng; v1=nexpnt+1;
189         while (++r1<=q) {*r1+=(n* *v1); *r1%=prime; v1++;}
190         len=0;
191         for (n=1;n<=onng;n++) if (r[n]!=0) len+=2;
192         if (len> *p) {p=rpf; extno[l]=p; rpf+=(len+1); }
193         *p=len; compress(p,r,onng);
194       }
195     }
196     extno[m]=rpf;
197     len=0;
198     for (n=1;n<=onng;n++) if (nexpnt[n]!=0) len+=2;
199     *rpf=len; compress(rpf,nexpnt,onng); rpf+=(len+1);
200     break;
201   }
202 }
203 
204 int
intact(void)205 intact (void)
206 /* In case act, appropriate quotient of H^i(P,M) is computed */
207 { int a,b,c,d,i,j,k,l,len,m,n,x,f1,f2,*p,*p1,*q,*q1,*r,*r1,*ia,*ib,*v1,
208         **bim,**cbim,**imcg,**cimcg,**dp,*null;
209   char pow,nz;
210   strcpy(inf1,inf0);
211   if (norm)
212   { if (ch1) strcpy(inf1,outcopy);
213     if (ingp(1)== -1) return(-1);
214     if (ch1) strcpy(inf1,inf0);
215     cbno=1; bim=mat[cbno]; onng=nng;
216     for (i=1;i<=dim;i++) {for (j=1;j<=dim;j++) bim[i][j]=0;bim[i][i]=1; }
217   }
218 /* It is now time to read in the full pcp for the Frattini extension of P
219    again, in order to compute the action on it. Before doing this, we must
220    save all necessary information about Q. intg and cintg are already safely
221    at the back of rel., and the cohomolgy gens of Q will also be copied there.
222    The definitions of the gens of Q will be copied to sd1 and sd2, but a
223    slightly messy method has been used to save long definitions.
224 */
225   p=d1; q=p+exp+dim+onng; v1=sd1+1;
226   while (++p<=q) *(v1++)= *p;
227   nsd1=sd1+exp+dim;
228   p=d2; q=p+exp+dim+onng; v1=sd2+1;
229   while (++p<=q) *(v1++)= *p;
230   nsd2=sd2+exp+dim;
231   if (ch1)
232   { for (i=exp+1;i<=exp+dim+nng;i++)
233     { p= (sd1[i]==0) ? 0 : *(comptr[sd1[i]]+sd2[i]);
234       if (p!=0)
235       { l= *p; if (i<=exp+dim) l-=2;
236         if (l>0)
237         { sd1[i]= -sd1[i]; q=p+l;
238           while (q>p) {*rpb= *q; q--; rpb--;}
239           *rpb=l; cintg[i]=rpb; rpb--;
240         }
241       }
242     }
243   }
244   else
245   for (i=1;i<=exp1;i++) if (sd1[i]!=0)
246   { p= sd1[i]==sd2[i] ? *powptr[sd1[i]] : *(comptr[sd1[i]]+sd2[i]);
247     l= *p;
248     if (l>2)
249     { sd1[i]= -sd1[i]; q=p+l-2;
250       while (q>p) {*rpb= *q; q--; rpb--; }
251       *rpb=l-2; cintg[i]=rpb; rpb--;
252     }
253   }
254   inng=onng; intexp=exp;
255   if (ch1==0)
256   { p=wt; q=p+facexp; v1=swt+1;
257     while (++p<=q) *(v1++)= *p;
258     inteno=extno; intcpd=chpdim; intfe=facexp;
259     if (norm==0)
260     { for (i=1;i<=onng;i++) if ((p=inteno[i])!=0)
261       { q=p+ *p; rpb-=(*p+1); v1=rpb;
262         while (p<=q) *(++v1)= *(p++);
263         inteno[i]=rpb+1;
264       }
265       ptrsp-=onng;
266     }
267   }
268   rsp=rpb-rel+1;
269   if (norm==0 || ch1) if (ingp(1)== -1) return(-1);
270   printf("Reading conj matrix.\n");
271 /* matrix of dcrep is read and multiplied by action base change matrix */
272   bim=mat[cbno]; cbim=mat[cbno+1];
273   ip=fopen(inf4,"r"); fseek(ip,inf4offset,0);
274   readmat(mat[cbno+2]);
275   inf4offset=ftell(ip); fclose(ip);
276   *cp=2; cp[1]=cbno; cp[2]=cbno+2; prod(cp,cbim);
277   if (ch1)
278   { printf("Computing action.\n"); wf=rpf; null=0;
279     for (i=1;i<=dim;i++) *(++npcb2)=0;
280     if (npcb2-pcptr>=ptrsp)
281     { fprintf(stderr,"Out of ptrsp. Increase PTRSP.\n"); return(-1); }
282     for (i=intexp+1;i<=intexp+dim+inng;i++)
283     { wc=wf-2; a=sd1[i]; if (a==0) continue;
284       b=sd2[i]; zero(nexpnt,enexpnt);
285       if (a<0)
286       { p=cintg[i]; q=p + *p -1;
287         while (q>p) { entvec(npcb[*q-intexp],bim[*q-intexp],-*(q+1)); q-=2;}
288       }
289       ia=bim[abs(a)-intexp]; ib=intg[b];
290       entvec(null,ia,-1); enter(ib,-1); entvec(null,ia,1); enter(ib,1);
291       zero(expnt,eexpnt); collect(wc,wf,1);
292       wc=wf-2;
293       if (a<0)
294       { p=cintg[i]; q=p + *p -1;
295         while (q>p) { entvec(null,cbim[*q-intexp],-*(q+1)); q-=2;}
296       }
297       ia=cbim[abs(a)-intexp]; ib=cintg[b];
298       entvec(null,ia,-1); enter(ib,-1); entvec(null,ia,1); enter(ib,1);
299       zero(expnt,eexpnt); collect(wc,wf,-1);
300       if (i<=intexp+dim)
301       { l=0;
302         for (j=nng;j>=1;j--) if ((k=nexpnt[j])!=0)
303         { if (k<0) k+=prime; *rpb=k; *(rpb-1)=j; rpb-=2; l+=2; }
304         if (l!=0) { npcb[i-intexp]= rpb; *rpb=l; *(rpb-1)=0; rpb-=2; }
305       }
306       else if ((l=prnrel())== -1 || l==0) return(l);
307     }
308     printf("End of this action. Present dimension=%d\n",nng);
309     fflush(stdout);
310     if (nng==0) return(2);
311   }
312   else
313   { printf("Computing Frattini embeddings.\n");
314 /* Now intg and cintg are computed as strings in gens of P for the gens of Q */
315     for (i=1;i<=exp1;i++) if (i>intfe || swt[i]>1)
316     { wf=rpf; a=sd1[i]; b=sd2[i]; wc=wf-2; pow = abs(a)==b;
317 /* a<0 means a long def */
318       if (a<0)
319       { p=cintg[i]; q=p+ *p-1;
320         while (q>p) { enter(intg[*q],-*(q+1)); q-=2; }
321       }
322       ia=intg[abs(a)]; ib=intg[b];
323       if (pow) enter(ia,prime);
324       else
325       { enter(ia,-1); enter(ib,-1); enter(ia,1); enter(ib,1); }
326       zero(expnt,eexpnt);
327       if (wc>=wf) collect(wc,wf,1);
328       l=0;
329       for (k=exp;k>=1;k--) if ((x=expnt[k])!=0)
330       { *rpb=x; *(rpb-1)=k; rpb-=2; l+=2; }
331       *rpb=l; intg[i]=rpb; rpb--; wc=wf-2;
332       if (a<0)
333       { a= -a; p=cintg[i]; q=p+ *p-1;
334         while (q>p) { enter(cintg[*q],-*(q+1)); q-=2; }
335       }
336       ia=cintg[a]; ib=cintg[b];
337       if (pow) enter(ia,prime);
338       else
339       { enter(ia,-1); enter(ib,-1); enter(ia,1); enter(ib,1); }
340       zero(expnt,eexpnt);
341       if (wc>=wf) collect(wc,wf,1);
342       l=0;
343       for (k=exp;k>=1;k--) if ((x=expnt[k])!=0)
344       { *rpb=x; *(rpb-1)=k; rpb-=2; l+=2; }
345       *rpb=l; cintg[i]=rpb; rpb--;
346       if (rpb-rpf<marg)
347       { fprintf(stderr,"Out of space. Increase RSP.\n"); return(-1); }
348     }
349     printf("Computing images of cohomology gens.\n");
350 /* Now images of cohomology gens of Q and its conjugte are computed as strings,
351    and stored in imcg and cimcg.
352 */
353 
354     imcg=pcb; cimcg=imcg+inng;
355     if (pcb+2*(inng+nng)-pcptr>=ptrsp)
356     { fprintf(stderr,"Out of ptr space. Increase PTRSP.\n"); return(-1); }
357     for (i=1;i<=inng;i++)
358     { a=nsd1[i]-intexp; b=nsd2[i];
359       zero(rpf,rpf+nng);
360       p=bim[a]; p1=p+dim+1; q=intg[b]; q1=q+ *q;
361       while (--p1>p) if ((f1= *p1)!=0)
362       { c=p1-p+exp; q=intg[b];
363         while (++q<q1)
364         { d= *(q++); f2= *q;
365           if ((r= *(comptr[c]+d))!=0)
366           { r1=r+ *r; while (++r<r1) {rpf[*r]+= (*(r+1)*f1*f2); r++; }}
367         }
368       }
369       p=rpf; p1=p+nng;
370       while (++p<=p1) *p%=prime;
371       len=0;
372       for (j=1;j<=nng;j++) if (rpf[j]!=0) len+=2;
373       rpb-=len; imcg[i]=rpb; *rpb=len; compress(rpb,rpf,nng); rpb--;
374       zero(rpf,rpf+nng);
375       p=cbim[a]; p1=p+dim+1; q=cintg[b]; q1=q+ *q;
376       while (--p1>p) if ((f1= *p1)!=0)
377       { c=p1-p+exp; q=cintg[b];
378         while (++q<q1)
379         { d= *(q++); f2= *q;
380           if ((r= *(comptr[c]+d))!=0)
381           { r1=r+ *r; while (++r<r1) {rpf[*r]+= (*(r+1)*f1*f2); r++; }}
382         }
383       }
384       p=rpf; p1=p+nng;
385       while (++p<=p1) *p%=prime;
386       len=0;
387       for (j=1;j<=nng;j++) if (rpf[j]!=0) len+=2;
388       rpb-=len; cimcg[i]=rpb; *rpb=len; compress(rpb,rpf,nng); rpb--;
389       if (rpb-rpf-marg>rsp)
390       { fprintf(stderr,"Out of space. Increase RSP.\n"); return(-1); }
391     }
392     printf("Computing Sub-cohomology generators.\n");
393 /* Finally we are ready to compute gens of the subgroup of H^2(P,M) to be
394    factored out. These will be put into echelon form.
395 */
396     for (i=1;i<=inng;i++) if ((p=inteno[i])!=0)
397     { zero(nexpnt,enexpnt); p1=p+ *p;
398       while (--p1>p)
399       { a= *p1; f1= *(p1+1); p1--; q=rpf; q1=q+nng; r=q1; r1=nexpnt;
400         expand(imcg[a],q,nng); expand(cimcg[a],r,nng);
401         while (++q<=q1) { r++; r1++; *r1+=(f1* *q); *r1-=(f1* *r);}
402       }
403       r=nexpnt; nz=0; r1=r+nng;
404       while (++r<=r1) {*r%=prime; if (*r!=0) nz=1; }
405       if (nz)
406       { for (m=1;m<=nng;m++) if ((n=nexpnt[m])!=0)
407         { if (n<0) {n+=prime; nexpnt[m]=n;}
408           if ((q=subno[m])!=0)
409           { n=prime-n; r=q+ *q;
410             while (++q<r) {q1=nexpnt+ *q;q++; *q1+= (n* *q); *q1%=prime;}
411           }
412         }
413         for (m=1;m<=nng;m++) if ((n=nexpnt[m])!=0)
414         { n=pinv[n]; q=nexpnt+m-1; r=nexpnt+nng;
415           while (++q<=r) {*q *=n; *q%=prime; }
416           chsdim++; printf("chsdim=%2d,    bno=%2d\n",chsdim,m);
417           for (l=1;l<=nng;l++) if ((p=subno[l])!=0)
418           { r=rpb-nng; expand(p,r,nng);
419             if ((n=r[m])!=0)
420             { n=prime-n; q=r+nng; q1=nexpnt+1; r1=r;
421               while (++r1<=q) {*r1+=(n* *q1); *r1%=prime; q1++;}
422               len=0;
423               for (n=1;n<=nng;n++) if (r[n]!=0) len+=2;
424               if (len> *p) {p=rpf; subno[l]=p; rpf+=(len+1); }
425               *p=len; compress(p,r,nng);
426             }
427           }
428           subno[m]=rpf;
429           len=0;
430           for (n=1;n<=nng;n++) if (nexpnt[n]!=0) len+=2;
431           *rpf=len; compress(rpf,nexpnt,nng); rpf+=(len+1);
432           if (rpb-rpf<marg)
433           { fprintf(stderr,"Out of space. Increase RSP.\n"); return(-1); }
434           break;
435         }
436       }
437     }
438     printf("End of this action. chpdim,chsdim=%d,%d\n\n",chpdim,chsdim);
439     fflush(stdout);
440     if (chpdim==chsdim) return(2);
441   }
442   strcpy(outf1,inf0); onng=nng; outgp();
443   return(0);
444 }
445 
446 int
enter(int * g,int pow)447 enter (int *g, int pow)
448 /* Enters a power of the word pointed to by g into rel for collection. */
449 { int *ps,*pf,*pc,i,sgn;
450   if (pow<0) { sgn= -1; pow= -pow; pf=g+1; ps=g+ *g+1; }
451   else { sgn=1; ps=g-1; pf=g+ *g-1; }
452   for (i=1;i<=pow;i++)
453   { pc=ps;
454     while (pc!=pf) { pc +=(2*sgn); wc+=2; *wc= *pc; *(wc+1)= *(pc+1) *sgn; }
455   }
456 }
457 
458 int
entvec(int * h,int * g,int pow)459 entvec (int *h, int *g, int pow)
460 /* Similar, but g is a vector. Used only for H^1. */
461 { int i,j,l,*p,*q;
462   for (i=1;i<=dim;i++) if ((j=g[i])!=0)
463   { j*=pow; j%=prime; if (j<0) j+=prime;
464     wc+=2; *wc=exp+i; *(wc+1)=j;
465   }
466   if (h!=0)
467   { l= *h; p=h+l;
468     while (++h<p)
469     { q=nexpnt+(*h); *q+=(pow* *(++h)); *q%=prime; if (*q<0) *q+=prime;}
470   }
471 }
472 
473 int
expand(int * p1,int * p2,int len)474 expand (int *p1, int *p2, int len)
475 /* Expand word p1 to vector p2 of length len. */
476 { int l,*p,*q;
477   l= *p1; p=p1; q=p+l; zero(p2,p2+len);
478   while (++p<q) { p2[*p]= *(p+1); p++; }
479 }
480 
481 int
compress(int * p1,int * p2,int len)482 compress (int *p1, int *p2, int len)
483 /* compress vector p2 of length len to word p1. */
484 { int i,n,*p;
485   p=p1;
486   for (i=1;i<=len;i++) if ((n=p2[i])!=0) { *(++p)=i; *(++p)=n; }
487 }
488