/* echelonise the relation stored in exponent form in two parts; left-handsideisiny[lused+1]toy[lused+lastg]; right-handsideisiny[lused+lastg+1]toy[lused+2*lastg];
therelationshouldbehomogeneousofclasspcp->cc; iftheresultisnontrivial,setitupasanewrelationpointed tobytheappropriatey[structure+..];thenremovealloccurrences
of newly found redundant generator from the other equations */
int echelon(struct pcp_vars *pcp)
{ register int *y = y_address;
register int i; register int j; register int k; register int p1; register int exp; register int redgen = 0; register int count = 0; register int factor; register int bound; register int offset; register int temp; register int value; register int free;
register Logical trivial; register Logical first;
register int p = pcp->p; register int pm1 = pcp->pm1;
#include"access.h"
pcp->redgen = 0;
pcp->eliminate_flag = FALSE;
/* check that the relation is homogeneous of class pcp->cc */
if (pcp->cc != 1) {
offset = pcp->lused - 1;
temp = pcp->lastg;
for (i = 2, bound = pcp->ccbeg; i <= bound; i++) {
if (y[offset + i] != y[offset + temp + i]) {
text(6, pcp->cc, 0, 0, 0);
pcp->eliminate_flag = TRUE; return -1;
}
}
}
/* compute quotient of the relations and store quotient as an exponent
vector in y[pcp->lused + pcp->ccbeg] to y[pcp->lused + pcp->lastg] */
k = 0;
offset = pcp->lused;
for (i = pcp->ccbeg, bound = pcp->lastg; i <= bound; i++) {
y[offset + i] -= y[offset + bound + i];
if ((j = y[offset + i])) {
if (j < 0)
y[offset + i] += p;
k = i;
}
}
if (k <= 0) return -1;
/* print out the quotient of the relations */
if (pcp->diagn) { /* a call to compact is not permitted at this point */
if (pcp->lused + 4 * pcp->lastg + 2 < pcp->structure) { /* first copy relevant entries to new position in y */
free = pcp->lused + 2 * pcp->lastg + 1;
for (i = 1; i < pcp->ccbeg; ++i)
y[free + i] = 0;
for (i = pcp->ccbeg; i <= pcp->lastg; ++i)
y[free + i] = y[pcp->lused + i];
setup_word_to_print( "quotient relation", free, free + pcp->lastg + 1, pcp);
}
}
first = TRUE;
while (first || --k >= pcp->ccbeg) { /* does generator k occur in the unechelonised relation? */
if (!first && y[pcp->lused + k] <= 0) continue;
/* yes */
first = FALSE;
exp = y[pcp->lused + k];
if ((i = y[pcp->structure + k]) <= 0) {
if (i < 0) { /* generator k was previously redundant, so eliminate it */
p1 = -y[pcp->structure + k];
count = y[p1 + 1];
offset = pcp->lused;
for (i = 1; i <= count; i++) {
value = y[p1 + i + 1];
j = FIELD2(value); /* integer overflow can occur here; see comments in collect */
y[offset + j] = (y[offset + j] + exp * FIELD1(value)) % p;
}
}
y[pcp->lused + k] = 0;
} else { /* generator k was previously irredundant; have we already
found a generator to eliminate using this relation? */
if (redgen > 0) { /* yes, so multiply this term by the appropriate factor
and note that the value of redgen is not trivial */
trivial = FALSE; /* integer overflow can occur here; see comments in collect */
y[pcp->lused + k] = (y[pcp->lused + k] * factor) % p;
} else { /* no, we will eliminate k using this relation */
redgen = k;
trivial = TRUE;
/* we want to compute the value of k so we will multiply the restoftherelationbytheappropriatefactor;
integer overflow can occur here; see comments in collect */
factor = pm1 * invert_modp(exp, p);
/* we carry out this mod computation to reduce possibility
of integer overflow */ #ifdefined(CAREFUL)
factor = factor % p; #endif
y[pcp->lused + k] = 0;
}
}
}
if (redgen <= 0) return -1; else
pcp->redgen = redgen;
/* the relation is nontrivial; redgen is either trivial or redundant */
if (trivial) { /* mark redgen as trivial */
y[pcp->structure + redgen] = 0;
if (pcp->fullop)
text(3, redgen, 0, 0, 0);
complete_echelon(1, redgen, pcp);
} else { /* redgen has value in exponent form in y[pcp->lused + pcp->ccbeg]
to y[pcp->lused + redgen(-1)] */
count = 0;
offset = pcp->lused;
for (i = pcp->ccbeg; i <= redgen; i++)
if (y[offset + i] > 0) {
count++;
y[offset + count] = PACK2(y[offset + i], i);
}
offset = pcp->lused + count + 1;
for (i = 1; i <= count; i++)
y[offset + 2 - i] = y[offset - i];
/* set up the relation for redgen */
y[pcp->lused + 1] = pcp->structure + redgen;
y[pcp->lused + 2] = count;
y[pcp->structure + redgen] = -(pcp->lused + 1);
pcp->lused += count + 2;
if (pcp->fullop)
text(4, redgen, 0, 0, 0);
complete_echelon(0, redgen, pcp);
}
pcp->eliminate_flag = TRUE;
if (redgen < pcp->first_pseudo)
pcp->newgen--;
if (pcp->newgen != 0 || pcp->multiplicator) return count;
/* group is completed because all actual generators are redundant,
so it is not necessary to continue calculation of this class */
pcp->complete = 1;
last_class(pcp);
if (pcp->fullop || pcp->diagn)
text(5, pcp->cc, p, pcp->lastg, 0);
return -1;
}
/* complete echelonisation of this relation by removing all occurrences ofredgenfromtheotherrelations;ifthegeneratorredgenis
trivial, then the flag trivial is TRUE */
void complete_echelon(Logical trivial, int redgen, struct pcp_vars *pcp)
{ register int *y = y_address;
int k;
int i, j, jj, exp;
int p1;
int factor;
int count, count1, count2;
int predg;
int offset;
int temp;
int value;
int bound;
int l;
int p = pcp->p;
#include"access.h"
if (trivial) { /* delete all occurrences of redgen from other equations */
for (k = redgen + 1, bound = pcp->lastg; k <= bound; k++) {
if (y[pcp->structure + k] >= 0) continue;
p1 = -y[pcp->structure + k];
count = y[p1 + 1];
for (j = 1; j <= count; j++)
if ((temp = FIELD2(y[p1 + j + 1])) >= redgen) break;
if (j > count || temp > redgen) continue;
/* redgen occurs in this relation, so eliminate it;
is redgen in the last word? */
count1 = count - 1;
if (j < count) { /* no, so pack up relation */
for (jj = j; jj <= count1; jj++)
y[p1 + jj + 1] = y[p1 + jj + 2];
}
if (j < count || (j >= count && count1 > 0)) { /* deallocate last word and fix count in header block */
y[p1 + count + 1] = -1;
y[p1 + 1] = count1; continue;
}
/* old relation is to be eliminated (it was 1 word long) */
y[p1] = 0;
y[pcp->structure + k] = 0;
}
} else {
p1 = -y[pcp->structure + redgen];
count = y[p1 + 1];
/* eliminate all occurrences of redgen from the other relations
by substituting its value */
for (k = redgen + 1, bound = pcp->lastg; k <= bound; k++) {
if (y[pcp->structure + k] >= 0) continue;
if (is_space_exhausted(pcp->lastg + 1, pcp)) return;
p1 = -y[pcp->structure + k];
count1 = y[p1 + 1];
for (j = 1; j <= count1; j++)
if ((temp = FIELD2(y[p1 + j + 1])) >= redgen) break;
if (j > count1 || temp > redgen) continue;
/* redgen occurs in this relation, so eliminate it */
factor = FIELD1(y[p1 + j + 1]);
predg = -y[pcp->structure + redgen];
/* merge old relation with factor * (new relation), deleting redgen;
old relation is longer than new relation since it contains redgen */
/* commence merge */
count2 = 0;
offset = pcp->lused + 2;
for (i = 1, l = 1;;) {
temp = FIELD2(y[p1 + i + 1]) - FIELD2(y[predg + l + 1]);
if (temp < 0) {
count2++;
y[offset + count2] = y[p1 + i + 1];
i++;
} else if (temp > 0) {
count2++; /* integer overflow can occur here; see comments in collect */
value = y[predg + l + 1];
y[offset + count2] =
PACK2((factor * FIELD1(value)) % p, FIELD2(value));
if (++l > count) break;
} else { /* integer overflow can occur here; see comments in collect */
value = y[p1 + i + 1];
exp = (FIELD1(value) + factor * FIELD1(y[predg + l + 1])) % p;
if (exp > 0) {
count2++;
y[offset + count2] = PACK2(exp, FIELD2(value));
}
i++;
if (++l > count) break;
}
}
/* all of the value of redgen has been merged in;
copy in the remainder of the old relation with redgen deleted */
offset = pcp->lused + 2;
for (jj = i; jj <= count1; jj++)
if (jj != j) {
count2++;
y[offset + count2] = y[p1 + jj + 1];
}
/* new relation is now in y[lused + 2 + 1] to y[lused + 2 + count2] */
/* new relation indicates generator k is trivial; deallocate old */
if (count2 <= 0) {
y[p1] = 0;
y[pcp->structure + k] = 0; continue;
}
/* new relation is nontrivial */
if (count2 < count1) { /* new relation is shorter than old; copy in new relation */
for (i = 1; i <= count2; i++)
y[p1 + i + 1] = y[pcp->lused + 2 + i];
/* reset count field for new relation */
y[p1 + 1] = count2;
/* deallocate rest of old relation */
if (count1 == count2 + 1)
y[p1 + count2 + 2] = -1; else {
y[p1 + count2 + 2] = 0;
y[p1 + count2 + 3] = count1 - count2 - 2;
}
} else if (count1 == count2) { /* new relation has same length as old; overwrite old relation */
offset = pcp->lused + 2;
for (i = 1; i <= count2; i++)
y[p1 + i + 1] = y[offset + i];
} else { /* new relation is longer than old; deallocate old relation */
y[p1] = 0;
/* set up pointer to new relation and header block */
y[pcp->structure + k] = -(pcp->lused + 1);
y[pcp->lused + 1] = pcp->structure + k;
y[pcp->lused + 2] = count2;
pcp->lused += count2 + 2;
}
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-09-04)
¤
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.