#include "defs.h"
extern char inf[], outf[], temp[], temp2[], mspace[], *vec[], **mat[], cvec[],
pinv[], mstr[], full, intop, opt, aut;
extern short svec[], mdim, mv, mm, mpr, msl;
extern int space;
char prime;
short dim, maxnull;
FILE *ip, *op;
int pkprog(void)
{
char ngens, neg, fac, there, saved, gottm, gotsgn, err, digexp, nc, provn,
trd, gotfac, heldc, len, **m0, **m1, *m01, irr;
short nvecs, i, j, rno1, rno2, nlty, fnz, adno, sdim, qdim, tdim;
int msp;
irr = opt ? 1 : 0;
if ((ip = fopen(inf, "r")) == 0) {
fprintf(stderr, "Cannot open %s.\n", inf);
return (-1);
}
fscanf(ip, "%hd%hd%hd", &rno1, &dim, &rno2);
prime = rno1;
ngens = rno2;
if (prime > mpr) {
fprintf(stderr, "prime too big. Nothing to be done.\n");
return (-1);
}
if (dim > mdim) {
fprintf(stderr, "dim too big. Increase MDIM.\n");
return (-1);
}
if (ngens >= mm) {
fprintf(stderr, "Too many generators. Nothing to be done.\n");
return (-1);
}
nvecs = dim * (ngens + 1);
if (nvecs > mv) {
fprintf(stderr, "Too many vectors. Increase MV.\n");
return (-1);
}
msp = nvecs * dim;
if (msp > space) {
fprintf(stderr, "Not enough space. Increase SPACE.\n");
return (-1);
}
seeknln();
setpinv();
/* Set vector and matrix pointers, as usual.
We take care only to use ngens+1 matrices, thus saving as much storage as
possible. This means using temporary files to store matrices
occasionally.
*/
for (i = 0; i < nvecs; i++)
vec[i] = mspace - 1 + i * dim;
for (i = 0; i <= ngens; i++)
mat[i] = vec - 1 + i * dim;
for (i = 1; i <= ngens; i++)
readmat(mat[i]);
fclose(ip);
if (aut) {
printf("Enter maximum value of nullity that should be handled: ");
scanf("%hd", &maxnull);
}
m0 = mat[0];
m1 = mat[1];
m01 = m0[1];
/* The next section reads in the given expression in the generators, and
computes the corresponding matrix as m0. A temporary file is used to
remember the sum so far, whilst a product is being computed.
*/
while (1) {
printf(
"Enter element of group algebra. End expression with $. Example:\n");
printf("Enter 3a[3]a[3]a[2] + a[2] - a[4] as 3.3*3*2 + 2 - 4$\n");
fflush(stdout);
there = 0;
saved = 0;
heldc = 0;
err = 0;
while (heldc != '$') {
gotfac = 0;
gotsgn = 0;
gottm = 0;
provn = 0;
digexp = 0;
len = 0;
while (gottm == 0) {
if (heldc) {
nc = heldc;
heldc = 0;
}
else
nc = findc();
if (gotsgn == 0) {
if (nc == '-') {
neg = 1;
gotsgn = 1;
digexp = 1;
continue;
}
else if (nc == '+') {
neg = 0;
gotsgn = 1;
digexp = 1;
continue;
}
else if (there == 0) {
neg = 0;
gotsgn = 1;
digexp = 1;
}
}
if ((nc == '+' || nc == '-' || nc == '$') && digexp == 0 &&
(len != 0 || provn != 0)) {
heldc = nc;
gottm = 1;
if (gotfac == 0) {
if (provn) {
fac = neg ? prime - 1 : 1;
len = 1;
mstr[1] = provn - '0';
}
}
}
else if (nc == '.' && digexp == 0 && provn != 0 && gotfac == 0) {
gotfac = 1;
fac = provn - '0';
fac %= prime;
provn = 0;
if (neg)
fac = prime - fac;
digexp = 1;
}
else if (nc == '*' && digexp == 0 && (provn != 0 || len != 0)) {
if (gotfac == 0) {
gotfac = 1;
fac = neg ? prime - 1 : 1;
len = 1;
mstr[1] = provn - '0';
}
digexp = 1;
}
else if (digit(nc) && digexp) {
if (gotfac == 0)
provn = nc;
else {
len++;
mstr[len] = nc - '0';
}
digexp = 0;
}
else {
fprintf(stderr, "Format error; Try again.\n");
err = 1;
while (getchar() != '\n')
;
break;
}
}
if (err)
break;
if (len == 1) {
if (there)
sum(fac, mat[mstr[1]], m0);
else
ncopy(fac, mat[mstr[1]], m0);
}
else {
if (there)
/* We have a partial sum, and now another product to compute, so we
must store the partial sum in a temporary file.
*/
{
op = fopen(temp, "w");
printmat(m0);
saved = 1;
fclose(op);
}
ncopy(fac, mat[mstr[1]], m0);
for (i = 2; i <= len; i++)
prod(m0, mat[mstr[i]], m0);
if (saved) {
ip = fopen(temp, "r");
for (i = 1; i <= dim; i++)
rvecsum(1, m0[i]);
fclose(ip);
saved = 0;
}
}
there = 1;
}
if (err)
continue;
/* err means the expression input was garbled */
if (intop)
for (i = 1; i <= dim; i++) {
for (j = 1; j <= dim; j++)
printf("%3d", m0[i][j]);
printf("\n");
}
/* Store the matrix m0 in a temporary file temp. Then compute its nullity.
(nlty writes generators of the null space to another temporary file,
temp)
*/
op = fopen(temp2, "w");
printmat(m0);
fclose(op);
op = fopen(temp, "w");
nlty = null(m0, m1);
fclose(op);
ip = fopen(inf, "r");
seeknln();
readmat(m1);
fclose(ip);
if (nlty == 0 || (aut && nlty > maxnull))
continue;
if (aut)
break;
printf("Shall we use this matrix (y/n)? ");
nc = findc();
if (nc == 'y')
break;
}
/* Now we have chosen the matrix that we are going to use for the
irreducibility test. Next we arrange to consider the one-dimensional
subspaces of the null-space in order. cvec is used for this purpose.
*/
for (i = 1; i <= nlty; i++)
cvec[i] = 0;
fnz = nlty;
adno = nlty;
trd = 0;
while (fnz != 0) {
cvec[adno]++;
for (i = 1; i <= dim; i++)
m01[i] = 0;
/* Compute the current vector in the nullspace by reading from the file
temp, and store it in m01
*/
ip = fopen(temp, "r");
for (i = 1; i <= nlty; i++) {
if ((fac = cvec[i]) == 0)
seeknln();
else {
rvecsum(fac, m01);
seeknln();
}
}
fclose(ip);
if (intop) {
for (j = 1; j <= dim; j++)
printf("%3d", m01[j]);
printf("\n");
if (opt) {
printf("Shall we skip this one? ");
nc = findc();
if (nc == 'y')
goto next;
}
}
/* Now compute the subspace it generates */
sdim = spgen(m0, ngens);
if (intop) {
for (i = 1; i <= dim; i++)
printf("%3d", svec[i]);
printf("\n");
for (i = 1; i <= dim; i++) {
for (j = 1; j <= dim; j++)
printf("%3d", m0[i][j]);
printf("\n");
}
}
if (sdim < dim)
/* sdim<dim means the module is reducible */
if (opt == 0)
break;
else {
printf("Shall we compute (y/n)? ");
nc = findc();
if (nc == 'y') {
opt = 0;
break;
}
irr = 0;
}
next:
/* The last vector generated the whole space, so go on to the next */
adno = nlty;
while (cvec[adno] == prime - 1) {
cvec[adno] = 0;
adno--;
}
if (adno <= fnz) {
if (adno == fnz) {
cvec[adno] = 0;
adno--;
}
fnz--;
}
}
if (opt || sdim == dim)
/* Each vector in the null-space generated the whole space. Finally we have
to transpose everything, and try just one vector in the null-space.
*/
{
printf("Transforming.\n");
fflush(stdout);
trd = 1;
ip = fopen(temp2, "r");
readmat(m0);
fclose(ip);
trans(m0, m1);
op = fopen(temp, "w");
null1(m1, m0);
fclose(op);
/* That ruined m1 (the first generator), so we must re-read it */
ip = fopen(inf, "r");
seeknln();
readmat(m1);
fclose(ip);
for (i = 1; i <= ngens; i++) {
trans(mat[i], m0);
copy(m0, mat[i]);
}
ip = fopen(temp, "r");
for (i = 1; i <= dim; i++) {
fscanf(ip, "%hd", &rno1);
m01[i] = rno1;
}
fclose(ip);
sdim = spgen(m0, ngens);
if (opt && sdim < dim) {
printf("Shall we compute (y/n)? ");
nc = findc();
if (nc == 'y')
opt = 0;
else
irr = 0;
}
if (intop) {
for (i = 1; i <= dim; i++)
printf("%3d", svec[i]);
printf("\n");
for (i = 1; i <= dim; i++) {
for (j = 1; j <= dim; j++)
printf("%3d", m0[i][j]);
printf("\n");
}
}
}
if (opt && irr == 0) {
unlink(temp);
unlink(temp2);
return (0);
}
if (sdim == dim) {
printf("Module is irreducible.\n");
unlink(temp);
unlink(temp2);
return (0);
}
/* Space is reducible. Finally, we compute the generators of the subspace
and quotient space
*/
qdim = dim - sdim;
strcpy(outf, inf);
if (full) {
strcat(outf, "f");
tdim = dim;
}
else {
strcat(outf, "s");
tdim = sdim;
}
/* if we have transposed, then we first output to the temporary file,
and then later read it back in and transpose it back again.
*/
if (trd)
op = fopen(temp, "w");
else {
op = fopen(outf, "w");
fprintf(op, "%3d%5d%3d\n", prime, tdim, ngens);
}
opnmat(m0, ngens, tdim, 1);
if (trd == 0 || full)
fclose(op);
if (full == 0) {
strcpy(outf, inf);
strcat(outf, "q");
if (trd == 0) {
op = fopen(outf, "w");
fprintf(op, "%3d%5d%3d\n", prime, qdim, ngens);
}
opnmat(m0, ngens, dim, sdim + 1);
fclose(op);
}
if (trd) {
if (full == 0)
dim = sdim;
/* Retranspose */
ip = fopen(temp, "r");
op = fopen(outf, "w");
fprintf(op, "%3d%5d%3d\n", prime, dim, ngens);
for (i = 1; i <= ngens; i++) {
readmat(m0);
trans(m0, m1);
printmat(m1);
}
fclose(op);
if (full == 0) {
dim = qdim;
strcpy(outf, inf);
strcat(outf, "s");
op = fopen(outf, "w");
fprintf(op, "%3d%5d%3d\n", prime, dim, ngens);
for (i = 1; i <= ngens; i++) {
readmat(m0);
trans(m0, m1);
printmat(m1);
}
fclose(ip);
fclose(op);
}
}
unlink(temp);
unlink(temp2);
return (0);
}
void seeknln(void)
{
while (getc(ip) != '\n')
;
}
void setpinv(void)
{
int i, j;
for (i = 0; i < prime; i++)
pinv[i] = 0;
for (i = 1; i < prime; i++)
if (pinv[i] == 0)
for (j = 1; j < prime; j++)
if (i * j % prime == 1) {
pinv[i] = j;
pinv[j] = i;
break;
}
}
int findc(void)
{
char c;
while ((c = getchar()) == ' ' || c == '\n')
;
return (c);
}
int digit(int c)
{
if (c >= '1' && c <= '9')
return (1);
else
return (0);
}
¤ Dauer der Verarbeitung: 0.7 Sekunden
¤
*© Formatika GbR, Deutschland
|
|