|
|
|
|
Quelle collect.c
Sprache: C
|
|
/*****************************************************************************
**
** collect.c NQ Werner Nickel
** nickel@mathematik.tu-darmstadt.de
*/
#include "config.h"
#include "mem.h"
#include "pc.h"
#include "pcarith.h"
#include "macro.h"
#include "collect.h"
#include "time.h"
#include "system.h"
int UseSimpleCollector = 0;
int UseCombiCollector = 0;
static int Error(const char *str, gen g) {
printf("Error in Collect() while treating generator %d:\n", (int)g);
printf(" %s\n", str);
SimpleCollectionTime += RunTime();
/* exit( 7 );*/
return 7;
}
/*
** Collection from the left needs 4 stacks during the collection.
**
** The word stack containes conjugates of generators, that were created
** by moving a generator through the exponent vector to its correct
** place or it containes powers of generators.
** The word exponent stack containes the exponent of the corresponding
** word in the word stack.
** The generator stack containes the current position in the corresponding
** word in the word stack.
** The generator exponent stack containes the exponent of the generator
** determined by the corresponding entry in the generator stack.
**
** The maximum number of elements on each stack is determined by the macro
** STACKHEIGHT.
*/
#define STACKHEIGHT (1 << 16)
word WordStack[STACKHEIGHT];
expo WordExpStack[STACKHEIGHT];
word GenStack[STACKHEIGHT];
expo GenExpStack[STACKHEIGHT];
int SimpleCollect(expvec lhs, word rhs, expo e) {
word *ws = WordStack;
expo *wes = WordExpStack;
word *gs = GenStack;
expo *ges = GenExpStack;
word **C = Conjugate;
word *P = Power;
gen g, h;
gen ag;
int sp = 0;
SimpleCollectionTime -= RunTime();
ws[ sp ] = rhs;
gs[ sp ] = rhs;
wes[ sp ] = e;
ges[ sp ] = rhs->e;
while (sp >= 0)
if ((g = gs[ sp ]->g) != EOW) {
ag = abs(g);
if (g < 0 && Exponent[-g] != (expo)0)
return Error("Inverse of a generator with power relation", ag);
e = (ag == Commute[ag]) ? gs[ sp ]->e : (expo)1;
if ((ges[ sp ] -= e) == (expo)0) {
/* The power of the generator g will have been moved
completely to its correct position after this
collection step. Therefore advance the generator
pointer. */
gs[ sp ]++;
ges[ sp ] = gs[ sp ]->e;
}
/* Now move the generator g to its correct position
in the exponent vector lhs. */
for (h = Commute[ag]; h > ag; h--)
if (lhs[h] != (expo)0) {
if (++sp == STACKHEIGHT)
return Error("Out of stack space", ag);
if (lhs[ h ] > (expo)0) {
gs[ sp ] = ws[ sp ] = C[ h ][ g ];
wes[ sp ] = lhs[h];
lhs[ h ] = (expo)0;
ges[ sp ] = gs[ sp ]->e;
} else {
gs[ sp ] = ws[ sp ] = C[ -h ][ g ];
wes[ sp ] = -lhs[h];
lhs[ h ] = (expo)0;
ges[ sp ] = gs[ sp ]->e;
}
}
lhs[ ag ] += e * sgn(g);
if (((lhs[ag] << 1) >> 1) != lhs[ag])
return Error("Possible integer overflow", ag);
if (Exponent[ag] != (expo)0)
while (lhs[ag] >= Exponent[ag]) {
if ((rhs = P[ ag ]) != (word)0) {
if (++sp == STACKHEIGHT)
return Error("Out of stack space", ag);
gs[ sp ] = ws[ sp ] = rhs;
wes[ sp ] = (expo)1;
ges[ sp ] = gs[ sp ]->e;
}
lhs[ ag ] -= Exponent[ ag ];
if (((lhs[ag] << 1) >> 1) != lhs[ag])
return Error("Possible integer overflow", ag);
}
} else {
/* the top word on the stack has been examined completely,
now check if its exponent is zero. */
if (--wes[ sp ] == (expo)0) {
/* All powers of this word have been treated, so
we have to move down in the stack. */
sp--;
} else {
gs[ sp ] = ws[ sp ];
ges[ sp ] = gs[ sp ]->e;
}
}
SimpleCollectionTime += RunTime();
return 0;
}
int Collect(expvec lhs, word rhs, expo e) {
int ret, storeClass;
int i;
expvec lhs2;
storeClass = Class;
if (Class < 0) Class = 0;
Commute = CommuteList[ Class + 1 ];
Commute2 = Commute2List[ Class + 1 ];
if (UseSimpleCollector && UseCombiCollector) {
lhs2 = (expvec)Allocate((NrPcGens + NrCenGens + 1) * sizeof(expo));
memcpy(lhs2, lhs, (NrPcGens + NrCenGens + 1) * sizeof(expo));
ret = SimpleCollect(lhs, rhs, e);
CombiCollect(lhs2, rhs, e);
if (memcmp(lhs, lhs2, (NrPcGens + NrCenGens + 1) * sizeof(expo)) != 0) {
for (i = 1; i <= NrPcGens + NrCenGens; i++)
if (lhs[i] != lhs2[i])
printf("lhs[%d] = "EXP_FORMAT" lhs2[%d] = "EXP_FORMAT"\n", i, lhs[i], i, lhs2[i]);
printf("Collector mismatch\n");
}
Free(lhs2);
}
else if (UseCombiCollector) ret = CombiCollect(lhs, rhs, e);
else ret = SimpleCollect(lhs, rhs, e);
Class = storeClass;
return ret;
}
/*
** Solve the equation u x = v for x.
*/
word Solve(word u, word v) {
word x;
gpower y[2];
gen g;
long lv, lx;
expo ev;
expvec uvec;
y[1].g = EOW;
y[1].e = (expo)0;
uvec = (expvec)calloc((NrPcGens + NrCenGens + 1), sizeof(expo));
if (uvec == (expvec)0) {
perror("Solve(), uvec");
exit(2);
}
x = (word)malloc((NrPcGens + NrCenGens + 1) * sizeof(gpower));
if (x == (word)0) {
perror("Solve(), x");
exit(2);
}
if (Collect(uvec, u, (expo)1)) {
Free(x);
Free(uvec);
return (word)0;
}
for (lv = lx = 0, g = 1; g <= NrPcGens + NrCenGens; g++) {
if (v[lv].g == g) ev = v[ lv++ ].e;
else if (v[lv].g == -g) ev = -v[ lv++ ].e;
else ev = (expo)0;
if (ev != uvec[g]) {
if (ev > uvec[g]) { /* ev - uvec[g] > 0 */
y[0].g = x[lx].g = g;
y[0].e = x[lx++].e = ev - uvec[g];
} else if (Exponent[g] != (expo)0) { /* ev - uvec[g] < 0 */
y[0].g = x[lx].g = g;
y[0].e = x[lx++].e = ev - uvec[g] + Exponent[g];
} else {
y[0].g = x[lx].g = -g;
y[0].e = x[lx++].e = uvec[g] - ev;
}
if (Collect(uvec, y, (expo)1)) {
Free(x);
Free(uvec);
return (word)0;
}
}
}
Free(uvec);
x[lx].g = EOW;
x[lx++].e = (expo)0;
x = (word)realloc(x, lx * sizeof(gpower));
if (x == (word)0) {
perror("Solve(), x (resize)");
exit(2);
}
return x;
}
word Invert(word u) {
gpower id;
id.g = EOW;
id.e = (expo)0;
return Solve(u, &id);
}
word Multiply(word u, word v) {
expvec ev;
word w;
ev = (expvec)Allocate((NrPcGens + NrCenGens + 1) * sizeof(expo));
if (Collect(ev, u, (expo)1) || Collect(ev, v, (expo)1)) {
Free(ev);
return (word)0;
}
w = WordExpVec(ev);
Free(ev);
return w;
}
word Exponentiate(word u, int n) {
word v;
expvec ev;
int copied_u = 0;
if (n < 0) {
if ((u = Invert(u)) == (word)0) return (word)0;
copied_u = 1;
n = -n;
}
ev = (expvec)Allocate((NrPcGens + NrCenGens + 1) * sizeof(expo));
while (n > 0) {
if (n % 2)
if (Collect(ev, u, (expo)1)) {
if (copied_u) Free(u);
Free(ev);
return (word)0;
}
n /= 2;
if (n > 0) {
if ((v = Multiply(u, u)) == (word)0) {
if (copied_u) Free(u);
Free(ev);
return (word)0;
}
if (copied_u) Free(u);
u = v;
copied_u = 1;
}
}
if (copied_u) Free(u);
u = WordExpVec(ev);
Free(ev);
return u;
}
/*
** Solve the equation vu x = uv for x. The solution is the commutator
** [u,v].
**
** In step i we have to solve the equation v'u' x = u''v''.
** That equation holds for the i-th generator if
**
** v'[i] + u'[i] + x[i] = u''[i] + v''[i]
**
** Hence x[i] = u''[i] + v''[i] - (v'[i] + u'[i]).
** To prepare the (i+1)-th step we need to collect i^x[i] first across
** u' and then across v' on the left hand side of the equation. On the
** right hand side of the equation we need to collect i^v''[i] across
** u''. This has the effect of moving the occurrences of generator i
** to the left on both sides of the equation such that it can be
** cancelled on both sides of the equation.
*/
word Commutator(word u, word v) {
expvec u1, u2, v1, v2, x;
gpower y[2];
word w = (word)0;
int i;
y[0].g = y[1].g = EOW;
y[0].e = y[1].e = (expo)0;
u1 = ExpVecWord(u);
u2 = ExpVecWord(u);
v1 = ExpVecWord(v);
v2 = ExpVecWord(v);
x = ExpVecWord(y);
for (i = 1; i <= NrPcGens + NrCenGens; i++) {
x[i] = u2[i] + v2[i] - (v1[i] + u1[i]);
if (Exponent[i] != (expo)0) {
while (x[i] < (expo)0) x[i] += Exponent[i];
if (x[i] >= Exponent[i]) x[i] -= Exponent[i];
}
if (x[i] != (expo)0) {
if (x[i] > (expo)0) { y[0].g = i; y[0].e = x[i]; }
else { y[0].g = -i; y[0].e = -x[i]; }
if (Collect(u1, y, (expo)1)) goto exit;
}
if (u1[i] != (expo)0) {
if (u1[i] > (expo)0) { y[0].g = i; y[0].e = u1[i]; }
else { y[0].g = -i; y[0].e = -u1[i]; }
if (Collect(v1, y, (expo)1)) goto exit;
}
if (v2[i] != (expo)0) {
if (v2[i] > (expo)0) { y[0].g = i; y[0].e = v2[i]; }
else { y[0].g = -i; y[0].e = -v2[i]; }
if (Collect(u2, y, (expo)1)) goto exit;
}
}
w = WordExpVec(x);
exit:
Free(u1);
Free(u2);
Free(v1);
Free(v2);
Free(x);
return w;
}
#if 0
word Commutator2(word v, word w) {
expvec ev;
word vw, wv, vwvw;
ev = ExpVecWord(v);
if (Collect(ev, w, (expo)1)) {
Free(ev);
return (word)0;
}
vw = WordExpVec(ev);
Free(ev);
ev = ExpVecWord(w);
if (Collect(ev, v, (expo)1)) {
Free(ev);
Free(vw);
return (word)0;
}
wv = WordExpVec(ev);
Free(ev);
vwvw = Solve(wv, vw);
Free(vw);
Free(wv);
return vwvw;
}
#endif
¤ Dauer der Verarbeitung: 0.7 Sekunden
¤
*© Formatika GbR, Deutschland
|
|
2026-11-01
|
|
|
|
|
Neuigkeiten |
| Aktuelles |
| Motto des Tages |
|
Open Source Software |
|
|
|
Jenseits des Üblichen ....
|
|
Besucherstatistik |
|
|
| Statistik |
| #Sources=1104856 |
| #Domains=417405 |
|
|