/**************************************************************************** ** ** This file is part of GAP, a system for computational discrete algebra. ** ** Copyright of GAP belongs to its developers, whose names are too numerous ** to list here. Please refer to the COPYRIGHT file for details. ** ** SPDX-License-Identifier: GPL-2.0-or-later ** ** This file contains the C functions for free group elements. There are ** basically three different (internal) types: 8 bits, 16 bits, and 32 bits ** for the generator/exponent pairs. The number of bits used for the ** generator numbers is determined by the number of free group generators in ** the family. Any object of this type looks like: ** ** +------+-----+-------+-------+-----+-----------+ ** | TYPE | len | g1/e1 | g2/e2 | ... | glen/elen | ** +------+-----+-------+-------+-----+-----------+ ** ** where <len> is a GAP integer object and <gi>/<ei> occupies 8, 16, or 32 ** bits depending on the type. A TYPE of such an objects looks like: ** ** +--------+-------+--------+----------+-------+------+------+ ** | FAMILY | FLAGS | SHARED | PURETYPE | EBITS | RANK | BITS | ** +--------+-------+--------+----------+-------+------+------+ ** ** <PURETYPE> is the type of a result, <EBITS> is the number of bits used ** for the exponent, <RANK> is number of free group generators. But instead ** of accessing these entries directly you should use the following macros. ** ** ** The file "objfgelm.h" defines the following functions and macros: ** ** NewWord(( <type>, <npairs> ) ** returns a new objects of type <type> with room for <npairs> ** generator/exponent pairs. ** ** ** BITS_WORD( <word> ) ** returns the number of bits as C integers ** ** DATA_WORD( <word> ) ** returns a pointer to the beginning of the data area ** ** EBITS_WORD( <word> ) ** returns the ebits as C integer ** ** NPAIRS_WORD( <word> ) ** returns the number of pairs as C integer ** ** RANK_WORD( <word> ) ** returns the rank as C integer ** ** PURETYPE_WORD( <word> ) ** returns the result type ** ** ** BITS_WORDTYPE( <type> ) ** returns the number of bits as C integers ** ** EBITS_WORDTYPE( <type> ) ** returns the ebits as C integer ** ** RANK_WORDTYPE( <type> ) ** returns the rank as C integer ** ** PURETYPE_WORDTYPE( <type> ) ** returns the result type
*/
// OverflowType<UIntN> is a type which is larger enough to detect // overflow of multiplication of two IntN values. For 8 and 16 bit // inputs, we use `Int`, for 32 bit inputs we use Int8. template <typename T> struct OverflowType {
}; template <> struct OverflowType<UInt1> { typedefInt type;
}; template <> struct OverflowType<UInt2> { typedefInt type;
}; template <> struct OverflowType<UInt4> { typedef Int8 type;
};
/**************************************************************************** ** *F FuncNBits_Equal( <self>, <l>, <r> )
*/ template <typename UIntN> static Obj NBits_Equal(Obj l, Obj r)
{ Int nl; // number of pairs to consider in <l> Int nr; // number of pairs in <r> const UIntN * pl; // data area in <l> const UIntN * pr; // data area in <r>
// if <l> or <r> is the identity it is easy
nl = NPAIRS_WORD(l);
nr = NPAIRS_WORD(r); if ( nl != nr ) { returnFalse;
}
/**************************************************************************** ** *F FuncNBits_ExponentSums3( <self>, <obj>, <start>, <end> )
*/ template <typename UIntN> static Obj NBits_ExponentSums3(Obj obj, Obj vstart, Obj vend)
{ Int start; // the lowest generator number Int end; // the highest generator number
Obj sums; // result, the exponent sums Int ebits; // number of bits in the exponent
UInt expm; // signed exponent mask
UInt exps; // sign exponent mask Int num; // number of gen/exp pairs in <data> Int i; // loop variable for gen/exp pairs Int pos; // current generator number Int exp; // current exponent const UIntN * ptr; // pointer into the data area of <obj>
// <start> must be positive
start = GetPositiveSmallIntEx("NBits_ExponentSums3", vstart, "");
// <end> must be positive
end = GetPositiveSmallIntEx("NBits_ExponentSums3", vend, "");
// <end> must be at least <start> if ( end < start ) {
sums = NewEmptyPlist(); return sums;
}
// get the number of bits for exponents
ebits = EBITS_WORD(obj);
// get the exponent masks
exps = (UInt)1 << (ebits-1);
expm = exps - 1;
// get the number of gen/exp pairs
num = NPAIRS_WORD(obj);
// create the zero vector
sums = NEW_PLIST( T_PLIST_CYC, end-start+1 );
SET_LEN_PLIST( sums, end-start+1 ); for ( i = start; i <= end; i++ )
SET_ELM_PLIST( sums, i-start+1, 0 );
// and unpack <obj> into <sums>
ptr = CONST_DATA_WORD(obj); for ( i = 1; i <= num; i++, ptr++ ) {
pos = ((*ptr) >> ebits)+1; if ( start <= pos && pos <= end ) { if ( (*ptr) & exps )
exp = ((*ptr)&expm)-exps; else
exp = (*ptr)&expm;
// this will not cause a garbage collection
exp = exp + (Int) ELM_PLIST( sums, pos-start+1 );
SET_ELM_PLIST( sums, pos-start+1, (Obj) exp );
assert( ptr == CONST_DATA_WORD(obj) + (i-1) );
}
}
// convert integers into values for ( i = start; i <= end; i++ ) {
exp = (Int) ELM_PLIST( sums, i-start+1 );
SET_ELM_PLIST( sums, i-start+1, INTOBJ_INT(exp) );
}
/**************************************************************************** ** *F FuncNBits_ExtRepOfObj( <self>, <obj> )
*/ template <typename UIntN> static Obj NBits_ExtRepOfObj(Obj obj)
{ Int ebits; // number of bits in the exponent
UInt expm; // signed exponent mask
UInt exps; // sign exponent mask Int num; // number of gen/exp pairs in <data> Int i; // loop variable for gen/exp pairs
Obj type; // type of <obj> const UIntN * ptr; // pointer into the data area of <obj>
Obj lst; // result
// get the type of <obj>
type = TYPE_DATOBJ(obj);
// get the number of bits for exponents
ebits = EBITS_WORDTYPE(type);
// get the exponent masks
exps = (UInt)1 << (ebits-1);
expm = exps - 1;
// get the number of gen/exp pairs
num = NPAIRS_WORD(obj);
// construct a list with 2*<num> entries
lst = NEW_PLIST( T_PLIST, 2*num );
SET_LEN_PLIST( lst, 2*num );
// and unpack <obj> into <lst>
ptr = CONST_DATA_WORD(obj);
// this will not cause a garbage collection for ( i = 1; i <= num; i++, ptr++ ) {
SET_ELM_PLIST( lst, 2*i-1, INTOBJ_INT(((*ptr) >> ebits)+1) ); if ( (*ptr) & exps )
SET_ELM_PLIST( lst, 2*i, INTOBJ_INT(((*ptr)&expm)-exps) ); else
SET_ELM_PLIST( lst, 2*i, INTOBJ_INT((*ptr)&expm) );
assert( ptr == CONST_DATA_WORD(obj) + (i-1) );
}
CHANGED_BAG(lst);
/**************************************************************************** ** *F FuncNBits_GeneratorSyllable( <self>, <w>, <i> )
*/ template <typename UIntN> static Obj NBits_GeneratorSyllable(Obj w, Obj pos)
{ Int ebits; // number of bits in the exponent Int num; // number of gen/exp pairs in <data> Int i; // integer corresponding to <vi>
UIntN p; // <i>th syllable
// check <i>
num = NPAIRS_WORD(w);
i = GetBoundedInt("NBits_GeneratorSyllable", pos, 1, num);
// get the number of bits for exponents
ebits = EBITS_WORD(w);
// return the <i> th generator
p = CONST_DATA_WORD(w)[i-1]; return INTOBJ_INT((p >> ebits)+1);
}
/**************************************************************************** ** *F FuncNBits_HeadByNumber( <self>, <l>, <gen> )
*/ template <typename UIntN> static Obj NBits_HeadByNumber(Obj l, Obj r)
{ Int ebits; // number of bits in the exponent
UInt genm; // generator mask Int sl; // start position in <obj> Int nl; // number of pairs to consider in <l> Int gr; // value of <r> const UIntN * pl; // data area in <l>
Obj obj; // the result
UIntN * po; // data area in <obj>
// get the generator number to stop
gr = INT_INTOBJ(r) - 1;
// get the number of bits for exponents
ebits = EBITS_WORD(l);
// get the generator mask
genm = (((UInt)1 << (8*sizeof(UIntN)-ebits)) - 1) << ebits;
// if <l> is the identity return
nl = NPAIRS_WORD(l); if ( 0 == nl ) return l;
// look closely at the generators
sl = 0;
pl = CONST_DATA_WORD(l); while ( sl < nl && ((*pl & genm) >> ebits) < gr ) {
sl++; pl++;
} if ( sl == nl ) return l;
// create a new word
obj = NewWord(PURETYPE_WORD(l), sl);
// copy the <l> part into the word
po = DATA_WORD(obj);
pl = CONST_DATA_WORD(l); while ( 0 < sl-- )
*po++ = *pl++;
/**************************************************************************** ** *F FuncNBits_Less( <self>, <l>, <r> ) ** ** This function implements a length-plus-lexicographic ordering on ** associative words. This ordering is translation invariant, therefore, ** we can skip common prefixes. This is done in the first loop of the ** function. When a difference in the two words is encountered, it is ** decided which is the lexicographically smaller. There are several case ** that can occur: ** ** The syllables where the difference occurs have different generators. In ** this case it is sufficient to compare the two generators. ** Example: x^3 < y^3. ** ** The syllables have the same generator but one exponent is the negative of ** the other. In this case the word with the negative exponent is smaller. ** Example: x^-1 < x. ** ** Now it suffices to compare the unsigned exponents. For the syllable ** with the smaller exponent we have to take the next generator in that ** word into account. This means that we are discarding the smaller ** syllable as a common prefix. Note that if this happens at the end of ** one of the two words, then this word (ignoring the common prefix) is the ** empty word and we can immediately decide which word is the smaller. ** Examples: y^3 x < y^2 z, y^3 x > y^2 x z, x^2 < x y^-1, x^2 < x^3. **
*/ template <typename UIntN> static Obj NBits_Less(Obj l, Obj r)
{ Int ebits; // number of bits in the exponent
UInt expm; // signed exponent mask
UInt exps; // sign exponent mask
UInt genm; // generator mask Int exl; // left exponent Int exr; // right exponent Int nl; // number of pairs to consider in <l> Int nr; // number of pairs in <r> const UIntN * pl; // data area in <l> const UIntN * pr; // data area in <r>
Obj lexico; // lexicographic order of <l> and <r>
Obj ll; // length of <l>
Obj lr; // length of <r>
// if <l> or <r> is the identity it is easy
nl = NPAIRS_WORD(l);
nr = NPAIRS_WORD(r); if ( nl == 0 || nr == 0 ) { return ( nr != 0 ) ? True : False;
}
// get the number of bits for exponents
ebits = EBITS_WORD(l);
// get the exponent masks
exps = (UInt)1 << (ebits-1);
expm = exps - 1;
// Skip the common prefix and determine if the first word is smaller // with respect to the lexicographic ordering.
pl = CONST_DATA_WORD(l);
pr = CONST_DATA_WORD(r); for ( lexico = False; 0 < nl && 0 < nr; nl--, nr--, pl++, pr++ ) if ( *pl != *pr ) { // got a difference
// get the generator mask
genm = (((UInt)1 << (8*sizeof(UIntN)-ebits)) - 1) << ebits;
/**************************************************************************** ** *F FuncNBits_AssocWord( <self>, <type>, <data> )
*/ template <typename UIntN> static Obj NBits_AssocWord(Obj type, Obj data)
{ Int ebits; // number of bits in the exponent
UInt expm; // unsigned exponent mask Int num; // number of gen/exp pairs in <data> Int i; // loop variable for gen/exp pairs
Obj vexp; // value of current exponent Int nexp; // current exponent
Obj vgen; // value of current generator Int ngen; // current generator
Obj obj; // result
UIntN * ptr; // pointer into the data area of <obj>
// get the number of bits for exponents
ebits = EBITS_WORDTYPE(type);
// get the exponent mask
expm = ((UInt)1 << ebits) - 1;
// construct a new object
num = LEN_LIST(data)/2;
obj = NewWord(type, num);
ptr = DATA_WORD(obj); for ( i = 1; i <= num; i++, ptr++ ) {
// this will not cause a garbage collection
vgen = ELMW_LIST( data, 2*i-1 );
ngen = INT_INTOBJ(vgen);
vexp = ELMW_LIST( data, 2*i ); if (!IS_INTOBJ(vexp) || vexp == INTOBJ_INT(0))
RequireArgument("NBits_AssocWord", vexp, "must be a non-zero small integer");
nexp = INT_INTOBJ(vexp) & expm;
*ptr = ((ngen-1) << ebits) | nexp;
assert( ptr == DATA_WORD(obj) + (i-1) );
}
CHANGED_BAG(obj);
/**************************************************************************** ** *F FuncNBits_ObjByVector( <self>, <type>, <data> )
*/ template <typename UIntN> static Obj NBits_ObjByVector(Obj type, Obj data)
{ Int ebits; // number of bits in the exponent
UInt expm; // unsigned exponent mask Int num; // number of gen/exp pairs in <data> Int i; // loop variable for gen/exp pairs Int j; // loop variable for exponent vector Int nexp; // current exponent
Obj vexp; // value of current exponent
Obj obj; // result
UIntN * ptr; // pointer into the data area of <obj>
// get the number of bits for exponents
ebits = EBITS_WORDTYPE(type);
// get the exponent mask
expm = ((UInt)1 << ebits) - 1;
// count the number of non-zero entries for ( i = LEN_LIST(data), num = 0, j = 1; 0 < i; i-- ) {
vexp = ELMW_LIST(data,i);
RequireSmallInt("NBits_ObjByVector", vexp); if ( vexp != INTOBJ_INT(0) ) {
j = i;
num++;
}
}
// construct a new object
obj = NewWord(type, num);
ptr = DATA_WORD(obj); for ( i = 1; i <= num; i++, ptr++, j++ ) {
// this will not cause a garbage collection while ( ELMW_LIST(data,j) == INTOBJ_INT(0) )
j++;
vexp = ELMW_LIST( data, j );
nexp = INT_INTOBJ(vexp) & expm;
*ptr = ((j-1) << ebits) | nexp;
assert( ptr == DATA_WORD(obj) + (i-1) );
}
CHANGED_BAG(obj);
Int ebits; // number of bits in the exponent
UInt expm; // signed exponent mask
UInt exps; // sign exponent mask
UInt genm; // generator mask Int invm; // mask used to invert exponent
Obj obj; // the result Int nl; // number of pairs to consider in <l> Int sr; // start position in <r> Int sl; // start position in <obj> const UIntN * pl; // data area in <l>
UIntN * pr; // data area in <obj> const UIntN * pe; // end marker
OInt ex = 0; // meeting exponent Int pow; // power to take Int apw; // absolute value of <pow>
// get the number of bits for exponents
ebits = EBITS_WORD(l);
// get the exponent masks
exps = (UInt)1 << (ebits-1);
expm = exps - 1;
invm = ((UInt)1<<ebits)-1;
// get the generator mask
genm = (((UInt)1 << (8*sizeof(UIntN)-ebits)) - 1) << ebits;
// if <l> is the identity return <l>
nl = NPAIRS_WORD(l); if ( 0 == nl ) return l;
// if <pow> is zero return the identity
pow = INT_INTOBJ(r); if ( pow == 0 ) {
obj = NewWord(PURETYPE_WORD(l), 0); return obj;
}
// if <pow> is one return <l> if ( pow == 1 ) return l;
// if <pow> is minus one invert <l> if ( pow == -1 ) {
obj = NewWord(PURETYPE_WORD(l), nl);
pl = CONST_DATA_WORD(l);
pr = DATA_WORD(obj) + (nl-1);
sl = nl;
// exponents are symmetric, so we cannot get an overflow while ( 0 < sl-- ) {
*pr-- = ( *pl++ ^ invm ) + 1;
} return obj;
}
// split word into w * h * w^-1
pl = CONST_DATA_WORD(l);
pe = pl + (nl-1);
sl = 0;
sr = nl-1; while ( (*pl & genm) == (*pe & genm) ) { if ( (*pl&exps) == (*pe&exps) ) break; if ( (*pl&expm) + (*pe&expm) != exps ) break;
pl++; sl++;
pe--; sr--;
}
// special case: w * gi^n * w^-1 if ( sl == sr ) {
ex = (*pl&expm); if ( *pl & exps ) ex -= exps;
ex = ex * pow;
// check that n*pow fits into the exponent if ( ( 0 < ex && expm < ex ) || ( ex < 0 && expm < -ex ) ) { return TRY_NEXT_METHOD;
}
// and fix the exponent at position <sr>
pr = DATA_WORD(obj);
pr[sr] = (pr[sr] & genm) | (ex & (((UInt)1<<ebits)-1)); return obj;
}
// special case: w * gj^x * t * gj^y * w^-1, x != -y if ( (*pl & genm) == (*pe & genm) ) {
ex = (*pl&expm) + (*pe&expm); if ( *pl & exps ) ex -= exps; if ( *pe & exps ) ex -= exps;
// check that <ex> fits into the exponent if ( ( 0 < ex && expm < ex ) || ( ex < 0 && expm < -ex ) ) { return TRY_NEXT_METHOD;
} if ( 0 < pow )
ex = ex & (((UInt)1<<ebits)-1); else
ex = (-ex) & (((UInt)1<<ebits)-1);
/**************************************************************************** ** *F FuncNBits_Product( <self>, <l>, <r> )
*/ template <typename UIntN> static Obj NBits_Product(Obj l, Obj r)
{ Int ebits; // number of bits in the exponent
UInt expm; // signed exponent mask
UInt exps; // sign exponent mask
UInt genm; // generator mask Int nl; // number of pairs to consider in <l> Int nr; // number of pairs in <r> Int sr; // start position in <r> const UIntN * pl; // data area in <l> const UIntN * pr; // data area in <r>
Obj obj; // the result
UIntN * po; // data area in <obj> Int ex = 0; // meeting exponent Int over; // overlap
// get the number of bits for exponents
ebits = EBITS_WORD(l);
// get the exponent masks
exps = (UInt)1 << (ebits-1);
expm = exps - 1;
// get the generator mask
genm = (((UInt)1 << (8*sizeof(UIntN)-ebits)) - 1) << ebits;
// if <l> or <r> is the identity return the other
nl = NPAIRS_WORD(l); if ( 0 == nl ) return r;
nr = NPAIRS_WORD(r); if ( 0 == nr ) return l;
// look closely at the meeting point
sr = 0;
pl = CONST_DATA_WORD(l)+(nl-1);
pr = CONST_DATA_WORD(r); while ( 0 < nl && sr < nr && (*pl & genm) == (*pr & genm) ) { if ( (*pl&exps) == (*pr&exps) ) break; if ( (*pl&expm) + (*pr&expm) != exps ) break;
pr++; sr++;
pl--; nl--;
}
// create a new word
over = ( 0 < nl && sr < nr && (*pl & genm) == (*pr & genm) ) ? 1 : 0; if ( over ) {
ex = ( *pl & expm ) + ( *pr & expm ); if ( *pl & exps ) ex -= exps; if ( *pr & exps ) ex -= exps; if ( ( 0 < ex && expm < ex ) || ( ex < 0 && expm < -ex ) ) { return TRY_NEXT_METHOD;
}
}
obj = NewWord(PURETYPE_WORD(l), nl + (nr - sr) - over);
// copy the <l> part into the word
po = DATA_WORD(obj);
pl = CONST_DATA_WORD(l); while ( 0 < nl-- )
*po++ = *pl++;
// handle the overlap if ( over ) {
po[-1] = (po[-1] & genm) | (ex & (((UInt)1<<ebits)-1));
sr++;
}
// copy the <r> part into the word
pr = CONST_DATA_WORD(r) + sr; while ( sr++ < nr )
*po++ = *pr++; return obj;
}
/**************************************************************************** ** *F FuncNBits_Quotient( <self>, <l>, <r> )
*/ template <typename UIntN> static Obj NBits_Quotient(Obj l, Obj r)
{ Int ebits; // number of bits in the exponent
UInt expm; // signed exponent mask
UInt sepm; // unsigned exponent mask
UInt exps; // sign exponent mask
UInt genm; // generator mask Int nl; // number of pairs to consider in <l> Int nr; // number of pairs in <r> const UIntN * pl; // data area in <l> const UIntN * pr; // data area in <r>
Obj obj; // the result
UIntN * po; // data area in <obj> Int ex = 0; // meeting exponent Int over; // overlap
// get the number of bits for exponents
ebits = EBITS_WORD(l);
// short check
RequirePlainList(SELF_NAME, a);
RequirePlainList(SELF_NAME, b);
// Find overlap // l:=Length(a);
l=LEN_PLIST(a); if (l==0) { return b;
} // m:=Length(b);
m=LEN_PLIST(b); if (m==0) { return a;
} // now we know both lists are length >0
// i:=l;
i=l; // j:=1;
j=1; // while i>=1 and j<=m and a[i]=-b[j] do while ((i>=1)&&(j<=m)&&
(INT_INTOBJ(ELM_PLIST(a,i))==-INT_INTOBJ(ELM_PLIST(b,j)))) { // i:=i-1;
i--; // j:=j+1;
j++; // od;
} // if i=0 then if (i==0) { // if j>m then if (j>m) { // full cancellation // return false; returnFalse;
} // fi; // a:=b{[j..m]};
as=1;
ae=0;
bs=j;
be=m;
newlen=m-j+1;
} // elif j>m then else { if (j>m) { // a:=a{[1..i]};
as=1;
ae=i;
bs=1;
be=0;
newlen=i;
} else { // else // a:=Concatenation(a{[1..i]},b{[j..m]});
as=1;
ae=i;
bs=j;
be=m;
newlen=m-j+1+i;
} // fi;
} // make the new list
n=NEW_PLIST(T_PLIST_CYC,newlen);
q=ADDR_OBJ(n);
q++;
j=as; // a[as] position
p=CONST_ADDR_OBJ(a) + as; while (j<=ae) {
*q++=*p++;
j++;
}
j=bs; // b[bs] position
p=CONST_ADDR_OBJ(b) + bs; while (j<=be) {
*q++=*p++;
j++;
}
SET_LEN_PLIST(n,newlen);
CHANGED_BAG(n); // return a; return n;
}
// short check, if necessary strings are compacted
RequireStringRep(SELF_NAME, a);
RequireStringRep(SELF_NAME, b);
// Find overlap // l:=Length(a);
l=GET_LEN_STRING(a); if (l==0) { return b;
} // m:=Length(b);
m=GET_LEN_STRING(b); if (m==0) { return a;
} // now we know both lists are length >0
// i:=l;
i=l; // j:=1;
j=1; // while i>=1 and j<=m and a[i]=-b[j] do
p=CONST_CSTR_STRING(a);
q=CONST_CSTR_STRING(b); while ((i>=1)&&(j<=m)&&
(SINT_CHAR(p[i-1])==-SINT_CHAR(q[j-1]))) { // i:=i-1;
i--; // j:=j+1;
j++; // od;
} // if i=0 then if (i==0) { // if j>m then if (j>m) { // full cancellation // return false; returnFalse;
} // fi; // a:=b{[j..m]};
as=1;
ae=0;
bs=j;
be=m;
newlen=m-j+1;
} // elif j>m then else { if (j>m) { // a:=a{[1..i]};
as=1;
ae=i;
bs=1;
be=0;
newlen=i;
} else { // else // a:=Concatenation(a{[1..i]},b{[j..m]});
as=1;
ae=i;
bs=j;
be=m;
newlen=m-j+1+i;
} // fi;
} // make the new list
n=NEW_STRING(newlen); Char *dst = CSTR_STRING(n);
p=CONST_CSTR_STRING(a);
j=as; // a[as] position while (j<=ae) {
*dst++=p[j-1];
j++;
}
j=bs;
p=CONST_CSTR_STRING(b); // b[bs] position while (j<=be) {
*dst++=p[j-1];
j++;
} // return a; return n;
}
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 ist noch experimentell.