1 /* File compgrp.c.  Contains main program for command compgrp, which can be
2    used to compare two groups.  The command format is
3 
4       compgrp  <options>  <group1>  <group2>
5 
6    where <group1> and <group2> are the permutation groups to be compared.
7    The command prints one of the following messages:
8 
9       i)   <group1> and <group2> are equal.
10       ii)  <group1> is properly contained in <group2>.
11       iii) <group2> is properly contained in <group1>.
12       iv)  Neither of <group1> or <group2> is contained in the other.
13 
14    The return value is 0, 1, 2, or 3 depending on whether (i), (ii), (iii),
15    or (iv) above hold, respectively.  If an error occurs, the return code
16    is 4.
17 
18    The only options are -c and -n (and the special options -l and -v, which
19    have their standard meaning).  If -c is specified, the program checks
20    whether the two groups centralize each other.  If -n is specified, it
21    checks whether either group normalizes the other.
22 */
23 
24 #include <errno.h>
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 
30 #define MAIN
31 
32 #include "group.h"
33 #include "groupio.h"
34 
35 #include "errmesg.h"
36 #include "permgrp.h"
37 #include "permut.h"
38 #include "readgrp.h"
39 #include "readpar.h"
40 #include "readper.h"
41 #include "readpts.h"
42 #include "util.h"
43 
44 /* Nonstandard error return code. */
45 #undef ERROR_RETURN_CODE
46 #define ERROR_RETURN_CODE 4
47 
48 static int comparePerm(
49    const Permutation *const perm1,
50    const Permutation *const perm2);
51 static int comparePointSet(
52    const PointSet *const set1,
53    const PointSet *const set2);
54 static int comparePartition(
55    const Partition *const partn1,
56    const Partition *const partn2);
57 static void verifyOptions(void);
58 
59 GroupOptions options;
60 
61 
main(int argc,char * argv[])62 int main( int argc, char *argv[])
63 {
64    char group1FileName[MAX_FILE_NAME_LENGTH] = "",
65         group2FileName[MAX_FILE_NAME_LENGTH] = "",
66         group1LibraryName[MAX_NAME_LENGTH] = "",
67         group2LibraryName[MAX_NAME_LENGTH] = "",
68         prefix[MAX_FILE_NAME_LENGTH] = "",
69         suffix[MAX_NAME_LENGTH] = "";
70    PermGroup *group1, *group2 = NULL;
71    Permutation *perm1, *perm2 = NULL;
72    Partition *partn1, *partn2 = NULL;
73    PointSet *set1, *set2 = NULL;
74    Unsigned optionCountPlus1, i, j;
75    Unsigned normalizeFlag = FALSE, centralizeFlag = FALSE,
76             skipNormalize = FALSE, returnCode, degree;
77    BOOLEAN comparePermFlag = FALSE, comparePointSetFlag = FALSE,
78            comparePartitionFlag = FALSE;
79 
80    /* If there are no options, provide usage information and exit. */
81    if ( argc == 1 ) {
82       printf( "\nUsage:  compgrp [-n] [-c] permGroup1 [permGroup2]\n");
83       return 0;
84    }
85    if ( argc == 2 && strncmp( argv[1], "-perm:", 6) == 0 ) {
86       printf( "\nUsage:  compper degree permutation1 [permutation2]\n");
87       return 0;
88    }
89    if ( argc == 2 && strncmp( argv[1], "-set:", 5) == 0 ) {
90       printf( "\nUsage:  compset degree set1 [set2]\n");
91       return 0;
92    }
93    if ( argc == 2 && strncmp( argv[1], "-partition:", 11 ) == 0 ) {
94       printf( "\nUsage:  comppar degree partition1 [partition2]\n");
95       return 0;
96    }
97 
98    /* Count the number of options. */
99    for ( optionCountPlus1 = 1 ; optionCountPlus1 <= argc-1 &&
100               argv[optionCountPlus1][0] == '-' ; ++optionCountPlus1 )
101       ;
102 
103    /* Translate options to lower case. */
104    for ( i = 1 ; i < optionCountPlus1 ; ++i ) {
105       for ( j = 1 ; argv[i][j] != ':' && argv[i][j] != '\0' ; ++j )
106 #ifdef EBCDIC
107          argv[i][j] = ( argv[i][j] >= 'A' && argv[i][j] <= 'I' ||
108                         argv[i][j] >= 'J' && argv[i][j] <= 'R' ||
109                         argv[i][j] >= 'S' && argv[i][j] <= 'Z' ) ?
110                         (argv[i][j] + 'a' - 'A') : argv[i][j];
111 #else
112          argv[i][j] = (argv[i][j] >= 'A' && argv[i][j] <= 'Z') ?
113                       (argv[i][j] + 'a' - 'A') : argv[i][j];
114 #endif
115    }
116 
117    /* Check for limits option.  If present in position 1, give limits and
118       return. */
119    if ( strcmp( argv[1], "-l") == 0 || strcmp( argv[1], "-L") == 0 ) {
120       showLimits();
121       return 0;
122    }
123    /* Check for verify option.  If present in position i (i as above) perform
124       verify (Note verifyOptions terminates program). */
125    if ( strcmp( argv[1], "-v") == 0 || strcmp( argv[1], "-V") == 0 )
126       verifyOptions();
127 
128    /* Check for at most 2 parameters following options. */
129    if ( argc - optionCountPlus1 > 2 )
130       ERROR( "Compgrp", "Exactly 2 non-option parameters are required.")
131 
132    /* Process options. */
133    options.maxBaseSize = DEFAULT_MAX_BASE_SIZE;
134    options.inform = TRUE;
135    for ( i = 1 ; i < optionCountPlus1 ; ++i )
136       if ( strcmp(argv[i],"-c") == 0 )
137          centralizeFlag = TRUE;
138       else if ( strcmp(argv[i],"-n") == 0 )
139          normalizeFlag = TRUE;
140       else if ( strncmp( argv[i], "-mb:", 4) == 0 ) {
141          errno = 0;
142          options.maxBaseSize = (Unsigned) strtol(argv[i]+4,NULL,0);
143          if ( errno )
144             ERROR( "main (cent)", "Invalid syntax for -mb option")
145       }
146       else if ( strncmp( argv[i], "-mw:", 4) == 0 ) {
147          errno = 0;
148          options.maxWordLength = (Unsigned) strtol(argv[i]+4,NULL,0);
149          if ( errno )
150             ERROR( "main (cent)", "Invalid syntax for -mw option")
151       }
152       else if ( strncmp( argv[i], "-p:", 3) == 0 ) {
153          strcpy( prefix, argv[i]+3);
154       }
155       else if ( strcmp( argv[i], "-q") == 0 )
156          options.inform = FALSE;
157       else if ( strncmp( argv[i], "-t:", 3) == 0 ) {
158          strcpy( suffix, argv[i]+3);
159       }
160       else if ( strncmp( argv[i], "-perm:", 6) == 0 ) {
161          errno = 0;
162          degree = (Unsigned) strtol(argv[i]+6,NULL,0);
163          comparePermFlag = TRUE;
164          if ( errno )
165             ERROR( "main (compgrp)", "Invalid syntax for -perm option")
166       }
167       else if ( strncmp( argv[i], "-set:", 5) == 0 ) {
168          errno = 0;
169          degree = (Unsigned) strtol(argv[i]+5,NULL,0);
170          comparePointSetFlag = TRUE;
171          if ( errno )
172             ERROR( "main (compgrp)", "Invalid syntax for -set option")
173       }
174       else if ( strncmp( argv[i], "-partition:", 11) == 0 ) {
175          errno = 0;
176          degree = (Unsigned) strtol(argv[i]+11,NULL,0);
177          comparePartitionFlag = TRUE;
178          if ( errno )
179             ERROR( "main (compgrp)", "Invalid syntax for -partition option")
180       }
181       else
182          ERROR1s( "main (compgrp command)", "Invalid option ", argv[i], ".")
183 
184 
185    /* Compute maximum degree and word length. */
186    options.maxWordLength = 200 + 5 * options.maxBaseSize;
187    options.maxDegree = MAX_INT - 2 - options.maxBaseSize;
188 
189    /* Compute file and library names. */
190    parseLibraryName( argv[optionCountPlus1], prefix, suffix,
191                      group1FileName, group1LibraryName);
192    parseLibraryName( argv[optionCountPlus1+1], prefix, suffix,
193                      group2FileName, group2LibraryName);
194 
195    /* Read in groups.  For types other than permutation groups, call special
196       function to perform comparison. */
197    if ( comparePermFlag ) {
198       perm1 = readPermutation( group1FileName, group1LibraryName, degree, FALSE);
199       if ( argc > optionCountPlus1+1 )
200          perm2 = readPermutation( group2FileName, group2LibraryName, degree, FALSE);
201       return comparePerm( perm1, perm2);
202    }
203    else if ( comparePointSetFlag ) {
204       set1 = readPointSet( group1FileName, group1LibraryName, degree);
205       if ( argc > optionCountPlus1+1 )
206          set2 = readPointSet( group2FileName, group2LibraryName, degree);
207       return comparePointSet( set1, set2);
208    }
209    else if ( comparePartitionFlag) {
210       partn1 = readPartition( group1FileName, group1LibraryName, degree);
211       if ( argc > optionCountPlus1+1 )
212          partn2 = readPartition( group2FileName, group2LibraryName, degree);
213       return comparePartition( partn1, partn2);
214    }
215    else {
216       group1 = readPermGroup( group1FileName, group1LibraryName, 0, "Generate");
217       if ( argc > optionCountPlus1+1 )
218          group2 = readPermGroup( group2FileName, group2LibraryName, group1->degree,
219                                                               "Generate");
220    }
221 
222    /* If second group is omitted, check if first group is the identity. */
223    if ( !group2 )
224       if ( group1->order->noOfFactors == 0 ) {
225          if ( options.inform )
226             printf( "\n  %s is the identity.\n", group1->name);
227          return 0;
228       }
229       else {
230          if ( options.inform )
231             printf( "\n  %s is not the identity.\n", group1->name);
232          return 1;
233       }
234 
235    /* Check containment. */
236    if ( isSubgroupOf(group1,group2) )
237       if ( isSubgroupOf(group2,group1) ) {
238          if ( options.inform )
239             printf( "\n  %s and %s are equal.\n", group1->name, group2->name);
240          if ( centralizeFlag )
241             if ( isCentralizedBy(group1,group2) ) {
242                printf( "  %s and %s centralize each other.\n",
243                        group1->name, group2->name);
244                skipNormalize = TRUE;
245             }
246             else
247                printf( "  %s and %s do not centralize each other.\n",
248                        group1->name, group2->name);
249          returnCode = 0;
250       }
251       else {
252          if ( options.inform )
253             printf( "\n  %s is properly contained in %s.\n", group1->name,
254                                                         group2->name);
255          if ( centralizeFlag )
256             if ( isCentralizedBy(group1,group2) ) {
257                printf( "  %s and %s centralize each other.\n",
258                        group1->name, group2->name);
259                skipNormalize = TRUE;
260             }
261             else
262                printf( "  %s and %s do not centralize each other.\n",
263                        group1->name, group2->name);
264          if ( normalizeFlag && !skipNormalize )
265             if ( isNormalizedBy(group1,group2) )
266                printf( "  %s is normal in %s.\n", group1->name,
267                                                     group2->name);
268             else
269                printf( "  %s is not normal in %s.\n", group1->name,
270                                                     group2->name);
271          returnCode = 1;
272       }
273    else
274       if ( isSubgroupOf(group2,group1) ) {
275          if ( options.inform )
276             printf( "\n  %s is properly contained in %s.\n", group2->name,
277                                                         group1->name);
278          if ( centralizeFlag )
279             if ( isCentralizedBy(group1,group2) ) {
280                printf( "  %s and %s centralize each other.\n",
281                        group1->name, group2->name);
282                skipNormalize = TRUE;
283             }
284             else
285                printf( "  %s and %s do not centralize each other.\n",
286                        group1->name, group2->name);
287          if ( normalizeFlag && !skipNormalize )
288             if ( isNormalizedBy( group2, group1) )
289                printf( "  %s is normal in %s.\n", group2->name,
290                                                     group1->name);
291             else
292                printf( "  %s is not normal in %s.\n", group2->name,
293                                                     group1->name);
294          returnCode = 2;
295       }
296       else {
297          if ( options.inform )
298             printf( "\n  Neither of %s or %s is contained in the other.\n",
299                                           group1->name, group2->name);
300          if ( centralizeFlag )
301             if ( isCentralizedBy(group1,group2) ) {
302                printf( "  %s and %s centralize each other.\n",
303                        group1->name, group2->name);
304                skipNormalize = TRUE;
305             }
306             else
307                printf( "  %s and %s do not centralize each other.\n",
308                        group1->name, group2->name);
309          if ( normalizeFlag && !skipNormalize ) {
310             if ( isNormalizedBy( group1, group2) )
311                printf( "  %s is normalized by %s.\n", group1->name,
312                                                     group2->name);
313             else
314                printf( "  %s is not normalized by %s.\n", group1->name,
315                                                     group2->name);
316             if ( isNormalizedBy( group2, group1) )
317                printf( "  %s is normalized by %s.\n", group2->name,
318                                                     group1->name);
319             else
320                printf( "  %s is not normalized by %s.\n", group2->name,
321                                                     group1->name);
322          }
323          returnCode = 3;
324       }
325 
326    return returnCode;
327 }
328 
329 
330 
331 /*-------------------------- comparePerm ---------------------------------*/
332 
comparePerm(const Permutation * const perm1,const Permutation * const perm2)333 static int comparePerm(
334    const Permutation *const perm1,
335    const Permutation *const perm2)
336 {
337    Unsigned pt;
338 
339    if ( perm2 ) {
340       for ( pt = 1 ; pt <= perm1->degree ; ++pt )
341          if ( perm1->image[pt] != perm2->image[pt] ) {
342             if ( options.inform )
343                printf( "\n  %s and %s are not equal.\n", perm1->name,
344                        perm2->name);
345             return 1;
346          }
347       if ( options.inform )
348          printf( "\n  %s and %s are equal.\n", perm1->name, perm2->name);
349       return 0;
350    }
351    else {
352       for ( pt = 1 ; pt <= perm1->degree ; ++pt )
353          if ( perm1->image[pt] != pt ) {
354             if ( options.inform )
355                printf( "\n  %s is not the identity.\n", perm1->name);
356             return 1;
357          }
358       if ( options.inform )
359          printf( "\n  %s is the identity.\n", perm1->name);
360       return 0;
361    }
362 }
363 
364 
365 
366 
367 /*-------------------------- comparePointSet -------------------------------*/
368 
comparePointSet(const PointSet * const set1,const PointSet * const set2)369 static int comparePointSet(
370    const PointSet *const set1,
371    const PointSet *const set2)
372 {
373    Unsigned i;
374    BOOLEAN set1InSet2 = TRUE, set2InSet1 = TRUE;
375 
376    if ( set2 ) {
377       for ( i = 1 ; i <= set1->size ; ++i )
378          if ( !set2->inSet[set1->pointList[i]] ) {
379             set1InSet2 = FALSE;
380             break;
381          }
382       for ( i = 1 ; i <= set2->size ; ++i )
383          if ( !set1->inSet[set2->pointList[i]] ) {
384             set2InSet1 = FALSE;
385             break;
386          }
387       if ( set1InSet2 && set2InSet1 ) {
388          if ( options.inform )
389             printf( "\n  Sets %s and %s are equal.\n", set1->name, set2->name);
390          return 0;
391       }
392       else if ( set1InSet2 ) {
393          if ( options.inform )
394             printf( "\n  Set %s is properly contained in set %s.\n", set1->name,
395                     set2->name);
396          return 1;
397       }
398       else if ( set2InSet1 ) {
399          if ( options.inform )
400             printf( "\n  Set %s is properly contained in set %s.\n", set2->name,
401                     set1->name);
402          return 2;
403       }
404       else {
405          if ( options.inform )
406             printf( "\n  Neither set %s or set %s is contained in the other.\n",
407                     set1->name, set2->name);
408          return 3;
409       }
410    }
411    else {
412       if ( set1->size == 0 ) {
413          if ( options.inform )
414             printf( "\n  %s is empty.\n", set1->name);
415          return 0;
416       }
417       else {
418          if ( options.inform )
419             printf( "\n  %s is not empty.\n", set1->name);
420          return 1;
421       }
422    }
423 }
424 
425 
426 /*-------------------------- comparePartition ----------------------------*/
427 
comparePartition(const Partition * const partn1,const Partition * const partn2)428 static int comparePartition(
429    const Partition *const partn1,
430    const Partition *const partn2)
431 {
432    ERROR( "comparePartition", "Comparison of partitions not yet implemented")
433 }
434 
435 
436 /*-------------------------- verifyOptions -------------------------------*/
437 
verifyOptions(void)438 static void verifyOptions(void)
439 {
440    CompileOptions mainOpts = { DEFAULT_MAX_BASE_SIZE, MAX_NAME_LENGTH,
441                                MAX_PRIME_FACTORS,
442                                MAX_REFINEMENT_PARMS, MAX_FAMILY_PARMS,
443                                MAX_EXTRA,  XLARGE, SGND, NFLT};
444    extern void xaddsge( CompileOptions *cOpts);
445    extern void xbitman( CompileOptions *cOpts);
446    extern void xcopy  ( CompileOptions *cOpts);
447    extern void xcstbor( CompileOptions *cOpts);
448    extern void xerrmes( CompileOptions *cOpts);
449    extern void xessent( CompileOptions *cOpts);
450    extern void xfactor( CompileOptions *cOpts);
451    extern void xnew   ( CompileOptions *cOpts);
452    extern void xoldcop( CompileOptions *cOpts);
453    extern void xpermgr( CompileOptions *cOpts);
454    extern void xpermut( CompileOptions *cOpts);
455    extern void xprimes( CompileOptions *cOpts);
456    extern void xrandgr( CompileOptions *cOpts);
457    extern void xrandsc( CompileOptions *cOpts);
458    extern void xreadgr( CompileOptions *cOpts);
459    extern void xreadpe( CompileOptions *cOpts);
460    extern void xstorag( CompileOptions *cOpts);
461    extern void xtoken ( CompileOptions *cOpts);
462    extern void xutil  ( CompileOptions *cOpts);
463 
464    xaddsge( &mainOpts);
465    xbitman( &mainOpts);
466    xcopy  ( &mainOpts);
467    xcstbor( &mainOpts);
468    xerrmes( &mainOpts);
469    xessent( &mainOpts);
470    xfactor( &mainOpts);
471    xnew   ( &mainOpts);
472    xoldcop( &mainOpts);
473    xpermgr( &mainOpts);
474    xpermut( &mainOpts);
475    xprimes( &mainOpts);
476    xrandgr( &mainOpts);
477    xrandsc( &mainOpts);
478    xreadgr( &mainOpts);
479    xreadpe( &mainOpts);
480    xstorag( &mainOpts);
481    xtoken ( &mainOpts);
482    xutil  ( &mainOpts);
483 }
484