// 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;
};
/**************************************************************************** ** *FFuncNBits_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;
}
/**************************************************************************** ** *FFuncNBits_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, "<start>");
// <end> must be positive
end = GetPositiveSmallIntEx("NBits_ExponentSums3", vend, "<end>");
// <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) );
}
/**************************************************************************** ** *FFuncNBits_ExponentSyllable(<self>,<w>,<i>)
*/ template <typename UIntN> static Obj NBits_ExponentSyllable(Obj w, Obj pos)
{ 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; // integer corresponding to <vi>
UIntN p; // <i>th syllable
// check <i>
num = NPAIRS_WORD(w);
i = GetBoundedInt("NBits_ExponentSyllable", pos, 1, num);
// get the number of bits for exponents
ebits = EBITS_WORD(w);
// get the exponent masks
exps = (UInt)1 << (ebits-1);
expm = exps - 1;
// return the <i> th exponent
p = CONST_DATA_WORD(w)[i-1]; if ( p & exps ) return INTOBJ_INT((p&expm)-exps); else return INTOBJ_INT(p&expm);
}
/**************************************************************************** ** *FFuncNBits_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);
/**************************************************************************** ** *FFuncNBits_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);
}
/**************************************************************************** ** *FFuncNBits_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++;
/**************************************************************************** ** *FFuncNBits_Less(<self>,<l>,<r>) ** **Thisfunctionimplementsalength-plus-lexicographicorderingon **associativewords.Thisorderingistranslationinvariant,therefore, **wecanskipcommonprefixes.Thisisdoneinthefirstloopofthe **function.Whenadifferenceinthetwowordsisencountered,itis **decidedwhichisthelexicographicallysmaller.Thereareseveralcase **thatcanoccur: ** **Thesyllableswherethedifferenceoccurshavedifferentgenerators.In **thiscaseitissufficienttocomparethetwogenerators. **Example:x^3<y^3. ** **Thesyllableshavethesamegeneratorbutoneexponentisthenegativeof **theother.Inthiscasethewordwiththenegativeexponentissmaller. **Example:x^-1<x. ** **Nowitsufficestocomparetheunsignedexponents.Forthesyllable **withthesmallerexponentwehavetotakethenextgeneratorinthat **wordintoaccount.Thismeansthatwearediscardingthesmaller **syllableasacommonprefix.Notethatifthishappensattheendof **oneofthetwowords,thenthisword(ignoringthecommonprefix)isthe **emptywordandwecanimmediatelydecidewhichwordisthesmaller. **Examples:y^3x<y^2z,y^3x>y^2xz,x^2<xy^-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;
/**************************************************************************** ** *FFuncNBits_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);
/**************************************************************************** ** *FFuncNBits_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);
/**************************************************************************** ** *FFuncNBits_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;
}
/**************************************************************************** ** *FFuncNBits_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 und die Messung sind noch experimentell.