/* 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 in Prozent C=93 H=78 G=85
¤ Dauer der Verarbeitung: 0.37 Sekunden
(vorverarbeitet am 2026-06-26)
¤
*© Formatika GbR, Deutschland