@@ -1678,11 +1678,11 @@ InstallMethod( ForAnyOp,
16781678InstallGlobalFunction( ListX, function ( arg )
16791679 local f;
16801680 f := Remove(arg);
1681- return FoldLeftX (arg,
1681+ return FOLD_LEFT_X (arg,
16821682 function (acc, x )
16831683 Add(acc, CallFuncList(f, x));
16841684 return acc;
1685- end , [] );
1685+ end , [] , false );
16861686end );
16871687
16881688
@@ -1778,8 +1778,24 @@ InstallOtherMethod( FoldLeftOp,
17781778# #
17791779# M FoldLeftX(<obj>,...)
17801780# #
1781- InstallGlobalFunction( FoldLeftX, function ( gens, f, init )
1782- local acc, args, FoldLeftXHelp;
1781+ InstallGlobalFunction( FoldLeftX, function ( gens, f, init, extra... )
1782+ local abortFunc, acc, args, FoldLeftXHelp;
1783+
1784+ # TODO: add a way to do short circuiting / early abort.
1785+ #
1786+ # one approach is to use fp pattern, via IteratorX (tricky to do; overhead?)
1787+ # alternatively, allow optional extra argument:
1788+ # variant 1: extra arg is abortFunc(); called after each
1789+ # call to the foldFunc, return a bool
1790+ # variant 2: extra arg is a plain list abortList
1791+
1792+ # TODO: add abortFunc to FoldLeft / FoldLeftOp, too
1793+
1794+ if Length(extra) > 0 then
1795+ abortFunc := extra[ 1 ] ;
1796+ else
1797+ abortFunc := ReturnFalse;
1798+ fi ;
17831799
17841800 acc := init;
17851801
@@ -1800,21 +1816,26 @@ InstallGlobalFunction( FoldLeftX, function ( gens, f, init )
18001816 if gen = true then
18011817 genIndex := genIndex + 1 ;
18021818 elif gen = false then
1803- return ;
1819+ return false ;
18041820 elif IsListOrCollection( gen ) then
18051821 for val in gen do
18061822 args[ valIndex] := val;
1807- FoldLeftXHelp( genIndex+ 1 , valIndex+ 1 );
1823+ if FoldLeftXHelp( genIndex+ 1 , valIndex+ 1 ) then
1824+ return true ;
1825+ fi ;
18081826 od ;
18091827 Unbind ( args[ valIndex] );
1810- return ;
1828+ return false ;
18111829 else
18121830 Error( " gens[" ,genIndex," ] must be a collection, a list, a boolean, " ,
18131831 " or a function" );
18141832 fi ;
18151833 od ;
18161834 acc := f( acc, args );
1835+ return false ;
1836+ # return abortFunc( acc );
18171837 end ;
1838+ # TODO: optimize the case where Length(gens) <= 1? <= 2? <= 3?
18181839
18191840 FoldLeftXHelp( 1 , 1 );
18201841 return acc;
@@ -1831,6 +1852,38 @@ ForAllX(Primes, [1..10], {p,n} -> IsPrimePowerInt(p^n));
18311852ForAllX([ 2 .. 6 ] , IsPrimeInt);
18321853ForAllX([ 2 .. 6 ] , [ 1 .. 10 ] , { p,n} -> IsPrimePowerInt(p^ n));
18331854
1855+ FoldLeftX([ [ 1 .. 10 ] , Primes ] , { acc,args} -> acc+ Sum(args), 0 , false );
1856+ FOLD_LEFT_X([ [ 1 .. 10 ] , Primes ] , { acc,args} -> acc+ Sum(args), 0 , false );
1857+
1858+ # timings
1859+ # ForAll([1..2^20], IsInt); time;
1860+ # ForAllX([1..2^20], IsInt); time;
1861+ # ForAllX([1..2^20], [1,2], {a,b}->IsInt(a+b)); time;
1862+ #
1863+ # gap> ForAllX([1..2^20], [1,2], {a,b}->IsInt(a+b)); time;
1864+ # true
1865+ # 1614
1866+ # gap> ForAllX([1..2^20], [1], {a,b}->IsInt(a+b)); time;
1867+ # true
1868+ # 1029
1869+ # gap> ForAllX([1..2^20], {a}->IsInt(a+a)); time;
1870+ # true
1871+ # 592
1872+
1873+ # gap> ForAll([1..2^20], {a}->IsInt(a+a)); time;
1874+ # true
1875+ # 103
1876+
1877+
1878+ # gap> ForAllX([1..2^20], [1], ReturnTrue); time;
1879+ # true
1880+ # 759
1881+ # gap> ForAllX([1..2^20], ReturnTrue); time;
1882+ # true
1883+ # 348
1884+ # gap> ForAll([1..2^20], ReturnTrue); time;
1885+ # true
1886+ # 24
18341887
18351888fi ;
18361889
@@ -1844,11 +1897,11 @@ fi;
18441897InstallGlobalFunction( SetX, function ( arg )
18451898 local f;
18461899 f := Remove(arg);
1847- return FoldLeftX (arg,
1900+ return FOLD_LEFT_X (arg,
18481901 function (acc, x )
18491902 AddSet(acc, CallFuncList(f, x));
18501903 return acc;
1851- end , [] );
1904+ end , [] , false );
18521905end );
18531906
18541907
@@ -1859,12 +1912,12 @@ end );
18591912InstallGlobalFunction( SumX, function ( arg )
18601913 local f;
18611914 f := Remove(arg);
1862- return FoldLeftX (arg,
1915+ return FOLD_LEFT_X (arg,
18631916 function (acc, x )
18641917 x := CallFuncList(f, x);
18651918 if acc = fail then return x; fi ;
18661919 return acc + x;
1867- end , fail );
1920+ end , fail , false );
18681921end );
18691922
18701923
@@ -1875,12 +1928,12 @@ end );
18751928InstallGlobalFunction( ProductX, function ( arg )
18761929 local f;
18771930 f := Remove(arg);
1878- return FoldLeftX (arg,
1931+ return FOLD_LEFT_X (arg,
18791932 function (acc, x )
18801933 x := CallFuncList(f, x);
18811934 if acc = fail then return x; fi ;
18821935 return acc * x;
1883- end , fail );
1936+ end , fail , false );
18841937end );
18851938
18861939
@@ -1889,16 +1942,10 @@ end );
18891942# M ForAllX(<obj>,...)
18901943# #
18911944InstallGlobalFunction( ForAllX, function ( arg )
1892- # local f;
1893- # f := Remove(args);
1894- # return FoldLeftX(args, {acc,x} -> acc and CallFuncList(f, x), true);
1895- local f, abort;
1896- f := Remove(args);
1897- abort := false ;
1898- Add(args, arg -> not abort);
1899- # TODO: implement early abort
1900- return FoldLeftX(args, { acc,x} -> acc and CallFuncList(f, x), true );
1901- end ;
1945+ local f;
1946+ f := Remove(arg);
1947+ return FOLD_LEFT_X(arg, { acc,x} -> acc and CallFuncList(f, x), true , acc -> acc = false );
1948+ end );
19021949
19031950
19041951# ############################################################################
@@ -1907,10 +1954,10 @@ end;
19071954# #
19081955InstallGlobalFunction( ForAnyX, function ( arg )
19091956 local f;
1910- f := Remove(args );
1957+ f := Remove(arg );
19111958 # TODO: implement early abort
1912- return FoldLeftX(args , { acc,x} -> acc or CallFuncList(f, x), false );
1913- end ;
1959+ return FOLD_LEFT_X(arg , { acc,x} -> acc or CallFuncList(f, x), false , acc -> acc = true );
1960+ end ) ;
19141961
19151962
19161963# ############################################################################
0 commit comments