|
24 | 24 | #include "permutat.h" |
25 | 25 | #include "plist.h" |
26 | 26 | #include "pperm.h" |
| 27 | +#include "precord.h" |
| 28 | +#include "records.h" |
27 | 29 | #include "set.h" |
| 30 | +#include "stats.h" |
28 | 31 | #include "stringobj.h" |
29 | 32 | #include "sysfiles.h" |
30 | 33 | #include "trans.h" |
@@ -1523,6 +1526,112 @@ static Obj FuncLIST_WITH_IDENTICAL_ENTRIES(Obj self, Obj n, Obj obj) |
1523 | 1526 | return list; |
1524 | 1527 | } |
1525 | 1528 |
|
| 1529 | + |
| 1530 | +static Obj FastCallFuncList(Obj func, Obj list) |
| 1531 | +{ |
| 1532 | + switch (LEN_PLIST(list)) { |
| 1533 | + case 0: |
| 1534 | + return CALL_0ARGS(func); |
| 1535 | + case 1: |
| 1536 | + return CALL_1ARGS(func, ELM_PLIST(list, 1)); |
| 1537 | + case 2: |
| 1538 | + return CALL_2ARGS(func, ELM_PLIST(list, 1), ELM_PLIST(list, 2)); |
| 1539 | + case 3: |
| 1540 | + return CALL_3ARGS(func, ELM_PLIST(list, 1), ELM_PLIST(list, 2), |
| 1541 | + ELM_PLIST(list, 3)); |
| 1542 | + case 4: |
| 1543 | + return CALL_4ARGS(func, ELM_PLIST(list, 1), ELM_PLIST(list, 2), |
| 1544 | + ELM_PLIST(list, 3), ELM_PLIST(list, 4)); |
| 1545 | + case 5: |
| 1546 | + return CALL_5ARGS(func, ELM_PLIST(list, 1), ELM_PLIST(list, 2), |
| 1547 | + ELM_PLIST(list, 3), ELM_PLIST(list, 4), |
| 1548 | + ELM_PLIST(list, 5)); |
| 1549 | + case 6: |
| 1550 | + return CALL_6ARGS(func, ELM_PLIST(list, 1), ELM_PLIST(list, 2), |
| 1551 | + ELM_PLIST(list, 3), ELM_PLIST(list, 4), |
| 1552 | + ELM_PLIST(list, 5), ELM_PLIST(list, 6)); |
| 1553 | + default: |
| 1554 | + return CALL_XARGS(func, list); |
| 1555 | + } |
| 1556 | +} |
| 1557 | + |
| 1558 | +// TODO: document this a bit |
| 1559 | +static int FoldLeftXHelp(Obj gens, |
| 1560 | + Obj foldFunc, |
| 1561 | + Obj * acc, |
| 1562 | + Obj abortValue, |
| 1563 | + Obj args, |
| 1564 | + int genIndex, |
| 1565 | + int valIndex) |
| 1566 | +{ |
| 1567 | + while (genIndex <= LEN_PLIST(gens)) { |
| 1568 | + Obj gen = ELM_PLIST(gens, genIndex); |
| 1569 | + if (IS_FUNC(gen)) |
| 1570 | + gen = FastCallFuncList(gen, args); |
| 1571 | + if (gen == True) |
| 1572 | + genIndex++; |
| 1573 | + else if (gen == False) |
| 1574 | + return 0; |
| 1575 | + else if (IS_LIST(gen)) { |
| 1576 | + const int len = LEN_LIST(gen); |
| 1577 | + for (int i = 1; i <= len; i++) { |
| 1578 | + Obj elm = ELM_LIST(gen, i); |
| 1579 | + AssPlist(args, valIndex, elm); |
| 1580 | + if (FoldLeftXHelp(gens, foldFunc, acc, abortValue, args, |
| 1581 | + genIndex + 1, valIndex + 1)) |
| 1582 | + return 1; |
| 1583 | + } |
| 1584 | + UNB_LIST(args, valIndex); |
| 1585 | + return 0; |
| 1586 | + } |
| 1587 | + else { |
| 1588 | + // get the iterator |
| 1589 | + Obj iter = CALL_1ARGS(ITERATOR, gen); |
| 1590 | + |
| 1591 | + Obj nfun, dfun; |
| 1592 | + if (IS_PREC_OR_COMOBJ(iter) && |
| 1593 | + CALL_1ARGS(STD_ITER, iter) == True) { |
| 1594 | + // this can avoid method selection overhead on iterator |
| 1595 | + dfun = ElmPRec(iter, RNamName("IsDoneIterator")); |
| 1596 | + nfun = ElmPRec(iter, RNamName("NextIterator")); |
| 1597 | + } |
| 1598 | + else { |
| 1599 | + dfun = IS_DONE_ITER; |
| 1600 | + nfun = NEXT_ITER; |
| 1601 | + } |
| 1602 | + |
| 1603 | + // loop over the iterator |
| 1604 | + while (CALL_1ARGS(dfun, iter) == False) { |
| 1605 | + |
| 1606 | + // get the element and assign it to the variable |
| 1607 | + Obj elm = CALL_1ARGS(nfun, iter); |
| 1608 | + |
| 1609 | + AssPlist(args, valIndex, elm); |
| 1610 | + if (FoldLeftXHelp(gens, foldFunc, acc, abortValue, args, |
| 1611 | + genIndex + 1, valIndex + 1)) |
| 1612 | + return 1; |
| 1613 | + } |
| 1614 | + UNB_LIST(args, valIndex); |
| 1615 | + return 0; |
| 1616 | + } |
| 1617 | + } |
| 1618 | + *acc = CALL_2ARGS(foldFunc, *acc, args); |
| 1619 | + return abortValue == *acc; |
| 1620 | +} |
| 1621 | + |
| 1622 | +// TODO: document this a bit |
| 1623 | +Obj FuncFOLD_LEFT_X(Obj self, Obj gens, Obj foldFunc, Obj init, Obj abortValue) |
| 1624 | +{ |
| 1625 | + if (!IS_PLIST(gens)) |
| 1626 | + return Fail; |
| 1627 | + if (!IS_FUNC(foldFunc)) |
| 1628 | + return Fail; |
| 1629 | + |
| 1630 | + Obj args = NEW_PLIST(T_PLIST, LEN_PLIST(gens)); |
| 1631 | + FoldLeftXHelp(gens, foldFunc, &init, abortValue, args, 1, 1); |
| 1632 | + return init; |
| 1633 | +} |
| 1634 | + |
1526 | 1635 | /**************************************************************************** |
1527 | 1636 | ** |
1528 | 1637 | *F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * * |
@@ -1574,6 +1683,7 @@ static StructGVarFunc GVarFuncs [] = { |
1574 | 1683 | GVAR_FUNC(COPY_LIST_ENTRIES, -1, "srclist,srcstart,srcinc,dstlist,dststart,dstinc,number"), |
1575 | 1684 | GVAR_FUNC(STRONGLY_CONNECTED_COMPONENTS_DIGRAPH, 1, "digraph"), |
1576 | 1685 | GVAR_FUNC(LIST_WITH_IDENTICAL_ENTRIES, 2, "n, obj"), |
| 1686 | + GVAR_FUNC(FOLD_LEFT_X, 4, "gens, foldFunc, init, abortValue"), |
1577 | 1687 | { 0, 0, 0, 0, 0 } |
1578 | 1688 |
|
1579 | 1689 | }; |
|
0 commit comments