Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346/****************************************************************************1**2*A collect.c ANUPQ source Eamonn O'Brien3**4*Y Copyright 1995-2001, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany5*Y Copyright 1995-2001, School of Mathematical Sciences, ANU, Australia6**7*/89#include "pq_defs.h"10#include "pcp_vars.h"11#include "constants.h"12#define MAXEXP (1 << 30)1314void stack_overflow(void);15void integer_overflow(void);16void add_string(int string,17int length,18int exponent,19int collected_part,20struct pcp_vars *pcp);2122/* an exponent vector with base address collected_part23is multiplied on the right by a string with base address24pointer; the string is assumed to be normal2526this routine follows the algorithm devised by27M.R. Vaughan-Lee for collection from the left;28step numbers correspond to step numbers in29"Collection from the Left" by M.R. Vaughan-Lee,30J. Symbolic Computation (1990) 9, 725-7333132this version embodies a simpler form of combinatorial33collection as described on page 733, which lessens the34chance of integer overflow; it also incorporates recursion35when adding strings and generators to the exponent vector3637during the collection algorithm, pointers to a number of strings38are stored on a stack; theoretically, the stack depth could get39as large as (p - 1) * pcp->lastg * pcp->cc, but, in practice, depths40this large do not arise; however, it could be necessary to increase41the dimensions of the stack arrays for some calculations with large42groups; STACK_SIZE is the maximum depth of the stack; this constant43is declared in the constants header file; overflow is tested in44this algorithm4546integer overflow is also tested for, although it can only arise47if p^3 > 2^31; if p^2 > 2^31, integer overflow can arise which48is not tested for4950if either overflow arises, a message is printed out and51the program terminates;5253#####################################################################5455note the sections in this code enclosed within5657#ifndef EXPONENT_P58#endif5960if you insert as part of the header material of this file6162#define EXPONENT_P6364or supply EXPONENT_P as a -D flag to the compiler, then the65resulting collector assumes that all generators of the pcp66have order p and does not execute these portions of the code */6768/* stack size on Apollo causes problems */6970#ifdef APOLLO71static t_int strstk[STACK_SIZE]; /* string stack */72static t_int lenstk[STACK_SIZE]; /* length stack */73static t_int expstk[STACK_SIZE]; /* exponent stack */74#endif7576/* if Lie program, use different collect routine */77#if defined(GROUP)7879void collect(int pointer, int collected_part, struct pcp_vars *pcp)80{81register int *y = y_address;8283register int p1; /* string pointer */84register int ce; /* collected exponent */85register int cg; /* collected generator */86register int ug; /* uncollected generator */87register int ue; /* uncollected exponent */88register int sp = 0; /* stack pointer */89register int exp; /* exponent */90register int len = 1; /* length */91register int str; /* string pointer */92register int halfwt; /* last generator with weight <= cc/2 */93register int thirdwt; /* last generator with weight <= cc/3 */94register int weight_diff; /* current class - weight of ug */95register int entry; /* value to be inserted in collected part */96register int firstcg; /* first collected generator for loop counter */97register int lastcg; /* last collected generator for loop counter */98register int maxexp; /* max exponent allowed in call to add_string */99100register int cp = collected_part;101register int class_end = pcp->clend;102register int current_class = pcp->cc;103register int prime = pcp->p;104register int pm1 = pcp->pm1;105register int p_pcomm = pcp->ppcomm;106register int p_power = pcp->ppower;107register int structure = pcp->structure;108109#ifndef APOLLO110int strstk[STACK_SIZE]; /* string stack */111int lenstk[STACK_SIZE]; /* length stack */112int expstk[STACK_SIZE]; /* exponent stack */113#endif114115register int i;116117#include "access.h"118119/* if prime is 2, use special collector */120if (prime == 2) {121collectp2(pointer, collected_part, pcp);122return;123}124125/* Step (0) --126initialize collector */127128if (pointer < 0)129lenstk[0] = y[-pointer + 1];130else if (pointer == 0)131return;132133strstk[0] = pointer;134expstk[0] = 1;135136maxexp = (MAXEXP / prime) * 2;137halfwt = y[class_end + current_class / 2];138thirdwt = y[class_end + current_class / 3];139140/* Step (1) --141process next word on stack */142143while (sp >= 0) {144145str = strstk[sp];146exp = expstk[sp];147148/* check if str is a string or a generator */149150if (str < 0) {151/* we have a genuine string */152len = lenstk[sp];153sp--;154155/* get first generator exponent pair from string */156i = y[-str + 2];157ug = FIELD2(i);158159/* if ug > halfwt, the string can be added to the160collected part without creating any commutators */161if (ug > halfwt) {162add_string(str, len, exp, cp, pcp);163continue;164}165166/* ug <= halfwt and so exp must equal 1; stack remainder of string */167ue = FIELD1(i);168if (len != 1) {169strstk[++sp] = str - 1;170lenstk[sp] = len - 1;171}172} else {173/* str is a generator */174ug = str;175ue = exp;176sp--;177/* if ug > halfwt, ug commutes with all higher generators */178if (ug > halfwt) {179add_string(ug, 1, ue, cp, pcp);180continue;181}182}183184/* ug <= halfwt; if ug > thirdwt, any commutators arising in185collecting ug commute with all generators after ug, so ug186can be collected without stacking up collected part */187188if (ug <= thirdwt) {189190/* Step (2) --191combinatorial collection;192scan collected part towards the left;193bypass generators we know must commute with ug;194when 2 * WT(cg) + WT(ug) > current_class, all generators195occurring in [cg, ug] commute with each other;196[cg^ce, ug] = [cg, ug]^ce;197if cg1,..., cgk all satisfy this weight condition then198[cg1 * ... * cgk, ug] = [cg1, ug] ... [cgk, ug] */199200if (ue != 1) {201/* we only move one ug at a time; stack ug^(ue - 1) */202if (++sp >= STACK_SIZE)203stack_overflow();204strstk[sp] = ug;205expstk[sp] = ue - 1;206ue = 1;207}208209weight_diff = current_class - WT(y[structure + ug]);210firstcg = y[class_end + weight_diff];211lastcg = y[class_end + weight_diff / 2];212213/* scan collected part to the left, bypassing generators214which must commute with ug; the collected part between215lastcg and firstcg contains a word w; we add in [w, ug] */216217for (cg = firstcg; cg > ug; cg--) {218ce = y[cp + cg];219if (ce != 0) {220/* add [cg, ug]^ce to the collected part */221p1 = y[p_pcomm + cg] + ug;222p1 = y[p1];223if (p1 != 0) {224if (cg <= lastcg)225break;226if (p1 < 0)227len = y[-p1 + 1];228add_string(p1, len, ce, cp, pcp);229}230}231}232233if (cg == ug) {234/* we have reached ug position during combinatorial235collection; add 1 to ug entry of collected part236without stacking any entries if appropriate */237if (y[cp + ug] == pm1) {238if (y[p_power + ug] == 0) {239y[cp + ug] = 0;240continue;241}242} else {243++y[cp + ug];244continue;245}246}247248/* we have now added in [w, ug]; stack up249collected part between firstcg and cg + 1 */250for (i = firstcg; i > cg; i--) {251ce = y[cp + i];252if (ce != 0) {253y[cp + i] = 0;254if (++sp >= STACK_SIZE)255stack_overflow();256strstk[sp] = i;257expstk[sp] = ce;258}259}260261/* Step (3) --262ordinary collection; we have moved ug to the cg position;263continue scanning to the left */264for (; cg > ug; cg--) {265ce = y[cp + cg];266if (ce != 0) {267/* zero the cg entry of collected part */268y[cp + cg] = 0;269270/* get [cg, ug] */271p1 = y[p_pcomm + cg] + ug;272p1 = y[p1];273if (p1 == 0) {274/* cg commutes with ug so stack cg^ce */275if (++sp >= STACK_SIZE)276stack_overflow();277strstk[sp] = cg;278expstk[sp] = ce;279} else {280/* cg does not commute with ug;281we can only move ug past one cg at a time;282stack [cg, ug] and then cg a total of ce times */283284if (sp + ce + ce >= STACK_SIZE)285stack_overflow();286if (p1 < 0)287len = y[-p1 + 1];288289for (; ce > 0; --ce) {290strstk[++sp] = p1;291lenstk[sp] = len;292expstk[sp] = 1;293strstk[++sp] = cg;294expstk[sp] = 1;295}296}297}298}299300/* we have moved ug to the correct position;301add 1 to the ug entry of collected part */302add_string(ug, 1, 1, cp, pcp);303continue;304} /* ug <= thirdwt */305306/* Step (6) -- ug > thirdwt;307move ug^ue past entries in the collected part, adding308commutators directly to the collected part;309scan collected part towards the left, bypassing generators310we know must commute with ug; if the cg position in311the collected part contains an entry ce then this312represents cg^ce; [cg^ce, ug^ue] = [cg, ug]^(ce * ue),313and we add the ce * ue power of [cg, ug] directly to314the collected part */315316weight_diff = current_class - WT(y[structure + ug]);317firstcg = y[class_end + weight_diff];318319for (cg = firstcg; cg > ug; cg--) {320ce = y[cp + cg];321if (ce != 0) {322/* add [cg, ug]^(ce * ue) directly to the collected part */323p1 = y[p_pcomm + cg];324p1 = y[p1 + ug];325if (p1 != 0) {326exp = ce * ue;327if (exp > maxexp)328integer_overflow();329if (p1 < 0)330len = y[-p1 + 1];331add_string(p1, len, exp, cp, pcp);332}333}334}335336/* add ue to the ug entry of collected part */337entry = y[cp + ug] + ue;338if (entry < prime) {339y[cp + ug] = entry;340continue;341} else {342y[cp + ug] = entry - prime;343p1 = y[p_power + ug];344if (p1 == 0)345continue;346}347348/* adding ue to the ug entry has created an entry >= prime;349we have to stack some of collected part */350for (cg = firstcg; cg > ug; cg--) {351ce = y[cp + cg];352if (ce != 0) {353/* set entry to zero and stack cg^ce */354y[cp + cg] = 0;355if (++sp >= STACK_SIZE)356stack_overflow();357strstk[sp] = cg;358expstk[sp] = ce;359}360}361362/* add in ug^p; p1 is a pointer to ug^p */363if (p1 < 0)364len = y[-p1 + 1];365add_string(p1, len, 1, cp, pcp);366continue;367}368}369370#endif /* GROUP*/371372/* add exponent times the string with address string and length length373directly to the collected part with base address collected_part,374recursively adding powers as required */375376void add_string(int string,377int length,378int exponent,379int collected_part,380struct pcp_vars *pcp)381{382register int *y = y_address;383384register int cp = collected_part;385register int exp = exponent;386register int len = length;387register int str = string;388register int entry;389register int ug;390register int ue;391register int power;392393register int class_begin = pcp->ccbeg;394register int prime = pcp->p;395register int p_power = pcp->ppower;396397register int i;398int lower, upper;399#include "access.h"400401if (str > 0) {402/* Step (4) --403we have moved generator str to the correct position;404add exp to the str entry of the collected part;405reduce entry modulo p and add a power of str^p406to the collected part if necessary */407408entry = y[cp + str] + exp;409y[cp + str] = entry % prime;410if (str < class_begin) {411exp = entry / prime;412#ifndef EXPONENT_P413if (exp != 0) {414/* we need to recursively add in (str^p)^exp */415str = y[p_power + str];416if (str != 0) {417if (str < 0)418len = y[-str + 1];419add_string(str, len, exp, cp, pcp);420}421}422#endif423}424} else {425/* Step (5) --426add string with base address -str and length len427directly to the collected part exp times; if this428creates an entry >= prime we reduce the entry modulo429prime and add in the appropriate power */430431lower = -str + 2;432upper = -str + len + 1;433434/* get one generator exponent pair at a time from string */435436for (i = lower; i <= upper; i++) {437ug = FIELD2(y[i]);438ue = FIELD1(y[i]) * exp;439entry = y[cp + ug] + ue;440441/* add ue to ug entry of the collected part and reduce mod p */442y[cp + ug] = entry % prime;443444#ifndef EXPONENT_P445/* we need to recursively add in (ug^p)^power */446if (ug < class_begin) {447power = entry / prime;448if (power != 0) {449str = y[p_power + ug];450if (str != 0) {451if (str < 0)452len = y[-str + 1];453add_string(str, len, power, cp, pcp);454}455}456}457#endif458}459}460}461462/* stack is not big enough */463464void stack_overflow(void)465{466printf("Stack overflow in collection routine; you should increase\n");467printf("value of STACK_SIZE in constants.h and recompile.\n");468exit(FAILURE);469}470471/* arithmetic overflow */472473void integer_overflow(void)474{475printf("Arithmetic overflow may occur in collection ");476printf("routine. Results may be invalid.\n");477exit(FAILURE);478}479480481