2424#include "permutat.h"
2525#include "plist.h"
2626#include "pperm.h"
27+ #include "precord.h"
28+ #include "records.h"
2729#include "set.h"
30+ #include "stats.h"
2831#include "stringobj.h"
2932#include "sysfiles.h"
3033#include "trans.h"
@@ -1460,6 +1463,121 @@ static Obj FuncLIST_WITH_IDENTICAL_ENTRIES(Obj self, Obj n, Obj obj)
14601463 return list ;
14611464}
14621465
1466+ static Obj FastCallFuncList (Obj func , Obj list )
1467+ {
1468+ switch (LEN_PLIST (list )) {
1469+ case 0 :
1470+ return CALL_0ARGS (func );
1471+ case 1 :
1472+ return CALL_1ARGS (func , ELM_PLIST (list , 1 ));
1473+ case 2 :
1474+ return CALL_2ARGS (func , ELM_PLIST (list , 1 ), ELM_PLIST (list , 2 ));
1475+ case 3 :
1476+ return CALL_3ARGS (func , ELM_PLIST (list , 1 ), ELM_PLIST (list , 2 ),
1477+ ELM_PLIST (list , 3 ));
1478+ case 4 :
1479+ return CALL_4ARGS (func , ELM_PLIST (list , 1 ), ELM_PLIST (list , 2 ),
1480+ ELM_PLIST (list , 3 ), ELM_PLIST (list , 4 ));
1481+ case 5 :
1482+ return CALL_5ARGS (func , ELM_PLIST (list , 1 ), ELM_PLIST (list , 2 ),
1483+ ELM_PLIST (list , 3 ), ELM_PLIST (list , 4 ),
1484+ ELM_PLIST (list , 5 ));
1485+ case 6 :
1486+ return CALL_6ARGS (func , ELM_PLIST (list , 1 ), ELM_PLIST (list , 2 ),
1487+ ELM_PLIST (list , 3 ), ELM_PLIST (list , 4 ),
1488+ ELM_PLIST (list , 5 ), ELM_PLIST (list , 6 ));
1489+ default :
1490+ return CALL_XARGS (func , list );
1491+ }
1492+ }
1493+
1494+ static Obj IsListOrCollection ;
1495+
1496+ // TODO: document this a bit
1497+ static int FoldLeftXHelp (Obj gens ,
1498+ Obj foldFunc ,
1499+ Obj * acc ,
1500+ Obj abortValue ,
1501+ Obj args ,
1502+ int genIndex ,
1503+ int valIndex )
1504+ {
1505+ while (genIndex <= LEN_PLIST (gens )) {
1506+ Obj gen = ELM_PLIST (gens , genIndex );
1507+ if (IS_FUNC (gen ))
1508+ gen = FastCallFuncList (gen , args );
1509+ if (gen == True )
1510+ genIndex ++ ;
1511+ else if (gen == False )
1512+ return 0 ;
1513+ else if (IS_LIST (gen )) {
1514+ const int len = LEN_LIST (gen );
1515+ for (int i = 1 ; i <= len ; i ++ ) {
1516+ Obj elm = ELM0_LIST (gen , i );
1517+ if (!elm )
1518+ continue ; // skip holes
1519+ AssPlist (args , valIndex , elm );
1520+ if (FoldLeftXHelp (gens , foldFunc , acc , abortValue , args ,
1521+ genIndex + 1 , valIndex + 1 ))
1522+ return 1 ;
1523+ }
1524+ UNB_LIST (args , valIndex );
1525+ return 0 ;
1526+ }
1527+ else if (CALL_1ARGS (IsListOrCollection , gen ) == True ) {
1528+ // get the iterator
1529+ Obj iter = CALL_1ARGS (ITERATOR , gen );
1530+
1531+ Obj nfun , dfun ;
1532+ if (IS_PREC_OR_COMOBJ (iter ) &&
1533+ CALL_1ARGS (STD_ITER , iter ) == True ) {
1534+ // this can avoid method selection overhead on iterator
1535+ dfun = ElmPRec (iter , RNamName ("IsDoneIterator" ));
1536+ nfun = ElmPRec (iter , RNamName ("NextIterator" ));
1537+ }
1538+ else {
1539+ dfun = IS_DONE_ITER ;
1540+ nfun = NEXT_ITER ;
1541+ }
1542+
1543+ // loop over the iterator
1544+ while (CALL_1ARGS (dfun , iter ) == False ) {
1545+
1546+ // get the element and assign it to the variable
1547+ Obj elm = CALL_1ARGS (nfun , iter );
1548+
1549+ AssPlist (args , valIndex , elm );
1550+ if (FoldLeftXHelp (gens , foldFunc , acc , abortValue , args ,
1551+ genIndex + 1 , valIndex + 1 ))
1552+ return 1 ;
1553+ }
1554+ UNB_LIST (args , valIndex );
1555+ return 0 ;
1556+ }
1557+ else {
1558+ ErrorMayQuit ("gens[%d] must be a collection, a list, a boolean, "
1559+ "or a function" ,
1560+ genIndex , 0 );
1561+ }
1562+ }
1563+ * acc = CALL_2ARGS (foldFunc , * acc , args );
1564+ return abortValue == * acc ;
1565+ }
1566+
1567+ // TODO: document this a bit
1568+ Obj FuncFOLD_LEFT_X (
1569+ Obj self , Obj gens , Obj foldFunc , Obj init , Obj abortValue )
1570+ {
1571+ if (!IS_PLIST (gens ))
1572+ return Fail ;
1573+ if (!IS_FUNC (foldFunc ))
1574+ return Fail ;
1575+
1576+ Obj args = NEW_PLIST (T_PLIST , LEN_PLIST (gens ));
1577+ FoldLeftXHelp (gens , foldFunc , & init , abortValue , args , 1 , 1 );
1578+ return init ;
1579+ }
1580+
14631581/****************************************************************************
14641582**
14651583*F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
@@ -1488,7 +1606,7 @@ static StructGVarOper GVarOpers [] = {
14881606**
14891607*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
14901608*/
1491- static StructGVarFunc GVarFuncs [] = {
1609+ static StructGVarFunc GVarFuncs [] = {
14921610
14931611 GVAR_FUNC_2ARGS (APPEND_LIST_INTR , list1 , list2 ),
14941612 GVAR_FUNC_2ARGS (POSITION_SORTED_LIST , list , obj ),
@@ -1511,6 +1629,9 @@ static StructGVarFunc GVarFuncs [] = {
15111629 GVAR_FUNC (COPY_LIST_ENTRIES , -1 , "srclist,srcstart,srcinc,dstlist,dststart,dstinc,number" ),
15121630 GVAR_FUNC_1ARGS (STRONGLY_CONNECTED_COMPONENTS_DIGRAPH , digraph ),
15131631 GVAR_FUNC_2ARGS (LIST_WITH_IDENTICAL_ENTRIES , n , obj ),
1632+
1633+ GVAR_FUNC_4ARGS (FOLD_LEFT_X , gens , foldFunc , init , abortValue ),
1634+
15141635 { 0 , 0 , 0 , 0 , 0 }
15151636
15161637};
@@ -1532,8 +1653,8 @@ static Int InitKernel (
15321653 InitHdlrOpersFromTable ( GVarOpers );
15331654 InitHdlrFuncsFromTable ( GVarFuncs );
15341655
1656+ ImportFuncFromLibrary ("IsListOrCollection" , & IsListOrCollection );
15351657
1536-
15371658 return 0 ;
15381659}
15391660
0 commit comments