diff --git a/base/operators.jl b/base/operators.jl index a35c44276a2e4..a91122e72dd31 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -577,17 +577,37 @@ xor(x::Integer) = x const ⊻ = xor -# foldl for argument lists. expand recursively up to a point, then -# switch to a loop. this allows small cases like `a+b+c+d` to be inlined +# foldl for argument lists. expand fully up to a point, then +# switch to a loop. this allows small cases like `a+b+c+d` to be managed # efficiently, without a major slowdown for `+(x...)` when `x` is big. -afoldl(op,a) = a -afoldl(op,a,b) = op(a,b) -afoldl(op,a,b,c...) = afoldl(op, op(a,b), c...) -function afoldl(op,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,qs...) - y = op(op(op(op(op(op(op(op(op(op(op(op(op(op(op(a,b),c),d),e),f),g),h),i),j),k),l),m),n),o),p) - for x in qs; y = op(y,x); end - y +# n.b.: keep this method count small, so it can be inferred without hitting the +# method count limit in inference +afoldl(op, a) = a +function afoldl(op, a, bs...) + l = length(bs) + i = 0; y = a; l == i && return y + #@nexprs 15 i -> (y = op(y, bs[i]); l == i && return y) + i = 1; y = op(y, bs[i]); l == i && return y + i = 2; y = op(y, bs[i]); l == i && return y + i = 3; y = op(y, bs[i]); l == i && return y + i = 4; y = op(y, bs[i]); l == i && return y + i = 5; y = op(y, bs[i]); l == i && return y + i = 6; y = op(y, bs[i]); l == i && return y + i = 7; y = op(y, bs[i]); l == i && return y + i = 8; y = op(y, bs[i]); l == i && return y + i = 9; y = op(y, bs[i]); l == i && return y + i = 10; y = op(y, bs[i]); l == i && return y + i = 11; y = op(y, bs[i]); l == i && return y + i = 12; y = op(y, bs[i]); l == i && return y + i = 13; y = op(y, bs[i]); l == i && return y + i = 14; y = op(y, bs[i]); l == i && return y + i = 15; y = op(y, bs[i]); l == i && return y + for i in (i + 1):l + y = op(y, bs[i]) + end + return y end +typeof(afoldl).name.mt.max_args = 18 for op in (:+, :*, :&, :|, :xor, :min, :max, :kron) @eval begin diff --git a/test/operators.jl b/test/operators.jl index c14858657ce3b..7b7711037cfb7 100644 --- a/test/operators.jl +++ b/test/operators.jl @@ -277,3 +277,5 @@ end a = rand(3, 3) @test transpose(a) === a'ᵀ + +@test [Base.afoldl(+, 1:i...) for i = 1:40] == [i * (i + 1) ÷ 2 for i = 1:40]