/* This file contains the interpreter. */ /* command = word. || md. || Md '=' word. || '?' || 'q' || 'p' ||'n' ||'P' word = comm('^'e || '%'comm)#('*'comm('^'e || '%'comm)) { e the exponent, %c means 'conjugate by c'} md = 'm' d; {the entry in the d-th memory slot} comm = elt || [word #(, word)] elt = md || g g = 'h' || f1,...,fr 'h' prompts for the entry of a group element fi is the i-th polynomial in the definition of a group element #(xxx) means 'repeat xxx any number of times' (yyy) means 'with an optional yyy' */ #include "global.h" #include #include extern int rank, total, prime, help; int pflag = 1; /* 1 means print as poly, 2 means print in normal form. */ memory mem; /* Imports from group_elt.c */ void gcopy(group_elt f, group_elt g); int checkgroupelt(group_elt g); void commutator(group_elt f, group_elt g, group_elt h); void groupinv(group_elt f, group_elt g); void gpower(group_elt g, int n); void conjugate(group_elt f, group_elt g, group_elt h); /* Other imports */ void Mpres(void); /* From Mpresentation.c */ void GapPres(void); /* From GapPresentation.c */ void initialise(void); /* From polynomial.c */ /* Prototypes */ int getg(group_elt g); int getelt(group_elt g); int getcomm(group_elt g); int getword(group_elt g); void getcommand(void); void assist(void); void prompt(void); void helpL(void); void helpE(void); void helpC(void); void helpM(void); void helpS(void); /* Procedures */ int getg(group_elt g) { char c[2]; scanf( "%1s", c); if (c[0] == 'h') help = 2; else { help = 0; ungetc(c[0], stdin); } return readgpelt(g); } int getelt(group_elt g) { char c[2]; int i; scanf("%1s", c); if (c[0] == 'm') { scanf("%d", &i); if (i > MEM || i < 0) { printf("%d is bad memory allocation. \n", i); return 0; } gcopy(g, mem[i]); if ( !checkgroupelt(g) ) { printf("The memory allocation m[%d] is not assigned.\n", i); return 0; } return 1; } ungetc(c[0], stdin); return (getg(g)); } int getcomm(group_elt g) { char c1[2], c2[2]; group_elt h, k; scanf("%1s", c1); if (c1[0] == '[') { if (!getword(h)) return 0; scanf("%1s", c2); if (c2[0] == ',') { ungetc(c1[0], stdin); if (!getcomm(k)) return 0; commutator(h, k, g); } else if (c2[0] == ']') gcopy(g, h); else { printf("Syntax error. Re-enter this commutator, starting at\n"); printf("the last bracket [, which you should re-enter.\n"); } return 1; } ungetc(c1[0], stdin); return(getelt(g)); } int getword(group_elt g) { group_elt h, k; char c[2]; int e; if (!getcomm(g)) return 0; scanf("%1s", c); if (c[0] == '^') { scanf("%d", &e); if (e < 0) { e = -e; groupinv(g, h); gcopy(g, h); } if (!e) { printf("Zero exponents not allowed.\n"); return 0; } gpower(g, e); scanf("%1s", c); } if (c[0] == '%') { if (!getcomm(h)) return 0; conjugate(g, h, k); gcopy(g, k); scanf("%1s", c); } if (c[0] == '*') { if (!getword(h)) return 0; gmult(g, h); return 1; } if (c[0] == '.') return 1; if ( (c[0] == ',') || (c[0] == ']') ) { ungetc(c[0], stdin); return 1; } printf("Bad syntax; unexpected character %c.\n", c[0]); return 0; } void getcommand(void) { group_elt g; char c[2]; int i; vector v; printf(">"); scanf("%1s", c); if ( c[0] == 'p') { pflag = 1; return;} if ( c[0] == 'n') { pflag = 2; return;} if ( c[0] == 'q') exit(0); if ( c[0] == '?') { assist(); return;} if ( c[0] == 'P') { Mpres(); return;} if ( c[0] == 'G') { GapPres(); return;} if ( c[0] == 'M') { scanf("%d", &i); if (i > MEM || i < 0) { printf("No such memory allocation, re-enter command.\n"); return; } scanf("%1s", c); /* Get rid of '=' */ getword(mem[i]); return; } ungetc(c[0], stdin); if (!getword(g)) { fflush(stdin); return;} if (pflag == 1) writegpelt(g); else if (pflag == 2) { normalform(g, v); printvec(v); } } void assist() { char c[2]; printf(" This calculator will evaluate expressions in the generalised"); printf(" Nottingham group \n in any number of variables, to any degree"); printf(" of accuracy. It has a memory with \n an unlimited capacity."); printf(" However, the number of variables, the accuracy, and the \n"); printf(" memory size are bounded at compile time. To find how to"); printf(" increase the allowed \n limits, enter 'L'.\n"); printf(" A simple expression for a group element consists of n"); printf(" suitable polynomials, in \n n unknowns. To find how to enter"); printf(" a simple expression, enter 'E'.\n"); printf(" The calculator accepts compound expressions, using products,"); printf(" conjugates, \n and commutators.\n"); printf(" To find how to use the memory, type 'M'.\n"); printf(" For a description of the general symtax, type 'S'.\n"); printf(" To leave HELP type 'Q'\n"); printf(" IMPORTANT. To get out of the calculator, enter 'q' in"); printf(" response to the\n prompt '>'.\n"); scanf("%1s", c); if (c[0] == 'L') helpL(); else if (c[0] == 'E') helpE(); else if (c[0] == 'C') helpC(); else if (c[0] == 'M') helpM(); else if (c[0] == 'S') helpS(); else if (c[0] == 'Q') return; else { printf("Illegal help command.\n"); assist();} } void prompt(void) { char c[2]; printf("Enter '?', 'L', 'C', 'M', 'S' or 'Q'\n"); scanf("%1s", c); if (c[0] == 'L') helpL(); else if (c[0] == 'E') helpE(); else if (c[0] == 'C') helpC(); else if (c[0] == 'M') helpM(); else if (c[0] == 'S') helpS(); else if (c[0] == 'Q') return; else if (c[0] == '?') assist(); else { printf("Illegal help command.\n"); prompt(); } } void helpL(void) { printf(" There are four constants whose values you should consider.\n"); printf(" These are MAXR, MAXL, MAXV, and MEM, and their current values"); printf(" are %d %d %d %d \n", MAXR, MAXL, MAXV, MEM); printf(" The first is the number of variables in the polynomials, so if"); printf(" you are \n only interested in the classical Nottingham group"); printf(" you don't need it to be\n bigger than 1.\n"); printf(" The second is an upper bound to the number of monomials"); printf(" in a polynomial, so \n if you want to have polynomials in"); printf(" r variables and degree upto d, you need\n to have MAXL"); printf(" at least d + r choose d.\n"); printf(" The third is the product of the first two.\n"); printf(" The fourth is the number of memory locations.\n"); printf(" These four constants are in the file global.h; edit them"); printf(" if they are unsuitable."); } void helpE(void) { int d; printf(" Entering simple expressions is done as follows:\n"); printf(" Suppose first that you are in the classical Nottingham"); printf(" group, with just one\n variable, so you need to enter a"); printf(" polynomial such as x + 3 x^2 + 4 x^5.\n"); printf(" This is entered as '1 1 3 2 4 5 0' ."); printf(" So you enter the polynomial in the form\n coefficient exponent.\n"); printf(" Note that the terminator is a zero coefficient. It follows that"); printf(" you cannot\n enter a zero coefficient.\n"); printf(" The order in which you enter the terms is irrelevant.\n"); printf(" If you enter two terms with the same exponent, the second"); printf(" will override\n the second. (However, you cannot correct an"); printf(" error caused by entering an exponent\n whose coefficient"); printf(" should be zero.)\n"); printf(" Coefficients are read modulo the prime.\n"); printf(" If you have erred, and wish to start again, give a negative"); printf(" exponent.\n"); printf( "Enter a digit for more.\n"); scanf("%d", &d); printf(" If you have two variables, just enter two polynomials. eg:\n"); printf(" x -> x + 2x^2 + xy + y^2 + 4x^2y\n"); printf(" y -> y + 3xy + x^2y\n"); printf(" is entered as\n"); printf(" 1 1 0 2 2 0 1 1 1 1 0 2 4 2 1 0\n"); printf(" 1 0 1 3 1 1 1 1 2 0\n"); printf(" Writing the polynomials on separate lines is not required.\n"); printf(" Also, a polynomial may take several lines.\n"); printf(" Note that an exponent is now an ordered pair of natural numbers.\n"); printf(" If the polynomials do not fix x and y modulo higher powers "); printf(" the program will complain.\n\n"); printf(" If you wish to try this out, quit help and try entering"); printf(" a few expressions. Each expression must be terminated with"); printf(" a '.'.\n"); printf(" You can enter 'h' when you want to enter a simple expression.\n"); printf(" You will then be prompted. This may not help.\n"); prompt(); } void helpC(void) { printf(" A word is an expression of the form\n"); printf(" g_1 $ e_1 * g_2 $ e_2 * ... * g_n $ e_n\n"); printf(" where n >= 1, and either '$' = '^' and e_i is a non-zero"); printf(" integer, or '$' = '%%', and e_i is a commutator, and the g_i"); printf(" are commutators, as\n defined below. If e_i = 1 then"); printf(" ' $ e_i' may be omitted.\n"); printf(" A commutator is either a simple group element (in polynomial"); printf(" form), or an\n expression [w_1, w_2, ..., w_m], where the"); printf(" w_i are words, as defined above,\n and m >= 1.\n"); printf(" If you enter a few trial words, terminate each with a '.'\n"); printf(" Examples: [w1 ^ 2 * w2 %% w3, w1], or [w1 ^ 2] %% w2.\n"); printf(" Note the use of [w], i.e. square brackets.\n"); prompt(); } void helpM(void) { printf(" To store a word w in memory location i enter Mi = w.\n"); printf(" If w is stored in location i, then you can enter mi as"); printf(" an alternative to w.\n"); printf(" For example, if you enter 'M0 = w.' for some word w, and"); printf(" then enter 'm0.', the\n response is w.\n"); printf(" Remember to use 'M' for entry, 'm' for retrieval.\n"); printf(" eg. 'M2 = [m0^2*m1, m1].' \n"); prompt(); } void helpS(void) { printf("The syntax is very simple.\n"); printf("The prompt for a command is '>'\n"); printf("A command is of one of the forms:\n"); printf(" 'w.' where 'w' is a word.\n"); printf(" 'q' to quit.\n"); printf(" '?' for help.\n"); printf(" 'Mi = w.'\n Stores the word w in memory i.\n"); printf(" 'p' to give answers as polynomials. This is the default.\n"); printf(" 'n' to give answers in normal form.\n"); printf(" 'P' to construct a presentation of the group in Magma format.\n"); printf(" 'G' to construct a presentation in GAP format.\n"); } void interpret(void) { initialise(); printf("Enter '?' for help.\n"); while(1) getcommand(); }