/* File relator.c. Contains miscellaneous functions for manipulating sets of
relators. */
#include <stdlib.h>
#include <stdio.h>
#include "group.h"
#include "enum.h"
#include "errmesg.h"
#include "new.h"
#include "permut.h"
#include "stcs.h"
#include "storage.h"
CHECK( relato)
extern GroupOptions options;
extern STCSOptions sOptions;
extern Unsigned shiftSelection[11];
extern Unsigned shiftPriority[11];
extern Unsigned *nextCos, *prevCos, *ff, *bb, *equivCoset;
extern Unsigned freeCosHeader, firstCos;
extern Unsigned extraCosetsAtLevel;
extern Unsigned currentExtraCosets;
BOOLEAN verifyCosetList(
Unsigned degree);
BOOLEAN onFreeList(
Unsigned coset);
/* static callCount = 0; */ /*DEBUG*/
/*-------------------------- relatorLevel ---------------------------------*/
/* The function relatorLevel( r) returns the level in G of the relator r.
This level is defined to be the minimum level of any of the generators
of G appearing in r. Naturally the level fields of the generators of G
must be filled in. */
UnsignedS relatorLevel(
const Relator *const r)
{
Unsigned i, minLevel = options.maxBaseSize + 1;
for ( i = 1 ; i <= r->length ; ++i )
if ( r->rel[i]->level < minLevel )
minLevel = r->rel[i]->level;
return minLevel;
}
/*-------------------------- symmetricLength ------------------------------*/
/* The function symmetricLength( r) returns the "symmetric length" of the
relator r. The symmetric length of r is defined to be the smallest
positive integer i such that an i-position cyclic shift of r leaves r
unchanged. The relator must have been created with doubleFlag set. */
Unsigned symmetricLength(
const Relator *const r)
{
Permutation **rel = r->rel;
Unsigned i, j, length = r->length;
for ( i = 1 ; i <= length / 2 ; ++i )
if ( length % i == 0 ) {
for ( j = 1 ; j <= length && rel[j+i] == rel[j] ; ++j )
;
if ( j > length )
return i;
}
return length;
}
/*-------------------------- symmetricWordLength --------------------------*/
/* The function symmetricWordLength( w) is identical to symmetricLength
(above) except that it uses a word, rather than a relator, as its input. */
Unsigned symmetricWordLength(
const Word *const w)
{
Permutation **rel = w->position;
Unsigned i, j, length = w->length;
for ( i = 1 ; i <= length / 2 ; ++i )
if ( length % i == 0 ) {
for ( j = 1 ; j <= length && rel[(j-1+i)%length + 1] == rel[j] ; ++j )
;
if ( j > length )
return i;
}
return length;
}
/*-------------------------- addRelatorSortedFromWord ---------------------*/
/* The function addRelatorSortedFromWord( G, w, fbRelFlag, doubleFlag) adds
a new relator, represented by a word w, to a permutation group G. The
new relator is positioned so that the relators remain sorted by level
(highest to lowest) and so that the new relator is last among relators
of its level. Note both the new relator and the word w will be reduced
by cancelling adjacent entries of form a * a^-1 or a^-1 * a. If fbRelFlag
is set, the fRel and bRel entries of the new relator will be constructed.
If doubleFlag is set, the each relator will be concatenated to itself (the
length field will still give the original length).
The function returns a pointer to the relator added, or NULL if it could
not be added. */
Relator *addRelatorSortedFromWord(
PermGroup *const G,
Word *const w,
BOOLEAN fbRelFlag,
BOOLEAN doubleFlag)
{
Relator *newRel, *r, *rPrev;
Unsigned newLevel;
newRel = newRelatorFromWord( w, fbRelFlag, doubleFlag);
if ( !newRel )
return NULL;
newLevel = relatorLevel( newRel);
newRel->level = newLevel;
rPrev = NULL;
for ( r = G->relator ; r && r->level >= newLevel ; rPrev = r , r = r->next )
;
newRel->next = r;
newRel->last = rPrev;
if ( rPrev )
rPrev->next = newRel;
else
G->relator = newRel;
if ( r )
r->last = newRel;
return newRel;
}
/*-------------------------- addOccurencesForRelator ---------------------*/
/* The function addOccurencesForRelator( r, priority) adds an occurenceOfGen record
for each significantly different occurence of each generator in r.
If shiftSelection[0] != UNKNOWN, only those specified shift selections
for which priority >= shiftPriority are added. It returns the number
of occurences added. */
Unsigned addOccurencesForRelator(
const Relator *const r,
Unsigned priority)
{
Unsigned i, j, addCount = 0, symLength = symmetricLength(r);
OccurenceOfGen *p, *q, *prevQ;
Permutation *gen;
if ( symLength <= 4 || shiftSelection[0] == UNKNOWN )
for ( i = 1 ; i <= symLength ; ++i ) {
++addCount;
p = allocOccurenceOfGen();
p->r = (Relator *)(r);
p->relLength = r->length;
p->level = r->level;
p->fRelStart = r->fRel + i;
p->bRelFinish = r->bRel + (i + r->length - 1);
gen = r->rel[i];
for ( prevQ = NULL , q = gen->occurHeader ; q && q->level >= p->level ;
prevQ = q , q = q->next )
;
p->next = q;
if ( prevQ )
prevQ->next = p;
else
gen->occurHeader = p;
}
else
for ( j = 0 ; shiftSelection[j] != UNKNOWN ; ++j ) {
i = shiftSelection[j] + 1;
if ( i < r->length && priority >= shiftPriority[j] ) {
++addCount;
p = allocOccurenceOfGen();
p->r = (Relator *)(r);
p->relLength = r->length;
p->level = r->level;
p->fRelStart = r->fRel + i;
p->bRelFinish = r->bRel + (i + r->length - 1);
gen = r->rel[i];
for ( prevQ = NULL , q = gen->occurHeader ; q && q->level >= p->level ;
prevQ = q , q = q->next )
;
p->next = q;
if ( prevQ )
prevQ->next = p;
else
gen->occurHeader = p;
}
}
return addCount;
}
/*-------------------------- resetTable -----------------------------------*/
void resetTable(
Permutation *genHeader,
Unsigned basicOrbLen,
Unsigned *basicOrbit)
{
Permutation *gen;
Unsigned i;
for ( gen = genHeader ; gen ; gen = gen->xNext )
for ( i = 1 ; i <= basicOrbLen ; ++i )
gen->image[basicOrbit[i]] &= NHB;
}
/*-------------------------- findConsequences -----------------------------*/
/* The function findConsequences( deductionQueuelevel, deduc) finds all direct
consequences of a given definition or deduction and its inverse by tracing
that definition/deduction at all significantly difference occurences of the
generators in all relators at the specified level or above. New deductions
are enqueued on deductionQueue but not processed.
This function returns the number of additional table entries filled in
as consequences. */
Unsigned findConsequences(
DeductionQueue *deductionQueue,
const Unsigned level,
const Deduction *const deduc)
{
OccurenceOfGen *occurence;
Unsigned count, fCos, bCos, newEntryCount = 0;
Unsigned **fPtr, **bPtr;
Deduction newDeduc;
Permutation *gen;
for ( occurence = deduc->gn->occurHeader ; occurence &&
occurence->level >= level; occurence = occurence->next ) {
count = occurence->relLength - 1;
for ( fCos = deduc->img , fPtr = occurence->fRelStart+1 ;
count && !((*fPtr)[fCos] & HB) ; ++fPtr , --count )
fCos = (*fPtr)[fCos];
for ( bCos = deduc->pnt , bPtr = occurence->bRelFinish ;
count && !((*bPtr)[bCos] & HB) ; --bPtr , --count )
bCos = (*bPtr)[bCos];
if ( count == 1 ) {
(*fPtr)[fCos] = bCos;
++newEntryCount;
gen = occurence->r->rel[fPtr - occurence->r->fRel];
newDeduc.pnt = fCos; newDeduc.img = bCos; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
if ( fCos != bCos || gen != gen->invPermutation ) {
(*bPtr)[bCos] = fCos;
++newEntryCount;
newDeduc.img = fCos; newDeduc.pnt = bCos; newDeduc.gn =
gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
}
}
return newEntryCount;
}
/*-------------------------- traceNewRelator ------------------------------*/
/* The function traceNewRelator( G, level, deductionQueue, newRel) processes
a new relator newRel at level level for a group G. It traces all cyclic
shifts of newRel from each coset. Deductions found are enqueued on
deductionQueue but not otherwise processed.
This function returns the number of additional table entries filled in
due to tracing the new relator. */
Unsigned traceNewRelator(
const PermGroup *const G,
const Unsigned level,
DeductionQueue *deductionQueue,
const Relator *const newRel)
{
Unsigned i, pt, startingPos, count, fCos, bCos, newEntryCount = 0;
Unsigned **fPtr, **bPtr;
Deduction newDeduc;
Permutation *gen;
for ( i = 1 ; i <= G->basicOrbLen[level] ; ++i ) {
pt = G->basicOrbit[level][i];
for ( startingPos = 1 ; startingPos <= newRel->length ; ++startingPos ) {
count = newRel->length;
for ( fCos = pt , fPtr = newRel->fRel+startingPos ;
count && !((*fPtr)[fCos] & HB) ; ++fPtr , --count )
fCos = (*fPtr)[fCos];
for ( bCos = pt , bPtr = newRel->bRel+startingPos+newRel->length-1 ;
count && !((*bPtr)[bCos] & HB) ; --bPtr , --count )
bCos = (*bPtr)[bCos];
if ( count == 1 ) {
(*fPtr)[fCos] = bCos;
++newEntryCount;
gen = newRel->rel[fPtr - newRel->fRel];
newDeduc.pnt = fCos; newDeduc.img = bCos; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
if ( fCos != bCos || gen != gen->invPermutation) {
(*bPtr)[bCos] = fCos;
++newEntryCount;
newDeduc.img = fCos; newDeduc.pnt = bCos; newDeduc.gn =
gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
}
}
}
return newEntryCount;
}
/*-------------------------- processCoincidence ---------------------------*/
/* The function processCoincidence( G, genHeader, coset1, coset2)
processes a coincidence between coset1 and coset2 in a special STCS
coset enumeration. Here genHeader is a header for the xNext-linked
list of generators at the appropriate level. It returns the extra
number of table positions filled (points <= degree). */
Unsigned processCoincidence(
const PermGroup *const G,
DeductionQueue *deductionQueue,
Permutation *const genHeader,
const Unsigned coset1,
const Unsigned coset2)
{
Unsigned degree = G->degree;
Unsigned retainCoset, deleteCoset, ffHead, ffTail, lambda, lambdaStar,
tau, tauStar, eta, etaStar, kappa, kappaStar, tsi1, tsi2;
Unsigned newTableEntries = 0;
Permutation *gen;
Deduction newDeduc;
/* DEBUG
++callCount;
if ( onFreeList(coset1) || onFreeList(coset2) )
tsi1 = tsi1;
if ( !verifyCosetList(G->degree) )
tsi1 = tsi1;
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !isValidPermutation(gen,G->degree,extraCosetsAtLevel,equivCoset) )
tsi1 = tsi1; */
/* Alg 3.4, line 1. */
if ( coset1 == coset2 )
return 0;
/* Alg 3.4, line 2. */
retainCoset = MIN( coset1, coset2);
deleteCoset = MAX( coset1, coset2);
ffTail = deleteCoset;
ff[deleteCoset] = 0;
bb[deleteCoset] = retainCoset;
/* Alg 3.4, lines 3, 5. */
for ( lambda = deleteCoset ; lambda ; lambda = ff[lambda] ) {
/* Alg 3.4, line 4. */
lambdaStar = bb[lambda];
while ( lambdaStar > degree && bb[lambdaStar] != lambdaStar )
lambdaStar = bb[lambdaStar];
/* Alg 3.4, line 5. */
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !(gen->image[lambda] & HB) ) {
tau = gen->image[lambda];
tauStar = tau;
while ( tauStar > degree && bb[tauStar] != tauStar )
tauStar = bb[tauStar];
gen->image[lambda] |= HB;
gen->invImage[tau] |= HB;
if ( tau <= degree )
--newTableEntries;
kappa = gen->image[lambdaStar];
if ( !(kappa & HB) ) {
kappaStar = kappa;
while ( kappaStar > degree && bb[kappaStar] != kappaStar )
kappaStar = bb[kappaStar];
if ( kappaStar != tauStar ) {
tsi1 = MIN( tauStar, kappaStar);
tsi2 = MAX( tauStar, kappaStar);
ff[ffTail] = tsi2;
ff[tsi2] = 0;
ffTail = tsi2;
bb[tsi2] = tsi1;
if ( lambdaStar == tsi2 )
lambdaStar = tsi1;
}
}
else {
eta = gen->invImage[tauStar];
if ( !(eta & HB) ) {
etaStar = eta;
while ( etaStar > degree && bb[etaStar] != etaStar )
etaStar = bb[etaStar];
if ( etaStar != lambdaStar ) {
tsi1 = MIN( lambdaStar, etaStar);
tsi2 = MAX( lambdaStar, etaStar);
ff[ffTail] = tsi2;
ff[tsi2] = 0;
ffTail = tsi2;
bb[tsi2] = tsi1;
lambdaStar = tsi1;
}
}
else {
if ( lambdaStar <= degree && (gen->image[lambdaStar] & HB) )
++newTableEntries;
gen->image[lambdaStar] = tauStar;
newDeduc.pnt = lambdaStar; newDeduc.img = tauStar;
newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
if ( lambdaStar != tauStar || gen != gen->invPermutation ) {
if ( tauStar <= degree && (gen->invImage[tauStar] & HB) )
++newTableEntries;
gen->invImage[tauStar] = lambdaStar;
newDeduc.pnt = tauStar; newDeduc.img = lambdaStar;
newDeduc.gn = gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
}
}
}
/*DEBUG
if ( onFreeList(lambda) )
tsi1 = tsi1; */
if ( lambda == firstCos )
firstCos = nextCos[lambda];
else
nextCos[prevCos[lambda]] = nextCos[lambda];
if ( nextCos[lambda] != 0 )
prevCos[nextCos[lambda]] = prevCos[lambda];
nextCos[lambda] = freeCosHeader;
freeCosHeader = lambda;
--currentExtraCosets;
/*DEBUG
if ( !verifyCosetList(G->degree) )
tsi1 = tsi1;*/
}
/* DEBUG
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !isValidPermutation(gen,G->degree,extraCosetsAtLevel,equivCoset) )
tsi1 = tsi1;*/
return newTableEntries;
}
/*-------------------------- xFindConsequences ----------------------------*/
/* The function xFindConsequences( deductionQueuelevel, deduc) finds all direct
consequences of a given definition or deduction and its inverse by tracing
that definition/deduction at all significantly difference occurences of the
generators in all relators at the specified level or above. New deductions
are enqueued on deductionQueue but not processed.
This function returns the number of additional table entries filled in
as consequences. */
Unsigned xFindConsequences(
const PermGroup *const G,
DeductionQueue *deductionQueue,
const Unsigned level,
const Deduction *const deduc,
Permutation *const genHeader)
{
OccurenceOfGen *occurence;
Unsigned count, fCos, bCos, newEntryCount = 0, degree = G->degree;
Unsigned **fPtr, **bPtr;
Deduction newDeduc;
Permutation *gen;
/* DEBUG
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !isValidPermutation(gen,G->degree,extraCosetsAtLevel,equivCoset) )
fCos = fCos; */
if ( (deduc->pnt > degree && bb[deduc->pnt] != deduc->pnt) ||
(deduc->img > degree && bb[deduc->img] != deduc->img) )
return 0;
for ( occurence = deduc->gn->occurHeader ; occurence &&
occurence->level >= level; occurence = occurence->next ) {
count = occurence->relLength - 1;
for ( fCos = deduc->img , fPtr = occurence->fRelStart+1 ;
count && !((*fPtr)[fCos] & HB) ; ++fPtr , --count )
fCos = (*fPtr)[fCos];
if ( count == 0 ) {
if ( fCos != deduc->pnt ) {
newEntryCount += processCoincidence( G, deductionQueue, genHeader,
deduc->pnt, fCos);
if ( (deduc->pnt > degree && bb[deduc->pnt] != deduc->pnt) ||
(deduc->img > degree && bb[deduc->img] != deduc->img) )
return 0;
}
continue ;
}
for ( bCos = deduc->pnt , bPtr = occurence->bRelFinish ;
count && !((*bPtr)[bCos] & HB) ; --bPtr , --count )
bCos = (*bPtr)[bCos];
if ( count == 1 ) {
(*fPtr)[fCos] = bCos;
if ( fCos <= G->degree )
++newEntryCount;
gen = occurence->r->rel[fPtr - occurence->r->fRel];
newDeduc.pnt = fCos; newDeduc.img = bCos; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
if ( fCos != bCos || gen != gen->invPermutation) {
(*bPtr)[bCos] = fCos;
if ( bCos <= G->degree )
++newEntryCount;
newDeduc.img = fCos; newDeduc.pnt = bCos; newDeduc.gn =
gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
}
}
/* DEBUG
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !isValidPermutation(gen,G->degree,extraCosetsAtLevel,equivCoset) )
fCos = fCos; */
return newEntryCount;
}
/*-------------------------- xTraceNewRelator ------------------------------*/
/* The function xTraceNewRelator( G, level, deductionQueue, newRel) processes
a new relator newRel at level level for a group G. It traces all cyclic
shifts of newRel from each coset. Deductions found are enqueued on
deductionQueue but not otherwise processed.
This function returns the number of additional table entries filled in
due to tracing the new relator. */
Unsigned xTraceNewRelator(
const PermGroup *const G,
const Unsigned level,
DeductionQueue *deductionQueue,
const Relator *const newRel,
Permutation *const genHeader)
{
Unsigned i, pt, startingPos, count, fCos, bCos, newEntryCount = 0;
Unsigned **fPtr, **bPtr;
Deduction newDeduc;
Permutation *gen;
/* DEBUG
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !isValidPermutation(gen,G->degree,extraCosetsAtLevel,equivCoset) )
fCos = fCos; */
for ( i = 1 ; i <= G->basicOrbLen[level] ; ++i ) {
pt = G->basicOrbit[level][i];
for ( startingPos = 1 ; startingPos <= newRel->length ; ++startingPos ) {
count = newRel->length;
for ( fCos = pt , fPtr = newRel->fRel+startingPos ;
count && !((*fPtr)[fCos] & HB) ; ++fPtr , --count )
fCos = (*fPtr)[fCos];
if ( count == 0 ) {
if ( fCos != pt )
newEntryCount += processCoincidence( G, deductionQueue, genHeader,
pt, fCos);
continue ;
}
for ( bCos = pt , bPtr = newRel->bRel+startingPos+newRel->length-1 ;
count && !((*bPtr)[bCos] & HB) ; --bPtr , --count )
bCos = (*bPtr)[bCos];
if ( count == 1 ) {
(*fPtr)[fCos] = bCos;
if ( fCos <= G->degree )
++newEntryCount;
gen = newRel->rel[fPtr - newRel->fRel];
newDeduc.pnt = fCos; newDeduc.img = bCos; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
if ( fCos != bCos || gen != gen->invPermutation) {
(*bPtr)[bCos] = fCos;
if ( bCos <= G->degree )
++newEntryCount;
newDeduc.img = fCos; newDeduc.pnt = bCos; newDeduc.gn =
gen->invPermutation;
ATTEMPT_ENQUEUE( deductionQueue, newDeduc)
}
}
}
}
/* DEBUG
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !isValidPermutation(gen,G->degree,extraCosetsAtLevel,equivCoset) )
fCos = fCos; */
return newEntryCount;
}
/*-------------------------- makeDefinition --------------------------------*/
void makeDefinition(
const Unsigned coset,
Permutation *const gen,
DeductionQueue *const deducQueue,
DefinitionList *const defnList,
Permutation *const genHeader)
{
Unsigned newCoset, trueCoset;
Deduction newDeduc;
Permutation *gen1;
/* DEBUG
if ( !verifyCosetList(255) )
trueCoset = trueCoset;
for ( gen1 = genHeader ; gen1 ; gen1 = gen1->xNext )
if ( !isValidPermutation(gen1,255,extraCosetsAtLevel,equivCoset) )
trueCoset = trueCoset; */
defnList->coset[defnList->tail] = coset;
defnList->gen[defnList->tail] = gen;
defnList->image[defnList->tail] = trueCoset = gen->image[coset] & NHB;
++defnList->size;
++defnList->tail;
defnList->tail %= extraCosetsAtLevel;
newCoset = freeCosHeader;
freeCosHeader = nextCos[freeCosHeader];
if ( firstCos != 0 )
prevCos[firstCos] = newCoset;
nextCos[newCoset] = firstCos;
firstCos = newCoset;
prevCos[newCoset] = 0;
equivCoset[newCoset] = trueCoset;
bb[newCoset] = newCoset;
for ( gen1 = genHeader ; gen1 ; gen1 = gen1->xNext )
gen1->image[newCoset] = HB;
gen->image[coset] = newCoset;
gen->invImage[newCoset] = coset;
++currentExtraCosets;
newDeduc.pnt = coset; newDeduc.img = newCoset; newDeduc.gn = gen;
ATTEMPT_ENQUEUE( deducQueue, newDeduc)
newDeduc.pnt = newCoset; newDeduc.img = coset;
newDeduc.gn = gen->invPermutation;
ATTEMPT_ENQUEUE( deducQueue, newDeduc)
/* DEBUG
if ( !verifyCosetList(255) )
trueCoset = trueCoset;
for ( gen1 = genHeader ; gen1 ; gen1 = gen1->xNext )
if ( !isValidPermutation(gen1,255,extraCosetsAtLevel,equivCoset) )
trueCoset = trueCoset; */
}
/*-------------------------- forceCollapse ---------------------------------*/
Unsigned forceCollapse(
const PermGroup *const G,
const Unsigned level,
Permutation *genHeader,
DeductionQueue *const deductionQueue,
DefinitionList *const defnList,
Unsigned *jPtr,
Permutation **hPtr,
Word **wPtr)
{
Unsigned coset, image, oldImage, j, newTableEntries;
Permutation *gen, *gen1;
WordImagePair wh;
Unsigned basicOrbLen = G->basicOrbLen[level];
UnsignedS *basicOrbit = G->basicOrbit[level];
Deduction *newDeduc;
/* ???????????????????
coset = defnList->coset[defnList->head];
gen = defnList->gen[defnList->head];
image = defnList->image[defnList->head];
++defnList->size;
++defnList->head;
defnList->head %= extraCosetsAtLevel; ?????????????*/
for ( j = 1 ; j <= G->basicOrbLen[level] ; ++j ) {
coset = G->basicOrbit[level][j];
for ( gen = genHeader ; gen ; gen = gen->xNext )
if ( !(gen->image[coset] & HB) && gen->image[coset] > G->degree ) {
j = G->basicOrbLen[level] + 2;
break ;
}
}
image = equivCoset[gen->image[coset]];
/* DEBUG
for ( gen1 = genHeader ; gen1 ; gen1 = gen1->xNext )
if ( !isValidPermutation(gen1,G->degree,extraCosetsAtLevel,equivCoset) )
j = j; */
wh = xComputeSchreierGen( G, level, coset, gen);
/* DEBUG
for ( gen1 = genHeader ; gen1 ; gen1 = gen1->xNext )
if ( !isValidPermutation(gen1,G->degree,extraCosetsAtLevel,equivCoset) )
j = j; */
if ( !xReduce( G, level, &j, &wh) ) {
*jPtr = j;
*hPtr = allocPermutation();
(*hPtr)->degree = G->degree;
(*hPtr)->image = wh.image;
adjoinInvImage( *hPtr);
*wPtr = allocWord();
**wPtr = wh.word;
resetTable( genHeader, basicOrbLen, basicOrbit);
return UNKNOWN;
}
/* DEBUG
for ( gen1 = genHeader ; gen1 ; gen1 = gen1->xNext )
if ( !isValidPermutation(gen1,G->degree,extraCosetsAtLevel,equivCoset) )
j = j; */
freeIntArrayDegree( wh.image);
*wPtr = allocWord();
**wPtr = wh.word;
newTableEntries = processCoincidence( G, deductionQueue, genHeader,
image, gen->image[coset]);
return newTableEntries;
}
/*-------------------------- verifyCosetList--------------------------------*/
BOOLEAN verifyCosetList(
Unsigned degree)
{
Unsigned inUseCount = 0, freeCount = 0, i, coset;
char *found = (char *) malloc( extraCosetsAtLevel+2) - degree;
for ( i = degree+1 ; i <= degree + extraCosetsAtLevel ; ++i )
found[i] = FALSE ;
for ( coset = firstCos ; coset != 0 ; coset = nextCos[coset] ) {
if ( coset <= degree || coset > degree+extraCosetsAtLevel ) {
printf( "\n*** Invalid coset %u on in use list." , coset);
return FALSE ;
}
if ( found[coset] ) {
printf ( "\n*** Coset %u appears twice on in use list." , coset);
return FALSE ;
}
found[coset] = 1;
++inUseCount;
}
for ( coset = freeCosHeader ; coset != 0 ; coset = nextCos[coset] ) {
if ( coset <= degree || coset > degree+extraCosetsAtLevel ) {
printf( "\n*** Invalid coset %u on free list." , coset);
return FALSE ;
}
if ( found[coset] == 1 ) {
printf ( "\n*** Coset %u appears on both lists." , coset);
return FALSE ;
}
else if ( found[coset] == 2 ) {
printf ( "\n*** Coset %u appears twice on free list." , coset);
return FALSE ;
}
found[coset] = 2;
++freeCount;
}
if ( inUseCount + freeCount != extraCosetsAtLevel ) {
printf( "\n*** Invalid coset counts: %u + %u != %u" , inUseCount,
freeCount, extraCosetsAtLevel);
return FALSE ;
}
if ( firstCos != 0 && prevCos[firstCos] != 0 ) {
printf( "\n*** firstCos = %u, prevCos[%u] = %u." , firstCos, firstCos,
prevCos[firstCos]);
return FALSE ;
}
for ( coset = firstCos ; coset != 0 ; coset = nextCos[coset] )
if ( (coset != firstCos && nextCos[prevCos[coset]] != coset) ||
(nextCos[coset] != 0 && prevCos[nextCos[coset]] != coset) ) {
printf( "\n*** Invalid linked list at %u." , coset);
return FALSE ;
}
free(found);
return TRUE ;
}
/*-------------------------- verifyCosetList--------------------------------*/
BOOLEAN onFreeList(
Unsigned coset)
{
Unsigned i;
for ( i = freeCosHeader ; i != 0 ; i = nextCos[i] )
if ( i == coset )
return TRUE ;
return FALSE ;
}
Messung V0.5 C=95 H=73 G=84
¤ Dauer der Verarbeitung: 0.4 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland