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 echelon.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 "pq_functions.h"
13
#define CAREFUL
14
15
/* echelonise the relation stored in exponent form in two parts;
16
left-hand side is in y[lused + 1] to y[lused + lastg];
17
right-hand side is in y[lused + lastg + 1] to y[lused + 2 * lastg];
18
19
the relation should be homogeneous of class pcp->cc;
20
if the result is nontrivial, set it up as a new relation pointed
21
to by the appropriate y[structure + ..]; then remove all occurrences
22
of newly found redundant generator from the other equations */
23
24
int echelon(struct pcp_vars *pcp)
25
{
26
register int *y = y_address;
27
28
register int i;
29
register int j;
30
register int k;
31
register int p1;
32
register int exp;
33
register int redgen = 0;
34
register int count = 0;
35
register int factor;
36
register int bound;
37
register int offset;
38
register int temp;
39
register int value;
40
register int free;
41
42
register Logical trivial;
43
register Logical first;
44
45
register int p = pcp->p;
46
register int pm1 = pcp->pm1;
47
48
#include "access.h"
49
50
pcp->redgen = 0;
51
pcp->eliminate_flag = FALSE;
52
53
/* check that the relation is homogeneous of class pcp->cc */
54
if (pcp->cc != 1) {
55
offset = pcp->lused - 1;
56
temp = pcp->lastg;
57
for (i = 2, bound = pcp->ccbeg; i <= bound; i++) {
58
if (y[offset + i] != y[offset + temp + i]) {
59
text(6, pcp->cc, 0, 0, 0);
60
pcp->eliminate_flag = TRUE;
61
return -1;
62
}
63
}
64
}
65
66
/* compute quotient of the relations and store quotient as an exponent
67
vector in y[pcp->lused + pcp->ccbeg] to y[pcp->lused + pcp->lastg] */
68
k = 0;
69
offset = pcp->lused;
70
for (i = pcp->ccbeg, bound = pcp->lastg; i <= bound; i++) {
71
y[offset + i] -= y[offset + bound + i];
72
if ((j = y[offset + i])) {
73
if (j < 0)
74
y[offset + i] += p;
75
k = i;
76
}
77
}
78
79
if (k <= 0)
80
return -1;
81
82
/* print out the quotient of the relations */
83
if (pcp->diagn) {
84
/* a call to compact is not permitted at this point */
85
if (pcp->lused + 4 * pcp->lastg + 2 < pcp->structure) {
86
/* first copy relevant entries to new position in y */
87
free = pcp->lused + 2 * pcp->lastg + 1;
88
for (i = 1; i < pcp->ccbeg; ++i)
89
y[free + i] = 0;
90
for (i = pcp->ccbeg; i <= pcp->lastg; ++i)
91
y[free + i] = y[pcp->lused + i];
92
setup_word_to_print(
93
"quotient relation", free, free + pcp->lastg + 1, pcp);
94
}
95
}
96
97
first = TRUE;
98
99
while (first || --k >= pcp->ccbeg) {
100
/* does generator k occur in the unechelonised relation? */
101
if (!first && y[pcp->lused + k] <= 0)
102
continue;
103
104
/* yes */
105
first = FALSE;
106
exp = y[pcp->lused + k];
107
if ((i = y[pcp->structure + k]) <= 0) {
108
if (i < 0) {
109
/* generator k was previously redundant, so eliminate it */
110
p1 = -y[pcp->structure + k];
111
count = y[p1 + 1];
112
offset = pcp->lused;
113
for (i = 1; i <= count; i++) {
114
value = y[p1 + i + 1];
115
j = FIELD2(value);
116
/* integer overflow can occur here; see comments in collect */
117
y[offset + j] = (y[offset + j] + exp * FIELD1(value)) % p;
118
}
119
}
120
y[pcp->lused + k] = 0;
121
} else {
122
/* generator k was previously irredundant; have we already
123
found a generator to eliminate using this relation? */
124
if (redgen > 0) {
125
/* yes, so multiply this term by the appropriate factor
126
and note that the value of redgen is not trivial */
127
trivial = FALSE;
128
/* integer overflow can occur here; see comments in collect */
129
y[pcp->lused + k] = (y[pcp->lused + k] * factor) % p;
130
} else {
131
/* no, we will eliminate k using this relation */
132
redgen = k;
133
trivial = TRUE;
134
135
/* we want to compute the value of k so we will multiply the
136
rest of the relation by the appropriate factor;
137
integer overflow can occur here; see comments in collect */
138
factor = pm1 * invert_modp(exp, p);
139
140
/* we carry out this mod computation to reduce possibility
141
of integer overflow */
142
#if defined(CAREFUL)
143
factor = factor % p;
144
#endif
145
y[pcp->lused + k] = 0;
146
}
147
}
148
}
149
150
if (redgen <= 0)
151
return -1;
152
else
153
pcp->redgen = redgen;
154
155
/* the relation is nontrivial; redgen is either trivial or redundant */
156
157
if (trivial) {
158
/* mark redgen as trivial */
159
y[pcp->structure + redgen] = 0;
160
161
if (pcp->fullop)
162
text(3, redgen, 0, 0, 0);
163
164
complete_echelon(1, redgen, pcp);
165
} else {
166
/* redgen has value in exponent form in y[pcp->lused + pcp->ccbeg]
167
to y[pcp->lused + redgen(-1)] */
168
count = 0;
169
offset = pcp->lused;
170
for (i = pcp->ccbeg; i <= redgen; i++)
171
if (y[offset + i] > 0) {
172
count++;
173
y[offset + count] = PACK2(y[offset + i], i);
174
}
175
offset = pcp->lused + count + 1;
176
for (i = 1; i <= count; i++)
177
y[offset + 2 - i] = y[offset - i];
178
179
/* set up the relation for redgen */
180
y[pcp->lused + 1] = pcp->structure + redgen;
181
y[pcp->lused + 2] = count;
182
y[pcp->structure + redgen] = -(pcp->lused + 1);
183
184
pcp->lused += count + 2;
185
186
if (pcp->fullop)
187
text(4, redgen, 0, 0, 0);
188
189
complete_echelon(0, redgen, pcp);
190
}
191
192
pcp->eliminate_flag = TRUE;
193
if (redgen < pcp->first_pseudo)
194
pcp->newgen--;
195
if (pcp->newgen != 0 || pcp->multiplicator)
196
return count;
197
198
/* group is completed because all actual generators are redundant,
199
so it is not necessary to continue calculation of this class */
200
pcp->complete = 1;
201
last_class(pcp);
202
203
if (pcp->fullop || pcp->diagn)
204
text(5, pcp->cc, p, pcp->lastg, 0);
205
206
return -1;
207
}
208
209
/* complete echelonisation of this relation by removing all occurrences
210
of redgen from the other relations; if the generator redgen is
211
trivial, then the flag trivial is TRUE */
212
213
void complete_echelon(Logical trivial, int redgen, struct pcp_vars *pcp)
214
{
215
register int *y = y_address;
216
217
int k;
218
int i, j, jj, exp;
219
int p1;
220
int factor;
221
int count, count1, count2;
222
int predg;
223
int offset;
224
int temp;
225
int value;
226
int bound;
227
int l;
228
int p = pcp->p;
229
230
#include "access.h"
231
232
if (trivial) {
233
/* delete all occurrences of redgen from other equations */
234
for (k = redgen + 1, bound = pcp->lastg; k <= bound; k++) {
235
if (y[pcp->structure + k] >= 0)
236
continue;
237
p1 = -y[pcp->structure + k];
238
count = y[p1 + 1];
239
for (j = 1; j <= count; j++)
240
if ((temp = FIELD2(y[p1 + j + 1])) >= redgen)
241
break;
242
if (j > count || temp > redgen)
243
continue;
244
245
/* redgen occurs in this relation, so eliminate it;
246
is redgen in the last word? */
247
count1 = count - 1;
248
249
if (j < count) {
250
/* no, so pack up relation */
251
for (jj = j; jj <= count1; jj++)
252
y[p1 + jj + 1] = y[p1 + jj + 2];
253
}
254
255
if (j < count || (j >= count && count1 > 0)) {
256
/* deallocate last word and fix count in header block */
257
y[p1 + count + 1] = -1;
258
y[p1 + 1] = count1;
259
continue;
260
}
261
262
/* old relation is to be eliminated (it was 1 word long) */
263
y[p1] = 0;
264
y[pcp->structure + k] = 0;
265
}
266
} else {
267
p1 = -y[pcp->structure + redgen];
268
count = y[p1 + 1];
269
270
/* eliminate all occurrences of redgen from the other relations
271
by substituting its value */
272
for (k = redgen + 1, bound = pcp->lastg; k <= bound; k++) {
273
if (y[pcp->structure + k] >= 0)
274
continue;
275
if (is_space_exhausted(pcp->lastg + 1, pcp))
276
return;
277
p1 = -y[pcp->structure + k];
278
count1 = y[p1 + 1];
279
for (j = 1; j <= count1; j++)
280
if ((temp = FIELD2(y[p1 + j + 1])) >= redgen)
281
break;
282
if (j > count1 || temp > redgen)
283
continue;
284
285
/* redgen occurs in this relation, so eliminate it */
286
factor = FIELD1(y[p1 + j + 1]);
287
predg = -y[pcp->structure + redgen];
288
289
/* merge old relation with factor * (new relation), deleting redgen;
290
old relation is longer than new relation since it contains redgen */
291
292
/* commence merge */
293
count2 = 0;
294
offset = pcp->lused + 2;
295
for (i = 1, l = 1;;) {
296
temp = FIELD2(y[p1 + i + 1]) - FIELD2(y[predg + l + 1]);
297
if (temp < 0) {
298
count2++;
299
y[offset + count2] = y[p1 + i + 1];
300
i++;
301
} else if (temp > 0) {
302
count2++;
303
/* integer overflow can occur here; see comments in collect */
304
value = y[predg + l + 1];
305
y[offset + count2] =
306
PACK2((factor * FIELD1(value)) % p, FIELD2(value));
307
if (++l > count)
308
break;
309
} else {
310
/* integer overflow can occur here; see comments in collect */
311
value = y[p1 + i + 1];
312
exp = (FIELD1(value) + factor * FIELD1(y[predg + l + 1])) % p;
313
if (exp > 0) {
314
count2++;
315
y[offset + count2] = PACK2(exp, FIELD2(value));
316
}
317
i++;
318
if (++l > count)
319
break;
320
}
321
}
322
323
/* all of the value of redgen has been merged in;
324
copy in the remainder of the old relation with redgen deleted */
325
offset = pcp->lused + 2;
326
for (jj = i; jj <= count1; jj++)
327
if (jj != j) {
328
count2++;
329
y[offset + count2] = y[p1 + jj + 1];
330
}
331
332
/* new relation is now in y[lused + 2 + 1] to y[lused + 2 + count2] */
333
334
/* new relation indicates generator k is trivial; deallocate old */
335
if (count2 <= 0) {
336
y[p1] = 0;
337
y[pcp->structure + k] = 0;
338
continue;
339
}
340
341
/* new relation is nontrivial */
342
343
if (count2 < count1) {
344
/* new relation is shorter than old; copy in new relation */
345
for (i = 1; i <= count2; i++)
346
y[p1 + i + 1] = y[pcp->lused + 2 + i];
347
348
/* reset count field for new relation */
349
y[p1 + 1] = count2;
350
351
/* deallocate rest of old relation */
352
if (count1 == count2 + 1)
353
y[p1 + count2 + 2] = -1;
354
else {
355
y[p1 + count2 + 2] = 0;
356
y[p1 + count2 + 3] = count1 - count2 - 2;
357
}
358
} else if (count1 == count2) {
359
/* new relation has same length as old; overwrite old relation */
360
offset = pcp->lused + 2;
361
for (i = 1; i <= count2; i++)
362
y[p1 + i + 1] = y[offset + i];
363
} else {
364
/* new relation is longer than old; deallocate old relation */
365
y[p1] = 0;
366
367
/* set up pointer to new relation and header block */
368
y[pcp->structure + k] = -(pcp->lused + 1);
369
y[pcp->lused + 1] = pcp->structure + k;
370
y[pcp->lused + 2] = count2;
371
pcp->lused += count2 + 2;
372
}
373
}
374
}
375
}
376
377