/* File miscio.c - 11. 10. 94. * 6/11/99 added add_expanded_word_to_buffer for dbae. * 9/10/98 moved set_separator to this file. More convenient here. * 9.1.98. change of `gen' to `char' for generator type - requires * functions genstrlen, genstrcmp, genstrcat to be written * with this type. * 21. 9. 95. - return type of read_word changed from void to boolean, * to distinguish between the cases when no word is read, and * when the empty word is read. * do same for read_int, read_string (although not needed yet) * 13. 8. 95. - added function read_word_list to read a list of words. * 13. 3. 95. - skip_gap_expression written * 27. 2. 95. - allowed generators of form string^-1 - read_ident gets * an extra parameter. * 12. 12. 94. transferred the function process_names to this file. * This file contains some miscellaneous input and output functions that * are used by both automata and string-rewriting programs. * Also we recode the standard function strlen as stringlen to avoid * some type incompatibilities resulting in warning messages on solaris!
*/
/* Note: '.' is not included in list of delimiters, since identifiers may * contain dots. * Integers are exceptional, however, in that they may be terminated by a * '.' as well as by as delimiter. * identifiers, strings and words are terminated by a delimiter.
*/
boolean isdelim(int c)
{ return c == '^' || c == '*' || c == '[' || c == ']' || c == ',' || c == '(' ||
c == '{' || c == '}' || c == ')' || c == ';' || c == '\"' ||
c == ':' || c == EOF;
}
/* Checks if symbol is valid in an identifier */
boolean isvalid(int c)
{ return isalpha(c) || isdigit(c) || c == '_' || c == '.';
}
/* This is the basic character-reading function, which all other routines * call. * It skips over a backslash '\' followed by a newline '\n'. * It replaces tabs, newlines and comments (starting with # ending with * carriage return) with a space. * Otherwise it returns the next character read. * Use getc diretcly when readin literal strings.
*/ staticint read_char(FILE *rfile)
{ staticint last; /* used to remember a character from the last call */ int n;
n = last ? last : getc(rfile); /* The input may contain a '\' character which is printed before '\n' * -- this is particularly true if the input file is generated by GAP
*/ while (n == '\\') {
n = getc(rfile); if (n == '\n')
n = getc(rfile); else {
last = n; return (int)'\\';
}
} if (n == '#') while ((n = getc(rfile)) != '\n' && n != EOF)
; if (n == '\n' || n == '\t') return (' '); return (n);
}
/* The next non-white character is expected to be 'c'. If not exit with error message.
*/ void check_next_char(FILE *rfile, int c)
{ int n; while ((n = read_char(rfile)) == ' ')
; if (n == '{' && c == '[') return; if (n == '}' && c == ']') return; if (n != c) {
fprintf(stderr, "#Input error: \'%c\' expected (not %c).\n", c, n); exit(1);
}
}
/* Read next delimiter. */ void read_delim(FILE *rfile, int *delim)
{ int n; while ((n = read_char(rfile)) == ' ')
; if (!isdelim(n)) {
fprintf(stderr, "#Input error: delimiter expected (not %c).\n", n); exit(1);
}
*delim = n; if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']';
}
/* Read stuff into token up to next delimiter or space - * leading spaces are removed from stuff.
*/ staticvoid read_token(FILE *rfile, char *token, int *delim)
{ int n;
*token = '\0'; while ((n = read_char(rfile)) == ' ')
; while (!isdelim(n) && !(n == ' ')) {
*(token++) = n;
n = read_char(rfile);
}
*token = '\0';
*delim = n; if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']';
}
/* Skip the next GAP expression - * probably not perfect, but should be adequate for the use intended.
*/ void skip_gap_expression(FILE *rfile, int *delim)
{ int n, br_ct = 0; char br_rec[1024];
while (1) {
read_token(rfile, kbm_buffer, delim); if (strcmp(kbm_buffer, "function") == 0)
br_rec[br_ct++] = 'f'; /*marks that we are in a function definition */ elseif (strcmp(kbm_buffer, "end") == 0) { if (br_ct > 0 && br_rec[br_ct - 1] == 'f')
br_ct--; else {
fprintf(stderr, "#Input error: \"end\" without \"function\".\n"); exit(1);
}
} if (*delim == '\'') {
n = getc(rfile); if (n == '\\')
n = getc(rfile);
n = getc(rfile); if (n != '\'') {
fprintf(stderr, "#Input error: ' expected.\n"); exit(1);
}
} elseif (*delim == '\"') { do {
n = getc(rfile); while (n == '\\') {
n = getc(rfile);
n = getc(rfile);
} if (n == '\n' || n == EOF) {
fprintf(stderr, "#Input error: newline or EOF in string.\n"); exit(1);
}
} while (n != '\"');
} elseif (*delim == '(' || *delim == '[' || *delim == '{') /*}*/
br_rec[br_ct++] = *delim; elseif (*delim == ')' && br_ct > 0) { if (br_rec[br_ct - 1] == '(')
br_ct--; else {
fprintf(stderr, "#Input error: ')' without '('.\n"); exit(1);
}
} elseif (*delim == ']') { if (br_ct > 0 && br_rec[br_ct - 1] == '[')
br_ct--; else {
fprintf(stderr, "#Input error: ']' without '['.\n"); exit(1);
}
} /*{*/ elseif (*delim == '}') { if (br_ct > 0 && br_rec[br_ct - 1] == '{') /*}*/
br_ct--; else {
fprintf(stderr, /*{*/ "#Input error: '}' without '{'.\n"); /*}*/ exit(1);
}
} elseif (br_ct == 0 && (*delim == ',' || *delim == ')' || *delim == ';')) break; if (br_ct >= 1024) {
fprintf(stderr, "#Input error: Bracket level too deep.\n"); exit(1);
}
}
}
/* Read next identifier, field name, etc. * if inv is true, it is allowed to end ^-1.
*/ void read_ident(FILE *rfile, char *ident, int *delim, boolean inv)
{ int n; char *ptr = ident; while ((n = read_char(rfile)) == ' ')
; while (n != ' ' && !isdelim(n)) {
*(ptr++) = n;
n = read_char(rfile);
} if (n == ' ') while ((n = read_char(rfile)) == ' ')
; if (!isdelim(n)) {
fprintf(stderr, "#Input error: delimiter expected to terminate ident (not %c).\n",
n); exit(1);
} if (inv && n == '^') { /* With some reluctance, I allow a generator to be called {ident}^-1 */
*(ptr++) = '^';
check_next_char(rfile, '-');
*(ptr++) = '-';
check_next_char(rfile, '1');
*(ptr++) = '1';
read_delim(rfile, &n);
}
*ptr = '\0';
*delim = n; if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']';
}
/* Read next integer - may be empty, when 0 is returned as *integ. * NOTE integer can be terminated by a '.' as well as a delimiter * FALSE returned if no int read, otherwise TRUE.
*/
boolean read_int(FILE *rfile, int *integ, int *delim)
{ int n, value = 0;
boolean neg = FALSE, ans = FALSE; while ((n = read_char(rfile)) == ' ')
; do { if (n == '-' && value == 0)
neg = TRUE; elseif (isdigit(n)) {
value = 10 * value + n - '0';
ans = TRUE;
} elseif (n == ' ' || n == '.' || isdelim(n)) break; else {
fprintf(stderr, "#Input error: integer expected.\n"); exit(1);
}
n = read_char(rfile);
} while (1); if (n == ' ') while ((n = read_char(rfile)) == ' ')
; if (n != '.' && !isdelim(n)) {
fprintf(stderr, "#Input error: delimiter expected to terminate integer (not %c).\n",
n); exit(1);
} if (neg)
value = -value;
*integ = value;
*delim = n; if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']'; return ans;
}
/* Read next string (enclosed in quotes) - if delim comes first, return * empty string as string. * FALSE returned if no string read, otherwise TRUE.
*/
boolean read_string(FILE *rfile, char *string, int *delim)
{ int n; char *ptr = string;
boolean ans = FALSE; while ((n = read_char(rfile)) == ' ')
; if (n == '\"') {
ans = TRUE; do {
n = getc(rfile); while (n == '\\') {
n = getc(rfile);
*(ptr++) = n;
n = getc(rfile);
} if (n == '\n' || n == EOF) {
fprintf(stderr, "#Input error: newline or EOF in string.\n"); exit(1);
} if (n != '\"')
*(ptr++) = n; else break;
} while (1);
read_delim(rfile, delim); /* We want the next delimiter after the terminating quotes */
} elseif (!isdelim(n)) {
fprintf(stderr, "#Input error: delimiter expected in read_string (not %c).\n", n); exit(1);
} else
*delim = n; if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']';
*ptr = '\0'; return ans;
}
/* name is a list of num_names names (probably names of monoid generators). * First they are checked for validity - they must start with a letter or * underscore, and all characters must be alphanumeric '_' or '.'. * (or they can end in ^-1). * They are then checked to see if they comply with one of the two * special formats a) and b) described at the top of the file rwsio.h. * If so, then the external variables kbm_algno and kbm_gen_no are set * accordingly. These are used by the next function read_next_word for * fast reading of words in the generators. * Otherwise, kbm_algno is set to -1, and words are located in the list * by a simple search.
*/ void process_names(char **name, int num_names)
{ int i, j, l; char *genname, *genname1, *ptr;
for (i = 0; i <= MAXGEN; i++)
kbm_gen_no[i] = 0;
kbm_algno = 0; if (num_names == 0) return; for (i = 1; i <= num_names; i++) {
genname = name[i]; if (stringlen(genname) == 0) {
fprintf(stderr, "#Input error: a generator name has length 0.\n"); exit(1);
} if (stringlen(genname) > 1)
kbm_algno = -1; if (!isalpha(genname[0]) && genname[0] != '_') {
fprintf(stderr, "#Input error: generators should start with a letter or `_'.\n"); exit(1);
} if (kbm_algno == 0) { if (kbm_gen_no[genname[0]] != 0) {
fprintf(stderr, "#Input error: repeated generator name.\n"); exit(1);
}
kbm_gen_no[genname[0]] = i;
}
} if (kbm_algno == 0) return; /* all generators are single letters or underscore. */
for (i = 1; i <= num_names; i++) {
genname = name[i];
l = stringlen(genname); for (j = 0; j < l; j++) if (!isvalid(genname[j])) { if (j != l - 3 || genname[j] != '^' || genname[j + 1] != '-' ||
genname[j + 2] != '1') {
fprintf(stderr, "#Input error: generator %s: names must be alphanumeric, " "'_', or '.'.\n",
genname); exit(1);
} else break;
} for (j = 1; j < i; j++) if (strcmp(genname, name[j]) == 0) {
fprintf(stderr, "#Input error: repeated generator name.\n"); exit(1);
}
}
/* Try to locate prefix for Case b). */
genname1 = name[1];
ptr = genname1 + stringlen(genname1) - 1; if (!isdigit(*ptr)) { /* not Case b) */
kbm_algno = -1; return;
} while (isdigit(*ptr))
ptr--;
kbm_algno = ptr - genname1 + 1; if (atoi(genname1 + kbm_algno) > MAXGEN) { /* numerical subscript too large */
kbm_algno = -1; return;
}
kbm_gen_no[atoi(genname1 + kbm_algno)] = 1; for (i = 2; i <= num_names; i++) {
genname = name[i]; if (stringlen(genname) < kbm_algno + 1) { /* not Case b) */
kbm_algno = -1; return;
} for (j = 0; j < kbm_algno; j++) if (genname[j] != genname1[j]) { /* not Case b) */
kbm_algno = -1; return;
} for (j = kbm_algno; j < stringlen(genname); j++) if (!isdigit(genname[j])) { /* not Case b) */
kbm_algno = -1; return;
} if (atoi(genname + kbm_algno) >
MAXGEN) { /* numerical subscript too large */
kbm_algno = -1; return;
}
kbm_gen_no[atoi(genname + kbm_algno)] = i;
}
}
/* A word is read into gen_word. It is assumed that space is already allocated for the word beginning at gen_word and ending at end_word. If the word is too long, the process aborts. The word must be empty or equal to "IdWord" (equivalent) or have the form t1*t2*...tr (for some r>=1), where each ti is either the name of a generator, or of form <gen-name>^<integer>. 2/6/95 - brackets are now allowed up to level 8, so expressions like (x*(y*z)^3)^9 are allowed. If <integer> is negative, then there must be a generator called <gen-name>^-1. The word is translated and expanded into a string of generator numbers and stored as a string of `gen's in gen_word. The external array kbm_gen_no, and the external integer kbm_algno are used for the translation - see comment in rwsio.h for explanation If check is set true, then the validity of the word is checked - using the list "name" of generator names. Otherwise it is processed as fast as possible. FALSE returned if no word read (delim comes first), otherwise TRUE.
*/
boolean read_word(FILE *rfile, gen *gen_word, gen *end_word, int *delim, char **name, int num_names, boolean check)
{ int i, g, n, delimchar, bracketlevel;
gen *ptr, *ptrr, *ptre, *bracketptr[9];
ptr = gen_word;
bracketlevel = 0; do {
read_ident(rfile, kbm_buffer, &delimchar, FALSE); if (delimchar == '(') { if (stringlen(kbm_buffer) != 0) {
fprintf(stderr, "Input error: '(' in wrong position in word.\n"); exit(1);
}
bracketlevel++; if (bracketlevel > 8) {
fprintf(stderr, "Input error: at most 8 levels of brackets allowed.\n"); exit(1);
}
bracketptr[bracketlevel] = ptr; continue;
} if (ptr == gen_word &&
(strcmp(kbm_buffer, "") == 0 || strcmp(kbm_buffer, "IdWord") == 0)) break; if (kbm_algno == -1) {
g = 0; for (i = 1; i <= num_names; i++) if (strcmp(kbm_buffer, name[i]) == 0) {
g = i; break;
} if (g == 0) {
fprintf(stderr, "#Input error: unknown generator in word.\n"); exit(1);
}
} else {
g = (kbm_algno == 0) ? kbm_gen_no[*kbm_buffer]
: kbm_gen_no[atoi(kbm_buffer + kbm_algno)]; if (check && (g == 0 || strcmp(kbm_buffer, name[g])) != 0) {
fprintf(stderr, "#Input error: invalid entry in word.\n"); exit(1);
}
} if (delimchar == '^') {
read_int(rfile, &n, &delimchar); if (delimchar != '*' && delimchar != ']' && delimchar != ',' &&
delimchar != ';' && delimchar != ')') {
fprintf(stderr, "#Input error: ',' '*', ')' or ']' expected.\n"); exit(1);
} if (n < 0) { /* This is only allowed if we have a generator ending in ^-1 */
g = 0; if (kbm_algno == -1) {
sprintf(kbm_buffer + stringlen(kbm_buffer), "^-1"); for (i = 1; i <= num_names; i++) if (strcmp(kbm_buffer, name[i]) == 0) {
g = i; break;
}
} if (g == 0) {
fprintf(stderr, "#Input error: unknown generator or illegal negative " "power in word.\n"); exit(1);
}
n = -n;
} for (i = 1; i <= n; i++) {
*(ptr++) = g; if (ptr > end_word) {
fprintf(stderr, "The word being read is too long. Increase maxreducelen.\n"); exit(1);
}
}
} elseif (delimchar == '*' || delimchar == ']' || delimchar == ',' ||
delimchar == ';' || delimchar == ')') {
*(ptr++) = g; if (ptr > end_word) {
fprintf(stderr, "The word being read is too long. Increase maxreducelen.\n"); exit(1);
}
} else {
fprintf(stderr, "#Input error: ',' '^' '*' ';' or ']' expected.\n"); exit(1);
} while (delimchar == ')') {
read_delim(rfile, &delimchar); while (delimchar == ')') {
bracketlevel--;
read_delim(rfile, &delimchar);
} if (bracketlevel <= 0) {
fprintf(stderr, "Input error: ')' with no matching '('.\n"); exit(1);
} if (delimchar == '^') {
read_int(rfile, &n, &delimchar); if (delimchar != '*' && delimchar != ']' && delimchar != ',' &&
delimchar != ';' && delimchar != ')') {
fprintf(stderr, "#Input error: ',' '*' ')' or ']' expected.\n"); exit(1);
} if (n <= 0) {
fprintf(stderr, "#Error: Non-positive powers not allowed in monoid words.\n"); exit(1);
}
ptre = ptr - 1; for (i = 1; i < n; i++) {
ptrr = bracketptr[bracketlevel]; while (ptrr <= ptre) {
*(ptr++) = *(ptrr++); if (ptr > end_word) {
fprintf(
stderr, "The word being read is too long. Increase maxreducelen.\n"); exit(1);
}
}
}
} elseif (delimchar != '*' && delimchar != ']' && delimchar != ',' &&
delimchar != ';') {
fprintf(stderr, "#Input error: ',' '^' '*' ';' or ']' expected.\n"); exit(1);
}
bracketlevel--;
}
} while (delimchar != ',' && delimchar != ']' && delimchar != ';');
if (bracketlevel != 0) {
fprintf(stderr, "#Input error: brackets do not balance in word.\n"); exit(1);
}
*delim = delimchar; if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']';
*ptr = 0; return (ptr != gen_word || strcmp(kbm_buffer, "IdWord") == 0);
}
/* Read a list of words separated by commas into wordlist, and return the * number read. space is the total space available - the program aborts * if this is exceeded. * The individual words are terminated by the string terminator 0 in * wordlist, so that they can be conveniently copied. * name, num_names and check are as in read_word.
*/ int read_word_list(FILE *rfile, gen *wordlist, int space, int *delim, char **name, int num_names, int check)
{ int ct;
gen *ptr, *ptre;
ptr = wordlist;
ptre = wordlist + space - 1;
ct = 0; do {
read_word(rfile, ptr, ptre, delim, name, num_names, check);
ct++;
ptr += (genstrlen(ptr) + 1);
} while (*delim == ','); if (*delim == '{')
*delim = '['; if (*delim == '}')
*delim = ']'; return ct;
}
/* prints contents of buffer, followed by new-line to wfile * and then clears buffer.
*/ void printbuffer(FILE *wfile)
{
fprintf(wfile, "%s\n", kbm_buffer);
*kbm_buffer = '\0';
}
/* w should be a string. * Add at least n characters to the end of the string buffer, with w at the end, * padding with spaces at beginning
*/ void add_to_buffer(int n, char *w)
{ int i, nsp;
nsp = n - stringlen(w); for (i = 1; i <= nsp; i++)
strcat(kbm_buffer, " ");
strcat(kbm_buffer, w);
}
/* word is a string of `gen's. to be printed as a word in GAP syntax. * If gen number i appears in the string, then * the gen is to be printed as the string symbols[i]. * The buffer contains the line to be printed, and the word is * appended to the end of the current contents of the buffer. * New lines are printed in mid-word if necessary, but not at the * end, since the calling function may need to append more. * The returned value is the number of newlines inserted.
*/ int add_word_to_buffer(FILE *wfile, gen *word, char **symbols)
{ int offset, pow, g, len, lg, nln = 0;
gen *w; char sg[256]; /* 256 here is the maximum length of a generator name in `symbols'. */
boolean first;
offset = stringlen(kbm_buffer) + 2; /* remember where word begins on the line,
* in case we need to add new lines. */ if (offset > 32)
offset = 32; /* to avoid silly situations */
w = word; if (*w == 0)
add_to_buffer(0, "IdWord");
first = TRUE; while (*w) {
g = *(w++);
pow = 1; while (*w == g) {
pow++;
w++;
}
len = first ? 0 : 1;
strcpy(sg, symbols[g]);
len += stringlen(sg); if (pow > 1) {
len += (1 + int_len(pow));
} if (stringlen(kbm_buffer) + len >= 76) { /* new line needed */
printbuffer(wfile);
add_to_buffer(offset, "");
nln++;
} if (!first)
add_to_buffer(0, "*"); /* Check if we have a power of a generator ending with ^-1 */
lg = stringlen(sg); if (pow > 1 && lg > 3 && sg[lg - 3] == '^' && sg[lg - 2] == '-' &&
sg[lg - 1] == '1') {
sg[lg - 3] = '\0';
pow = -pow;
}
add_to_buffer(0, sg); if (pow > 1 || pow < -1)
sprintf(kbm_buffer + stringlen(kbm_buffer), "^%d", pow);
first = FALSE;
} return nln;
}
/* The same as add_word_to_buffer, but powers of generators are * printed out in full rather than as powers.
*/ int add_expanded_word_to_buffer(FILE *wfile, gen *word, char **symbols)
{ int offset, g, len, nln = 0;
gen *w; char sg[256]; /* 256 here is the maximum length of a generator name in `symbols'. */
boolean first;
offset = stringlen(kbm_buffer) + 2; /* remember where word begins on the line,
* in case we need to add new lines. */ if (offset > 32)
offset = 32; /* to avoid silly situations */
w = word; if (*w == 0)
add_to_buffer(0, "IdWord");
first = TRUE; while (*w) {
g = *(w++);
len = first ? 0 : 1;
strcpy(sg, symbols[g]);
len += stringlen(sg); if (stringlen(kbm_buffer) + len >= 76) { /* new line needed */
printbuffer(wfile);
add_to_buffer(offset, "");
nln++;
} if (!first)
add_to_buffer(0, "*");
add_to_buffer(0, sg);
first = FALSE;
} return nln;
}
/* This is the same as add_word_to_buffer, except that "word" is a string of * integers instead of gens.
*/ int add_iword_to_buffer(FILE *wfile, int *word, char **symbols)
{ int offset, pow, g, lg, len, nln = 0; int *w; char sg[128];
boolean first;
offset = stringlen(kbm_buffer) + 2; /* remember where word begins on the line,
* in case we need to add new lines. */
w = word; if (*w == 0)
add_to_buffer(0, "IdWord");
first = TRUE; while (*w) {
g = *(w++);
pow = 1; while (*w == g) {
pow++;
w++;
}
len = first ? 0 : 1;
strcpy(sg, symbols[g]);
len += stringlen(sg); if (pow > 1) {
len += (1 + int_len(pow));
} if (stringlen(kbm_buffer) + len >= 76) { /* new line needed */
printbuffer(wfile);
add_to_buffer(offset, "");
nln++;
} if (!first)
add_to_buffer(0, "*"); /* Check if we have a power of a generator ending with ^-1 */
lg = stringlen(sg); if (pow > 1 && lg > 3 && sg[lg - 3] == '^' && sg[lg - 2] == '-' &&
sg[lg - 1] == '1') {
sg[lg - 3] = '\0';
pow = -pow;
}
add_to_buffer(0, sg); if (pow > 1 || pow < -1)
sprintf(kbm_buffer + stringlen(kbm_buffer), "^%d", pow);
first = FALSE;
} return nln;
}
int /* The length of the integer n */
int_len(int n)
{ int l = 0; if (n < 0) {
n = -n;
l = 1;
} while (n != 0) {
l++;
n = n / 10;
} return l;
}
/* returns true if the string x is an integer */
boolean is_int(char *x)
{ int i, l;
l = stringlen(x); if (l == 0 || (l == 1 && x[0] == '-')) returnFALSE; for (i = 0; i < l; i++) if (!isdigit(x[i]) && (i != 0 || x[i] != '-')) returnFALSE; returnTRUE;
}
/* We recode this standard function, since the solaris version returns a type * other than int, which causes irritating warning messages!
*/ int stringlen(char *c)
{ int l = 0; while (*(c++))
l++; return l;
}
int genstrlen(gen *c)
{ int l = 0; while (*(c++))
l++; return l;
}
int genstrcmp(gen *c, gen *d)
{ while (*c) { if (*(c++) != *(d++)) return 1;
} if (*c != *d) return 1; return 0;
}
void genstrcat(gen *c, gen *d)
{ while (*c)
c++; while (*d)
*(c++) = *(d++);
*c = 0;
}
void genstrcpy(gen *c, gen *d)
{ while (*d)
*(c++) = *(d++);
*c = 0;
} /* Locates separator, and checks the level conditions on G-generators and * H-generators.
*/ void set_separator(rewriting_system *rwsptr)
{ int i, lev; /* Locate separator */
rwsptr->separator = 0; for (i = 1; i <= rwsptr->num_gens; i++) if (strcmp(rwsptr->gen_name[i], "_H") == 0) {
rwsptr->separator = i; break;
} if (rwsptr->separator == 0) {
fprintf(stderr, "Error - there is no generator named '_H'.\n"); exit(1);
} if (rwsptr->inv_of[rwsptr->separator]) {
fprintf(stderr, "Error - generator '_H' should have no inverse!.\n"); exit(1);
}
if (rwsptr->level == 0) {
fprintf(stderr, "Error - ordering must be WREATHPROD in cosets program.\n"); exit(1);
}
lev = rwsptr->level[rwsptr->separator]; for (i = 1; i < rwsptr->separator; i++) if (rwsptr->level[i] <= lev) {
fprintf(stderr, "Error: G-generators must precede separator and have " "higher level.\n"); exit(1);
} for (i = rwsptr->separator + 1; i <= rwsptr->num_gens; i++) if (rwsptr->level[i] > lev) {
fprintf(stderr, "Error: G-generators must follow separator and not have " "higher level.\n"); exit(1);
}
/* Now determine Gislevel, Hislevel, Hhasinverses */
rwsptr->Gislevel = TRUE;
lev = 0; for (i = 1; i < rwsptr->separator; i++) if (lev == 0)
lev = rwsptr->level[i]; elseif (rwsptr->level[i] != lev) {
rwsptr->Gislevel = FALSE; break;
}
rwsptr->Hislevel = TRUE;
lev = 0; for (i = rwsptr->separator + 1; i <= rwsptr->num_gens; i++) if (lev == 0)
lev = rwsptr->level[i]; elseif (rwsptr->level[i] != lev) {
rwsptr->Hislevel = FALSE; break;
}
if (rwsptr->finitestop && !rwsptr->Gislevel) {
printf( " #Warning: finiteness test only works when all G-gens have the same weight.\n\ #Finiteness test swithched off.\n");
rwsptr->finitestop = FALSE;
}
rwsptr->Hhasinverses = TRUE; for (i = rwsptr->separator + 1; i <= rwsptr->num_gens; i++) if (!rwsptr->inv_of[i]) {
rwsptr->Hhasinverses = FALSE; break;
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.45 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.