1 /* gpaxioms.c 14.12.94.
2 * 13/10/98 large scale reorganisation to omit globals, etc.
3 * 25/5/98 added -n option, which means do not form the generalised
4 * length 2 multiplier, but check all group relations, including the
5 * inverse relations, by forming composites of the multipliers.
6 * This may be advantageous when there is a very large number of
7 * generators.
8 *
9 * 5/2/98 change generators from type char to type `gen'.
10 * 1/11/96 added experimental option -x, meaning read group relators from a
11 * different file (groupname_x) and do not balance relators when axiom checking.
12 * This is for the case when generators may reduce to words of length
13 * greater than one, when using orderings other than shortlex.
14 *
15 * 8/1/96 - output a file gpname.kbprog.exitcode containing a GAP statement
16 * giving the exit code - for use with GAP interface
17 * 15/3/96 changed syntax of -cos call to
18 * gpmakefsa -cos groupname [cosname]
19 * where cosname defaults to "cos".
20 * In the coset case, we can now read the relators from groupname rather than
21 * groupname.cosname, which is better.
22 *
23 * 17/1/96 - remove all of the processing of redundant generators, which is
24 * no longer necessary, and merely complicates the program.
25 *
26 * 25/9/95 -added capability of doing the calculations for coset
27 * automatic groups - with the -cos option
28 *
29 * Carry out the axiom-checking for a short-lex (or wtlex) automatic group.
30 *
31 * SYNOPSIS:
32 * gpaxioms [-ip d/s[dr]] [-op d/s] [-silent] [-v] [-l] [-f] [-s] [-n]
33 * [-cos] groupname [-cosname]
34 *
35 * OPTIONS:
36 * -ip d/s[dr] input in dense or sparse format - dense is default
37 * -op d/s output in dense or sparse format - sparse is default
38 * -v verbose
39 * -silent no diagnostics
40 * -l/-h large/huge hash-tables (for big examples)
41 * -f read the transition table repeatedly from file while mimimizing,
42 * in calls of fsa_genmult2 and fsa_composite.
43 * This avoids storing large tables, but is a little slower.
44 * -s Throw away files immediately after use whenever possible, to
45 * save disk-space. This will slow things down considerably.
46 * -n do not form generalised length 2 multiplier.
47 * -cos Do the calculation for coset automatic groups (by setting
48 * global variable cosets to be TRUE).
49 */
50
51 #include <stdio.h>
52
53 #include "defs.h"
54 #include "fsa.h"
55 #include "rws.h"
56 #include "definitions.h"
57
58 #define MAXEQNS 1024
59 #define MAXREDUCELEN 2048
60
61 static rewriting_system rws, *rwsptr;
62 static boolean xset = FALSE;
63
64 static char gpname[100], cosgpname[100], inf[100], outf[100], outfec[100],
65 fsaname[100], tablefilename[100], *rwsfilename;
66 static fsa genmult, genmult2, *genmult2ptr, mult1, mult2, *compmult;
67 static int ngens, neqns, *inv, nlabgm2;
68 static int numstoredmult;
69 static reduction_equation *eqn;
70 static gen *lhs, *rhs, ***labgm2;
71 static char **storedmult;
72 static boolean allshort;
73 static storage_type ip_store = DENSE;
74 static int dr = 0;
75 static storage_type op_store = SPARSE;
76 static boolean readback = TRUE;
77 static boolean keepfiles = TRUE;
78 static boolean usegm2 = TRUE;
79 static FILE *rfile, *wfile;
80
81 /* Functions defined in this file */
82
83 static void balance_equations(void);
84 static int check_short_relation(void);
85 static int check_long_relation(void);
86 static char *file_suffix(gen *w);
87 static int long_word_multiplier(gen *w, char *s);
88 static void badusage(void);
89
main(int argc,char * argv[])90 int main(int argc, char *argv[])
91 {
92 int arg, i, ct, clr;
93 boolean seengpname, seencosname, cosets;
94
95 setbuf(stdout, (char *)0);
96 setbuf(stderr, (char *)0);
97
98 rwsptr = &rws;
99 rwsptr->maxeqns = MAXEQNS;
100 rwsptr->maxreducelen = MAXREDUCELEN;
101 rwsptr->maxreducelenset = FALSE;
102 rwsptr->cosets = FALSE;
103 /* even in the cosets case we read relations from original group file */
104 rwsptr->inv_of = 0;
105 rwsptr->weight = 0;
106 rwsptr->level = 0;
107 rwsptr->history = 0;
108 rwsptr->slowhistory = 0;
109 rwsptr->slowhistorysp = 0;
110 rwsptr->preflen = 0;
111 rwsptr->prefno = 0;
112 arg = 1;
113 seengpname = seencosname = cosets = FALSE;
114 while (argc > arg) {
115 if (strcmp(argv[arg], "-ip") == 0) {
116 arg++;
117 if (arg >= argc)
118 badusage();
119 if (strcmp(argv[arg], "d") == 0)
120 ip_store = DENSE;
121 else if (argv[arg][0] == 's') {
122 ip_store = SPARSE;
123 if (stringlen(argv[arg]) > 1)
124 dr = atoi(argv[arg] + 1);
125 }
126 else
127 badusage();
128 }
129 else if (strcmp(argv[arg], "-op") == 0) {
130 arg++;
131 if (arg >= argc)
132 badusage();
133 if (strcmp(argv[arg], "d") == 0)
134 op_store = DENSE;
135 else if (strcmp(argv[arg], "s") == 0)
136 op_store = SPARSE;
137 else
138 badusage();
139 }
140 else if (strcmp(argv[arg], "-silent") == 0)
141 kbm_print_level = 0;
142 else if (strcmp(argv[arg], "-v") == 0)
143 kbm_print_level = 2;
144 else if (strcmp(argv[arg], "-vv") == 0)
145 kbm_print_level = 3;
146 else if (strcmp(argv[arg], "-l") == 0)
147 kbm_large = TRUE;
148 else if (strcmp(argv[arg], "-h") == 0)
149 kbm_huge = TRUE;
150 else if (strcmp(argv[arg], "-f") == 0)
151 readback = FALSE;
152 else if (strcmp(argv[arg], "-s") == 0)
153 keepfiles = FALSE;
154 else if (strncmp(argv[arg], "-cos", 4) == 0)
155 cosets = TRUE;
156 else if (strcmp(argv[arg], "-x") == 0)
157 xset = TRUE;
158 else if (strcmp(argv[arg], "-n") == 0)
159 usegm2 = FALSE;
160 else if (argv[arg][0] == '-')
161 badusage();
162 else if (!seengpname) {
163 seengpname = TRUE;
164 strcpy(gpname, argv[arg]);
165 }
166 else if (!seencosname) {
167 seencosname = TRUE;
168 sprintf(cosgpname, "%s.%s", gpname, argv[arg]);
169 }
170 else
171 badusage();
172 arg++;
173 }
174 if (!seengpname)
175 badusage();
176 if (cosets && !seencosname)
177 sprintf(cosgpname, "%s.cos", gpname);
178
179 if (cosets)
180 sprintf(outfec, "%s.axioms.ec", cosgpname);
181 else
182 sprintf(outfec, "%s.axioms.ec", gpname);
183
184 rwsfilename = cosets ? cosgpname : gpname;
185 strcpy(tablefilename, rwsfilename);
186 strcat(tablefilename, "temp_axXXX");
187
188 /* First read in the defining relations for the group. */
189 strcpy(inf, gpname);
190 if (xset)
191 strcat(inf, "_x");
192 if ((rfile = fopen(inf, "r")) == 0) {
193 fprintf(stderr, "Cannot open file %s.\n", inf);
194 exit(1);
195 }
196 read_kbinput_simple(rfile, FALSE, rwsptr);
197 fclose(rfile);
198 ngens = rws.num_gens;
199 neqns = rws.num_eqns;
200 inv = rws.inv_of;
201 eqn = rws.eqns;
202
203 /* Now balance the equations. */
204 balance_equations();
205
206 if (usegm2) {
207 allshort = TRUE;
208 /* See if all relations are short (length(lhs)=2 ) */
209 for (i = 1; i <= neqns; i++)
210 if (genstrlen(eqn[i].lhs) > 2) {
211 allshort = FALSE;
212 break;
213 }
214 }
215 else
216 allshort = FALSE;
217
218 if (usegm2) {
219 /* Now calculate the general multiplier for words of length 2.
220 * If allshort is true, we don't need the transitions - only the state
221 * labels.
222 */
223 strcpy(inf, rwsfilename);
224 strcat(inf, ".gm");
225 if ((rfile = fopen(inf, "r")) == 0) {
226 fprintf(stderr, "Cannot open file %s.\n", inf);
227 exit(1);
228 }
229 fsa_read(rfile, &genmult, ip_store, dr, 0, TRUE, fsaname);
230 fclose(rfile);
231
232 if (kbm_print_level > 1)
233 printf(" #Calculating general word-length 2 multiplier.\n");
234 if (allshort) {
235 genmult2ptr = fsa_genmult2(&genmult, op_store, TRUE, "", FALSE);
236 if (genmult2ptr == 0)
237 exit(1);
238 if (kbm_print_level > 1)
239 printf(" #Number of states of genmult2 = %d.\n",
240 genmult2ptr->states->size);
241 }
242 else {
243 genmult2ptr =
244 fsa_genmult2(&genmult, op_store, TRUE, tablefilename, readback);
245 if (genmult2ptr == 0)
246 exit(1);
247 if (kbm_print_level > 1)
248 printf(" #Number of states of genmult2 = %d.\n",
249 genmult2ptr->states->size);
250
251 if (readback) {
252 if (fsa_labeled_minimize(genmult2ptr) == -1)
253 exit(1);
254 }
255 else {
256 if (fsa_ip_labeled_minimize(genmult2ptr) == -1)
257 exit(1);
258 }
259 if (kbm_print_level > 1)
260 printf(" #Number of states of genmult2 after minimization = %d.\n",
261 genmult2ptr->states->size);
262 strcpy(fsaname, rws.name);
263 strcat(fsaname, ".gm2");
264 strcpy(outf, rwsfilename);
265 strcat(outf, ".gm2");
266 wfile = fopen(outf, "w");
267 fsa_print(wfile, genmult2ptr, fsaname);
268 if (kbm_print_level > 0)
269 printf("#General length-2 multiplier with %d states computed.\n",
270 genmult2ptr->states->size);
271 fclose(wfile);
272 }
273
274 /* Now we check axioms for inverse-relators and short-relators, by simply
275 * checking that the state-labels for the lhs and rhs correspond in
276 * *genmult2ptr.
277 */
278 if (kbm_print_level > 0) {
279 printf("#Checking inverse and short relations.\n");
280 }
281 nlabgm2 = genmult2ptr->states->labels->size;
282 labgm2 = genmult2ptr->states->labels->wordslist;
283 lhs = rws.testword1;
284 rhs = rws.testword2;
285 for (i = 1; i <= ngens; i++)
286 if (inv[i]) {
287 lhs[0] = i;
288 lhs[1] = inv[i];
289 lhs[2] = '\0';
290 rhs[0] = '\0';
291 if (check_short_relation() == 2)
292 exit(2);
293 }
294 for (i = 1; i <= neqns; i++)
295 if (genstrlen(eqn[i].lhs) == 2) {
296 lhs = eqn[i].lhs;
297 rhs = eqn[i].rhs;
298 if (check_short_relation() == 2)
299 exit(2);
300 }
301 fsa_clear(genmult2ptr);
302 }
303
304 /* Finally we deal with the other relations, if any */
305 if (!allshort) {
306 /* If keepfiles is false, then we will throw away every multiplier
307 * immediately after it has been used. Otherwise, we will keep them, in case
308 * they are needed again. We store a list of words for which we have got the
309 * multipliers in storedmult. We first form a rough upper bound on how long
310 * this list could get - ngens + total relator length - 1.
311 */
312 strcpy(fsaname, rws.name);
313 strcat(fsaname, ".mult"); /* this is unimportant, since file is temporary */
314 if (keepfiles) {
315 ct = usegm2 ? ngens : 2 * ngens;
316 for (i = 1; i <= neqns; i++)
317 if (!usegm2 || genstrlen(eqn[i].lhs) > 2)
318 ct += (genstrlen(eqn[i].lhs) + genstrlen(eqn[i].rhs));
319 tmalloc(storedmult, char *, ct);
320 numstoredmult = 0;
321 }
322
323 if (!usegm2)
324 for (i = 1; i <= ngens; i++)
325 if (inv[i]) {
326 lhs = rws.testword1;
327 rhs = rws.testword2;
328 lhs[0] = i;
329 lhs[1] = inv[i];
330 lhs[2] = '\0';
331 rhs[0] = '\0';
332 clr = check_long_relation();
333 if (clr == -1)
334 exit(1);
335 if (clr == 2)
336 exit(2);
337 }
338 for (i = 1; i <= neqns; i++)
339 if (!usegm2 || genstrlen(eqn[i].lhs) > 2) {
340 lhs = eqn[i].lhs;
341 rhs = eqn[i].rhs;
342 clr = check_long_relation();
343 if (clr == -1)
344 exit(1);
345 if (clr == 2)
346 exit(2);
347 }
348 if (keepfiles) {
349 for (i = 1; i <= numstoredmult; i++) {
350 sprintf(outf, "%s.m%s", rwsfilename, storedmult[i]);
351 unlink(outf);
352 tfree(storedmult[i]);
353 }
354 tfree(storedmult);
355 }
356 strcpy(outf, rwsfilename);
357 strcat(outf, ".gm2");
358 unlink(outf);
359 }
360 tfree(genmult2ptr);
361 rws_clear(&rws);
362 if (kbm_print_level > 0)
363 printf("#Axiom checking succeeded.\n");
364 wfile = fopen(outfec, "w");
365 fprintf(wfile, "_ExitCode := 0;\n");
366 fclose(wfile);
367 exit(0);
368 }
369
balance_equations(void)370 void balance_equations(void)
371 {
372 int i, l1, l2;
373 gen *lhs, *rhs;
374 if (kbm_print_level > 1)
375 printf(" #Simplifying and balancing inverse-list and relations.\n");
376
377 for (i = 1; i <= neqns; i++) {
378 lhs = eqn[i].lhs;
379 rhs = eqn[i].rhs;
380 l1 = genstrlen(lhs);
381 l2 = genstrlen(rhs);
382 if (l1 + l2 <= 2) { /*We no longer need keep this equation */
383 if (kbm_print_level > 1)
384 printf(" #Equation number %d is being discarded.\n", i);
385 lhs[0] = rhs[0] = '\0';
386 }
387 else { /* balance the lengths of the lhs and rhs. */
388 if (l2 > l1) { /* swap lhs and rhs */
389 eqn[i].lhs = rhs;
390 eqn[i].rhs = lhs;
391 lhs = eqn[i].lhs;
392 rhs = eqn[i].rhs;
393 l1 = genstrlen(lhs);
394 l2 = genstrlen(rhs);
395 }
396 if (!xset)
397 while (l1 - l2 > 1) { /* move a generator from lhs to rhs */
398 rhs[l2] = inv[lhs[l1 - 1]];
399 l2++;
400 rhs[l2] = '\0';
401 l1--;
402 lhs[l1] = '\0';
403 }
404 }
405 }
406 }
407
408 /* Check that the general multiplier automaton *genmult2ptr for words of
409 * length two satisfies the short-equation lhs = rhs.
410 * This is done merely by looking at the state-labels of *genmult2ptr.
411 * The transitions are not needed.
412 */
check_short_relation(void)413 int check_short_relation(void)
414 {
415 int i, j;
416 gen **lab;
417 boolean foundlhs, foundrhs;
418 if (kbm_print_level > 1) {
419 kbm_buffer[0] = '\0';
420 add_to_buffer(0, " #Checking short relation: ");
421 add_word_to_buffer(stdout, lhs, rws.gen_name);
422 add_to_buffer(0, " = ");
423 add_word_to_buffer(stdout, rhs, rws.gen_name);
424 printbuffer(stdout);
425 }
426 /* pad rhs to length 2 if necessary */
427 if (genstrlen(rhs) == 0) {
428 rhs[0] = rhs[1] = ngens + 1;
429 rhs[2] = '\0';
430 }
431 else if (genstrlen(rhs) == 1) {
432 rhs[1] = ngens + 1;
433 rhs[2] = '\0';
434 }
435 /* Search through the state-labels of genmult2ptr.
436 * For the relation to be satisfied by the fsa, it must be the case that
437 * lhs occurs in a label <=> rhs occurs in that label.
438 */
439 for (i = 1; i <= nlabgm2; i++) {
440 foundlhs = foundrhs = FALSE;
441 lab = labgm2[i];
442 j = 0;
443 while (lab[j]) {
444 if (lab[j][0] == lhs[0] && lab[j][1] == lhs[1])
445 foundlhs = TRUE;
446 if (lab[j][0] == rhs[0] && lab[j][1] == rhs[1])
447 foundrhs = TRUE;
448 j++;
449 }
450 if (foundlhs != foundrhs) {
451 kbm_buffer[0] = '\0';
452 add_to_buffer(0, "#Relation check fails for short relation: ");
453 add_word_to_buffer(stdout, lhs, rws.gen_name);
454 add_to_buffer(0, " = ");
455 add_word_to_buffer(stdout, rhs, rws.gen_name);
456 printbuffer(stdout);
457 wfile = fopen(outfec, "w");
458 fprintf(wfile, "_ExitCode := 2;\n");
459 fclose(wfile);
460 return 2;
461 }
462 }
463 return 0;
464 }
465
466 /* Check that the multipliers satisfy the long relation of which the
467 * left and right hand sides are store din lhs and rhs, by forming
468 * the necessary composites.
469 */
check_long_relation(void)470 int check_long_relation(void)
471 {
472 int j, l;
473 char *suffl, *suffr;
474 boolean gotl, gotr;
475 if (kbm_print_level > 0) {
476 kbm_buffer[0] = '\0';
477 add_to_buffer(0, "#Checking relation: ");
478 add_word_to_buffer(stdout, lhs, rws.gen_name);
479 add_to_buffer(0, " = ");
480 if ((l = stringlen(kbm_buffer)) > 44) {
481 printbuffer(stdout);
482 add_to_buffer(21, "");
483 }
484 add_word_to_buffer(stdout, rhs, rws.gen_name);
485 printbuffer(stdout);
486 }
487 suffl = file_suffix(lhs);
488 suffr = file_suffix(rhs);
489 gotl = gotr = FALSE;
490 if (keepfiles) {
491 /* Check to see if we have either of these multipliers already */
492 for (j = 1; j <= numstoredmult; j++) {
493 if (strcmp(suffl, storedmult[j]) == 0)
494 gotl = TRUE;
495 if (strcmp(suffr, storedmult[j]) == 0)
496 gotr = TRUE;
497 }
498 }
499 if (!gotl) {
500 if (long_word_multiplier(lhs, suffl) == -1)
501 return -1;
502 }
503 if (!gotr) {
504 if (long_word_multiplier(rhs, suffr) == -1)
505 return -1;
506 }
507 /* Read in the two multipliers and compare them */
508 sprintf(inf, "%s.m%s", rwsfilename, suffl);
509
510 if ((rfile = fopen(inf, "r")) == 0) {
511 fprintf(stderr, "Cannot open file %s.\n", inf);
512 exit(1);
513 }
514 fsa_read(rfile, &mult1, ip_store, 0, 0, TRUE, fsaname);
515 fclose(rfile);
516 sprintf(inf, "%s.m%s", rwsfilename, suffr);
517 if ((rfile = fopen(inf, "r")) == 0) {
518 fprintf(stderr, "Cannot open file %s.\n", inf);
519 exit(1);
520 }
521 fsa_read(rfile, &mult2, ip_store, 0, 0, TRUE, fsaname);
522 fclose(rfile);
523 if (!fsa_equal(&mult1, &mult2)) {
524 kbm_buffer[0] = '\0';
525 add_to_buffer(0, "#Relation check fails for relation: ");
526 add_word_to_buffer(stdout, lhs, rws.gen_name);
527 add_to_buffer(0, " = ");
528 add_word_to_buffer(stdout, rhs, rws.gen_name);
529 printbuffer(stdout);
530 wfile = fopen(outfec, "w");
531 fprintf(wfile, "_ExitCode := 2;\n");
532 fclose(wfile);
533 return 2;
534 }
535 fsa_clear(&mult1);
536 fsa_clear(&mult2);
537 if (keepfiles) {
538 if (gotl)
539 tfree(suffl) else storedmult[++numstoredmult] = suffl;
540 if (gotr)
541 tfree(suffr) else storedmult[++numstoredmult] = suffr;
542 }
543 else {
544 sprintf(inf, "%s.m%s", rwsfilename, suffl);
545 unlink(inf);
546 sprintf(inf, "%s.m%s", rwsfilename, suffr);
547 unlink(inf);
548 tfree(suffl);
549 tfree(suffr);
550 }
551 return 0;
552 }
553
554 /* For a word w in the generators, this function returns a corresponding
555 * string with the terms of w replaced by integers separated by '_'.
556 * This is used as a suffix in the filenames used for storing the
557 * corresponding multiplier fsa's.
558 */
file_suffix(gen * w)559 char *file_suffix(gen *w)
560 {
561 char *s;
562 gen *p;
563 boolean first;
564 int len;
565 /* First work out the length of the required string. */
566 len = genstrlen(w);
567 if (len == 0) {
568 tmalloc(s, char, 2);
569 s[0] = '0';
570 s[1] = '\0';
571 return s;
572 }
573 p = w - 1;
574 while (*(++p) != 0)
575 len += int_len((int)(*p));
576 tmalloc(s, char, len);
577 s[0] = '\0';
578 first = TRUE;
579 p = w - 1;
580 while (*(++p) != 0) {
581 if (first)
582 first = FALSE;
583 else
584 sprintf(s + stringlen(s), "_");
585 sprintf(s + stringlen(s), "%d", *p);
586 }
587 return s;
588 }
589
590 /* Calculate the multiplier associated with the word w.
591 * s is the suffix of the file in which it will be stored.
592 * (s has been derived from w by a call of file_suffix).
593 */
long_word_multiplier(gen * w,char * s)594 int long_word_multiplier(gen *w, char *s)
595 {
596 int i, l;
597 gen *wl, *wlt, *wr, *wrt;
598 char *suffl, *sufflt, *suffr, *suffrt;
599 boolean gotl, gotr, gotlt, gotrt;
600 if (kbm_print_level >= 3) {
601 kbm_buffer[0] = '\0';
602 add_to_buffer(0, " #Calculating multiplier for word: ");
603 add_word_to_buffer(stdout, w, rws.gen_name);
604 printbuffer(stdout);
605 }
606 l = genstrlen(w);
607
608 if (l <= 1) { /* Length <=1 - use fsa_makemult */
609 strcpy(inf, rwsfilename);
610 strcat(inf, ".gm");
611 if ((rfile = fopen(inf, "r")) == 0) {
612 fprintf(stderr, "Cannot open file %s.\n", inf);
613 exit(1);
614 }
615 fsa_read(rfile, &genmult, op_store, 0, 0, TRUE, fsaname);
616 fclose(rfile);
617 if (fsa_makemult(&genmult, w[0]) == -1)
618 return -1;
619 if (fsa_minimize(&genmult) == -1)
620 return -1;
621 sprintf(outf, "%s.m%s", rwsfilename, s);
622 wfile = fopen(outf, "w");
623 fsa_print(wfile, &genmult, fsaname);
624 fclose(wfile);
625 fsa_clear(&genmult);
626 }
627 else if (usegm2 && l == 2) { /* Length 2 - use fsa_makemult2 */
628 strcpy(inf, rwsfilename);
629 strcat(inf, ".gm2");
630 if ((rfile = fopen(inf, "r")) == 0) {
631 fprintf(stderr, "Cannot open file %s.\n", inf);
632 exit(1);
633 }
634 fsa_read(rfile, &genmult2, op_store, 0, 0, TRUE, fsaname);
635 fclose(rfile);
636 if (fsa_makemult2(&genmult2, w[0], w[1]) == -1)
637 return -1;
638 if (fsa_minimize(&genmult2) == -1)
639 return -1;
640 sprintf(outf, "%s.m%s", rwsfilename, s);
641 wfile = fopen(outf, "w");
642 fsa_print(wfile, &genmult2, fsaname);
643 fclose(wfile);
644 fsa_clear(&genmult2);
645 }
646 else { /* general case - we have to split w up */
647 if (l % 2 == 0) {
648 tmalloc(wl, gen, l / 2 + 1);
649 tmalloc(wr, gen, l / 2 + 1);
650 for (i = 0; i < l / 2; i++)
651 wl[i] = w[i];
652 wl[l / 2] = '\0';
653 genstrcpy(wr, w + l / 2);
654 suffl = file_suffix(wl);
655 suffr = file_suffix(wr);
656 }
657 else {
658 tmalloc(wl, gen, l / 2 + 2);
659 tmalloc(wr, gen, l / 2 + 1);
660 for (i = 0; i <= l / 2; i++)
661 wl[i] = w[i];
662 wl[l / 2 + 1] = '\0';
663 genstrcpy(wr, w + l / 2 + 1);
664 suffl = file_suffix(wl);
665 suffr = file_suffix(wr);
666 }
667 /* See whether we have either of them already */
668 gotl = gotr = FALSE;
669 if (keepfiles) {
670 for (i = 1; i <= numstoredmult; i++) {
671 if (strcmp(suffl, storedmult[i]) == 0)
672 gotl = TRUE;
673 if (strcmp(suffr, storedmult[i]) == 0)
674 gotr = TRUE;
675 }
676 }
677
678 if (keepfiles && l % 2 == 1 && (!gotl || !gotr)) {
679 /* In this case, there are two possible ways to split w up -
680 * we see if the other way has more multipliers already stored.
681 */
682 tmalloc(wlt, gen, l / 2 + 1);
683 tmalloc(wrt, gen, l / 2 + 2);
684 for (i = 0; i < l / 2; i++)
685 wlt[i] = w[i];
686 wlt[l / 2] = '\0';
687 genstrcpy(wrt, w + l / 2);
688 sufflt = file_suffix(wlt);
689 suffrt = file_suffix(wrt);
690 gotlt = gotrt = FALSE;
691 for (i = 1; i <= numstoredmult; i++) {
692 if (strcmp(sufflt, storedmult[i]) == 0)
693 gotlt = TRUE;
694 if (strcmp(suffrt, storedmult[i]) == 0)
695 gotrt = TRUE;
696 }
697 if ((gotlt && gotrt) || ((gotlt || gotrt) && !gotl && !gotr)) {
698 tfree(wl);
699 tfree(wr);
700 tfree(suffl);
701 tfree(suffr);
702 wl = wlt;
703 wr = wrt;
704 suffl = sufflt;
705 suffr = suffrt;
706 gotl = gotlt;
707 gotr = gotrt;
708 }
709 else {
710 tfree(wlt);
711 tfree(wrt);
712 tfree(sufflt);
713 tfree(suffrt);
714 }
715 }
716 if (!gotl) {
717 if (long_word_multiplier(wl, suffl) == -1)
718 return -1;
719 }
720 if (!gotr && genstrcmp(wl, wr) != 0) {
721 if (keepfiles) {
722 /* Check again to see if we have got it recently */
723 for (i = 1; i <= numstoredmult; i++)
724 if (strcmp(suffr, storedmult[i]) == 0)
725 gotr = TRUE;
726 }
727 if (!gotr) {
728 if (long_word_multiplier(wr, suffr) == -1)
729 return -1;
730 }
731 }
732 /* Read back in the two multipliers and form their composite */
733 sprintf(inf, "%s.m%s", rwsfilename, suffl);
734 if ((rfile = fopen(inf, "r")) == 0) {
735 fprintf(stderr, "Cannot open file %s.\n", inf);
736 exit(1);
737 }
738 fsa_read(rfile, &mult1, ip_store, dr, 0, TRUE, fsaname);
739 fclose(rfile);
740 sprintf(inf, "%s.m%s", rwsfilename, suffr);
741 if ((rfile = fopen(inf, "r")) == 0) {
742 fprintf(stderr, "Cannot open file %s.\n", inf);
743 exit(1);
744 }
745 fsa_read(rfile, &mult2, ip_store, dr, 0, TRUE, fsaname);
746 fclose(rfile);
747
748 compmult =
749 fsa_composite(&mult1, &mult2, op_store, TRUE, tablefilename, readback);
750 if (compmult == 0)
751 return -1;
752 fsa_clear(&mult1);
753 fsa_clear(&mult2);
754 if (readback) {
755 if (fsa_minimize(compmult) == -1)
756 return -1;
757 }
758 else {
759 if (fsa_ip_minimize(compmult) == -1)
760 return -1;
761 }
762 sprintf(outf, "%s.m%s", rwsfilename, s);
763 wfile = fopen(outf, "w");
764 fsa_print(wfile, compmult, fsaname);
765 fclose(wfile);
766 fsa_clear(compmult);
767 tfree(compmult);
768
769 if (keepfiles) {
770 if (gotl)
771 tfree(suffl) else storedmult[++numstoredmult] = suffl;
772 if (gotr)
773 tfree(suffr) else storedmult[++numstoredmult] = suffr;
774 }
775 else {
776 sprintf(inf, "%s.m%s", rwsfilename, suffl);
777 unlink(inf);
778 sprintf(inf, "%s.m%s", rwsfilename, suffr);
779 unlink(inf);
780 tfree(suffl);
781 tfree(suffr);
782 }
783 tfree(wl);
784 tfree(wr);
785 }
786 return 0;
787 }
788
badusage(void)789 void badusage(void)
790 {
791 fprintf(stderr, "Usage: gpaxioms [-ip d/s[dr]] [-op d/s] [-silent] [-v] [-l] "
792 "[-f] [-n]\n");
793 fprintf(stderr, "\t\t[-cos] groupname [cosname].\n");
794 exit(1);
795 }
796