Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346/****************************************************************************1**2*W blister.c GAP source Frank Celler3*W & Martin Schönert4**5**6*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany7*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland8*Y Copyright (C) 2002 The GAP Group9**10** This file contains the functions that mainly operate on boolean lists.11** Because boolean lists are just a special case of lists many things are12** done in the list package.13**14** A *boolean list* is a list that has no holes and contains only 'true' and15** 'false'. For the full definition of boolean list see chapter "Boolean16** Lists" in the {\GAP} Manual. Read also the section "More about Boolean17** Lists" about the different internal representations of such lists.18**19** A list that is known to be a boolean list is represented by a bag of type20** 'T_BLIST', which has the following format:21**22** +-------+-------+-------+-------+- - - -+-------+23** |logical| block | block | block | | last |24** |length | 0 | 1 | 2 | | block |25** +-------+-------+-------+-------+- - - -+-------+26** / \27** .---' `-----------.28** / \29** +---+---+---+---+- - - -+---+---+30** |bit|bit|bit|bit| |bit|bit|31** | 0 | 1 | 2 | 3 | |n-1| n |32** +---+---+---+---+- - - -+---+---+33**34** The first entry is the logical length of the list, represented as a35** {\GAP} immediate integer. The other entries are blocks, represented as C36** unsigned long integer. Each block corresponds to <n> (usually 32)37** elements of the list. The <j>-th bit (the bit corresponding to '2\^<j>')38** in the <i>-th block is 1 if the element '<list>[BIPEB*<i>+<j>+1]' it39** 'true' and '0' if it is 'false'. If the logical length of the boolean40** list is not a multiple of BIPEB the last block will contain unused bits,41** which are then zero.42**43** Note that a list represented by a bag of type 'T_PLIST' might still be a44** boolean list. It is just that the kernel does not known this.45**46** This package consists of three parts.47**48** The first part consists of the macros 'BIPEB', 'SIZE_PLEN_BLIST',49** 'PLEN_SIZE_BLIST', 'LEN_BLIST', 'SET_LEN_BLIST', 'ELM_BLIST', and50** 'SET_ELM_BLIST'. They determine the representation of boolean lists.51** The rest of the {\GAP} kernel uses those macros to access and modify52** boolean lists.53**54** The second part consists of the functions 'LenBlist', 'ElmBlist',55** 'ElmsBlist', 'AssBlist', 'AsssBlist', 'PosBlist', 'PlainBlist',56** 'IsDenseBlist', 'IsPossBlist', 'EqBlist', and 'LtBlist'. They are the57** functions required by the generic lists package. Using these functions58** the other parts of the {\GAP} kernel can access and modify boolean lists59** without actually being aware that they are dealing with a boolean list.60**61** The third part consists of the functions 'IsBlistConv', 'FuncIsBlist',62** 'FuncBLIST_LIST', 'FuncLIST_BLIST', 'FuncSIZE_BLIST', 'FuncIS_SUB_BLIST',63** 'FuncUNITE_BLIST', 'FuncINTER_BLIST', and 'FuncSUBTR_BLIST'. These64** functions make it possible to make boolean lists, either by converting a65** list to a boolean list, or by computing the characteristic boolean list66** of a sublist, or by computing the union, intersection or difference of67** two boolean lists.68**69*N 1992/12/16 martin should have 'LtBlist'70*/71#include "system.h" /* system dependent part */727374#include "gasman.h" /* garbage collector */75#include "objects.h" /* objects */76#include "scanner.h" /* scanner */7778#include "gap.h" /* error handling, initialisation */7980#include "gvars.h" /* global variables */81#include "calls.h" /* generic call mechanism */82#include "opers.h" /* generic operations */8384#include "ariths.h" /* basic arithmetic */8586#include "bool.h" /* booleans */8788#include "records.h" /* generic records */89#include "precord.h" /* plain records */9091#include "lists.h" /* generic lists */92#include "plist.h" /* plain lists */93#include "set.h" /* plain sets */94#include "blister.h" /* boolean lists */95#include "range.h" /* ranges */96#include "string.h" /* strings */9798#include "saveload.h" /* saving and loading */99100#include "code.h" /* coder */101#include "thread.h" /* threads */102#include "tls.h" /* thread-local storage */103104105/****************************************************************************106**107108*F TypeBlist( <list> ) . . . . . . . . . . . . . . . type of a boolean list109**110** 'TypeBlist' returns the type of a boolean list.111**112** 'TypeBlist' is the function in 'TypeObjFuncs' for boolean lists.113*/114115/* The following are imported from the GAP level, we have one type for116* each blist TNUM. */117Obj TYPE_BLIST_MUT;118Obj TYPE_BLIST_IMM;119Obj TYPE_BLIST_NSORT_MUT;120Obj TYPE_BLIST_NSORT_IMM;121Obj TYPE_BLIST_SSORT_MUT;122Obj TYPE_BLIST_SSORT_IMM;123Obj TYPE_BLIST_EMPTY_MUT;124Obj TYPE_BLIST_EMPTY_IMM;125126Obj TypeBlistMut (127Obj list )128{129/* special case for the empty blist */130if ( LEN_BLIST(list) == 0 ) {131return TYPE_BLIST_EMPTY_MUT;132} else {133return TYPE_BLIST_MUT;134}135}136137Obj TypeBlistImm (138Obj list )139{140/* special case for the empty blist */141if ( LEN_BLIST(list) == 0 ) {142return TYPE_BLIST_EMPTY_IMM;143} else {144return TYPE_BLIST_IMM;145}146}147148Obj TypeBlistNSortMut (149Obj list )150{151/* special case for the empty blist */152if ( LEN_BLIST(list) == 0 ) {153return TYPE_BLIST_EMPTY_MUT;154} else {155return TYPE_BLIST_NSORT_MUT;156}157}158159Obj TypeBlistNSortImm (160Obj list )161{162/* special case for the empty blist */163if ( LEN_BLIST(list) == 0 ) {164return TYPE_BLIST_EMPTY_IMM;165} else {166return TYPE_BLIST_NSORT_IMM;167}168}169170Obj TypeBlistSSortMut (171Obj list )172{173/* special case for the empty blist */174if ( LEN_BLIST(list) == 0 ) {175return TYPE_BLIST_EMPTY_MUT;176} else {177return TYPE_BLIST_SSORT_MUT;178}179}180181Obj TypeBlistSSortImm (182Obj list )183{184/* special case for the empty blist */185if ( LEN_BLIST(list) == 0 ) {186return TYPE_BLIST_EMPTY_IMM;187} else {188return TYPE_BLIST_SSORT_IMM;189}190}191192/****************************************************************************193**194*F SaveBlist( <blist> ) . . . . . . . . . . . . . . . . . . . . save a blist195**196** The saving method for the blist tnums197*/198void SaveBlist (199Obj bl )200{201UInt i;202UInt * ptr;203204/* logical length */205SaveSubObj(ADDR_OBJ(bl)[0]);206ptr = BLOCKS_BLIST(bl);207for (i = 1; i <= NUMBER_BLOCKS_BLIST( bl ); i++ )208SaveUInt(*ptr++);209return;210}211212/****************************************************************************213**214*F LoadBlist( <blist> ) . . . . . . . . . . . . . . . . . . . . load a blist215**216** The loading method for the blist tnums217*/218void LoadBlist (219Obj bl )220{221UInt i;222UInt * ptr;223224/* get the length back, then NUMBER_BLOCKS_BLIST is OK */225ADDR_OBJ(bl)[0] = LoadSubObj();226227/* Now load the real data */228ptr = (UInt *)BLOCKS_BLIST(bl);229for (i = 1; i <= NUMBER_BLOCKS_BLIST( bl ); i++ )230*ptr++ = LoadUInt();231return;232}233234235/****************************************************************************236**237238*F * * * * * * * * * * * * * * copy functions * * * * * * * * * * * * * * * *239*/240241/****************************************************************************242**243244245*F CopyBlist( <list>, <mut> ) . . . . . . . . . . . . . copy a boolean list246**247** 'CopyBlist' returns a structural (deep) copy of the boolean list <list>,248** i.e., a recursive copy that preserves the structure.249**250** If <list> has not yet been copied, it makes a copy, leaves a forward251** pointer to the copy in the first entry of the boolean list, where the252** size of the boolean list usually resides, and copies all the entries. If253** the boolean list has already been copied, it returns the value of the254** forwarding pointer.255**256** 'CopyBlist' is the function in 'CopyObjFuncs' for boolean lists.257**258** 'CleanBlist' removes the mark and the forwarding pointer from the boolean259** list <list>.260**261** 'CleanBlist' is the function in 'CleanObjFuncs' for boolean lists.262*/263264Obj DoCopyBlist(Obj list, Int mut) {265Obj copy;266UInt *l;267UInt *c;268/* make a copy */269if ( mut ) {270copy = NewBag( MUTABLE_TNUM(TNUM_OBJ(list)), SIZE_OBJ(list) );271}272else {273copy = NewBag( IMMUTABLE_TNUM( TNUM_OBJ(list) ), SIZE_OBJ(list) );274}275276277/* copy the subvalues */278l = (UInt*)(ADDR_OBJ(list));279c = (UInt*)(ADDR_OBJ(copy));280memcpy((void *)c, (void *)l, sizeof(UInt)*(1+NUMBER_BLOCKS_BLIST(list)));281282/* return the copy */283return copy;284285}286287Obj CopyBlist (288Obj list,289Int mut )290{291292/* don't change immutable objects */293if ( ! IS_MUTABLE_OBJ(list) ) {294return list;295}296297return DoCopyBlist(list, mut);298}299300Obj ShallowCopyBlist ( Obj list)301{302return DoCopyBlist(list, 1);303}304305306307/****************************************************************************308**309*F CopyBlistCopy( <list>, <mut> ) . . . . . . . copy a already copied blist310*/311Obj CopyBlistCopy (312Obj list,313Int mut )314{315return ADDR_OBJ(list)[0];316}317318319/****************************************************************************320**321*F CleanBlist( <list> ) . . . . . . . . . . . . . . clean up a boolean list322*/323void CleanBlist (324Obj list )325{326}327328329/****************************************************************************330**331*F CleanBlistCopy( <list> ) . . . . . . . . . . . . . clean a copied blist332*/333void CleanBlistCopy (334Obj list )335{336/* remove the forwarding pointer */337ADDR_OBJ(list)[0] = ADDR_OBJ( ADDR_OBJ(list)[0] )[0];338339/* now it is cleaned */340UNMARK_LIST( list, COPYING );341}342343344/****************************************************************************345**346347*F * * * * * * * * * * * * * * list functions * * * * * * * * * * * * * * * *348*/349350/****************************************************************************351**352353354*F EqBlist( <listL>, <listR> ) . . . . . test if two boolean lists are equal355**356** 'EqBlist' returns 'true' if the two boolean lists <listL> and <listR> are357** equal and 'false' otherwise.358*/359Int EqBlist (360Obj listL,361Obj listR )362{363long lenL; /* length of the left operand */364long lenR; /* length of the right operand */365UInt * ptrL; /* pointer to the left operand */366UInt * ptrR; /* pointer to the right operand */367UInt i; /* loop variable */368369/* get the lengths of the lists and compare them */370lenL = LEN_BLIST( listL );371lenR = LEN_BLIST( listR );372if ( lenL != lenR ) {373return 0L;374}375376/* test for equality blockwise */377ptrL = BLOCKS_BLIST(listL);378ptrR = BLOCKS_BLIST(listR);379for ( i = (lenL+BIPEB-1)/BIPEB; 0 < i; i-- ) {380if ( *ptrL++ != *ptrR++ )381return 0L;382}383384/* no differences found, the lists are equal */385return 1L;386}387388389/****************************************************************************390**391*F LenBlist( <list> ) . . . . . . . . . . . . . . length of a boolean list392**393** 'LenBlist' returns the length of the boolean list <list> as a C integer.394**395** 'LenBlist' is the function in 'LenListFuncs' for boolean lists.396*/397Int LenBlist (398Obj list )399{400return LEN_BLIST( list );401}402403404/****************************************************************************405**406*F IsbBlist( <list>, <pos> ) . . . . . test for an element of a boolean list407**408** 'IsbBlist' returns 1 if the boolean list <list> contains an element at409** the position <pos> and 0 otherwise. It is the responsibility of the410** caller to ensure that <pos> is a positive integer.411**412** 'IsbBlist' is the function in 'IsbListFuncs' for boolean lists.413*/414Int IsbBlist (415Obj list,416Int pos )417{418return (pos <= LEN_BLIST(list));419}420421422/****************************************************************************423**424*F IsbvBlist( <list>, <pos> ) . . . . test for an element of a boolean list425*/426Int IsbvBlist (427Obj list,428Int pos )429{430return 1L;431}432433434/****************************************************************************435**436437*F Elm0Blist( <list>, <pos> ) . . . . . select an element of a boolean list438**439** 'Elm0Blist' returns the element at the position <pos> of the boolean list440** <list>, or 0 if <list> has no assigned object at <pos>. It is the441** responsibility of the caller to ensure that <pos> is a positive integer.442*/443Obj Elm0Blist (444Obj list,445Int pos )446{447if ( pos <= LEN_BLIST( list ) ) {448return ELM_BLIST( list, pos );449}450else {451return 0;452}453}454455456/****************************************************************************457**458*F Elm0vBlist( <list>, <pos> ) . . . . . select an element of a boolean list459**460** 'Elm0vPlist' does the same thing than 'Elm0List', but need not check that461** <pos> is less than or equal to the length of <list>, this is the462** responsibility of the caller.463*/464Obj Elm0vBlist (465Obj list,466Int pos )467{468return ELM_BLIST( list, pos );469}470471472/****************************************************************************473**474*F ElmBlist( <list>, <pos> ) . . . . . . select an element of a boolean list475**476** 'ElmBlist' selects the element at position <pos> of the boolean list477** <list>. It is the responsibility of the caller to ensure that <pos> is a478** positive integer. An error is signalled if <pos> is larger than the479** length of <list>.480**481** 'ElmBlist' is the function in 'ElmListFuncs' for boolean lists.482** 'ElmvBlist' is the function in 'ElmvListFuncs' for boolean lists.483*/484Obj ElmBlist (485Obj list,486Int pos )487{488489/* check the position */490if ( LEN_BLIST( list ) < pos ) {491ErrorReturnVoid(492"List Element: <list>[%d] must have an assigned value",493pos, 0L,494"you can assign a value and 'return;'" );495return ELM_LIST( list, pos );496}497498/* select and return the element */499return ELM_BLIST( list, pos );500}501502/****************************************************************************503**504*F ElmvBlist( <list>, <pos> ) . . . . . select an element of a boolean list505**506** 'ElmvBlist' does the same thing than 'ElmBlist', but need not check that507** <pos> is less than or equal to the length of <list>, this is the508** responsibility of the caller.509**510*/511Obj ElmvBlist (512Obj list,513Int pos )514{515/* select and return the element */516return ELM_BLIST( list, pos );517}518519520/****************************************************************************521**522*F ElmsBlist( <list>, <poss> ) . . . . select a sublist from a boolean list523**524** 'ElmsBlist' returns a new list containing the elements at the positions525** given in the list <poss> from the boolean list <list>. It is the526** responsibility of the caller to ensure that <poss> is dense and contains527** only positive integers. An error is signalled if an element of <poss> is528** larger than the length of <list>.529**530** 'ElmsBlist' is the function in 'ElmsListFuncs' for boolean lists.531*/532Obj ElmsBlist (533Obj list,534Obj poss )535{536Obj elms; /* selected sublist, result */537Int lenList; /* length of <list> */538Obj elm; /* one element from <list> */539Int lenPoss; /* length of <positions> */540Int pos; /* <position> as integer */541Int inc; /* increment in a range */542UInt block; /* one block of <elms> */543UInt bit; /* one bit of a block */544UInt i; /* loop variable */545546/* general code */547if ( ! IS_RANGE(poss) ) {548549/* get the length of <list> */550lenList = LEN_BLIST( list );551552/* get the length of <positions> */553lenPoss = LEN_LIST( poss );554555/* make the result list */556elms = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenPoss ) );557SET_LEN_BLIST( elms, lenPoss );558559/* loop over the entries of <positions> and select */560block = 0; bit = 1;561for ( i = 1; i <= lenPoss; i++ ) {562563/* get <position> */564pos = INT_INTOBJ( ELMW_LIST( poss, (Int)i ) );565if ( lenList < pos ) {566ErrorReturnVoid(567"List Elements: <list>[%d] must have an assigned value",568pos, 0L,569"you can assign a value and 'return;'" );570return ELMS_LIST( list, poss );571}572573/* select the element */574elm = ELM_BLIST( list, pos );575576/* assign the element into <elms> */577if ( elm == True )578block |= bit;579bit <<= 1;580if ( bit == 0 || i == lenPoss ) {581BLOCK_ELM_BLIST( elms, i) = block;582block = 0;583bit = 1;584}585586}587588}589590/* special code for ranges */591/*N 1992/12/15 martin special code for ranges with increment 1 */592else {593594/* get the length of <list> */595lenList = LEN_PLIST( list );596597/* get the length of <positions>, the first elements, and the inc. */598lenPoss = GET_LEN_RANGE( poss );599pos = GET_LOW_RANGE( poss );600inc = GET_INC_RANGE( poss );601602/* check that no <position> is larger than 'LEN_LIST(<list>)' */603if ( lenList < pos ) {604ErrorReturnVoid(605"List Elements: <list>[%d] must have an assigned value",606pos, 0L,607"you can assign a value and 'return;'" );608return ELMS_LIST( list, poss );609}610if ( lenList < pos + (lenPoss-1) * inc ) {611ErrorReturnVoid(612"List Elements: <list>[%d] must have an assigned value",613pos+(lenPoss-1)*inc, 0L,614"you can assign a value and 'return;'" );615return ELMS_LIST( list, poss );616}617618/* make the result list */619elms = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenPoss ) );620SET_LEN_BLIST( elms, lenPoss );621622/* loop over the entries of <positions> and select */623block = 0; bit = 1;624for ( i = 1; i <= lenPoss; i++, pos += inc ) {625626/* select the element */627elm = ELM_BLIST( list, pos );628629/* assign the element to <elms> */630if ( elm == True )631block |= bit;632bit <<= 1;633if ( bit == 0 || i == lenPoss ) {634BLOCK_ELM_BLIST(elms, i) = block;635block = 0;636bit = 1;637}638639}640641}642643/* return the result */644return elms;645}646647648/****************************************************************************649**650651*F AssBlist( <list>, <pos>, <val> ) . . . . . . . assign to a boolean list652**653** 'AssBlist' assigns the value <val> to the boolean list <list> at the654** position <pos>. It is the responsibility of the caller to ensure that655** <pos> is positive, and that <val> is not 0.656**657** 'AssBlist' is the function in 'AssListFuncs' for boolean lists.658**659** If <pos> is less than or equal to the logical length of the boolean list660** and <val> is 'true' or 'false' the assignment is done by setting the661** corresponding bit. If <pos> is one more than the logical length of the662** boolean list the assignment is done by resizing the boolean list if663** necessary, setting the corresponding bit and incrementing the logical664** length by one. Otherwise the boolean list is converted to an ordinary665** list and the assignment is performed the ordinary way.666*/667void AssBlist (668Obj list,669Int pos,670Obj val )671{672/* if <pos> is less than the logical length and <elm> is 'true' */673if ( pos <= LEN_BLIST(list) && val == True ) {674SET_ELM_BLIST( list, pos, True );675CLEAR_FILTS_LIST(list);676}677678/* if <i> is less than the logical length and <elm> is 'false' */679else if ( pos <= LEN_BLIST(list) && val == False ) {680SET_ELM_BLIST( list, pos, False );681CLEAR_FILTS_LIST(list);682}683684/* if <i> is one more than the logical length and <elm> is 'true' */685else if ( pos == LEN_BLIST(list)+1 && val == True ) {686if ( SIZE_OBJ(list) < SIZE_PLEN_BLIST(pos) )687ResizeBag( list, SIZE_PLEN_BLIST(pos) );688SET_LEN_BLIST( list, pos );689SET_ELM_BLIST( list, pos, True );690CLEAR_FILTS_LIST(list);691}692693/* if <i> is one more than the logical length and <elm> is 'false' */694else if ( pos == LEN_BLIST(list)+1 && val == False ) {695if ( SIZE_OBJ(list) < SIZE_PLEN_BLIST(pos) )696ResizeBag( list, SIZE_PLEN_BLIST(pos) );697SET_LEN_BLIST( list, pos );698SET_ELM_BLIST( list, pos, False );699CLEAR_FILTS_LIST(list);700}701702/* otherwise convert to ordinary list and assign as in 'AssList' */703else {704PLAIN_LIST(list);705CLEAR_FILTS_LIST(list);706if ( LEN_PLIST(list) < pos ) {707GROW_PLIST( list, (UInt)pos );708SET_LEN_PLIST( list, pos );709}710SET_ELM_PLIST( list, pos, val );711CHANGED_BAG( list );712}713}714715716/****************************************************************************717**718*F AssBlistImm( <list>, <pos>, <val> ) . assign to an immutable boolean list719*/720void AssBlistImm (721Obj list,722Int pos,723Obj val )724{725ErrorReturnVoid(726"Lists Assignment: <list> must be a mutable list",7270L, 0L,728"you can 'return;' and ignore the assignment" );729}730731732/****************************************************************************733**734*F AsssBlist( <list>, <poss>, <vals> ) . assign several elements to a blist735**736** 'AsssBlist' assignes the values from the list <vals> at the positions737** given in the list <poss> to the boolean list <list>. It is the738** responsibility of the caller to ensure that <poss> is dense and contains739** only positive integers, that <poss> and <vals> have the same length, and740** that <vals> is dense.741**742** 'AsssBlist' is intended as function in 'AsssListFuncs' for boolean lists.743** Note that currently, we use AsssListDefault instead. This ensures744** automatically that <list> remains a blist if possible.745**746*/747void AsssBlist ( /* currently not used */748Obj list,749Obj poss,750Obj vals )751{752Int i, len, pos;753Obj val;754755len = LEN_LIST(poss);756for (i=1; i <= len; i++) {757/* use generic macros because list might be unpacked */758pos = INT_INTOBJ(ELMW_LIST(poss, i));759val = ELMW_LIST(vals, i);760ASS_LIST( list, pos, val);761}762}763764765/****************************************************************************766**767*F AsssBlistImm( <list>, <poss>, <vals> ) . . assign to an immutable blist768*/769void AsssBlistImm (770Obj list,771Obj poss,772Obj val )773{774ErrorReturnVoid(775"Lists Assignments: <list> must be a mutable list",7760L, 0L,777"you can 'return;' and ignore the assignment" );778}779780781/****************************************************************************782**783784*F PosBlist( <list>, <val>, <start> ) position of an elm in a boolean list785**786** 'PosBlist' returns the position of the first occurrence of the value787** <val>, which may be an object of arbitrary type, in the boolean list788** <list> after <start> as a C integer. If <val> does not occur in <list>789** after <start>, then 0 is returned.790**791** 'PosBlist' is the function in 'PosListFuncs' for boolean lists.792*/793Obj PosBlist (794Obj list,795Obj val,796Obj start )797{798Int len; /* logical length of the list */799UInt * ptr; /* pointer to the blocks */800UInt i, j; /* loop variables */801UInt istart;802UInt firstblock, lastblock;803UInt firstoffset, lastoffset;804UInt x;805806if (!IS_INTOBJ(start))807return Fail;808809istart = INT_INTOBJ(start);810811len = LEN_BLIST(list);812813/* look just beyond end */814if ( len == istart ) {815return Fail;816}817818ptr = BLOCKS_BLIST(list);819firstblock = istart/BIPEB;820lastblock = (len-1)/BIPEB;821firstoffset = istart%BIPEB;822lastoffset = (len-1)%BIPEB;823824/* look for 'true' */825if ( val == True ) {826827x = ptr[firstblock];828if (firstblock == lastblock)829{830if (x != 0)831for (j = firstoffset; j <= lastoffset; j++)832if ((x & (1UL << j)) != 0)833return INTOBJ_INT(BIPEB*firstblock + j + 1);834return Fail;835}836if (x != 0)837for (j = firstoffset; j < BIPEB; j++)838if ((x & (1UL << j)) != 0)839return INTOBJ_INT(BIPEB*firstblock + j + 1);840for (i = firstblock + 1; i < lastblock; i++)841{842x = ptr[i];843if (x != 0)844for (j = 0; j < BIPEB; j++)845if ((x & (1UL << j)) != 0)846return INTOBJ_INT(BIPEB*i + j + 1);847}848x = ptr[lastblock];849if (x != 0)850for (j = 0; j <= lastoffset; j++)851if ((x & (1UL << j)) != 0)852return INTOBJ_INT(BIPEB*lastblock + j + 1);853return Fail;854}855856/* look for 'false' */857else if ( val == False ) {858x = ptr[firstblock];859if (firstblock == lastblock)860{861if (x != ~0UL)862for (j = firstoffset; j <= lastoffset; j++)863if ((x & (1UL << j)) == 0)864return INTOBJ_INT(BIPEB*firstblock + j + 1);865return Fail;866}867if (x != ~0UL)868for (j = firstoffset; j < BIPEB; j++)869if ((x & (1UL << j)) == 0)870return INTOBJ_INT(BIPEB*firstblock + j + 1);871for (i = firstblock + 1; i < lastblock; i++)872{873x = ptr[i];874if (x != ~0UL)875for (j = 0; j < BIPEB; j++)876if ((x & (1UL << j)) == 0)877return INTOBJ_INT(BIPEB*i + j + 1);878}879x = ptr[lastblock];880if (x != ~0UL)881for (j = 0; j <= lastoffset; j++)882if ((x & (1UL << j)) == 0)883return INTOBJ_INT(BIPEB*lastblock + j + 1);884return Fail;885}886887/* look for something else */888else {889return Fail;890}891892}893894895/****************************************************************************896**897*F PlainBlist( <list> ) . . . convert a boolean list into an ordinary list898**899** 'PlainBlist' converts the boolean list <list> to a plain list.900**901** 'PlainBlist' is the function in 'PlainListFuncs' for boolean lists.902*/903void PlainBlist (904Obj list )905{906Int len; /* length of <list> */907UInt i; /* loop variable */908909/* resize the list and retype it, in this order */910len = LEN_BLIST(list);911RetypeBag( list, IS_MUTABLE_OBJ(list) ? T_PLIST : T_PLIST+IMMUTABLE );912GROW_PLIST( list, (UInt)len );913SET_LEN_PLIST( list, len );914915/* replace the bits by 'True' or 'False' as the case may be */916/* this must of course be done from the end of the list backwards */917for ( i = len; 0 < i; i-- )918SET_ELM_PLIST( list, i, ELM_BLIST( list, i ) );919920/* 'CHANGED_BAG' not needed, 'True' and 'False' are safe */921}922923924925/****************************************************************************926**927*F IsPossBlist( <list> ) . . positions list test function for boolean lists928**929** 'IsPossBlist' returns 1 if <list> is empty, and 0 otherwise, since a930** boolean list is a positions list if and only if it is empty.931*/932Int IsPossBlist (933Obj list )934{935return LEN_BLIST(list) == 0;936}937938939/****************************************************************************940**941942*F IsDenseBlist( <list> ) . . . dense list test function for boolean lists943**944** 'IsDenseBlist' returns 1, since boolean lists are always dense.945**946** 'IsDenseBlist' is the function in 'IsDenseBlistFuncs' for boolean lists.947*/948Int IsDenseBlist (949Obj list )950{951return 1L;952}953954955/****************************************************************************956**957*F IsHomogBlist( <list> ) . . . . . . . . . . check if <list> is homogenous958*/959Int IsHomogBlist (960Obj list )961{962return (0 < LEN_BLIST(list));963}964965966/****************************************************************************967**968*F IsSSortBlist( <list> ) . . . . . . . check if <list> is strictly sorted969*/970Int IsSSortBlist (971Obj list )972{973Int isSort;974975if ( LEN_BLIST(list) <= 1 ) {976isSort = 1;977}978else if ( LEN_BLIST(list) == 2 ) {979isSort = (ELM_BLIST(list,1) == True && ELM_BLIST(list,2) == False);980}981else {982isSort = 0;983}984SET_FILT_LIST( list, (isSort ? FN_IS_SSORT : FN_IS_NSORT) );985986return isSort;987}988989990/****************************************************************************991**992*F IsSSortBlistNot( <list> ) . . . . . . . . . . . . . unsorted boolean list993*/994Int IsSSortBlistNot (995Obj list )996{997return 0L;998}99910001001/****************************************************************************1002**1003*F IsSSortBlistYes( <list> ) . . . . . . . . . . . . . . sorted boolean list1004*/1005Int IsSSortBlistYes (1006Obj list )1007{1008return 1L;1009}101010111012/****************************************************************************1013**10141015*F ConvBlist( <list> ) . . . . . . . . . convert a list into a boolean list1016**1017** `ConvBlist' changes the representation of boolean lists into the compact1018** representation of type 'T_BLIST' described above.1019*/1020void ConvBlist (1021Obj list )1022{1023Int len; /* logical length of the list */1024UInt block; /* one block of the boolean list */1025UInt bit; /* one bit of a block */1026UInt i; /* loop variable */10271028/* if <list> is known to be a boolean list, it is very easy */1029if ( IS_BLIST_REP(list) ) {1030return;1031}10321033/* change its representation */1034block = 0;1035bit = 1;1036len = LEN_LIST( list );1037for ( i = 1; i <= len; i++ ) {1038if ( ELMW_LIST( list, (Int)i ) == True )1039block |= bit;1040bit = bit << 1;1041if ( bit == 0 || i == len ) {1042BLOCK_ELM_BLIST(list,i) = block;1043block = 0;1044bit = 1;1045}1046}1047RetypeBag( list, IS_MUTABLE_OBJ(list) ? T_BLIST : T_BLIST+IMMUTABLE );1048ResizeBag( list, SIZE_PLEN_BLIST(len) );1049SET_LEN_BLIST( list, len );1050}105110521053/****************************************************************************1054**1055*F IsBlist( <list> ) . . . . . . . . . test whether a list is a boolean list1056**1057** 'IsBlist' returns 1 if the list <list> is a boolean list, i.e., a1058** list that has no holes and contains only 'true' and 'false', and 01059** otherwise.1060*/1061Int IsBlist (1062Obj list )1063{1064UInt isBlist; /* result of the test */1065Int len; /* logical length of the list */1066UInt i; /* loop variable */10671068/* if <list> is known to be a boolean list, it is very easy */1069if ( IS_BLIST_REP(list) ) {1070isBlist = 1;1071}10721073/* if <list> is not a small list, its not a boolean list (convert to list) */1074else if ( ! IS_SMALL_LIST( list ) ) {1075isBlist = 0;1076}10771078/* otherwise test if there are holes and if all elements are boolean */1079else {10801081/* test that all elements are bound and either 'true' or 'false' */1082len = LEN_LIST( list );1083for ( i = 1; i <= len; i++ ) {1084if ( ELMV0_LIST( list, (Int)i ) == 01085|| (ELMW_LIST( list, (Int)i ) != True1086&& ELMW_LIST( list, (Int)i ) != False) ) {1087break;1088}1089}10901091isBlist = (len < i);1092}10931094/* return the result */1095return isBlist;1096}109710981099/****************************************************************************1100**1101*F IsBlistConv( <list> ) . test whether a list is a boolean list and convert1102**1103** 'IsBlistConv' returns 1 if the list <list> is a boolean list, i.e., a1104** list that has no holes and contains only 'true' and 'false', and 01105** otherwise. As a side effect 'IsBlistConv' changes the representation of1106** boolean lists into the compact representation of type 'T_BLIST' described1107** above.1108*/1109Int IsBlistConv (1110Obj list )1111{1112UInt isBlist; /* result of the test */1113Int len; /* logical length of the list */1114UInt i; /* loop variable */11151116/* if <list> is known to be a boolean list, it is very easy */1117if ( IS_BLIST_REP(list) ) {1118isBlist = 1;1119}11201121/* if <list> is not a list, its not a boolean list (convert to list) */1122else if ( ! IS_SMALL_LIST(list) ) {1123isBlist = 0;1124}11251126/* otherwise test if there are holes and if all elements are boolean */1127else {11281129/* test that all elements are bound and either 'true' or 'false' */1130len = LEN_LIST( list );1131for ( i = 1; i <= len; i++ ) {1132if ( ELMV0_LIST( list, (Int)i ) == 01133|| (ELMW_LIST( list, (Int)i ) != True1134&& ELMW_LIST( list, (Int)i ) != False) ) {1135break;1136}1137}11381139/* if <list> is a boolean list, change its representation */1140isBlist = (len < i);1141if ( isBlist ) {1142ConvBlist(list);1143}1144}11451146/* return the result */1147return isBlist;1148}114911501151/****************************************************************************1152**1153*F SizeBlist( <blist> ) . . . . number of 'true' entries in a boolean list1154**1155** 'SizeBlist' returns the number of entries of the boolean list <blist>1156** that are 'true'.1157**1158** The sequence to compute the number of bits in a block is quite clever.1159** The idea is that after the <i>-th instruction each subblock of $2^i$ bits1160** holds the number of bits of this subblock in the original block <m>.1161** This is illustrated in the example below for a block of with 8 bits:1162**1163** // a b c d e f g h1164** m = (m & 0x55) + ((m >> 1) & 0x55);1165** // . b . d . f . h + . a . c . e . g = a+b c+d e+f g+h1166** m = (m & 0x33) + ((m >> 2) & 0x33);1167** // . . c+d . . g+h + . . a+b . . e+f = a+b+c+d e+f+g+h1168** m = (m & 0x0f) + ((m >> 4) & 0x0f);1169** // . . . . e+f+g+h + . . . . a+b+c+d = a+b+c+d+e+f+g+h1170**1171** In the actual code some unnecessary mask have been removed, improving1172** performance quite a bit, because masks are 32 bit immediate values for1173** which most RISC processors need two instructions to load them. Talking1174** about performance. The code is close to optimal, it should compile to1175** only about 22 MIPS or SPARC instructions. Dividing the block into 41176** bytes and looking up the number of bits of a byte in a table may be 10%1177** faster, but only if the table lives in the data cache.1178**1179*N 1992/12/15 martin this depends on 'BIPEB' being 321180*N 1996/11/12 Steve altered to handle 64 bit also1181**1182** Introduced the SizeBlist function for kernel use, and the1183** COUNT_TRUES_BLOCK( <var> ) macro which replaces a block of bits in <var>1184** by the number of ones it contains. It will fail horribly if <var> is not1185** a variable.1186*/1187UInt SizeBlist (1188Obj blist )1189{1190UInt * ptr; /* pointer to blist */1191UInt nrb; /* number of blocks in blist */1192UInt m; /* number of bits in a block */1193UInt n; /* number of bits in blist */1194UInt i; /* loop variable */11951196/* get the number of blocks and a pointer */1197nrb = NUMBER_BLOCKS_BLIST(blist);1198ptr = BLOCKS_BLIST( blist );11991200/* loop over the blocks, adding the number of bits of each one */1201n = 0;1202for ( i = 1; i <= nrb; i++ ) {1203m = *ptr++;1204COUNT_TRUES_BLOCK(m);1205n += m;1206}12071208/* return the number of bits */1209return n;1210}121112121213/****************************************************************************1214**12151216*F * * * * * * * * * * * * * * GAP level functions * * * * * * * * * * * * *1217*/12181219/****************************************************************************1220**122112221223*F FuncIS_BLIST( <self>, <val> ) . . . . . test if a value is a boolean list1224**1225** 'FuncIS_BLIST' handles the internal function 'IsBlist'.1226**1227** 'IsBlist( <val> )'1228**1229** 'IsBlist' returns 'true' if the value <val> is a boolean list and 'false'1230** otherwise. A value is a boolean list if it is a lists without holes1231** containing only 'true' and 'false'.1232*/1233Obj IsBlistFilt;12341235Obj FuncIS_BLIST (1236Obj self,1237Obj val )1238{1239/* let 'IsBlist' do the work */1240return IsBlist( val ) ? True : False;1241}124212431244/****************************************************************************1245**1246*F FuncIS_BLIST_CONV( <self>, <val> ) . . test if a value is a boolean list1247**1248** 'FuncIS_BLIST_CONV' handles the internal function 'IsBlist'.1249**1250** 'IsBlistConv( <val> )'1251**1252** 'IsBlist' returns 'true' if the value <val> is a boolean list and 'false'1253** otherwise. A value is a boolean list if it is a lists without holes1254** containing only 'true' and 'false'.1255*/1256Obj IsBlistFilt;12571258Obj FuncIS_BLIST_CONV (1259Obj self,1260Obj val )1261{1262/* let 'IsBlist' do the work */1263return IsBlistConv( val ) ? True : False;1264}126512661267/****************************************************************************1268**1269*F FuncCONV_BLIST( <self>, <blist> ) . . . . convert into a boolean list rep1270*/1271Obj FuncCONV_BLIST (1272Obj self,1273Obj blist )1274{1275/* check whether <blist> is a boolean list */1276while ( ! IsBlistConv(blist) ) {1277blist = ErrorReturnObj(1278"CONV_BLIST: <blist> must be a boolean list (not a %s)",1279(Int)TNAM_OBJ(blist), 0L,1280"you can replace <blist> via 'return <blist>;'" );1281}12821283/* return nothing */1284return 0;1285}12861287/****************************************************************************1288**1289**1290*F FuncIS_BLIST_REP( <self>, <obj> ) . . test if value is a boolean list rep1291*/1292Obj IsBlistRepFilt;12931294Obj FuncIS_BLIST_REP (1295Obj self,1296Obj obj )1297{1298return (IS_BLIST_REP( obj ) ? True : False);1299}130013011302/****************************************************************************1303**13041305*F FuncSIZE_BLIST( <self>, <blist> ) . . number of 'true' entries in <blist>1306**1307** 'FuncSIZE_BLIST' implements the internal function 'SizeBlist'1308*/1309Obj FuncSIZE_BLIST (1310Obj self,1311Obj blist )1312{1313/* get and check the argument */1314while ( ! IsBlistConv(blist) ) {1315blist = ErrorReturnObj(1316"SizeBlist: <blist> must be a boolean list (not a %s)",1317(Int)TNAM_OBJ(blist), 0L,1318"you can replace <blist> via 'return <blist>;'" );1319}13201321return INTOBJ_INT(SizeBlist(blist));1322}1323132413251326/****************************************************************************1327**1328*F FuncBLIST_LIST( <self>, <list>, <sub> ) make boolean list from a sublist1329**1330** 'FuncBLIST_LIST' implements the internal function 'BlistList'.1331**1332** 'BlistList( <list>, <sub> )'1333**1334** 'BlistList' creates a boolean list that describes the list <sub> as1335** sublist of the list <list>. The result is a new boolean list <blist>,1336** which has the same length as <list>, such that '<blist>[<i>]' is 'true'1337** if '<list>[<i>]' is an element of <sub> and 'false' otherwise.1338**1339** 'BlistList' is most effective if <list> is a set, but can be used with an1340** arbitrary list that has no holes.1341*/1342Obj FuncBLIST_LIST (1343Obj self,1344Obj list,1345Obj sub )1346{1347Obj blist; /* boolean list, result */1348UInt * ptrBlist; /* pointer to the boolean list */1349UInt block; /* one block of boolean list */1350UInt bit; /* one bit of block */1351Int lenList; /* logical length of the list */1352Obj * ptrSub; /* pointer to the sublist */1353UInt lenSub; /* logical length of sublist */1354UInt i, j, k = 0, l; /* loop variables */1355long s, t; /* elements of a range */13561357/* get and check the arguments */1358while ( ! IS_SMALL_LIST(list) ) {1359list = ErrorReturnObj(1360"BlistList: <list> must be a small list (not a %s)",1361(Int)TNAM_OBJ(list), 0L,1362"you can replace <list> via 'return <list>;'" );1363}1364while ( ! IS_SMALL_LIST(sub) ) {1365sub = ErrorReturnObj(1366"BlistList: <sub> must be a small list (not a %s)",1367(Int)TNAM_OBJ(sub), 0L,1368"you can replace <sub> via 'return <sub>;'" );1369}13701371/* for a range as subset of a range, it is extremely easy */1372if ( IS_RANGE(list) && IS_RANGE(sub) && GET_INC_RANGE( list ) == 11373&& GET_INC_RANGE( sub ) == 1) {13741375/* allocate the boolean list and get pointer */1376lenList = GET_LEN_RANGE( list );1377lenSub = GET_LEN_RANGE( sub );1378blist = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenList ) );1379ADDR_OBJ(blist)[0] = INTOBJ_INT(lenList);1380ptrBlist = BLOCKS_BLIST(blist);13811382/* get the bounds of the subset with respect to the boolean list */1383s = INT_INTOBJ( GET_ELM_RANGE( list, 1 ) );1384t = INT_INTOBJ( GET_ELM_RANGE( sub, 1 ) );1385if ( s <= t ) i = t - s + 1;1386else i = 1;13871388if ( i + lenSub - 1 <= lenList ) j = i + lenSub - 1;1389else j = lenList;13901391/* set the corresponding entries to 'true' */1392for ( k = i; k <= j && (k-1)%BIPEB != 0; k++ )1393ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);1394for ( ; k+BIPEB <= j; k += BIPEB )1395ptrBlist[(k-1)/BIPEB] = ~(UInt)0;1396for ( ; k <= j; k++ )1397ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);13981399}14001401/* for a list as subset of a range, we need basically no search */1402else if ( IS_RANGE(list) && GET_INC_RANGE( list) == 11403&& IS_PLIST(sub) ) {14041405/* allocate the boolean list and get pointer */1406lenList = GET_LEN_RANGE( list );1407lenSub = LEN_LIST( sub );1408blist = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenList ) );1409ADDR_OBJ(blist)[0] = INTOBJ_INT(lenList);1410ptrBlist = BLOCKS_BLIST(blist);1411ptrSub = ADDR_OBJ(sub);14121413/* loop over <sub> and set the corresponding entries to 'true' */1414s = INT_INTOBJ( GET_ELM_RANGE( list, 1 ) );1415for ( l = 1; l <= LEN_LIST(sub); l++ ) {1416if ( ptrSub[l] != 0 ) {14171418/* if <sub>[<l>] is an integer it is very easy */1419if ( TNUM_OBJ( ptrSub[l] ) == T_INT ) {1420t = INT_INTOBJ( ptrSub[l] ) - s + 1;1421if ( 0 < t && t <= lenList )1422ptrBlist[(t-1)/BIPEB] |= (1UL << (t-1)%BIPEB);1423}14241425/* Nobody seems to remember what the code below is good for,1426* we will now just assume that non-immediate integers are1427* never in a range. I'll leave the old code in a comment1428* for a while, the third arg for PosRange is wrong anyway.1429* FL */1430/* otherwise it may be a record, let 'PosRange' handle it */1431/* else {1432Obj pos;1433pos = PosRange( list, ptrSub[l], 0L );1434if (pos != Fail) {1435k = INT_INTOBJ(pos);1436ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);1437}1438} */14391440}1441}14421443}14441445/* if <list> is a set we have two possibilities */1446else if ( IsSet( list ) ) {14471448/* get the length of <list> and its logarithm */1449lenList = LEN_PLIST( list );1450for ( i = lenList, l = 0; i != 0; i >>= 1, l++ ) ;1451PLAIN_LIST( sub );1452lenSub = LEN_LIST( sub );14531454/* if <sub> is small, we loop over <sub> and use binary search */1455if ( l * lenSub < 2 * lenList ) {14561457/* allocate the boolean list and get pointer */1458blist = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenList ) );1459ADDR_OBJ(blist)[0] = INTOBJ_INT(lenList);14601461/* run over the elements of <sub> and search for the elements */1462for ( l = 1; l <= LEN_LIST(sub); l++ ) {1463if ( ADDR_OBJ(sub)[l] != 0 ) {14641465/* perform the binary search to find the position */1466i = 0; k = lenList+1;1467while ( i+1 < k ) {1468j = (i + k) / 2;1469if ( LT(ADDR_OBJ(list)[j],ADDR_OBJ(sub)[l]) )1470i = j;1471else1472k = j;1473}14741475/* set bit if <sub>[<l>] was found at position k */1476if ( k <= lenList1477&& EQ( ADDR_OBJ(list)[k], ADDR_OBJ(sub)[l] ) )1478SET_ELM_BLIST( blist, k, True);1479}1480}14811482}14831484/* if <sub> is large, run over both list in parallel */1485else {14861487/* turn the <sub> into a set for faster searching */1488if ( ! IsSet( sub ) ) {1489sub = SetList( sub );1490lenSub = LEN_LIST( sub );1491}14921493/* allocate the boolean list and get pointer */1494blist = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenList ) );1495ADDR_OBJ(blist)[0] = INTOBJ_INT(lenList);14961497/* run over the elements of <list> */1498k = 1;1499block = 0;1500bit = 1;1501for ( l = 1; l <= lenList; l++ ) {15021503/* test if <list>[<l>] is in <sub> */1504while ( k <= lenSub1505&& LT(ADDR_OBJ(sub)[k],ADDR_OBJ(list)[l]) )1506k++;15071508/* if <list>[<k>] is in <sub> set the current bit in block */1509if ( k <= lenSub1510&& EQ(ADDR_OBJ(sub)[k],ADDR_OBJ(list)[l]) ) {1511block |= bit;1512k++;1513}15141515/* if block is full add it to boolean list and start next */1516bit = bit << 1;1517if ( bit == 0 || l == lenList ) {1518BLOCK_ELM_BLIST( blist, l) = block;1519block = 0;1520bit = 1;1521}15221523}1524}15251526}15271528/* if <list> is not a set, we have to use brute force */1529else {15301531/* convert left argument to an ordinary list, ignore return value */1532PLAIN_LIST( list );15331534/* turn <sub> into a set for faster searching */1535if ( ! IsSet( sub ) ) sub = SetList( sub );15361537/* allocate the boolean list and get pointer */1538lenList = LEN_LIST( list );1539lenSub = LEN_PLIST( sub );1540blist = NewBag( T_BLIST, SIZE_PLEN_BLIST( lenList ) );1541ADDR_OBJ(blist)[0] = INTOBJ_INT(lenList);15421543/* run over the elements of <list> */1544k = 1;1545block = 0;1546bit = 1;1547for ( l = 1; l <= lenList; l++ ) {15481549/* test if <list>[<l>] is in <sub> */1550if ( l == 1 || LT(ADDR_OBJ(list)[l-1],ADDR_OBJ(list)[l]) ){1551while ( k <= lenSub1552&& LT(ADDR_OBJ(sub)[k],ADDR_OBJ(list)[l]) )1553k++;1554}1555else {1556i = 0; k = LEN_PLIST(sub) + 1;1557while ( i+1 < k ) {1558j = (i + k) / 2;1559if ( LT( ADDR_OBJ(sub)[j], ADDR_OBJ(list)[l] ) )1560i = j;1561else1562k = j;1563}1564}15651566/* if <list>[<k>] is in <sub> set the current bit in the block */1567if ( k <= lenSub1568&& EQ( ADDR_OBJ(sub)[k], ADDR_OBJ(list)[l] ) ) {1569block |= bit;1570k++;1571}15721573/* if block is full add it to the boolean list and start next */1574bit = bit << 1;1575if ( bit == 0 || l == lenList ) {1576BLOCK_ELM_BLIST( blist, l) = block;1577block = 0;1578bit = 1;1579}1580}15811582}15831584/* return the boolean list */1585return blist;1586}1587158815891590/****************************************************************************1591**1592*F FuncLIST_BLIST( <self>, <list>, <blist> ) . make a sublist from a <blist>1593**1594** 'FuncListBlist' implements the internal function 'ListBlist'.1595**1596** 'ListBlist( <list>, <blist> )'1597**1598** 'ListBlist' returns the sublist of the elements of the list <list> for1599** which the boolean list <blist>, which must have the same length as1600** <list>, contains 'true'. The order of the elements in the result is the1601** same as in <list>.1602**1603*/1604Obj FuncLIST_BLIST (1605Obj self,1606Obj list,1607Obj blist )1608{1609Obj sub; /* handle of the result */1610Int len; /* logical length of the list */1611UInt n; /* number of bits in blist */1612UInt nn;1613UInt i; /* loop variable */16141615/* get and check the first argument */1616while ( ! IS_SMALL_LIST( list ) ) {1617list = ErrorReturnObj(1618"ListBlist: <list> must be a small list (not a %s)",1619(Int)TNAM_OBJ(list), 0L,1620"you can replace <list> via 'return <list>;'" );1621}1622/* get and check the second argument */1623while ( ! IsBlistConv( blist ) ) {1624blist = ErrorReturnObj(1625"ListBlist: <blist> must be a boolean list (not a %s)",1626(Int)TNAM_OBJ(blist), 0L,1627"you can replace <blist> via 'return <blist>;'" );1628}1629while ( LEN_LIST( list ) != LEN_BLIST( blist ) ) {1630blist = ErrorReturnObj(1631"ListBlist: <blist> must have the same length as <list> (%d)",1632LEN_PLIST( list ), 0L,1633"you can replace <blist> via 'return <blist>;'" );1634}16351636/* compute the number of 'true'-s */1637n = SizeBlist(blist);16381639/* make the sublist (we now know its size exactly) */1640sub = NEW_PLIST( IS_MUTABLE_OBJ(list) ? T_PLIST : T_PLIST+IMMUTABLE, n );1641SET_LEN_PLIST( sub, n );16421643/* loop over the boolean list and stuff elements into <sub> */1644len = LEN_LIST( list );1645nn = 1;1646for ( i = 1; nn <= n && i <= len; i++ ) {1647if ( ELM_BLIST( blist, i ) == True ) {1648SET_ELM_PLIST( sub, (Int)nn, ELMW_LIST( list, (Int)i ) );1649CHANGED_BAG( sub );1650nn++;1651}1652}16531654/* return the sublist */1655return sub;1656}165716581659/****************************************************************************1660**16611662*F FuncPositionsTrueBlist( <self>, <blist> ) . . . true positions in a blist1663**1664*N 1992/12/15 martin this depends on 'BIPEB' being 321665*N Fix up for 64 bit SL1666*/1667Obj FuncPositionsTrueBlist (1668Obj self,1669Obj blist )1670{1671Obj sub; /* handle of the result */1672Int len; /* logical length of the list */1673UInt * ptr; /* pointer to blist */1674UInt nrb; /* number of blocks in blist */1675UInt m; /* number of bits in a block */1676UInt n; /* number of bits in blist */1677UInt nn;1678UInt i; /* loop variable */16791680/* get and check the first argument */1681while ( ! IsBlistConv( blist ) ) {1682blist = ErrorReturnObj(1683"ListBlist: <blist> must be a boolean list (not a %s)",1684(Int)TNAM_OBJ(blist), 0L,1685"you can replace <blist> via 'return <blist>;'" );1686}16871688/* compute the number of 'true'-s just as in 'FuncSIZE_BLIST' */1689nrb = NUMBER_BLOCKS_BLIST( blist);1690ptr = BLOCKS_BLIST( blist );1691n = 0;1692for ( i = 1; i <= nrb; i++ ) {1693m = *ptr++;1694COUNT_TRUES_BLOCK(m);1695n += m;1696}16971698/* make the sublist (we now know its size exactly) */1699sub = NEW_PLIST( T_PLIST, n );1700SET_LEN_PLIST( sub, n );17011702/* loop over the boolean list and stuff elements into <sub> */1703/* This could be a bit quicker for sparse blists by skipping whole empty1704blocks as we go past SL 9/1/97 */1705len = LEN_BLIST( blist );1706nn = 1;1707for ( i = 1; nn <= n && i <= len; i++ ) {1708if ( ELM_BLIST( blist, i ) == True ) {1709SET_ELM_PLIST( sub, nn, INTOBJ_INT(i) );1710nn++;1711}1712}1713CHANGED_BAG(sub);17141715/* return the sublist */1716return sub;1717}171817191720/****************************************************************************1721**1722*F FuncPositionNthTrueBlist( <self>, <blist>, <Nth> ) . . . find true value1723**1724*N 1992/12/15 martin this depends on 'BIPEB' being 321725*N Fixed up for 64 SL1726*/1727Obj FuncPositionNthTrueBlist (17281729Obj self,1730Obj blist,1731Obj Nth )1732{1733UInt nrb;1734Int nth, pos, i;1735UInt m, mask;1736UInt * ptr;17371738/* Check the arguments. */1739while ( ! IsBlistConv( blist ) ) {1740blist = ErrorReturnObj(1741"ListBlist: <blist> must be a boolean list (not a %s)",1742(Int)TNAM_OBJ(blist), 0L,1743"you can replace <blist> via 'return <blist>;'" );1744}1745while ( ! IS_INTOBJ(Nth) || INT_INTOBJ(Nth) <= 0 ) {1746Nth = ErrorReturnObj(1747"Position: <nth> must be a positive integer (not a %s)",1748(Int)TNAM_OBJ(Nth), 0L,1749"you can replace <nth> via 'return <nth>;'" );1750}17511752nrb = NUMBER_BLOCKS_BLIST(blist);1753if ( ! nrb ) return Fail;1754nth = INT_INTOBJ( Nth );1755pos = 0;1756ptr = BLOCKS_BLIST( blist );1757i = 1;1758m = *ptr;1759COUNT_TRUES_BLOCK(m);1760while ( nth > m ) {1761if ( ++i > nrb ) return Fail;1762nth -= m;1763pos += BIPEB;1764ptr++;1765m = *ptr;1766COUNT_TRUES_BLOCK(m);1767}1768m = *ptr;1769mask = 0x1;1770while ( nth > 0 ) {1771pos++;1772if ( m & mask ) nth--;1773mask <<= 1;1774}1775return INTOBJ_INT( pos );1776}177717781779/****************************************************************************1780**1781*F FuncIsSubsetBlist( <self>, <list1>, <list2> ) . . . . . . . . subset test1782**1783** 'FuncIsSubsetBlist' implements the internal function 'IsSubsetBlist'.1784**1785** 'IsSubsetBlist( <list1>, <list2> )'1786**1787** 'IsSubsetBlist' returns 'true' if the boolean list <list2> is a subset of1788** the boolean list <list1>, which must have equal length. <list2> is a1789** subset if <list1> if '<list2>[<i>] >= <list1>[<i>]' for all <i>.1790*/1791Obj FuncIS_SUB_BLIST (1792Obj self,1793Obj list1,1794Obj list2 )1795{1796UInt * ptr1; /* pointer to the first argument */1797UInt * ptr2; /* pointer to the second argument */1798UInt i; /* loop variable */17991800/* get and check the arguments */1801while ( ! IsBlistConv( list1 ) ) {1802list1 = ErrorReturnObj(1803"IsSubsetBlist: <blist1> must be a boolean list (not a %s)",1804(Int)TNAM_OBJ(list1), 0L,1805"you can replace <blist1> via 'return <blist1>;'" );1806}1807while ( ! IsBlistConv( list2 ) ) {1808list2 = ErrorReturnObj(1809"IsSubsetBlist: <blist2> must be a boolean list (not a %s)",1810(Int)TNAM_OBJ(list2), 0L,1811"you can replace <blist2> via 'return <blist2>;'" );1812}1813while ( LEN_BLIST(list1) != LEN_BLIST(list2) ) {1814list2 = ErrorReturnObj(1815"IsSubsetBlist: <blist2> must have the same length as <blist1> (%d)",1816LEN_BLIST(list1), 0L,1817"you can replace <blist2> via 'return <blist2>;'" );1818}18191820/* test for subset property blockwise */1821ptr1 = BLOCKS_BLIST(list1);1822ptr2 = BLOCKS_BLIST(list2);18231824for ( i = NUMBER_BLOCKS_BLIST(list1); 0 < i; i-- ) {1825if ( *ptr1 != (*ptr1 | *ptr2) )1826break;1827ptr1++; ptr2++;1828}18291830/* if no counterexample was found, <blist2> is a subset of <blist1> */1831return (i == 0) ? True : False;1832}183318341835/****************************************************************************1836**1837*F FuncUNITE_BLIST( <self>, <list1>, <list2> ) . unite one list with another1838**1839** 'FuncUNITE_BLIST' implements the internal function 'UniteBlist'.1840**1841** 'UniteBlist( <blist1>, <blist2> )'1842**1843** 'UniteBlist' unites the boolean list <blist1> with the boolean list1844** <blist2>, which must have the same length. This is equivalent to1845** assigning '<blist1>[<i>] := <blist1>[<i>] or <blist2>[<i>]' for all <i>.1846*/1847Obj FuncUNITE_BLIST (1848Obj self,1849Obj list1,1850Obj list2 )1851{1852UInt * ptr1; /* pointer to the first argument */1853UInt * ptr2; /* pointer to the second argument */1854UInt i; /* loop variable */18551856/* get and check the arguments */1857while ( ! IsBlistConv( list1 ) ) {1858list1 = ErrorReturnObj(1859"UniteBlist: <blist1> must be a boolean list (not a %s)",1860(Int)TNAM_OBJ(list1), 0L,1861"you can replace <blist1> via 'return <blist1>;'" );1862}1863while ( ! IsBlistConv( list2 ) ) {1864list2 = ErrorReturnObj(1865"UniteBlist: <blist2> must be a boolean list (not a %s)",1866(Int)TNAM_OBJ(list2), 0L,1867"you can replace <blist2> via 'return <blist2>;'" );1868}1869while ( LEN_BLIST(list1) != LEN_BLIST(list2) ) {1870list2 = ErrorReturnObj(1871"UniteBlist: <blist2> must have the same length as <blist1> (%d)",1872LEN_BLIST(list1), 0L,1873"you can replace <blist2> via 'return <blist2>;'" );1874}18751876/* compute the union by *or*-ing blockwise */1877ptr1 = BLOCKS_BLIST(list1);1878ptr2 = BLOCKS_BLIST(list2);1879for ( i = (LEN_BLIST(list1)+BIPEB-1)/BIPEB; 0 < i; i-- ) {1880*ptr1++ |= *ptr2++;1881}18821883/* return nothing, this function is a procedure */1884return 0;1885}188618871888/****************************************************************************1889**1890*F FuncUNITE_BLIST_LIST( <self>, <list>,<blist>, <sub> )1891**1892** 'FuncUNITE_BLIST_LIST' implements the internal function 'BlistList'.1893**1894** 'UniteBlistList( <list>,<blist>, <sub> )'1895**1896** 'UniteBlistList' works like `BlistList', but adds the entries to the1897** existing <blist>.1898*/1899Obj FuncUNITE_BLIST_LIST (1900Obj self,1901Obj list,1902Obj blist,1903Obj sub )1904{1905UInt * ptrBlist; /* pointer to the boolean list */1906UInt block; /* one block of boolean list */1907UInt bit; /* one bit of block */1908Int lenList; /* logical length of the list */1909Obj * ptrSub; /* pointer to the sublist */1910UInt lenSub; /* logical length of sublist */1911UInt i, j, k = 0, l; /* loop variables */1912long s, t; /* elements of a range */19131914/* get and check the arguments */1915while ( ! IS_SMALL_LIST(list) ) {1916list = ErrorReturnObj(1917"UniteBlistList: <list> must be a small list (not a %s)",1918(Int)TNAM_OBJ(list), 0L,1919"you can replace <list> via 'return <list>;'" );1920}1921while ( ! IsBlistConv( blist ) ) {1922blist = ErrorReturnObj(1923"UniteBlistList: <blist> must be a boolean list (not a %s)",1924(Int)TNAM_OBJ(blist), 0L,1925"you can replace <blist> via 'return <blist>;'" );1926}1927while ( ! IS_SMALL_LIST(sub) ) {1928sub = ErrorReturnObj(1929"UniteBlistList: <sub> must be a small list (not a %s)",1930(Int)TNAM_OBJ(sub), 0L,1931"you can replace <sub> via 'return <sub>;'" );1932}19331934/* for a range as subset of a range, it is extremely easy */1935if ( IS_RANGE(list) && IS_RANGE(sub) && GET_INC_RANGE( list ) == 11936&& GET_INC_RANGE( sub ) == 1) {19371938/* allocate the boolean list and get pointer */1939lenList = GET_LEN_RANGE( list );19401941/* check length */1942while ( LEN_BLIST(blist) != lenList ) {1943blist = ErrorReturnObj(1944"UniteBlistList: <blist> must have the same length as <list> (%d)",1945lenList, 0L,1946"you can replace <blist> via 'return <blist>;'" );1947}19481949lenSub = GET_LEN_RANGE( sub );1950ptrBlist = BLOCKS_BLIST(blist);19511952/* get the bounds of the subset with respect to the boolean list */1953s = INT_INTOBJ( GET_ELM_RANGE( list, 1 ) );1954t = INT_INTOBJ( GET_ELM_RANGE( sub, 1 ) );1955if ( s <= t ) i = t - s + 1;1956else i = 1;19571958if ( i + lenSub - 1 <= lenList ) j = i + lenSub - 1;1959else j = lenList;19601961/* set the corresponding entries to 'true' */1962for ( k = i; k <= j && (k-1)%BIPEB != 0; k++ )1963ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);1964for ( ; k+BIPEB <= j; k += BIPEB )1965ptrBlist[(k-1)/BIPEB] = ~(UInt)0;1966for ( ; k <= j; k++ )1967ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);19681969}19701971/* for a list as subset of a range, we need basically no search */1972else if ( IS_RANGE(list) && GET_INC_RANGE( list) == 11973&& IS_PLIST(sub) ) {19741975/* allocate the boolean list and get pointer */1976lenList = GET_LEN_RANGE( list );19771978/* check length */1979while ( LEN_BLIST(blist) != lenList ) {1980blist = ErrorReturnObj(1981"UniteBlistList: <blist> must have the same length as <list> (%d)",1982lenList, 0L,1983"you can replace <blist> via 'return <blist>;'" );1984}19851986lenSub = LEN_LIST( sub );1987ptrBlist = BLOCKS_BLIST(blist);1988ptrSub = ADDR_OBJ(sub);19891990/* loop over <sub> and set the corresponding entries to 'true' */1991s = INT_INTOBJ( GET_ELM_RANGE( list, 1 ) );1992for ( l = 1; l <= LEN_LIST(sub); l++ ) {1993if ( ptrSub[l] != 0 ) {19941995/* if <sub>[<l>] is an integer it is very easy */1996if ( TNUM_OBJ( ptrSub[l] ) == T_INT ) {1997t = INT_INTOBJ( ptrSub[l] ) - s + 1;1998if ( 0 < t && t <= lenList )1999ptrBlist[(t-1)/BIPEB] |= (1UL << (t-1)%BIPEB);2000}20012002/* see comment where PosRange was used above FL */2003/* otherwise it may be a record, let 'PosRange' handle it */2004/* else {2005Obj pos;2006pos = PosRange( list, ptrSub[l], 0L );2007if (pos != Fail)2008k = INT_INTOBJ(pos);2009ptrBlist[(k-1)/BIPEB] |= (1UL << (k-1)%BIPEB);2010} */20112012}2013}20142015}20162017/* if <list> is a set we have two possibilities */2018else if ( IsSet( list ) ) {20192020/* get the length of <list> and its logarithm */2021lenList = LEN_PLIST( list );20222023/* check length */2024while ( LEN_BLIST(blist) != lenList ) {2025blist = ErrorReturnObj(2026"UniteBlistList: <blist> must have the same length as <list> (%d)",2027lenList, 0L,2028"you can replace <blist> via 'return <blist>;'" );2029}20302031for ( i = lenList, l = 0; i != 0; i >>= 1, l++ ) ;2032PLAIN_LIST( sub );2033lenSub = LEN_LIST( sub );20342035/* if <sub> is small, we loop over <sub> and use binary search */2036if ( l * lenSub < 2 * lenList ) {20372038/* allocate the boolean list and get pointer */20392040/* run over the elements of <sub> and search for the elements */2041for ( l = 1; l <= LEN_LIST(sub); l++ ) {2042if ( ADDR_OBJ(sub)[l] != 0 ) {20432044/* perform the binary search to find the position */2045i = 0; k = lenList+1;2046while ( i+1 < k ) {2047j = (i + k) / 2;2048if ( LT(ADDR_OBJ(list)[j],ADDR_OBJ(sub)[l]) )2049i = j;2050else2051k = j;2052}20532054/* set bit if <sub>[<l>] was found at position k */2055if ( k <= lenList2056&& EQ( ADDR_OBJ(list)[k], ADDR_OBJ(sub)[l] ) )2057SET_ELM_BLIST( blist, k, True);2058}2059}20602061}20622063/* if <sub> is large, run over both list in parallel */2064else {20652066/* turn the <sub> into a set for faster searching */2067if ( ! IsSet( sub ) ) {2068sub = SetList( sub );2069lenSub = LEN_LIST( sub );2070}20712072/* run over the elements of <list> */2073k = 1;2074block = 0;2075bit = 1;2076for ( l = 1; l <= lenList; l++ ) {20772078/* test if <list>[<l>] is in <sub> */2079while ( k <= lenSub2080&& LT(ADDR_OBJ(sub)[k],ADDR_OBJ(list)[l]) )2081k++;20822083/* if <list>[<k>] is in <sub> set the current bit in block */2084if ( k <= lenSub2085&& EQ(ADDR_OBJ(sub)[k],ADDR_OBJ(list)[l]) ) {2086block |= bit;2087k++;2088}20892090/* if block is full add it to boolean list and start next */2091bit = bit << 1;2092if ( bit == 0 || l == lenList ) {2093BLOCK_ELM_BLIST( blist, l) |= block;2094block = 0;2095bit = 1;2096}20972098}2099}21002101}21022103/* if <list> is not a set, we have to use brute force */2104else {21052106/* convert left argument to an ordinary list, ignore return value */2107PLAIN_LIST( list );21082109/* turn <sub> into a set for faster searching */2110if ( ! IsSet( sub ) ) sub = SetList( sub );21112112/* allocate the boolean list and get pointer */2113lenList = LEN_LIST( list );21142115/* check length */2116while ( LEN_BLIST(blist) != lenList ) {2117blist = ErrorReturnObj(2118"UniteBlistList: <blist> must have the same length as <list> (%d)",2119lenList, 0L,2120"you can replace <blist> via 'return <blist>;'" );2121}21222123lenSub = LEN_PLIST( sub );21242125/* run over the elements of <list> */2126k = 1;2127block = 0;2128bit = 1;2129for ( l = 1; l <= lenList; l++ ) {21302131/* test if <list>[<l>] is in <sub> */2132if ( l == 1 || LT(ADDR_OBJ(list)[l-1],ADDR_OBJ(list)[l]) ){2133while ( k <= lenSub2134&& LT(ADDR_OBJ(sub)[k],ADDR_OBJ(list)[l]) )2135k++;2136}2137else {2138i = 0; k = LEN_PLIST(sub) + 1;2139while ( i+1 < k ) {2140j = (i + k) / 2;2141if ( LT( ADDR_OBJ(sub)[j], ADDR_OBJ(list)[l] ) )2142i = j;2143else2144k = j;2145}2146}21472148/* if <list>[<k>] is in <sub> set the current bit in the block */2149if ( k <= lenSub2150&& EQ( ADDR_OBJ(sub)[k], ADDR_OBJ(list)[l] ) ) {2151block |= bit;2152k++;2153}21542155/* if block is full add it to the boolean list and start next */2156bit = bit << 1;2157if ( bit == 0 || l == lenList ) {2158BLOCK_ELM_BLIST( blist,l) |= block;2159block = 0;2160bit = 1;2161}2162}21632164}21652166/* return */2167return 0;2168}216921702171/****************************************************************************2172**2173*F FuncINTER_BLIST( <self>, <list1>, <list2> ) . <list1> intersection <list2>2174**2175** 'FuncINTER_BLIST' implements the function 'IntersectBlist'.2176**2177** 'IntersectBlist( <list1>, <list2> )'2178**2179** 'IntersectBlist' intersects the boolean list <list1> with the boolean2180** list <list2>, which must have the same length. This is equivalent to2181** assigning '<list1>[<i>] := <list1>[<i>] and <list2>[<i>]' for all <i>.2182*/2183Obj FuncINTER_BLIST (2184Obj self,2185Obj list1,2186Obj list2 )2187{2188UInt * ptr1; /* pointer to the first argument */2189UInt * ptr2; /* pointer to the second argument */2190UInt i; /* loop variable */21912192/* get and check the arguments */2193while ( ! IsBlistConv( list1 ) ) {2194list1 = ErrorReturnObj(2195"IntersectBlist: <blist1> must be a boolean list (not a %s)",2196(Int)TNAM_OBJ(list1), 0L,2197"you can replace <blist1> via 'return <blist1>;'" );2198}2199while ( ! IsBlistConv( list2 ) ) {2200list2 = ErrorReturnObj(2201"IntersectBlist: <blist2> must be a boolean list (not a %s)",2202(Int)TNAM_OBJ(list2), 0L,2203"you can replace <blist2> via 'return <blist2>;'" );2204}2205while ( LEN_BLIST(list1) != LEN_BLIST(list2) ) {2206list2 = ErrorReturnObj(2207"IntersectBlist: <blist2> must have the same length as <blist1> (%d)",2208LEN_BLIST(list1), 0L,2209"you can replace <blist2> via 'return <blist2>;'" );2210}22112212/* compute the intersection by *and*-ing blockwise */2213ptr1 = BLOCKS_BLIST(list1);2214ptr2 = BLOCKS_BLIST(list2);2215for ( i = NUMBER_BLOCKS_BLIST(list1); 0 < i; i-- ) {2216*ptr1++ &= *ptr2++;2217}22182219/* return nothing, this function is a procedure */2220return 0;2221}222222232224/****************************************************************************2225**2226*F FuncSUBTR_BLIST( <self>, <list1>, <list2> ) . . . . . . <list1> - <list2>2227**2228** 'FuncSUBTR_BLIST' implements the internal function 'SubtractBlist'.2229**2230** 'SubtractBlist( <list1>, <list2> )'2231**2232** 'SubtractBlist' subtracts the boolean list <list2> from the boolean list2233** <list1>, which must have the same length. This is equivalent assigning2234** '<list1>[<i>] := <list1>[<i>] and not <list2>[<i>]' for all <i>.2235*/2236Obj FuncSUBTR_BLIST (2237Obj self,2238Obj list1,2239Obj list2 )2240{2241UInt * ptr1; /* pointer to the first argument */2242UInt * ptr2; /* pointer to the second argument */2243UInt i; /* loop variable */22442245/* get and check the arguments */2246while ( ! IsBlistConv( list1 ) ) {2247list1 = ErrorReturnObj(2248"SubtractBlist: <blist1> must be a boolean list (not a %s)",2249(Int)TNAM_OBJ(list1), 0L,2250"you can replace <blist1> via 'return <blist1>;'" );2251}2252while ( ! IsBlistConv( list2 ) ) {2253list2 = ErrorReturnObj(2254"SubtractBlist: <blist2> must be a boolean list (not a %s)",2255(Int)TNAM_OBJ(list2), 0L,2256"you can replace <blist2> via 'return <blist2>;'" );2257}2258while ( LEN_BLIST(list1) != LEN_BLIST(list2) ) {2259list2 = ErrorReturnObj(2260"SubtractBlist: <blist2> must have the same length as <blist1> (%d)",2261LEN_BLIST(list1), 0L,2262"you can replace <blist2> via 'return <blist2>;'" );2263}22642265/* compute the difference by operating blockwise */2266ptr1 = BLOCKS_BLIST(list1);2267ptr2 = BLOCKS_BLIST(list2);2268for ( i = NUMBER_BLOCKS_BLIST(list1); 0 < i; i-- )2269{2270*ptr1++ &= ~ *ptr2++;2271}22722273/* return nothing, this function is a procedure */ return 0; }22742275/****************************************************************************2276**2277*F FuncMEET_BLIST( <self>, <list1>, <list2> ) . . .2278**2279** 'FuncSUBTR_BLIST' implements the internal function 'MeetBlist'.2280**2281** 'MeetBlist( <list1>, <list2> )'2282**2283** 'MeetBlist' returns true if list1 and list2 have true in the same2284** position and false otherwise. It is equivalent to, but faster than2285** SizeBlist(IntersectionBlist(list1, list2)) <> 02286** The lists must have the same length.2287*/22882289Obj FuncMEET_BLIST (2290Obj self,2291Obj list1,2292Obj list2 )2293{2294UInt * ptr1; /* pointer to the first argument */2295UInt * ptr2; /* pointer to the second argument */2296UInt i; /* loop variable */22972298/* get and check the arguments */2299while ( ! IsBlistConv( list1 ) ) {2300list1 = ErrorReturnObj(2301"MeetBlist: <blist1> must be a boolean list (not a %s)",2302(Int)TNAM_OBJ(list1), 0L,2303"you can replace <blist1> via 'return <blist1>;'" );2304}2305while ( ! IsBlistConv( list2 ) ) {2306list2 = ErrorReturnObj(2307"MeetBlist: <blist2> must be a boolean list (not a %s)",2308(Int)TNAM_OBJ(list2), 0L,2309"you can replace <blist2> via 'return <blist2>;'" );2310}2311while ( LEN_BLIST(list1) != LEN_BLIST(list2) ) {2312list2 = ErrorReturnObj(2313"MeetBlist: <blist2> must have the same length as <blist1> (%d)",2314LEN_BLIST(list1), 0L,2315"you can replace <blist2> via 'return <blist2>;'" );2316}23172318/* compute the difference by operating blockwise */2319ptr1 = BLOCKS_BLIST(list1);2320ptr2 = BLOCKS_BLIST(list2);2321for ( i = NUMBER_BLOCKS_BLIST(list1); 0 < i; i-- )2322{2323if (*ptr1++ & *ptr2++) return True;2324}23252326return False;2327}232823292330/****************************************************************************2331**2332**2333*F MakeImmutableBlist( <blist> )2334*/23352336void MakeImmutableBlist( Obj blist )2337{2338RetypeBag(blist, IMMUTABLE_TNUM(TNUM_OBJ(blist)));2339}23402341/****************************************************************************2342**2343**2344*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *2345*/234623472348/****************************************************************************2349**23502351*V BagNames . . . . . . . . . . . . . . . . . . . . . . . list of bag names2352*/2353static StructBagNames BagNames[] = {2354{ T_BLIST, "list (boolean)" },2355{ T_BLIST +IMMUTABLE, "list (boolean,imm)" },2356{ T_BLIST +COPYING, "list (boolean,copied)" },2357{ T_BLIST +IMMUTABLE +COPYING, "list (boolean,imm,copied)" },2358{ T_BLIST_NSORT, "list (boolean,nsort)" },2359{ T_BLIST_NSORT +IMMUTABLE, "list (boolean,nsort,imm)" },2360{ T_BLIST_NSORT +COPYING, "list (boolean,nsort,copied)" },2361{ T_BLIST_NSORT +IMMUTABLE +COPYING, "list (boolean,nsort,imm,copied)" },2362{ T_BLIST_SSORT, "list (boolean,ssort)" },2363{ T_BLIST_SSORT +IMMUTABLE, "list (boolean,ssort,imm)" },2364{ T_BLIST_SSORT +COPYING, "list (boolean,ssort,copied)" },2365{ T_BLIST_SSORT +IMMUTABLE +COPYING, "list (boolean,ssort,imm,copied)" },2366{ -1, "" }2367};236823692370/****************************************************************************2371**2372*V ClearFiltsTab . . . . . . . . . . . . . . . . . . . . clear filter tnums2373*/2374static Int ClearFiltsTab [] = {2375T_BLIST, T_BLIST,2376T_BLIST +IMMUTABLE, T_BLIST+IMMUTABLE,2377T_BLIST_NSORT, T_BLIST,2378T_BLIST_NSORT+IMMUTABLE, T_BLIST+IMMUTABLE,2379T_BLIST_SSORT, T_BLIST,2380T_BLIST_SSORT+IMMUTABLE, T_BLIST+IMMUTABLE,2381-1, -12382};238323842385/****************************************************************************2386**2387*V HasFiltTab . . . . . . . . . . . . . . . . . . . . . tester filter tnum2388*/2389static Int HasFiltTab [] = {23902391/* mutable boolean list */2392T_BLIST, FN_IS_MUTABLE, 1,2393T_BLIST, FN_IS_EMPTY, 0,2394T_BLIST, FN_IS_DENSE, 1,2395T_BLIST, FN_IS_NDENSE, 0,2396T_BLIST, FN_IS_HOMOG, 1,2397T_BLIST, FN_IS_NHOMOG, 0,2398T_BLIST, FN_IS_TABLE, 0,2399T_BLIST, FN_IS_SSORT, 0,2400T_BLIST, FN_IS_NSORT, 0,24012402/* immutable boolean list */2403T_BLIST +IMMUTABLE, FN_IS_MUTABLE, 0,2404T_BLIST +IMMUTABLE, FN_IS_EMPTY, 0,2405T_BLIST +IMMUTABLE, FN_IS_DENSE, 1,2406T_BLIST +IMMUTABLE, FN_IS_NDENSE, 0,2407T_BLIST +IMMUTABLE, FN_IS_HOMOG, 1,2408T_BLIST +IMMUTABLE, FN_IS_NHOMOG, 0,2409T_BLIST +IMMUTABLE, FN_IS_TABLE, 0,2410T_BLIST +IMMUTABLE, FN_IS_SSORT, 0,2411T_BLIST +IMMUTABLE, FN_IS_NSORT, 0,24122413/* nsort mutable boolean list */2414T_BLIST_NSORT, FN_IS_MUTABLE, 1,2415T_BLIST_NSORT, FN_IS_EMPTY, 0,2416T_BLIST_NSORT, FN_IS_DENSE, 1,2417T_BLIST_NSORT, FN_IS_NDENSE, 0,2418T_BLIST_NSORT, FN_IS_HOMOG, 1,2419T_BLIST_NSORT, FN_IS_NHOMOG, 0,2420T_BLIST_NSORT, FN_IS_TABLE, 0,2421T_BLIST_NSORT, FN_IS_SSORT, 0,2422T_BLIST_NSORT, FN_IS_NSORT, 1,24232424/* nsort immutable boolean list */2425T_BLIST_NSORT+IMMUTABLE, FN_IS_MUTABLE, 0,2426T_BLIST_NSORT+IMMUTABLE, FN_IS_EMPTY, 0,2427T_BLIST_NSORT+IMMUTABLE, FN_IS_DENSE, 1,2428T_BLIST_NSORT+IMMUTABLE, FN_IS_NDENSE, 0,2429T_BLIST_NSORT+IMMUTABLE, FN_IS_HOMOG, 1,2430T_BLIST_NSORT+IMMUTABLE, FN_IS_NHOMOG, 0,2431T_BLIST_NSORT+IMMUTABLE, FN_IS_TABLE, 0,2432T_BLIST_NSORT+IMMUTABLE, FN_IS_SSORT, 0,2433T_BLIST_NSORT+IMMUTABLE, FN_IS_NSORT, 1,24342435/* ssort mutable boolean list */2436T_BLIST_SSORT, FN_IS_MUTABLE, 1,2437T_BLIST_SSORT, FN_IS_EMPTY, 0,2438T_BLIST_SSORT, FN_IS_DENSE, 1,2439T_BLIST_SSORT, FN_IS_NDENSE, 0,2440T_BLIST_SSORT, FN_IS_HOMOG, 1,2441T_BLIST_SSORT, FN_IS_NHOMOG, 0,2442T_BLIST_SSORT, FN_IS_TABLE, 0,2443T_BLIST_SSORT, FN_IS_SSORT, 1,2444T_BLIST_SSORT, FN_IS_NSORT, 0,24452446/* ssort immutable boolean list */2447T_BLIST_SSORT+IMMUTABLE, FN_IS_MUTABLE, 0,2448T_BLIST_SSORT+IMMUTABLE, FN_IS_EMPTY, 0,2449T_BLIST_SSORT+IMMUTABLE, FN_IS_DENSE, 1,2450T_BLIST_SSORT+IMMUTABLE, FN_IS_NDENSE, 0,2451T_BLIST_SSORT+IMMUTABLE, FN_IS_HOMOG, 1,2452T_BLIST_SSORT+IMMUTABLE, FN_IS_NHOMOG, 0,2453T_BLIST_SSORT+IMMUTABLE, FN_IS_TABLE, 0,2454T_BLIST_SSORT+IMMUTABLE, FN_IS_SSORT, 1,2455T_BLIST_SSORT+IMMUTABLE, FN_IS_NSORT, 0,24562457-1, -1, -12458};245924602461/****************************************************************************2462**2463*V SetFiltTab . . . . . . . . . . . . . . . . . . . . . setter filter tnum2464*/2465static Int SetFiltTab [] = {24662467/* mutable boolean list */2468T_BLIST, FN_IS_MUTABLE, T_BLIST,2469T_BLIST, FN_IS_EMPTY, T_BLIST_SSORT,2470T_BLIST, FN_IS_DENSE, T_BLIST,2471T_BLIST, FN_IS_NDENSE, -1,2472T_BLIST, FN_IS_HOMOG, T_BLIST,2473T_BLIST, FN_IS_NHOMOG, -1,2474T_BLIST, FN_IS_TABLE, -1,2475T_BLIST, FN_IS_SSORT, T_BLIST_SSORT,2476T_BLIST, FN_IS_NSORT, T_BLIST_NSORT,24772478/* immutable boolean list */2479T_BLIST +IMMUTABLE, FN_IS_MUTABLE, T_BLIST,2480T_BLIST +IMMUTABLE, FN_IS_EMPTY, T_BLIST_SSORT+IMMUTABLE,2481T_BLIST +IMMUTABLE, FN_IS_DENSE, T_BLIST +IMMUTABLE,2482T_BLIST +IMMUTABLE, FN_IS_NDENSE, -1,2483T_BLIST +IMMUTABLE, FN_IS_HOMOG, T_BLIST +IMMUTABLE,2484T_BLIST +IMMUTABLE, FN_IS_NHOMOG, -1,2485T_BLIST +IMMUTABLE, FN_IS_TABLE, -1,2486T_BLIST +IMMUTABLE, FN_IS_SSORT, T_BLIST_SSORT+IMMUTABLE,2487T_BLIST +IMMUTABLE, FN_IS_NSORT, T_BLIST_NSORT+IMMUTABLE,24882489/* nsort mutable boolean list */2490T_BLIST_NSORT, FN_IS_MUTABLE, T_BLIST_NSORT,2491T_BLIST_NSORT, FN_IS_EMPTY, -1,2492T_BLIST_NSORT, FN_IS_DENSE, T_BLIST_NSORT,2493T_BLIST_NSORT, FN_IS_NDENSE, -1,2494T_BLIST_NSORT, FN_IS_HOMOG, T_BLIST_NSORT,2495T_BLIST_NSORT, FN_IS_NHOMOG, -1,2496T_BLIST_NSORT, FN_IS_TABLE, -1,2497T_BLIST_NSORT, FN_IS_SSORT, -1,2498T_BLIST_NSORT, FN_IS_NSORT, T_BLIST_NSORT,24992500/* nsort immutable boolean list */2501T_BLIST_NSORT+IMMUTABLE, FN_IS_MUTABLE, T_BLIST_NSORT,2502T_BLIST_NSORT+IMMUTABLE, FN_IS_EMPTY, -1,2503T_BLIST_NSORT+IMMUTABLE, FN_IS_DENSE, T_BLIST_NSORT+IMMUTABLE,2504T_BLIST_NSORT+IMMUTABLE, FN_IS_NDENSE, -1,2505T_BLIST_NSORT+IMMUTABLE, FN_IS_HOMOG, T_BLIST_NSORT+IMMUTABLE,2506T_BLIST_NSORT+IMMUTABLE, FN_IS_NHOMOG, -1,2507T_BLIST_NSORT+IMMUTABLE, FN_IS_TABLE, -1,2508T_BLIST_NSORT+IMMUTABLE, FN_IS_SSORT, -1,2509T_BLIST_NSORT+IMMUTABLE, FN_IS_NSORT, T_BLIST_NSORT+IMMUTABLE,25102511/* ssort mutable boolean list */2512T_BLIST_SSORT, FN_IS_MUTABLE, T_BLIST_SSORT,2513T_BLIST_SSORT, FN_IS_EMPTY, T_BLIST_SSORT,2514T_BLIST_SSORT, FN_IS_DENSE, T_BLIST_SSORT,2515T_BLIST_SSORT, FN_IS_NDENSE, -1,2516T_BLIST_SSORT, FN_IS_HOMOG, T_BLIST_SSORT,2517T_BLIST_SSORT, FN_IS_NHOMOG, -1,2518T_BLIST_SSORT, FN_IS_TABLE, -1,2519T_BLIST_SSORT, FN_IS_SSORT, T_BLIST_SSORT,2520T_BLIST_SSORT, FN_IS_NSORT, -1,25212522/* ssort immutable boolean list */2523T_BLIST_SSORT+IMMUTABLE, FN_IS_MUTABLE, T_BLIST_SSORT,2524T_BLIST_SSORT+IMMUTABLE, FN_IS_EMPTY, T_BLIST_SSORT+IMMUTABLE,2525T_BLIST_SSORT+IMMUTABLE, FN_IS_DENSE, T_BLIST_SSORT+IMMUTABLE,2526T_BLIST_SSORT+IMMUTABLE, FN_IS_NDENSE, -1,2527T_BLIST_SSORT+IMMUTABLE, FN_IS_HOMOG, T_BLIST_SSORT+IMMUTABLE,2528T_BLIST_SSORT+IMMUTABLE, FN_IS_NHOMOG, -1,2529T_BLIST_SSORT+IMMUTABLE, FN_IS_TABLE, -1,2530T_BLIST_SSORT+IMMUTABLE, FN_IS_SSORT, T_BLIST_SSORT+IMMUTABLE,2531T_BLIST_SSORT+IMMUTABLE, FN_IS_NSORT, -1,25322533-1, -1, -125342535};253625372538/****************************************************************************2539**2540*V ResetFiltTab . . . . . . . . . . . . . . . . . . . unsetter filter tnum2541*/2542static Int ResetFiltTab [] = {25432544/* mutable boolean list */2545T_BLIST, FN_IS_MUTABLE, T_BLIST +IMMUTABLE,2546T_BLIST, FN_IS_EMPTY, T_BLIST,2547T_BLIST, FN_IS_DENSE, T_BLIST,2548T_BLIST, FN_IS_NDENSE, T_BLIST,2549T_BLIST, FN_IS_HOMOG, T_BLIST,2550T_BLIST, FN_IS_NHOMOG, T_BLIST,2551T_BLIST, FN_IS_TABLE, T_BLIST,2552T_BLIST, FN_IS_SSORT, T_BLIST,2553T_BLIST, FN_IS_NSORT, T_BLIST,25542555/* immutable boolean list */2556T_BLIST +IMMUTABLE, FN_IS_MUTABLE, T_BLIST +IMMUTABLE,2557T_BLIST +IMMUTABLE, FN_IS_EMPTY, T_BLIST +IMMUTABLE,2558T_BLIST +IMMUTABLE, FN_IS_DENSE, T_BLIST +IMMUTABLE,2559T_BLIST +IMMUTABLE, FN_IS_NDENSE, T_BLIST +IMMUTABLE,2560T_BLIST +IMMUTABLE, FN_IS_HOMOG, T_BLIST +IMMUTABLE,2561T_BLIST +IMMUTABLE, FN_IS_NHOMOG, T_BLIST +IMMUTABLE,2562T_BLIST +IMMUTABLE, FN_IS_NSORT, T_BLIST +IMMUTABLE,2563T_BLIST +IMMUTABLE, FN_IS_SSORT, T_BLIST +IMMUTABLE,2564T_BLIST +IMMUTABLE, FN_IS_TABLE, T_BLIST +IMMUTABLE,25652566/* nsort mutable boolean list */2567T_BLIST_NSORT, FN_IS_MUTABLE, T_BLIST_NSORT+IMMUTABLE,2568T_BLIST_NSORT, FN_IS_EMPTY, T_BLIST_NSORT,2569T_BLIST_NSORT, FN_IS_DENSE, T_BLIST_NSORT,2570T_BLIST_NSORT, FN_IS_NDENSE, T_BLIST_NSORT,2571T_BLIST_NSORT, FN_IS_HOMOG, T_BLIST_NSORT,2572T_BLIST_NSORT, FN_IS_NHOMOG, T_BLIST_NSORT,2573T_BLIST_NSORT, FN_IS_TABLE, T_BLIST_NSORT,2574T_BLIST_NSORT, FN_IS_SSORT, T_BLIST_NSORT,2575T_BLIST_NSORT, FN_IS_NSORT, T_BLIST,25762577/* nsort immutable boolean list */2578T_BLIST_NSORT+IMMUTABLE, FN_IS_MUTABLE, T_BLIST_NSORT+IMMUTABLE,2579T_BLIST_NSORT+IMMUTABLE, FN_IS_EMPTY, T_BLIST_NSORT+IMMUTABLE,2580T_BLIST_NSORT+IMMUTABLE, FN_IS_DENSE, T_BLIST_NSORT+IMMUTABLE,2581T_BLIST_NSORT+IMMUTABLE, FN_IS_NDENSE, T_BLIST_NSORT+IMMUTABLE,2582T_BLIST_NSORT+IMMUTABLE, FN_IS_HOMOG, T_BLIST_NSORT+IMMUTABLE,2583T_BLIST_NSORT+IMMUTABLE, FN_IS_NHOMOG, T_BLIST_NSORT+IMMUTABLE,2584T_BLIST_NSORT+IMMUTABLE, FN_IS_TABLE, T_BLIST_NSORT+IMMUTABLE,2585T_BLIST_NSORT+IMMUTABLE, FN_IS_SSORT, T_BLIST_NSORT+IMMUTABLE,2586T_BLIST_NSORT+IMMUTABLE, FN_IS_NSORT, T_BLIST +IMMUTABLE,25872588/* ssort mutable boolean list */2589T_BLIST_SSORT, FN_IS_MUTABLE, T_BLIST_SSORT+IMMUTABLE,2590T_BLIST_SSORT, FN_IS_EMPTY, T_BLIST_SSORT,2591T_BLIST_SSORT, FN_IS_DENSE, T_BLIST_SSORT,2592T_BLIST_SSORT, FN_IS_NDENSE, T_BLIST_SSORT,2593T_BLIST_SSORT, FN_IS_HOMOG, T_BLIST_SSORT,2594T_BLIST_SSORT, FN_IS_NHOMOG, T_BLIST_SSORT,2595T_BLIST_SSORT, FN_IS_TABLE, T_BLIST_SSORT,2596T_BLIST_SSORT, FN_IS_SSORT, T_BLIST,2597T_BLIST_SSORT, FN_IS_NSORT, T_BLIST_SSORT,25982599/* ssort immutable boolean list */2600T_BLIST_SSORT+IMMUTABLE, FN_IS_MUTABLE, T_BLIST_SSORT+IMMUTABLE,2601T_BLIST_SSORT+IMMUTABLE, FN_IS_EMPTY, T_BLIST_SSORT+IMMUTABLE,2602T_BLIST_SSORT+IMMUTABLE, FN_IS_DENSE, T_BLIST_SSORT+IMMUTABLE,2603T_BLIST_SSORT+IMMUTABLE, FN_IS_NDENSE, T_BLIST_SSORT+IMMUTABLE,2604T_BLIST_SSORT+IMMUTABLE, FN_IS_HOMOG, T_BLIST_SSORT+IMMUTABLE,2605T_BLIST_SSORT+IMMUTABLE, FN_IS_NHOMOG, T_BLIST_SSORT+IMMUTABLE,2606T_BLIST_SSORT+IMMUTABLE, FN_IS_TABLE, T_BLIST_SSORT+IMMUTABLE,2607T_BLIST_SSORT+IMMUTABLE, FN_IS_SSORT, T_BLIST +IMMUTABLE,2608T_BLIST_SSORT+IMMUTABLE, FN_IS_NSORT, T_BLIST_SSORT+IMMUTABLE,26092610-1, -1, -126112612};261326142615/****************************************************************************2616**2617*V GVarFilts . . . . . . . . . . . . . . . . . . . list of filters to export2618*/2619static StructGVarFilt GVarFilts [] = {26202621{ "IS_BLIST", "obj", &IsBlistFilt,2622FuncIS_BLIST, "src/blister.c:IS_BLIST" },26232624{ "IS_BLIST_REP", "obj", &IsBlistRepFilt,2625FuncIS_BLIST_REP, "src/blister.c:IS_BLIST_REP" },26262627{ 0 }26282629};263026312632/****************************************************************************2633**2634*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export2635*/2636static StructGVarFunc GVarFuncs [] = {26372638{ "IS_BLIST_CONV", 1, "obj",2639FuncIS_BLIST_CONV, "src/blister.c:IS_BLIST_CONV" },26402641{ "CONV_BLIST", 1, "blist",2642FuncCONV_BLIST, "src/blister.c:CONV_BLIST" },26432644{ "BLIST_LIST", 2, "list, sub",2645FuncBLIST_LIST, "src/blister.c:BLIST_LIST" },26462647{ "LIST_BLIST", 2, "list, blist",2648FuncLIST_BLIST, "src/blister.c:LIST_BLIST" },26492650{ "SIZE_BLIST", 1, "blist",2651FuncSIZE_BLIST, "src/blister.c:SIZE_BLIST" },26522653{ "IS_SUB_BLIST", 2, "blist1, blist2",2654FuncIS_SUB_BLIST, "src/blister.c:IS_SUB_BLIST" },26552656{ "UNITE_BLIST", 2, "blist1, blist2",2657FuncUNITE_BLIST, "src/blister.c:UNITE_BLIST" },26582659{ "UNITE_BLIST_LIST", 3, "list, blist, sub",2660FuncUNITE_BLIST_LIST, "src/blister.c:UNITE_BLIST_LIST" },26612662{ "INTER_BLIST", 2, "blist1, blist2",2663FuncINTER_BLIST, "src/blister.c:INTER_BLIST" },26642665{ "SUBTR_BLIST", 2, "blist1, blist2",2666FuncSUBTR_BLIST, "src/blister.c:SUBTR_BLIST" },26672668{ "MEET_BLIST", 2, "blist1, blist2",2669FuncMEET_BLIST, "src/blister.c:MEET_BLIST" },26702671{ "PositionNthTrueBlist", 2, "blist, nth",2672FuncPositionNthTrueBlist, "src/blister.c:PositionNthTrueBlist" },26732674{ "PositionsTrueBlist", 1, "blist",2675FuncPositionsTrueBlist, "src/blister.c:PositionsTrueBlist" },26762677{ 0 }26782679};268026812682/****************************************************************************2683**26842685*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures2686*/2687static Int InitKernel (2688StructInitInfo * module )2689{2690UInt t1;2691UInt t2;26922693/* check dependencies */2694RequireModule( module, "lists", 403600000UL );26952696/* init filters and functions */2697InitHdlrFiltsFromTable( GVarFilts );2698InitHdlrFuncsFromTable( GVarFuncs );26992700/* GASMAN marking functions and GASMAN names */2701InitBagNamesFromTable( BagNames );27022703for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT; t1 += 2 ) {2704InitMarkFuncBags( t1, MarkNoSubBags );2705InitMarkFuncBags( t1 +IMMUTABLE, MarkNoSubBags );2706InitMarkFuncBags( t1 +COPYING , MarkOneSubBags );2707InitMarkFuncBags( t1 +IMMUTABLE +COPYING , MarkOneSubBags );2708}27092710/* Make immutable blists public */2711for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT; t1 += 2 ) {2712MakeBagTypePublic( t1 + IMMUTABLE );2713}27142715/* install the type methods */2716TypeObjFuncs[ T_BLIST ] = TypeBlistMut;2717TypeObjFuncs[ T_BLIST +IMMUTABLE ] = TypeBlistImm;2718TypeObjFuncs[ T_BLIST_NSORT ] = TypeBlistNSortMut;2719TypeObjFuncs[ T_BLIST_NSORT +IMMUTABLE ] = TypeBlistNSortImm;2720TypeObjFuncs[ T_BLIST_SSORT ] = TypeBlistSSortMut;2721TypeObjFuncs[ T_BLIST_SSORT +IMMUTABLE ] = TypeBlistSSortImm;27222723/* initialise list tables */2724InitClearFiltsTNumsFromTable ( ClearFiltsTab );2725InitHasFiltListTNumsFromTable ( HasFiltTab );2726InitSetFiltListTNumsFromTable ( SetFiltTab );2727InitResetFiltListTNumsFromTable( ResetFiltTab );27282729/* Install the saving functions -- cannot save while copying */2730for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT; t1 += 2 ) {2731SaveObjFuncs[ t1 ] = SaveBlist;2732SaveObjFuncs[ t1 +IMMUTABLE ] = SaveBlist;2733LoadObjFuncs[ t1 ] = LoadBlist;2734LoadObjFuncs[ t1 +IMMUTABLE ] = LoadBlist;2735}27362737/* install the copy functions */2738for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT; t1 += 2 ) {2739CopyObjFuncs [ t1 ] = CopyBlist;2740CopyObjFuncs [ t1 +IMMUTABLE ] = CopyBlist;2741CopyObjFuncs [ t1 +COPYING ] = CopyBlistCopy;2742CopyObjFuncs [ t1 +IMMUTABLE +COPYING ] = CopyBlistCopy;2743CleanObjFuncs[ t1 ] = CleanBlist;2744CleanObjFuncs[ t1 +IMMUTABLE ] = CleanBlist;2745CleanObjFuncs[ t1 +COPYING ] = CleanBlistCopy;2746CleanObjFuncs[ t1 +IMMUTABLE +COPYING ] = CleanBlistCopy;2747ShallowCopyObjFuncs[ t1 ] = ShallowCopyBlist;2748ShallowCopyObjFuncs[ t1 +IMMUTABLE ] = ShallowCopyBlist;2749}27502751/* install the comparison methods */2752for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT+IMMUTABLE; t1++ ) {2753for ( t2 = T_BLIST; t2 <= T_BLIST_SSORT+IMMUTABLE; t2++ ) {2754EqFuncs[ t1 ][ t2 ] = EqBlist;2755}2756}27572758/* install the list functions in the tables */2759for ( t1 = T_BLIST; t1 <= T_BLIST_SSORT; t1 += 2 ) {2760LenListFuncs [ t1 ] = LenBlist;2761LenListFuncs [ t1 +IMMUTABLE ] = LenBlist;2762IsbListFuncs [ t1 ] = IsbBlist;2763IsbListFuncs [ t1 +IMMUTABLE ] = IsbBlist;2764IsbvListFuncs [ t1 ] = IsbvBlist;2765IsbvListFuncs [ t1 +IMMUTABLE ] = IsbvBlist;2766Elm0ListFuncs [ t1 ] = Elm0Blist;2767Elm0ListFuncs [ t1 +IMMUTABLE ] = Elm0Blist;2768Elm0vListFuncs [ t1 ] = Elm0vBlist;2769Elm0vListFuncs [ t1 +IMMUTABLE ] = Elm0vBlist;2770ElmListFuncs [ t1 ] = ElmBlist;2771ElmListFuncs [ t1 +IMMUTABLE ] = ElmBlist;2772ElmvListFuncs [ t1 ] = ElmvBlist;2773ElmvListFuncs [ t1 +IMMUTABLE ] = ElmvBlist;2774ElmwListFuncs [ t1 ] = ElmvBlist;2775ElmwListFuncs [ t1 +IMMUTABLE ] = ElmvBlist;2776ElmsListFuncs [ t1 ] = ElmsBlist;2777ElmsListFuncs [ t1 +IMMUTABLE ] = ElmsBlist;2778AssListFuncs [ t1 ] = AssBlist;2779AssListFuncs [ t1 +IMMUTABLE ] = AssBlistImm;2780AsssListFuncs [ t1 ] = AsssListDefault;2781AsssListFuncs [ t1 +IMMUTABLE ] = AsssBlistImm;2782IsDenseListFuncs[ t1 ] = IsDenseBlist;2783IsDenseListFuncs[ t1 +IMMUTABLE ] = IsDenseBlist;2784IsHomogListFuncs[ t1 ] = IsHomogBlist;2785IsHomogListFuncs[ t1 +IMMUTABLE ] = IsHomogBlist;2786IsSSortListFuncs[ t1 ] = IsSSortBlist;2787IsSSortListFuncs[ t1 +IMMUTABLE ] = IsSSortBlist;2788IsPossListFuncs [ t1 ] = IsPossBlist;2789IsPossListFuncs [ t1 +IMMUTABLE ] = IsPossBlist;2790PosListFuncs [ t1 ] = PosBlist;2791PosListFuncs [ t1 +IMMUTABLE ] = PosBlist;2792PlainListFuncs [ t1 ] = PlainBlist;2793PlainListFuncs [ t1 +IMMUTABLE ] = PlainBlist;2794MakeImmutableObjFuncs [ t1 ] = MakeImmutableBlist;2795}2796IsSSortListFuncs[ T_BLIST_NSORT ] = IsSSortBlistNot;2797IsSSortListFuncs[ T_BLIST_NSORT +IMMUTABLE ] = IsSSortBlistNot;2798IsSSortListFuncs[ T_BLIST_SSORT ] = IsSSortBlistYes;2799IsSSortListFuncs[ T_BLIST_SSORT +IMMUTABLE ] = IsSSortBlistYes;28002801/* Import the types of blists: */2802ImportGVarFromLibrary( "TYPE_BLIST_MUT", &TYPE_BLIST_MUT );2803ImportGVarFromLibrary( "TYPE_BLIST_IMM", &TYPE_BLIST_IMM );2804ImportGVarFromLibrary( "TYPE_BLIST_NSORT_MUT", &TYPE_BLIST_NSORT_MUT );2805ImportGVarFromLibrary( "TYPE_BLIST_NSORT_IMM", &TYPE_BLIST_NSORT_IMM );2806ImportGVarFromLibrary( "TYPE_BLIST_SSORT_MUT", &TYPE_BLIST_SSORT_MUT );2807ImportGVarFromLibrary( "TYPE_BLIST_SSORT_IMM", &TYPE_BLIST_SSORT_IMM );2808ImportGVarFromLibrary( "TYPE_BLIST_EMPTY_MUT", &TYPE_BLIST_EMPTY_MUT );2809ImportGVarFromLibrary( "TYPE_BLIST_EMPTY_IMM", &TYPE_BLIST_EMPTY_IMM );28102811/* return success */2812return 0;2813}281428152816/****************************************************************************2817**2818*F InitLibrary( <module> ) . . . . . . . initialise library data structures2819*/2820static Int InitLibrary (2821StructInitInfo * module )2822{2823/* init filters and functions */2824InitGVarFiltsFromTable( GVarFilts );2825InitGVarFuncsFromTable( GVarFuncs );28262827/* return success */2828return 0;2829}283028312832/****************************************************************************2833**2834*F InitInfoBlist() . . . . . . . . . . . . . . . . . table of init functions2835*/2836static StructInitInfo module = {2837MODULE_BUILTIN, /* type */2838"blister", /* name */28390, /* revision entry of c file */28400, /* revision entry of h file */28410, /* version */28420, /* crc */2843InitKernel, /* initKernel */2844InitLibrary, /* initLibrary */28450, /* checkInit */28460, /* preSave */28470, /* postSave */28480 /* postRestore */2849};28502851StructInitInfo * InitInfoBlist ( void )2852{2853return &module;2854}285528562857/****************************************************************************2858**28592860*E blister.c . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here2861*/286228632864