/**************************************************************************** ** ** 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 functions of the generic list package. ** ** This package provides a uniform interface to the functions that access ** lists and their elements for the other packages in the GAP kernel. For ** example, 'ExecFor' can loop over the elements in a list using 'LEN_LIST' ** and 'ELM_LIST' independently of the type of the list. ** ** This package uses plain lists (of type 'T_PLIST') and assumes that it is ** possible to put values of any type into these. It uses the functions ** 'LEN_PLIST', 'SET_LEN_PLIST', 'ELM_PLIST', and 'SET_ELM_PLIST' exported ** by the plain list package to access and modify plain lists.
*/
/**************************************************************************** ** *F IS_SMALL_LIST(<obj>) . . . . . . . . . . . . . . . . . . . is an object a list *V IsListFuncs[<type>] . . . . . . . . . . . . . . . . . table for list test ** ** 'IS_SMALL_LIST' only calls the function pointed to by 'IsListFuncs[<type>]', ** passing <obj> as argument. ** ** This is, in some sense, a workaround for the not yet implemented features ** below (see LENGTH).
*/ BOOL (*IsSmallListFuncs[LAST_REAL_TNUM + 1])(Obj obj);
/**************************************************************************** ** *F AttrLENGTH( <self>, <list> ) . . . . . . . . . . . 'Length' interface ** ** There are the ``relatively'' easy changes to 'LEN_LIST' to allow it ** return GAP objects instead of small C integers, but then the kernel has ** to be very careful not to assume that the length is small and most of the ** code has to duplicated, namely one large and one small version. So ** instead the following solution has been taken: ** ** - internal lists have always a small length, that means that it is not ** possible to have plain list of length larger than 2^28 (or maybe 2^32) ** on 32-bit machines, 'LEN_LIST' can only be applied to internal objects, ** 'LENGTH' is the GAP interface for all kind of objects ** ** - on the other hand we want ranges to have large start and end points, ** therefore ranges are no longer *internal* objects, they are now ** external objects (NOT YET IMPLEMENTED) ** ** - the for/list assignment has to be careful to catch the special case of ** a range constructor with small integer bounds ** ** - the list access/assignment is a binary operation (NOT YET IMPLEMENTED) ** ** - the conversion/test functions are split into three different functions ** (NOT YET IMPLEMENTED) ** ** - 'ResetFilterObj' and 'SetFilterObj' are implemented using a table for ** internal types (NOT YET IMPLEMENTED)
*/
/**************************************************************************** ** *F LEN_LIST(<list>) . . . . . . . . . . . . . . . . . . . length of a list *V LenListFuncs[<type>] . . . . . . . . . . . . . table of length functions *F LenListError(<list>) . . . . . . . . . . . . . . . error length function ** ** 'LEN_LIST' only calls the function pointed to by 'LenListFuncs[<type>]', ** passing <list> as argument. If <type> is not the type of a list, then ** 'LenListFuncs[<type>]' points to 'LenListError', which just signals an ** error. ** ** At the moment this also handles external types but this is a hack, ** because external lists can have large length or even be infinite. See ** 'AttrLENGTH'.
*/ Int (*LenListFuncs[LAST_REAL_TNUM+1]) ( Obj list );
static Obj FuncLEN_LIST(Obj self, Obj list)
{ // special case for plain lists (avoid conversion back and forth) if ( IS_PLIST(list) ) { return INTOBJ_INT( LEN_PLIST( list ) );
}
// generic case (will signal an error if <list> is not a list) else { return AttrLENGTH( LengthAttr, list );
}
}
staticInt LenListError(Obj list)
{
RequireArgument("Length", list, "must be a list");
}
staticInt LenListObject(Obj obj)
{
Obj len;
len = AttrLENGTH( LengthAttr, obj ); if (!IS_NONNEG_INTOBJ(len)) {
RequireArgumentEx("Length", len, 0, "method must return a non-negative small integer");
} return INT_INTOBJ( len );
}
/**************************************************************************** ** *F LENGTH(<list>) . . . . . . . . . . . . . . . . . . . length of a list *V LengthFuncs[<type>] . . . . . . . . . . . . . table of length functions ** ** 'LENGTH' returns the logical length of the list <list> as a GAP object ** An error is signalled if <list> is not a list. ** ** A package implementing a list type <type> must provide such a function ** and install it in 'LengthFuncs[<type>]'.
*/
Obj (*LengthFuncs[LAST_REAL_TNUM+1]) ( Obj list );
static Obj LengthError(Obj list)
{
RequireArgument("Length", list, "must be a list");
}
/**************************************************************************** ** *F ISB_LIST(<list>,<pos>) . . . . . . . . . . test for element from a list *V IsbListFuncs[<type>] . . . . . . . . . . . . . . table of test functions ** ** 'ISB_LIST' only calls the function pointed to by 'IsbListFuncs[<type>]', ** passing <list> and <pos> as arguments. If <type> is not the type of a ** list, then 'IsbListFuncs[<type>]' points to 'IsbListError', which signals ** the error.
*/ BOOL (*IsbListFuncs[LAST_REAL_TNUM + 1])(Obj list, Int pos);
/**************************************************************************** ** *V Elm0ListFuncs[ <type> ] . . . . . . . . . . table of selection functions ** ** 'ELM0_LIST' returns the element at the position <pos> in the list <list>, ** or 0 if <list> has no assigned object at position <pos>. An error is ** signalled if <list> is not a list. It is the responsibility of the ** caller to ensure that <pos> is a positive integer.
*/
Obj (*Elm0ListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Int pos );
/**************************************************************************** ** *V ElmDefListFuncs[ <type> ] . . . . . . . . . table of selection functions ** ** 'ELM_DEFAULT_LIST' returns the element at the position <pos> in the list ** <list>, or <default> if <list> has no assigned object at position <pos>. ** An error is signalled if <list> is not a list. It is the responsibility ** of the caller to ensure that <pos> is a positive integer.
*/
Obj (*ElmDefListFuncs[LAST_REAL_TNUM + 1])(Obj list, Int pos, Obj def);
// Default implementation of ELM_DEFAULT_LIST static Obj ElmDefListDefault(Obj list, Int pos, Obj def)
{
Obj val = ELM0_LIST(list, pos); if (val) { return val;
} else { return def;
}
}
/**************************************************************************** ** *F ElmDefListObject( <list>, <pos>, <default> )select an element from a list ** ** `ElmDefListObject' is the `ELM_DEFAULT_LIST' function for objects. **
*/ static Obj ElmDefListOper;
/**************************************************************************** ** *V Elm0vListFuncs[ <type> ] . . . . . . . . . table of selection functions ** ** 'ELMV0_LIST' does the same as 'ELM0_LIST', but the caller also guarantees ** that <list> is a list and that <pos> is less than or equal to the length ** of <list>.
*/
Obj (*Elm0vListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Int pos );
/**************************************************************************** ** *F Elm0ListObject( <list>, <pos> ) . . . . . . select an element from a list ** ** `Elm0ListObject' is the `ELM0_LIST' and `ELMV0_LIST' function for ** objects. The function returns the element at the position <pos> of the ** list object <list>, or 0 if <list> has no assigned object at <pos>. It ** is the responsibility of the caller to ensure that <pos> is a positive ** integer.
*/ static Obj Elm0ListObject(Obj list, Int pos)
{ if (ISB_LIST(list, pos)) return ELM_LIST(list, pos); else return 0;
}
/**************************************************************************** ** *V ElmListFuncs[<type>] . . . . . . . . . . . table of selection functions ** ** 'ELM_LIST' returns the element at the position <pos> in the list <list>. ** An error is signalled if <list> is not a list, if <pos> is larger than ** the length of <list>, or if <list> has no assigned object at <pos>. It ** is the responsibility of the caller to ensure that <pos> is a positive ** integer. ** ** 'ELM_LIST' only calls the functions pointed to by 'ElmListFuncs[<type>]' ** passing <list> and <pos> as arguments. If <type> is not the type of a ** list, then 'ElmListFuncs[<type>]' points to 'ElmListError', which signals ** the error.
*/
Obj (*ElmListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Int pos );
/**************************************************************************** ** *V ElmvListFuncs[<type>] . . . . . . . . . . . table of selection functions ** ** 'ELMV_LIST' does the same as 'ELM_LIST', but the caller also guarantees ** that <list> is a list and that <pos> is less than or equal to the length ** of <list>.
*/
Obj (*ElmvListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Int pos );
/**************************************************************************** ** *V ElmwListFuncs[<type>] . . . . . . . . . . . table of selection functions ** ** 'ELMW_LIST' does the same as 'ELMV_LIST', but the caller also guarantees ** that <list> has an assigned object at the position <pos>.
*/
Obj (*ElmwListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Int pos );
/**************************************************************************** ** *F ElmListObject( <list>, <pos> . . . . . . . select an element from a list ** ** `ElmListObject' is the `ELM_LIST', `ELMV_LIST', and `ELMW_LIST' function ** for objects. 'ElmListObjects' selects the element at position <pos> of ** list object <list>. It is the responsibility of the caller to ensure ** that <pos> is a positive integer. The methods have to signal an error if ** <pos> is larger than the length of <list> or if the entry is not bound.
*/ static Obj ElmListOper;
Obj ELM_MAT(Obj mat, Obj row, Obj col)
{
Obj elm; if (IS_POS_INTOBJ(row) && IS_POS_INTOBJ(col) && IS_PLIST(mat)) { Int r = INT_INTOBJ(row); if (r <= LEN_PLIST(mat)) {
Obj rowlist = ELM_PLIST(mat, r); Int c = INT_INTOBJ(col);
if (!rowlist)
ErrorMayQuit("Matrix Element: [%d] must have an assigned value",
(Int)r, (Int)c); if (IS_PLIST(rowlist) && c <= LEN_PLIST(rowlist)) {
elm = ELM_PLIST(rowlist, c); if (!elm)
ErrorMayQuit("Matrix Element: [%d,%d] must have an assigned value",
(Int)r, (Int)c); return elm;
}
// fallback to generic list access code (also triggers error if // row isn't a list) return ELM_LIST(rowlist, c);
}
}
elm = DoOperation3Args(ElmMatOper, mat, row, col); if (elm == 0) {
ErrorMayQuit("Matrix access method must return a value", 0, 0);
} return elm;
}
/**************************************************************************** ** *V ElmsListFuncs[<type>] . . . . . . . . . . . table of selection functions ** ** 'ELMS_LIST' returns a new list containing the elements at the positions ** given in the list <poss> from the <list>. It is the responsibility of ** the caller to ensure that <poss> is dense and contains only positive ** integers. An error is signalled if an element of <poss> is larger than ** the length of <list>. ** ** 'ELMS_LIST' only calls the function pointed to by ** 'ElmsListFuncs[<type>]', passing <list> and <poss> as arguments. If ** <type> is not the type of a list, then 'ElmsListFuncs[<type>]' points to ** 'ElmsListError', which just signals an error.
*/
Obj (*ElmsListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Obj poss );
/**************************************************************************** ** *F ElmsListObject( <list>, <pos> ) . . . . . . . select elements from a list ** ** `ElmsListObject' is the `ELMS_LIST' function for objects.
*/ static Obj ElmsListOper;
/**************************************************************************** ** *F ElmsListDefault( <list>, <poss> ) . . . default function for `ELMS_LIST' ** ** Create a new plain list as result. <list> must be small.
*/
Obj ElmsListDefault (
Obj list,
Obj poss )
{
Obj elms; // selected sublist, result
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 <positions> // OK because all positions lists are small
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
elm = ELM0_LIST( list, pos ); if ( elm == 0 ) {
ErrorMayQuit( "List Elements: [%d] must have an assigned value",
(Int)pos, 0);
}
// assign the element into <elms>
SET_ELM_PLIST( elms, i, elm );
// notify Gasman
CHANGED_BAG( elms );
}
}
// special code for ranges else {
// get the length of <list> Int lenList = LEN_LIST( 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: [%d] must have an assigned value",
(Int)pos, 0);
} if ( lenList < pos + (lenPoss-1) * inc ) {
ErrorMayQuit( "List Elements: [%d] must have an assigned value",
(Int)pos + (lenPoss - 1) * inc, 0);
}
// 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++, pos += inc ) {
// select the element
elm = ELMV0_LIST( list, pos ); if ( elm == 0 ) {
ErrorMayQuit( "List Elements: [%d] must have an assigned value",
(Int)pos, 0);
}
// assign the element to <elms>
SET_ELM_PLIST( elms, i, elm );
/**************************************************************************** ** *F ASS_LIST(<list>,<pos>,<obj>) . . . . . . . . assign an element to a list *V AssListFuncs[<type>] . . . . . . . . . . . table of assignment functions *F AssListError(<list>,<pos>,<obj>) . . . . . . . error assignment function ** ** 'ASS_LIST' only calls the function pointed to by 'AssListFuncs[<type>]', ** passing <list>, <pos>, and <obj> as arguments. If <type> is not the type ** of a list, then 'AssListFuncs[<type>]' points to 'AssListError', which ** just signals an error. **
*/ void (*AssListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Int pos, Obj obj );
/**************************************************************************** ** *F ASSS_LIST(<list>,<poss>,<objs>) . . . . assign several elements to a list *V AsssListFuncs[<type>] . . . . . . . . . . . table of assignment function *F AsssListError(<list>,<poss>,<objs>) . . . . . . error assignment function ** ** 'ASSS_LIST' only calls the function pointed to by ** 'AsssListFuncs[<type>]', passing <list>, <poss>, and <objs> as arguments. ** If <type> is not the type of a list, then 'AsssListFuncs[<type>]' points ** to 'AsssListError', which just signals an error.
*/ void (*AsssListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Obj poss, Obj objs );
staticvoid AsssListError(Obj list, Obj poss, Obj objs)
{
RequireArgument("List Assignments", list, "must be a list");
}
void AsssListDefault (
Obj list,
Obj poss,
Obj objs )
{ Int lenPoss; // length of <positions>
Obj p; // <position> Int pos; // <position> as integer Int inc; // increment in a range
Obj obj; // one element from <objs> Int i; // loop variable
// get the length of <positions>
lenPoss = LEN_LIST( poss );
// loop over the entries of <positions> and select for ( i = 1; i <= lenPoss; i++ ) {
// get <position>
p = ELMW_LIST( poss, i );
// select the element
obj = ELMW_LIST( objs, i ); if (IS_INTOBJ(p) )
{ // assign the element into <elms>
ASS_LIST( list, INT_INTOBJ(p), obj );
} else
ASSB_LIST(list, p, obj);
}
}
// special code for ranges else {
// get the length of <positions>
lenPoss = GET_LEN_RANGE( poss );
pos = GET_LOW_RANGE( poss );
inc = GET_INC_RANGE( poss );
// loop over the entries of <positions> and select for ( i = 1; i <= lenPoss; i++, pos += inc ) {
// select the element
obj = ELMW_LIST( objs, i );
// assign the element to <elms>
ASS_LIST( list, pos, obj );
/**************************************************************************** ** *F IS_DENSE_LIST(<list>) . . . . . . . . . . . . . . . test for dense lists *V IsDenseListFuncs[<type>] . . . . . . table for dense list test functions ** ** 'IS_DENSE_LIST' only calls the function pointed to by ** 'IsDenseListFuncs[<type>]', passing <list> as argument. If <type> is not ** the type of a list, then 'IsDenseListFuncs[<type>]' points to ** 'AlwaysNo', which just returns 0.
*/ BOOL (*IsDenseListFuncs[LAST_REAL_TNUM + 1])(Obj list);
/**************************************************************************** ** *F IS_HOMOG_LIST(<list>) . . . . . . . . . . . . test for homogeneous lists *V IsHomogListFuncs[<type>] . . . table for homogeneous list test functions ** ** 'IS_HOMOG_LIST' only calls the function pointed to by ** 'IsHomogListFuncs[<type>]', passing <list> as argument. If <type> is not ** the type of a list, then 'IsHomogListFuncs[<type>]' points to ** 'AlwaysNo', which just returns 0. **
*/ BOOL (*IsHomogListFuncs[LAST_REAL_TNUM + 1])(Obj list);
/**************************************************************************** ** *F IS_TABLE_LIST(<list>) . . . . . . . . . . . . . . . test for table lists *V IsTableListFuncs[<type>] . . . . . . table for table list test functions ** ** 'IS_TABLE_LIST' only calls the function pointed to by ** 'IsTableListFuncs[<type>]', passing <list> as argument. If <type> is not ** the type of a list, then 'IsTableListFuncs[<type>]' points to ** 'AlwaysNo', which just returns 0.
*/ BOOL (*IsTableListFuncs[LAST_REAL_TNUM + 1])(Obj list);
/**************************************************************************** ** *F IS_SSORT_LIST( <list> ) . . . . . . . . . test for strictly sorted lists *V IsSSortListFuncs[<type>] . table of strictly sorted list test functions ** ** 'IS_SSORT_LIST' only calls the function pointed to by ** 'IsSSortListFuncs[<type>]', passing <list> as argument. ** If <type> is not the type of a list, then 'IsSSortListFuncs[<type>]' ** points to 'AlwaysNo', which just returns 0. **
*/ BOOL (*IsSSortListFuncs[LAST_REAL_TNUM + 1])(Obj list);
staticBOOL IsSSortListDefault(Obj list)
{ Int lenList;
Obj elm1;
Obj elm2; Int i;
// get the length of the list
lenList = LEN_LIST( list );
// special case for the empty list if ( lenList == 0 ) { returnTRUE;
}
// get the first element
elm1 = ELM0_LIST(list, 1);
if (!elm1) { returnFALSE;
}
// compare each element with its precursor for ( i = 2; i <= lenList; i++ ) {
elm2 = ELM0_LIST(list, i); if (!elm2) { returnFALSE;
} if ( ! LT( elm1, elm2 ) ) { returnFALSE;
}
elm1 = elm2;
}
/**************************************************************************** ** *F IS_POSS_LIST(<list>) . . . . . . . . . . . . . test for positions lists *V IsPossListFuncs[<type>] . . . . . . table of positions list test function ** ** 'IS_POSS_LIST' only calls the function pointed to by ** 'IsPossListFuncs[<type>]', passing <list> as argument. If <type> is not ** the type of a list, then 'IsPossListFuncs[<type>]' points to ** 'NotIsPossList', which just returns 0.
*/ BOOL (*IsPossListFuncs[LAST_REAL_TNUM + 1])(Obj list);
staticBOOL IsPossListDefault(Obj list)
{ Int lenList; // length of <list>
Obj elm; // one element of <list> Int i; // loop variable
// get the length of the variable
lenList = LEN_LIST( list );
// loop over the entries of the list for ( i = 1; i <= lenList; i++ ) {
elm = ELMV0_LIST( list, i );
// if it has a hole then it isn't a poss list if ( elm == 0) returnFALSE;
/* if it's a small integer and non-positive then
it's not a poss list */ if ( IS_INTOBJ(elm)) { if (INT_INTOBJ(elm) <= 0) returnFALSE;
} /* or if it's not a small integer or a positive large integer then it's
not a poss list */ elseif (TNUM_OBJ(elm) != T_INTPOS) returnFALSE;
}
/**************************************************************************** ** *F POS_LIST(<list>,<obj>,<start>) . . . . . . . . find an element in a list *V PosListFuncs[<type>] . . . . . . . . . . . table of searching functions *F PosListError(<list>,<obj>,<start>) . . . . . . error searching function ** ** 'POS_LIST' only calls the function pointed to by 'PosListFuncs[<type>]', ** passing <list>, <obj>, and <start> as arguments. If <type> is not the ** type of a list, then 'PosListFuncs[<type>]' points to 'PosListError', ** which just signals an error.
*/
Obj (*PosListFuncs[LAST_REAL_TNUM+1]) ( Obj list, Obj obj, Obj start );
static Obj PosListError(Obj list, Obj obj, Obj start)
{
RequireArgument("Position", list, "must be a list");
}
static Obj PosListDefault (
Obj list,
Obj obj,
Obj start )
{ Int lenList;
Obj elm; Int i;
/* 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;
// get the length of the list
lenList = LEN_LIST( list );
// loop over all bound entries of the list, and compare against <obj> for ( i = INT_INTOBJ(start)+1; i <= lenList; i++ ) {
elm = ELMV0_LIST( list, i ); if ( elm != 0 && EQ( elm, obj ) ) { break;
}
}
// return the position if found, and 0 otherwise if ( i <= lenList ) { return INTOBJ_INT(i);
} else { return Fail;
}
}
/**************************************************************************** ** *F ElmListLevel(<lists>,<pos>,<level>) . . . . . . . . . . . . . . . . . . . *F . . . . . . . . . . . . . select an element of several lists in parallel ** ** 'ElmListLevel' either selects an element from all lists in parallel if ** <level> is 1, or recurses if <level> is greater than 1.
*/ void ElmListLevel (
Obj lists,
Obj ixs, Int level )
{ Int len; // length of <lists>
Obj list; // one list from <lists>
Obj elm; // selected element from <list> Int i; // loop variable
Obj pos;
Obj row;
Obj col;
RequirePlainList("List Elements", lists);
// if <level> is one, perform the replacements if ( level == 1 ) {
// loop over the elements of <lists> (which must be a plain list)
len = LEN_PLIST( lists ); for ( i = 1; i <= len; i++ ) {
// get the list
list = ELM_PLIST( lists, i );
// select the element switch(LEN_PLIST(ixs)) { case 1:
pos = ELM_PLIST(ixs,1); if (IS_INTOBJ(pos))
elm = ELM_LIST( list, INT_INTOBJ(pos) ); else
elm = ELMB_LIST(list, pos); break;
case 2:
row = ELM_PLIST(ixs, 1);
col = ELM_PLIST(ixs, 2);
elm = ELM_MAT(list, row, col); break;
default:
elm = ELMB_LIST(list, ixs);
}
// replace the list with the element
SET_ELM_PLIST( lists, i, elm );
// notify Gasman
CHANGED_BAG( lists );
}
RetypeBag(lists, T_PLIST_DENSE);
}
// otherwise recurse else {
// loop over the elements of <lists> (which must be a plain list)
len = LEN_PLIST( lists ); for ( i = 1; i <= len; i++ ) {
// get the list
list = ELM_PLIST( lists, i );
// recurse
ElmListLevel( list, ixs, level-1 );
}
}
}
/**************************************************************************** ** *F ElmsListLevel(<lists>,<poss>,<level>) . . . . . . . . . . . . . . . . . . *F . . . . . . . . . . select several elements of several lists in parallel ** ** 'ElmsListLevel' either selects elements from all lists in parallel if ** <level> is 1, or recurses if <level> is greater than 1.
*/ void ElmsListLevel (
Obj lists,
Obj poss, Int level )
{ Int len; // length of <lists>
Obj list; // one list from <lists>
Obj elm; // selected elements from <list> Int i; // loop variable
RequirePlainList("List Elements", lists);
// if <level> is one, perform the replacements if ( level == 1 ) {
// loop over the elements of <lists> (which must be a plain list)
len = LEN_PLIST( lists ); for ( i = 1; i <= len; i++ ) {
// get the list
list = ELM_PLIST( lists, i );
// select the elements
elm = ELMS_LIST( list, poss );
// replace the list with the elements
SET_ELM_PLIST( lists, i, elm );
// notify Gasman
CHANGED_BAG( lists );
}
/* Since the elements of lists are now mutable lists (made by ELMS_LIST in the list above), we cannot remember too much
about them */
RetypeBag(lists, T_PLIST_DENSE);
}
// otherwise recurse else {
// loop over the elements of <lists> (which must be a plain list)
len = LEN_PLIST( lists ); for ( i = 1; i <= len; i++ ) {
// get the list
list = ELM_PLIST( lists, i );
// recurse
ElmsListLevel( list, poss, level-1 );
}
RetypeBag(lists, T_PLIST_DENSE);
}
}
/**************************************************************************** ** *F AssListLevel(<lists>,<ixs>,<objs>,<level>) . . . . . . . . . . . . . . . *F . . . . . . . . . . . . . assign an element to several lists in parallel ** ** 'AssListLevel' either assigns an element to all lists in parallel if ** <level> is 1, or recurses if <level> is greater than 1.
*/ void AssListLevel (
Obj lists,
Obj ixs,
Obj objs, Int level )
{ Int len; // length of <lists> and <objs>
Obj list; // one list of <lists>
Obj obj; // one value from <objs> Int i; // loop variable
Obj pos;
Obj row;
Obj col;
/**************************************************************************** ** *F AsssListLevel(<lists>,<poss>,<objs>,<level>) . . . . . . . . . . . . . . *F . . . . . . . . . . assign several elements to several lists in parallel ** ** 'AsssListLevel' either assigns elements to all lists in parallel if ** <level> is 1, or recurses if <level> is greater than 1.
*/ void AsssListLevel (
Obj lists,
Obj poss,
Obj objs, Int lev )
{ Int len; // length of <lists> and <objs>
Obj list; // one list of <lists>
Obj obj; // one value from <objs> Int i; // loop variable
/**************************************************************************** ** *F PLAIN_LIST(<list>) . . . . . . . . . . . convert a list to a plain list *V PlainListFuncs[<type>] . . . . . . . . . . table of conversion functions *F PlainListError(<list>) . . . . . . . . . . . . error conversion function ** ** 'PLAIN_LIST' only calls the function pointed to by ** 'PlainListFuncs[<type>]', passing <list> as argument. If <type> is not ** the type of a list, then 'PlainListFuncs[<type>]' points to ** 'PlainListError', which just signals an error.
*/ void (*PlainListFuncs[LAST_REAL_TNUM+1]) ( Obj list );
staticvoid PlainListError(Obj list)
{
ErrorQuit("Panic: cannot convert (is a %s) to a plain list",
(Int)TNAM_OBJ(list), 0);
}
Obj PLAIN_LIST_COPY(Obj list)
{ if (IS_PLIST(list)) { return SHALLOW_COPY_OBJ(list);
} constInt len = LEN_LIST(list); if (len == 0) return NewEmptyPlist();
Obj res = NEW_PLIST(T_PLIST, len);
SET_LEN_PLIST(res, len); for (Int i = 1; i <= len; i++) {
SET_ELM_PLIST(res, i, ELMV0_LIST(list, i));
CHANGED_BAG(res);
} return res;
}
/**************************************************************************** ** *F TYPES_LIST_FAM(<fam>) . . . . . . . list of types of lists over a family
*/ static UInt TYPES_LIST_FAM_RNam;
/**************************************************************************** ** *F PrintListDefault(<list>) . . . . . . . . . . . . . . . . . print a list ** ** 'PrintListDefault' simply prints the elements in the given list. ** The line break hints are consistent with those ** that appear in the 'ViewObj' and 'ViewString' methods for finite lists.
*/ staticvoid PrintListDefault(Obj list)
{
Obj elm;
Pr("%2>[ %2>", 0, 0); for (UInt i = 1; i <= LEN_LIST(list); i++) {
elm = ELMV0_LIST(list, i); if ( elm != 0 ) { if (1 < i)
Pr("%<,%< %2>", 0, 0);
SetPrintObjIndex(i);
PrintObj( elm );
} else { if (1 < i)
Pr("%2<,%2>", 0, 0);
}
}
Pr(" %4<]", 0, 0);
}
/**************************************************************************** ** *V SetFiltListTNums[ <tnum> ][ <fnum> ] . . . . . new tnum after filter set ** ** If a list with type number <tnum> gains the filter with filter number ** <fnum>, then the new type number is stored in: ** ** `SetFiltListTNums[<tnum>][<fnum>]' ** ** The macro `SET_FILT_LIST' is used to set the filter for a list by ** changing its type number.
*/
UInt SetFiltListTNums [ LAST_REAL_TNUM ] [ LAST_FN + 1 ];
/**************************************************************************** ** *V ResetFiltListTNums[ <tnum> ][ <fnum> ] . . . new tnum after filter reset ** ** If a list with type number <tnum> loses the filter with filter number ** <fnum>, then the new type number is stored in: ** ** `ResetFiltListTNums[<tnum>][<fnum>]' ** ** The macro `RESET_FILT_LIST' is used to set the filter for a list by ** changing its type number.
*/
UInt ResetFiltListTNums [ LAST_REAL_TNUM ] [ LAST_FN + 1];
/**************************************************************************** ** *V ClearFiltsTNums[ <tnum> ] . . . . . . . . . . . . clear all list filters ** ** The type number without any known properties of a list of type number ** <tnum> is stored in: ** ** `ClearPropsTNums[<tnum>]' ** ** The macro `CLEAR_PROPS_LIST' is used to clear all properties of a list.
*/
UInt ClearFiltsTNums [ LAST_REAL_TNUM ];
flags = FLAGS_FILT(filter); if (IS_SUBSET_FLAGS(flags, FLAGS_FILT(IsSSortListProp))) { new = SetFiltListTNums[TNUM_OBJ(list)][FN_IS_DENSE]; if ( new < 0 ) goto error; new = SetFiltListTNums[TNUM_OBJ(list)][FN_IS_SSORT]; if ( new > 0 ) RetypeBag( list, new ); elsegoto error;
} return 0;
// setting of filter failed
error:
ErrorMayQuit("filter not possible for %s", (Int)TNAM_OBJ(list), 0); return 0;
}
// POS_LIST can take 2 or 3 arguments; since NewOperation ignores the // handler for variadic operations, use DoOperation0Args as a placeholder.
{ "POS_LIST", -1, "list, obj[, start]", &PosListOper, DoOperation0Args, "src/lists.c:POS_LIST" },
// make and install the 'POS_LIST' operation
InitHandlerFunc( PosListHandler2, "src/lists.c:PosListHandler2" );
InitHandlerFunc( PosListHandler3, "src/lists.c:PosListHandler3" );
// import small list machinery from the library
ImportFuncFromLibrary("IsSmallList", &IsSmallListFilt);
ImportFuncFromLibrary("HasIsSmallList", &HasIsSmallListFilt);
ImportFuncFromLibrary("SetIsSmallList", &SetIsSmallList);
// make and install the 'IS_LIST' filter for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(IsListFuncs[ type ] == 0);
IsListFuncs[ type ] = AlwaysNo;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
IsListFuncs[ type ] = AlwaysYes;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
IsListFuncs[ type ] = IsListObject;
}
// make and install the 'IS_SMALL_LIST' filter // non-lists are not small lists for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(IsSmallListFuncs[ type ] == 0);
IsSmallListFuncs[ type ] = AlwaysNo;
} // internal lists ARE small lists for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
IsSmallListFuncs[ type ] = AlwaysYes;
} // external lists need to be asked for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
IsSmallListFuncs[ type ] = IsSmallListObject;
}
// make and install the 'LEN_LIST' function for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(LenListFuncs[ type ] == 0);
LenListFuncs[ type ] = LenListError;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
LenListFuncs[ type ] = LenListObject;
}
// make and install the 'LENGTH' function for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(LengthFuncs[ type ] == 0);
LengthFuncs[ type ] = LengthError;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
LengthFuncs[ type ] = LengthObject;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
LengthFuncs[ type ] = LengthInternal;
}
// make and install the 'ISB_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
IsbListFuncs[ type ] = IsbListError;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
IsbListFuncs[ type ] = IsbListObject;
}
// make and install the 'ELM0_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(Elm0ListFuncs[ type ] == 0);
Elm0ListFuncs[ type ] = Elm0ListError;
assert(Elm0vListFuncs[ type ] == 0);
Elm0vListFuncs[ type ] = Elm0ListError;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
Elm0ListFuncs[ type ] = Elm0ListObject;
Elm0vListFuncs[ type ] = Elm0ListObject;
}
// make and install ELM_DEFAULT_LIST operation // we install this for all TNUMs, as the default implementation delegates // to other list operations, we can error if appropriate for (type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++) {
ElmDefListFuncs[type] = ElmDefListDefault;
} for (type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++) {
ElmDefListFuncs[type] = ElmDefListObject;
}
// make and install the 'ELM_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(ElmListFuncs[ type ] == 0);
ElmListFuncs[ type ] = ElmListError;
assert(ElmvListFuncs[ type ] == 0);
ElmvListFuncs[ type ] = ElmListError;
assert(ElmwListFuncs[ type ] == 0);
ElmwListFuncs[ type ] = ElmListError;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
ElmListFuncs[ type ] = ElmListObject;
ElmvListFuncs[ type ] = ElmListObject;
ElmwListFuncs[ type ] = ElmListObject;
}
// make and install the 'ELMS_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(ElmsListFuncs[ type ] == 0);
ElmsListFuncs[ type ] = ElmsListError;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
ElmsListFuncs[ type ] = ElmsListDefault;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
ElmsListFuncs[ type ] = ElmsListObject;
}
// make and install the 'UNB_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(UnbListFuncs[ type ] == 0);
UnbListFuncs[ type ] = UnbListError;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
UnbListFuncs[ type ] = 0;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
UnbListFuncs[ type ] = UnbListObject;
}
// make and install the 'ASS_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(AssListFuncs[ type ] == 0);
AssListFuncs[ type ] = AssListError;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
AssListFuncs[ type ] = 0;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
AssListFuncs[ type ] = AssListObject;
}
// make and install the 'ASSS_LIST' operation for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(AsssListFuncs[ type ] == 0);
AsssListFuncs[ type ] = AsssListError;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
AsssListFuncs[ type ] = AsssListDefault;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
AsssListFuncs[ type ] = AsssListObject;
}
// make and install the 'IS_DENSE_LIST' filter for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(IsDenseListFuncs[ type ] == 0);
IsDenseListFuncs[ type ] = AlwaysNo;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
IsDenseListFuncs[ type ] = 0;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
IsDenseListFuncs[ type ] = IsDenseListObject;
}
// make and install the 'IS_HOMOG_LIST' filter for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(IsHomogListFuncs[ type ] == 0);
IsHomogListFuncs[ type ] = AlwaysNo;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
IsHomogListFuncs[ type ] = 0;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
IsHomogListFuncs[ type ] = IsHomogListObject;
}
// make and install the 'IS_TABLE_LIST' filter for ( type = FIRST_REAL_TNUM; type <= LAST_REAL_TNUM; type++ ) {
assert(IsTableListFuncs[ type ] == 0);
IsTableListFuncs[ type ] = AlwaysNo;
} for ( type = FIRST_LIST_TNUM; type <= LAST_LIST_TNUM; type++ ) {
IsTableListFuncs[ type ] = 0;
} for ( type = FIRST_EXTERNAL_TNUM; type <= LAST_EXTERNAL_TNUM; type++ ) {
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.54 Sekunden
(vorverarbeitet)
¤
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.