/**************************************************************************** ** *FLtRange(<listL>,<listR>).........testiftworangesareequal ** **'LtRange'returns'true'iftherange<listL>islessthantherange **<listR>and'false'otherwise.
*/ staticInt LtRange(Obj listL, Obj listR)
{ // first compare the first elements if ( GET_LOW_RANGE(listL) < GET_LOW_RANGE(listR) ) return1; elseif ( GET_LOW_RANGE(listR) < GET_LOW_RANGE(listL) ) return0;
// next compare the increments (or the second elements) if ( GET_INC_RANGE(listL) < GET_INC_RANGE(listR) ) return1; elseif ( GET_INC_RANGE(listR) < GET_INC_RANGE(listL) ) return0;
// finally compare the lengths if ( GET_LEN_RANGE(listL) < GET_LEN_RANGE(listR) ) return1; elseif ( GET_LEN_RANGE(listR) < GET_LEN_RANGE(listL) ) return0;
/**************************************************************************** ** *FElmsRange(<list>,<poss>).........selectasublistfromarange ** **'ElmsRange'returnsanewlistcontainingtheelementsatthepositions **giveninthelist<poss>fromtherange<list>.Itistheresponsibility **ofthecallertoensurethat<poss>isdenseandcontainsonlypositive **integers.Anerrorissignalledifanelementof<poss>islargerthan **thelengthof<list>. ** **'ElmsRange'isthefunctionin'ElmsListFuncs'forranges.
*/ static Obj ElmsRange(Obj list, Obj poss)
{
Obj elms; // selected sublist, result Int lenList; // length of <list>
Obj elm; // one element from <list> Int lenPoss; // length of <positions> Int pos; // <position> as integer Int inc; // increment in a range Int i; // loop variable
// select no element if ( LEN_LIST(poss) == 0 ) {
elms = NewEmptyPlist();
}
// general code elseif ( ! IS_RANGE(poss) ) {
// get the length of <list>
lenList = GET_LEN_RANGE( list );
// get the length of <positions>
lenPoss = LEN_LIST( poss );
// make the result list
elms = NEW_PLIST( T_PLIST, lenPoss );
SET_LEN_PLIST( elms, lenPoss );
// loop over the entries of <positions> and select for ( i = 1; i <= lenPoss; i++ ) {
// get <position>
Obj p = ELMW_LIST(poss, i); if (!IS_INTOBJ(p)) {
ErrorMayQuit("List Elements: position is too large for " "this type of list", 0, 0);
}
pos = INT_INTOBJ(p);
// select the element if ( lenList < pos ) {
ErrorMayQuit( "List Elements: <list>[%d] must have an assigned value",
(Int)pos, 0);
}
// select the element
elm = GET_ELM_RANGE( list, pos );
// assign the element into <elms>
SET_ELM_PLIST( elms, i, elm );
}
}
// special code for ranges else {
// get the length of <list>
lenList = GET_LEN_RANGE( list );
// get the length of <positions>, the first elements, and the inc.
lenPoss = GET_LEN_RANGE( poss );
pos = GET_LOW_RANGE( poss );
inc = GET_INC_RANGE( poss );
// check that no <position> is larger than 'LEN_LIST(<list>)' if ( lenList < pos ) {
ErrorMayQuit( "List Elements: <list>[%d] must have an assigned value",
(Int)pos, 0);
} if ( lenList < pos + (lenPoss-1) * inc ) {
ErrorMayQuit( "List Elements: <list>[%d] must have an assigned value",
(Int)(pos + (lenPoss - 1) * inc), 0);
}
// make the result range
inc *= GET_INC_RANGE(list);
elms = NEW_RANGE(lenPoss, INT_INTOBJ( GET_ELM_RANGE( list, pos ) ), inc);
}
return elms;
}
/**************************************************************************** ** *FUnbRange(<list>,<pos>)....unbindanelementfromarange ** **Thisistoavoidunpackingoftherangetoaplainlistwhen<pos>is **largerorequaltothelengthof<list>.
*/ staticvoid UnbRange(Obj list, Int pos)
{
GAP_ASSERT(IS_MUTABLE_OBJ(list)); constInt len = GET_LEN_RANGE(list); if (len == pos && len > 2) {
SET_LEN_RANGE(list, len - 1);
} elseif (pos <= len) {
PLAIN_LIST(list);
UNB_LIST(list, pos);
}
}
/**************************************************************************** ** *FAssRange(<list>,<pos>,<val>).............assigntoarange ** **'AssRange'assignsthevalue<val>totherange<list>attheposition **<pos>.Itistheresponsibilityofthecallertoensurethat<pos>is **positive,andthat<val>isnot0. ** **'AssRange'isthefunctionin'AssListFuncs'forranges. ** **'AssRange'simplyconvertstherangeintoaplainlist,andthendoesthe **samestuffas'AssPlist'.Thisisbecausearangeisnotverylikelyto **stayarangeaftertheassignment.
*/ staticvoid AssRange(Obj list, Int pos, Obj val)
{ // convert the range into a plain list
PLAIN_LIST( list );
RetypeBag( list, T_PLIST );
// resize the list if necessary if ( LEN_PLIST( list ) < pos ) {
GROW_PLIST( list, pos );
SET_LEN_PLIST( list, pos );
}
// now perform the assignment and return the assigned value
SET_ELM_PLIST( list, pos, val );
CHANGED_BAG( list );
}
/**************************************************************************** ** *FAsssRange(<list>,<poss>,<vals>)...assignseveralelementstoarange ** **'AsssRange'assignsthevaluesfromthelist<vals>atthepositions **giveninthelist<poss>totherange<list>.Itistheresponsibility **ofthecallertoensurethat<poss>isdenseandcontainsonlypositive **integers,that<poss>and<vals>havethesamelength,andthat<vals>is **dense. ** **'AsssRange'isthefunctionin'AsssListFuncs'forranges. ** **'AsssRange'simplyconvertstherangetoaplainlistandthendoesthe **samestuffas'AsssPlist'.Thisisbecausearangeisnotverylikelyto **stayarangeaftertheassignment.
*/ staticvoid AsssRange(Obj list, Obj poss, Obj vals)
{ // convert <list> to a plain list
PLAIN_LIST( list );
RetypeBag( list, T_PLIST );
// and delegate
ASSS_LIST( list, poss, vals );
}
/**************************************************************************** ** *FIsPossRange(<list>).......positionslisttestfunctionforranges ** **'IsPossRange'returns1iftherange<list>isadenselistcontaining **onlypositiveintegers,and0otherwise. ** **'IsPossRange'isthefunctionin'IsPossListFuncs'forranges.
*/ staticBOOL IsPossRange(Obj list)
{ // test if the first element is positive if ( GET_LOW_RANGE( list ) <= 0 ) returnFALSE;
// test if the last element is positive if ( INT_INTOBJ( GET_ELM_RANGE( list, GET_LEN_RANGE(list) ) ) <= 0 ) returnFALSE;
// otherwise <list> is a positions list returnTRUE;
}
/**************************************************************************** ** *FPosRange(<list>,<val>,<start>)....positionofanelementinarange ** **'PosRange'returnsthepositionofthevalue<val>intherange<list> **afterthefirstposition<start>asaGAPinteger.Failisreturnedif<val> **isnotinthelist. ** **'PosRange'isthefunctionin'PosListFuncs'forranges.
*/
Obj PosRange (
Obj list,
Obj val,
Obj start )
{ Int k; // position, result Int lenList; // length of <list> Int low; // first element of <list> Int inc; // increment of <list> Int v; // numerical value of <val> Int istart;
// if the starting position is too big to be a small int // then there can't be anything to find if (!IS_INTOBJ(start)) return Fail;
istart = INT_INTOBJ(start); // get the length, the first element, and the increment of <list>
lenList = GET_LEN_RANGE(list);
low = GET_LOW_RANGE(list);
inc = GET_INC_RANGE(list);
// look for an integer, and not beyond the list end if ( IS_INTOBJ(val) && istart < lenList ) {
v = INT_INTOBJ(val); if ( 0 < inc
&& low + istart * inc <= v && v <= low + (lenList-1) * inc
&& (v - low) % inc == 0 ) {
k = (v - low) / inc + 1;
} elseif ( inc < 0
&& low + (lenList-1) * inc <= v && v <= low + istart * inc
&& (v - low) % inc == 0 ) {
k = (v - low) / inc + 1;
} else {
k = 0;
}
}
// otherwise it cannot be an element of the range else {
k = 0;
}
// return the position return k == 0 ? Fail : INTOBJ_INT(k);
}
/**************************************************************************** ** *FPlainRange(<list>)...........convertarangetoaplainlist ** **'PlainRange'convertstherange<list>toaplainlist. ** **'PlainRange'isthefunctionin'PlainListFuncs'forranges.
*/ staticvoid PlainRange(Obj list)
{ Int lenList; // length of <list> Int low; // first element of <list> Int inc; // increment of <list> Int i; // loop variable
// get the length, the first element, and the increment of <list>
lenList = GET_LEN_RANGE( list );
low = GET_LOW_RANGE( list );
inc = GET_INC_RANGE( list );
// change the type of the list, and allocate enough space if (lenList == 0)
RetypeBagSM(list, T_PLIST_EMPTY); elseif (inc > 0)
RetypeBagSM(list, T_PLIST_CYC_SSORT); else
RetypeBagSM(list, T_PLIST_CYC_NSORT);
GROW_PLIST( list, lenList );
SET_LEN_PLIST( list, lenList );
// enter the values in <list> for ( i = 1; i <= lenList; i++ ) {
SET_ELM_PLIST( list, i, INTOBJ_INT( low + (i-1) * inc ) );
}
}
staticBOOL IsRange(Obj list)
{ BOOL isRange; // result of the test Int len; // logical length of list Int low; // value of first element of range Int inc; // increment Int i; // loop variable
// if <list> is represented as a range, it is of course a range if ( TNUM_OBJ(list) == T_RANGE_NSORT
|| TNUM_OBJ(list) == T_RANGE_SSORT ) {
isRange = TRUE;
}
// if <list> is not a list, it is not a range at the moment elseif ( ! IS_SMALL_LIST( list ) ) { // isRange = FALSE;
isRange = (DoFilter(IsRangeFilt, list) == True);
}
// if <list> is the empty list, it is a range by definition elseif ( LEN_LIST(list) == 0 ) {
isRange = TRUE;
}
// if <list> is a list with just one integer, it is also a range elseif ( LEN_LIST(list)==1 && IS_INTOBJ(ELMW_LIST(list,1)) ) {
isRange = TRUE;
}
// if the first element is not an integer, it is not a range elseif ( ELMV0_LIST(list,1)==0 || !IS_INTOBJ(ELMW_LIST(list,1)) ) {
isRange = FALSE;
}
// if the second element is not an integer, it is not a range elseif ( ELMV0_LIST(list,2)==0 || !IS_INTOBJ(ELMW_LIST(list,2)) ) {
isRange = FALSE;
}
// if the first and the second element are equal it is also not a range elseif ( ELMW_LIST(list,1) == ELMW_LIST(list,2) ) {
isRange = FALSE;
}
// otherwise, test if the elements are consecutive integers else {
// get the logical length of the list
len = LEN_LIST(list);
low = INT_INTOBJ( ELMW_LIST( list, 1 ) );
inc = INT_INTOBJ( ELMW_LIST( list, 2 ) ) - low;
// test all entries against the first one for ( i = 3; i <= len; i++ ) { if ( ELMV0_LIST(list,i) != INTOBJ_INT( low + (i-1) * inc ) ) break;
}
// if <list> is a range, convert to the compact representation
isRange = (len < i); if ( isRange ) {
RetypeBagSM( list, (0 < inc ? T_RANGE_SSORT : T_RANGE_NSORT) );
ResizeBag( list, 3 * sizeof(Obj) );
SET_LEN_RANGE( list, len );
SET_LOW_RANGE( list, low );
SET_INC_RANGE( list, inc );
}
}
return isRange;
}
/**************************************************************************** ** *FFuncIsRange(<self>,<obj>)...............testforarange ** **'FuncIsRange'implementstheinternalfunction'IsRange'. ** **'IsRange(<obj>)' ** **'IsRange'returns'true'if<obj>,whichmaybeanobjectofanytype,is **arangeand'false'otherwise.Arangeisalistwithoutholessuchthat **theelementsareconsecutiveintegers.
*/ static Obj FiltIS_RANGE(Obj self, Obj obj)
{ // let 'IsRange' do the work for lists return IsRange(obj) ? True : False;
}
/**************************************************************************** ** *FRange2Check(<first>,<last>).............constructrange
*/
Obj Range2Check (
Obj first,
Obj last )
{
Obj range; Int f, l;
f = GetSmallInt("Range", first);
l = GetSmallInt("Range", last); if ( f > l ) {
range = NEW_PLIST( T_PLIST, 0 );
} elseif ( f == l ) {
range = NEW_PLIST( T_PLIST, 1 );
SET_LEN_PLIST( range, 1 );
SET_ELM_PLIST( range, 1, first );
} else {
range = NEW_RANGE((l-f) + 1, f, 1);
} return range;
}
/**************************************************************************** ** *FRange3Check(<first>,<second>,<last>)........constructrange
*/
Obj Range3Check (
Obj first,
Obj second,
Obj last )
{
Obj range; if ( first == second ) {
ErrorQuit("Range: <second> must not be equal to <first> (%d)",
(Int)INT_INTOBJ(first), 0);
} Int f = GetSmallInt("Range", first); Int i = GetSmallInt("Range", second) - f; Int l = GetSmallInt("Range", last); if ( (l - f) % i != 0 ) {
ErrorQuit( "Range: <last>-<first> (%d) must be divisible by <inc> (%d)",
(Int)(l - f), (Int)i );
} if ( (0 < i && f > l) || (i < 0 && f < l) ) {
range = NEW_PLIST( T_PLIST, 0 );
} elseif ( f == l ) {
range = NEW_PLIST( T_PLIST, 1 );
SET_LEN_PLIST( range, 1 );
SET_ELM_PLIST( range, 1, first );
} else {
range = NEW_RANGE((l - f) / i + 1, f, i);
} return range;
}
staticInt egcd (Int a, Int b, Int *lastx, Int *lasty)
{ Int x = 0, y = 1;
*lastx = 1; *lasty = 0;
while (b != 0) { Int t, q;
t = b; q = a / b; b = a % b; a = t; if (lastx) { t = x; x = *lastx - q*x; *lastx = t; } if (lasty) { t = y; y = *lasty - q*y; *lasty = t; }
} return a;
} // returns g=gcd(a,b), with lastx*a+lasty*b = g
if (!IS_RANGE(r1) || !IS_MUTABLE_OBJ(r1))
RequireArgumentEx(SELF_NAME, r1, "<range1>", "must be a mutable range"); if (!IS_RANGE(r2))
RequireArgumentEx(SELF_NAME, r2, "<range2>", "must be a range");
/**************************************************************************** ** *FInitInfoRange().................tableofinitfunctions
*/ static StructInitInfo module = { // init struct using C99 designated initializers; for a full list of // fields, please refer to the definition of StructInitInfo
.type = MODULE_BUILTIN,
.name = "range",
.initKernel = InitKernel,
.initLibrary = InitLibrary,
};
¤ 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.0.299Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-27)
¤
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.