CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

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

Views: 418346
1
/****************************************************************************
2
**
3
*A collect.c ANUPQ source Eamonn O'Brien
4
**
5
*Y Copyright 1995-2001, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany
6
*Y Copyright 1995-2001, School of Mathematical Sciences, ANU, Australia
7
**
8
*/
9
10
#include "pq_defs.h"
11
#include "pcp_vars.h"
12
#include "constants.h"
13
#define MAXEXP (1 << 30)
14
15
void stack_overflow(void);
16
void integer_overflow(void);
17
void add_string(int string,
18
int length,
19
int exponent,
20
int collected_part,
21
struct pcp_vars *pcp);
22
23
/* an exponent vector with base address collected_part
24
is multiplied on the right by a string with base address
25
pointer; the string is assumed to be normal
26
27
this routine follows the algorithm devised by
28
M.R. Vaughan-Lee for collection from the left;
29
step numbers correspond to step numbers in
30
"Collection from the Left" by M.R. Vaughan-Lee,
31
J. Symbolic Computation (1990) 9, 725-733
32
33
this version embodies a simpler form of combinatorial
34
collection as described on page 733, which lessens the
35
chance of integer overflow; it also incorporates recursion
36
when adding strings and generators to the exponent vector
37
38
during the collection algorithm, pointers to a number of strings
39
are stored on a stack; theoretically, the stack depth could get
40
as large as (p - 1) * pcp->lastg * pcp->cc, but, in practice, depths
41
this large do not arise; however, it could be necessary to increase
42
the dimensions of the stack arrays for some calculations with large
43
groups; STACK_SIZE is the maximum depth of the stack; this constant
44
is declared in the constants header file; overflow is tested in
45
this algorithm
46
47
integer overflow is also tested for, although it can only arise
48
if p^3 > 2^31; if p^2 > 2^31, integer overflow can arise which
49
is not tested for
50
51
if either overflow arises, a message is printed out and
52
the program terminates;
53
54
#####################################################################
55
56
note the sections in this code enclosed within
57
58
#ifndef EXPONENT_P
59
#endif
60
61
if you insert as part of the header material of this file
62
63
#define EXPONENT_P
64
65
or supply EXPONENT_P as a -D flag to the compiler, then the
66
resulting collector assumes that all generators of the pcp
67
have order p and does not execute these portions of the code */
68
69
/* stack size on Apollo causes problems */
70
71
#ifdef APOLLO
72
static t_int strstk[STACK_SIZE]; /* string stack */
73
static t_int lenstk[STACK_SIZE]; /* length stack */
74
static t_int expstk[STACK_SIZE]; /* exponent stack */
75
#endif
76
77
/* if Lie program, use different collect routine */
78
#if defined(GROUP)
79
80
void collect(int pointer, int collected_part, struct pcp_vars *pcp)
81
{
82
register int *y = y_address;
83
84
register int p1; /* string pointer */
85
register int ce; /* collected exponent */
86
register int cg; /* collected generator */
87
register int ug; /* uncollected generator */
88
register int ue; /* uncollected exponent */
89
register int sp = 0; /* stack pointer */
90
register int exp; /* exponent */
91
register int len = 1; /* length */
92
register int str; /* string pointer */
93
register int halfwt; /* last generator with weight <= cc/2 */
94
register int thirdwt; /* last generator with weight <= cc/3 */
95
register int weight_diff; /* current class - weight of ug */
96
register int entry; /* value to be inserted in collected part */
97
register int firstcg; /* first collected generator for loop counter */
98
register int lastcg; /* last collected generator for loop counter */
99
register int maxexp; /* max exponent allowed in call to add_string */
100
101
register int cp = collected_part;
102
register int class_end = pcp->clend;
103
register int current_class = pcp->cc;
104
register int prime = pcp->p;
105
register int pm1 = pcp->pm1;
106
register int p_pcomm = pcp->ppcomm;
107
register int p_power = pcp->ppower;
108
register int structure = pcp->structure;
109
110
#ifndef APOLLO
111
int strstk[STACK_SIZE]; /* string stack */
112
int lenstk[STACK_SIZE]; /* length stack */
113
int expstk[STACK_SIZE]; /* exponent stack */
114
#endif
115
116
register int i;
117
118
#include "access.h"
119
120
/* if prime is 2, use special collector */
121
if (prime == 2) {
122
collectp2(pointer, collected_part, pcp);
123
return;
124
}
125
126
/* Step (0) --
127
initialize collector */
128
129
if (pointer < 0)
130
lenstk[0] = y[-pointer + 1];
131
else if (pointer == 0)
132
return;
133
134
strstk[0] = pointer;
135
expstk[0] = 1;
136
137
maxexp = (MAXEXP / prime) * 2;
138
halfwt = y[class_end + current_class / 2];
139
thirdwt = y[class_end + current_class / 3];
140
141
/* Step (1) --
142
process next word on stack */
143
144
while (sp >= 0) {
145
146
str = strstk[sp];
147
exp = expstk[sp];
148
149
/* check if str is a string or a generator */
150
151
if (str < 0) {
152
/* we have a genuine string */
153
len = lenstk[sp];
154
sp--;
155
156
/* get first generator exponent pair from string */
157
i = y[-str + 2];
158
ug = FIELD2(i);
159
160
/* if ug > halfwt, the string can be added to the
161
collected part without creating any commutators */
162
if (ug > halfwt) {
163
add_string(str, len, exp, cp, pcp);
164
continue;
165
}
166
167
/* ug <= halfwt and so exp must equal 1; stack remainder of string */
168
ue = FIELD1(i);
169
if (len != 1) {
170
strstk[++sp] = str - 1;
171
lenstk[sp] = len - 1;
172
}
173
} else {
174
/* str is a generator */
175
ug = str;
176
ue = exp;
177
sp--;
178
/* if ug > halfwt, ug commutes with all higher generators */
179
if (ug > halfwt) {
180
add_string(ug, 1, ue, cp, pcp);
181
continue;
182
}
183
}
184
185
/* ug <= halfwt; if ug > thirdwt, any commutators arising in
186
collecting ug commute with all generators after ug, so ug
187
can be collected without stacking up collected part */
188
189
if (ug <= thirdwt) {
190
191
/* Step (2) --
192
combinatorial collection;
193
scan collected part towards the left;
194
bypass generators we know must commute with ug;
195
when 2 * WT(cg) + WT(ug) > current_class, all generators
196
occurring in [cg, ug] commute with each other;
197
[cg^ce, ug] = [cg, ug]^ce;
198
if cg1,..., cgk all satisfy this weight condition then
199
[cg1 * ... * cgk, ug] = [cg1, ug] ... [cgk, ug] */
200
201
if (ue != 1) {
202
/* we only move one ug at a time; stack ug^(ue - 1) */
203
if (++sp >= STACK_SIZE)
204
stack_overflow();
205
strstk[sp] = ug;
206
expstk[sp] = ue - 1;
207
ue = 1;
208
}
209
210
weight_diff = current_class - WT(y[structure + ug]);
211
firstcg = y[class_end + weight_diff];
212
lastcg = y[class_end + weight_diff / 2];
213
214
/* scan collected part to the left, bypassing generators
215
which must commute with ug; the collected part between
216
lastcg and firstcg contains a word w; we add in [w, ug] */
217
218
for (cg = firstcg; cg > ug; cg--) {
219
ce = y[cp + cg];
220
if (ce != 0) {
221
/* add [cg, ug]^ce to the collected part */
222
p1 = y[p_pcomm + cg] + ug;
223
p1 = y[p1];
224
if (p1 != 0) {
225
if (cg <= lastcg)
226
break;
227
if (p1 < 0)
228
len = y[-p1 + 1];
229
add_string(p1, len, ce, cp, pcp);
230
}
231
}
232
}
233
234
if (cg == ug) {
235
/* we have reached ug position during combinatorial
236
collection; add 1 to ug entry of collected part
237
without stacking any entries if appropriate */
238
if (y[cp + ug] == pm1) {
239
if (y[p_power + ug] == 0) {
240
y[cp + ug] = 0;
241
continue;
242
}
243
} else {
244
++y[cp + ug];
245
continue;
246
}
247
}
248
249
/* we have now added in [w, ug]; stack up
250
collected part between firstcg and cg + 1 */
251
for (i = firstcg; i > cg; i--) {
252
ce = y[cp + i];
253
if (ce != 0) {
254
y[cp + i] = 0;
255
if (++sp >= STACK_SIZE)
256
stack_overflow();
257
strstk[sp] = i;
258
expstk[sp] = ce;
259
}
260
}
261
262
/* Step (3) --
263
ordinary collection; we have moved ug to the cg position;
264
continue scanning to the left */
265
for (; cg > ug; cg--) {
266
ce = y[cp + cg];
267
if (ce != 0) {
268
/* zero the cg entry of collected part */
269
y[cp + cg] = 0;
270
271
/* get [cg, ug] */
272
p1 = y[p_pcomm + cg] + ug;
273
p1 = y[p1];
274
if (p1 == 0) {
275
/* cg commutes with ug so stack cg^ce */
276
if (++sp >= STACK_SIZE)
277
stack_overflow();
278
strstk[sp] = cg;
279
expstk[sp] = ce;
280
} else {
281
/* cg does not commute with ug;
282
we can only move ug past one cg at a time;
283
stack [cg, ug] and then cg a total of ce times */
284
285
if (sp + ce + ce >= STACK_SIZE)
286
stack_overflow();
287
if (p1 < 0)
288
len = y[-p1 + 1];
289
290
for (; ce > 0; --ce) {
291
strstk[++sp] = p1;
292
lenstk[sp] = len;
293
expstk[sp] = 1;
294
strstk[++sp] = cg;
295
expstk[sp] = 1;
296
}
297
}
298
}
299
}
300
301
/* we have moved ug to the correct position;
302
add 1 to the ug entry of collected part */
303
add_string(ug, 1, 1, cp, pcp);
304
continue;
305
} /* ug <= thirdwt */
306
307
/* Step (6) -- ug > thirdwt;
308
move ug^ue past entries in the collected part, adding
309
commutators directly to the collected part;
310
scan collected part towards the left, bypassing generators
311
we know must commute with ug; if the cg position in
312
the collected part contains an entry ce then this
313
represents cg^ce; [cg^ce, ug^ue] = [cg, ug]^(ce * ue),
314
and we add the ce * ue power of [cg, ug] directly to
315
the collected part */
316
317
weight_diff = current_class - WT(y[structure + ug]);
318
firstcg = y[class_end + weight_diff];
319
320
for (cg = firstcg; cg > ug; cg--) {
321
ce = y[cp + cg];
322
if (ce != 0) {
323
/* add [cg, ug]^(ce * ue) directly to the collected part */
324
p1 = y[p_pcomm + cg];
325
p1 = y[p1 + ug];
326
if (p1 != 0) {
327
exp = ce * ue;
328
if (exp > maxexp)
329
integer_overflow();
330
if (p1 < 0)
331
len = y[-p1 + 1];
332
add_string(p1, len, exp, cp, pcp);
333
}
334
}
335
}
336
337
/* add ue to the ug entry of collected part */
338
entry = y[cp + ug] + ue;
339
if (entry < prime) {
340
y[cp + ug] = entry;
341
continue;
342
} else {
343
y[cp + ug] = entry - prime;
344
p1 = y[p_power + ug];
345
if (p1 == 0)
346
continue;
347
}
348
349
/* adding ue to the ug entry has created an entry >= prime;
350
we have to stack some of collected part */
351
for (cg = firstcg; cg > ug; cg--) {
352
ce = y[cp + cg];
353
if (ce != 0) {
354
/* set entry to zero and stack cg^ce */
355
y[cp + cg] = 0;
356
if (++sp >= STACK_SIZE)
357
stack_overflow();
358
strstk[sp] = cg;
359
expstk[sp] = ce;
360
}
361
}
362
363
/* add in ug^p; p1 is a pointer to ug^p */
364
if (p1 < 0)
365
len = y[-p1 + 1];
366
add_string(p1, len, 1, cp, pcp);
367
continue;
368
}
369
}
370
371
#endif /* GROUP*/
372
373
/* add exponent times the string with address string and length length
374
directly to the collected part with base address collected_part,
375
recursively adding powers as required */
376
377
void add_string(int string,
378
int length,
379
int exponent,
380
int collected_part,
381
struct pcp_vars *pcp)
382
{
383
register int *y = y_address;
384
385
register int cp = collected_part;
386
register int exp = exponent;
387
register int len = length;
388
register int str = string;
389
register int entry;
390
register int ug;
391
register int ue;
392
register int power;
393
394
register int class_begin = pcp->ccbeg;
395
register int prime = pcp->p;
396
register int p_power = pcp->ppower;
397
398
register int i;
399
int lower, upper;
400
#include "access.h"
401
402
if (str > 0) {
403
/* Step (4) --
404
we have moved generator str to the correct position;
405
add exp to the str entry of the collected part;
406
reduce entry modulo p and add a power of str^p
407
to the collected part if necessary */
408
409
entry = y[cp + str] + exp;
410
y[cp + str] = entry % prime;
411
if (str < class_begin) {
412
exp = entry / prime;
413
#ifndef EXPONENT_P
414
if (exp != 0) {
415
/* we need to recursively add in (str^p)^exp */
416
str = y[p_power + str];
417
if (str != 0) {
418
if (str < 0)
419
len = y[-str + 1];
420
add_string(str, len, exp, cp, pcp);
421
}
422
}
423
#endif
424
}
425
} else {
426
/* Step (5) --
427
add string with base address -str and length len
428
directly to the collected part exp times; if this
429
creates an entry >= prime we reduce the entry modulo
430
prime and add in the appropriate power */
431
432
lower = -str + 2;
433
upper = -str + len + 1;
434
435
/* get one generator exponent pair at a time from string */
436
437
for (i = lower; i <= upper; i++) {
438
ug = FIELD2(y[i]);
439
ue = FIELD1(y[i]) * exp;
440
entry = y[cp + ug] + ue;
441
442
/* add ue to ug entry of the collected part and reduce mod p */
443
y[cp + ug] = entry % prime;
444
445
#ifndef EXPONENT_P
446
/* we need to recursively add in (ug^p)^power */
447
if (ug < class_begin) {
448
power = entry / prime;
449
if (power != 0) {
450
str = y[p_power + ug];
451
if (str != 0) {
452
if (str < 0)
453
len = y[-str + 1];
454
add_string(str, len, power, cp, pcp);
455
}
456
}
457
}
458
#endif
459
}
460
}
461
}
462
463
/* stack is not big enough */
464
465
void stack_overflow(void)
466
{
467
printf("Stack overflow in collection routine; you should increase\n");
468
printf("value of STACK_SIZE in constants.h and recompile.\n");
469
exit(FAILURE);
470
}
471
472
/* arithmetic overflow */
473
474
void integer_overflow(void)
475
{
476
printf("Arithmetic overflow may occur in collection ");
477
printf("routine. Results may be invalid.\n");
478
exit(FAILURE);
479
}
480
481