From bcfe26144ede526832c3e8a0a5abbcf1579a3f1e Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 24 Apr 2025 18:25:39 -0400 Subject: [PATCH 01/11] consistently use `init` in whole-array mapreduce --- base/missing.jl | 36 +++++++++++++-------------- base/reduce.jl | 47 +++++++++++++++++++++-------------- base/reducedim.jl | 8 +++--- base/reinterpretarray.jl | 18 ++++++++------ contrib/juliac-buildscript.jl | 8 +++--- test/reducedim.jl | 3 ++- 6 files changed, 66 insertions(+), 54 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index 6a8c09dc02aff..bee872de3ff3d 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -270,10 +270,10 @@ end # Optimized mapreduce implementation # The generic method is faster when !(eltype(A) >: Missing) since it does not need # additional loops to identify the two first non-missing values of each block -mapreduce(f, op, itr::SkipMissing{<:AbstractArray}) = - _mapreduce(f, op, IndexStyle(itr.x), eltype(itr.x) >: Missing ? itr : itr.x) +mapreduce(f, op, itr::SkipMissing{<:AbstractArray}; init=Base._InitialValue()) = + _mapreduce(f, op, IndexStyle(itr.x), eltype(itr.x) >: Missing ? itr : itr.x, init) -function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}) +function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}, init) A = itr.x ai = missing inds = LinearIndices(A) @@ -283,27 +283,27 @@ function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}) @inbounds ai = A[i] !ismissing(ai) && break end - ismissing(ai) && return mapreduce_empty(f, op, eltype(itr)) + ismissing(ai) && return _mapreduce_start(f, op, itr, init) a1::eltype(itr) = ai - i == typemax(typeof(i)) && return mapreduce_first(f, op, a1) + i == typemax(typeof(i)) && return _mapreduce_start(f, op, itr, init, a1) i += 1 ai = missing for outer i in i:ilast @inbounds ai = A[i] !ismissing(ai) && break end - ismissing(ai) && return mapreduce_first(f, op, a1) + ismissing(ai) && return _mapreduce_start(f, op, itr, init, a1) # We know A contains at least two non-missing entries: the result cannot be nothing - something(mapreduce_impl(f, op, itr, first(inds), last(inds))) + something(mapreduce_impl(f, op, itr, init, first(inds), last(inds))) end -_mapreduce(f, op, ::IndexCartesian, itr::SkipMissing) = mapfoldl(f, op, itr) +_mapreduce(f, op, ::IndexCartesian, itr::SkipMissing, init) = mapfoldl(f, op, itr; init) -mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = - mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op)) +mapreduce_impl(f, op, A::SkipMissing, init, ifirst::Integer, ilast::Integer) = + mapreduce_impl(f, op, A, init, ifirst, ilast, pairwise_blocksize(f, op)) # Returns nothing when the input contains only missing values, and Some(x) otherwise -@noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray}, +@noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray}, init, ifirst::Integer, ilast::Integer, blksize::Int) A = itr.x if ifirst > ilast @@ -313,7 +313,7 @@ mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = if ismissing(a1) return nothing else - return Some(mapreduce_first(f, op, a1)) + return Some(_mapreduce_start(f, op, itr, init, a1)) end elseif ilast - ifirst < blksize # sequential portion @@ -325,18 +325,18 @@ mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = end ismissing(ai) && return nothing a1 = ai::eltype(itr) - i == typemax(typeof(i)) && return Some(mapreduce_first(f, op, a1)) + i == typemax(typeof(i)) && return Some(mapreduce_mapreduce_start(f, op, itr, init, a1)) i += 1 ai = missing for outer i in i:ilast @inbounds ai = A[i] !ismissing(ai) && break end - ismissing(ai) && return Some(mapreduce_first(f, op, a1)) + ismissing(ai) && return Some(_mapreduce_start(f, op, itr, init, a1)) a2 = ai::eltype(itr) - i == typemax(typeof(i)) && return Some(op(f(a1), f(a2))) + i == typemax(typeof(i)) && return Some(_mapreduce_start(f, op, itr, init, a1, a2)) i += 1 - v = op(f(a1), f(a2)) + v = _mapreduce_start(f, op, itr, init, a1, a2) @simd for i = i:ilast @inbounds ai = A[i] if !ismissing(ai) @@ -347,8 +347,8 @@ mapreduce_impl(f, op, A::SkipMissing, ifirst::Integer, ilast::Integer) = else # pairwise portion imid = ifirst + (ilast - ifirst) >> 1 - v1 = mapreduce_impl(f, op, itr, ifirst, imid, blksize) - v2 = mapreduce_impl(f, op, itr, imid+1, ilast, blksize) + v1 = mapreduce_impl(f, op, itr, init, ifirst, imid, blksize) + v2 = mapreduce_impl(f, op, itr, init, imid+1, ilast, blksize) if v1 === nothing && v2 === nothing return nothing elseif v1 === nothing diff --git a/base/reduce.jl b/base/reduce.jl index c132ef385358d..265ed15f025bf 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -235,6 +235,14 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) ## reduce & mapreduce +_mapreduce_start(f, op, A, ::_InitialValue) = mapreduce_empty(f, op, eltype(A)) +_mapreduce_start(f, op, A, ::_InitialValue, a1) = mapreduce_first(f, op, a1) +_mapreduce_start(f, op, A, ::_InitialValue, a1, a2) = op(f(a1), f(a2)) +_mapreduce_start(f, op, A, init) = init +_mapreduce_start(f, op, A, init, a1) = op(init, f(a1)) +_mapreduce_start(f, op, A, init, a1, a2) = op(op(init, f(a1)), f(a2)) + + # `mapreduce_impl()` is called by `mapreduce()` (via `_mapreduce()`, when `A` # supports linear indexing) and does actual calculations (for `A[ifirst:ilast]` subset). # For efficiency, no parameter validity checks are done, it's the caller's responsibility. @@ -242,16 +250,15 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) # This is a generic implementation of `mapreduce_impl()`, # certain `op` (e.g. `min` and `max`) may have their own specialized versions. -@noinline function mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, +@noinline function mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, init, ifirst::Integer, ilast::Integer, blksize::Int) if ifirst == ilast - @inbounds a1 = A[ifirst] - return mapreduce_first(f, op, a1) + throw(AssertionError("mapreduce_impl must process at least two elements")) elseif ilast - ifirst < blksize # sequential portion @inbounds a1 = A[ifirst] @inbounds a2 = A[ifirst+1] - v = op(f(a1), f(a2)) + v = _mapreduce_start(f, op, A, init, a1, a2) @simd for i = ifirst + 2 : ilast @inbounds ai = A[i] v = op(v, f(ai)) @@ -260,14 +267,14 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) else # pairwise portion imid = ifirst + (ilast - ifirst) >> 1 - v1 = mapreduce_impl(f, op, A, ifirst, imid, blksize) - v2 = mapreduce_impl(f, op, A, imid+1, ilast, blksize) + v1 = mapreduce_impl(f, op, A, init, ifirst, imid, blksize) + v2 = mapreduce_impl(f, op, A, init, imid+1, ilast, blksize) return op(v1, v2) end end -mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, ifirst::Integer, ilast::Integer) = - mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op)) +mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, init, ifirst::Integer, ilast::Integer) = + mapreduce_impl(f, op, A, init, ifirst, ilast, pairwise_blocksize(f, op)) """ mapreduce(f, op, itrs...; [init]) @@ -412,34 +419,34 @@ The default is `reduce_first(op, f(x))`. """ mapreduce_first(f, op, x) = reduce_first(op, f(x)) -_mapreduce(f, op, A::AbstractArrayOrBroadcasted) = _mapreduce(f, op, IndexStyle(A), A) +_mapreduce(f, op, A::AbstractArrayOrBroadcasted, init) = _mapreduce(f, op, IndexStyle(A), A, init) -function _mapreduce(f, op, ::IndexLinear, A::AbstractArrayOrBroadcasted) +function _mapreduce(f, op, ::IndexLinear, A::AbstractArrayOrBroadcasted, init) inds = LinearIndices(A) n = length(inds) if n == 0 - return mapreduce_empty_iter(f, op, A, IteratorEltype(A)) + return _mapreduce_start(f, op, A, init) elseif n == 1 @inbounds a1 = A[first(inds)] - return mapreduce_first(f, op, a1) + return _mapreduce_start(f, op, A, init, a1) elseif n < 16 # process short array here, avoid mapreduce_impl() compilation @inbounds i = first(inds) @inbounds a1 = A[i] @inbounds a2 = A[i+=1] - s = op(f(a1), f(a2)) + s = _mapreduce_start(f, op, A, init, a1, a2) while i < last(inds) @inbounds Ai = A[i+=1] s = op(s, f(Ai)) end return s else - return mapreduce_impl(f, op, A, first(inds), last(inds)) + return mapreduce_impl(f, op, A, init, first(inds), last(inds)) end end -mapreduce(f, op, a::Number) = mapreduce_first(f, op, a) +mapreduce(f, op, a::Number; init=Base._InitialValue()) = _mapreduce_start(f, op, a, init, a) -_mapreduce(f, op, ::IndexCartesian, A::AbstractArrayOrBroadcasted) = mapfoldl(f, op, A) +_mapreduce(f, op, ::IndexCartesian, A::AbstractArrayOrBroadcasted, init) = mapfoldl(f, op, A; init) """ reduce(op, itr; [init]) @@ -629,13 +636,15 @@ isbadzero(op, x) = false isgoodzero(::typeof(max), x) = isbadzero(min, x) isgoodzero(::typeof(min), x) = isbadzero(max, x) -function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, +function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, init, A::AbstractArrayOrBroadcasted, first::Int, last::Int) + last == first && throw(AssertionError("mapreduce_impl must process at least two elements")) a1 = @inbounds A[first] - v1 = mapreduce_first(f, op, a1) + a2 = @inbounds A[first+1] + v1 = _mapreduce_start(f, op, A, init, a1, a2) v2 = v3 = v4 = v1 chunk_len = 256 - start = first + 1 + start = first + 2 simdstop = start + chunk_len - 4 while simdstop <= last - 3 for i in start:4:simdstop diff --git a/base/reducedim.jl b/base/reducedim.jl index 0478afe1a46b6..193f7bab1b604 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -259,7 +259,7 @@ function _mapreducedim!(f, op, R::AbstractArray, A::AbstractArrayOrBroadcasted) nslices = div(length(A), lsiz) ibase = first(LinearIndices(A))-1 for i in eachindex(R) - r = op(@inbounds(R[i]), mapreduce_impl(f, op, A, ibase+1, ibase+lsiz)) + r = op(@inbounds(R[i]), mapreduce_impl(f, op, A, _InitialValue(), ibase+1, ibase+lsiz)) @inbounds R[i] = r ibase += lsiz end @@ -329,10 +329,10 @@ mapreduce(f, op, A::AbstractArrayOrBroadcasted, B::AbstractArrayOrBroadcasted... reduce(op, map(f, A, B...); kw...) _mapreduce_dim(f, op, nt, A::AbstractArrayOrBroadcasted, ::Colon) = - mapfoldl_impl(f, op, nt, A) + _mapreduce(f, op, IndexStyle(A), A, nt) -_mapreduce_dim(f, op, ::_InitialValue, A::AbstractArrayOrBroadcasted, ::Colon) = - _mapreduce(f, op, IndexStyle(A), A) +_mapreduce_dim(f, op, nt::_InitialValue, A::AbstractArrayOrBroadcasted, ::Colon) = + _mapreduce(f, op, IndexStyle(A), A, nt) _mapreduce_dim(f, op, nt, A::AbstractArrayOrBroadcasted, dims) = mapreducedim!(f, op, reducedim_initarray(A, dims, nt), A) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index d7f6a15afa0a7..bceb4b17a67b2 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -905,17 +905,19 @@ end # Reductions with IndexSCartesian2 -function _mapreduce(f::F, op::OP, style::IndexSCartesian2{K}, A::AbstractArrayOrBroadcasted) where {F,OP,K} +function _mapreduce(f::F, op::OP, style::IndexSCartesian2{K}, A::AbstractArrayOrBroadcasted, init) where {F,OP,K} inds = eachindex(style, A) n = size(inds)[2] if n == 0 - return mapreduce_empty_iter(f, op, A, IteratorEltype(A)) + return _mapreduce_start(f, op, A, init) + elseif n == 1 + return _mapreduce_start(f, op, A, init, first(A)) else - return mapreduce_impl(f, op, A, first(inds), last(inds)) + return mapreduce_impl(f, op, A, init, first(inds), last(inds)) end end -@noinline function mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, +@noinline function mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, init, ifirst::SCI, ilast::SCI, blksize::Int) where {F,OP,SCI<:SCartesianIndex2{K}} where K if ilast.j - ifirst.j < blksize # sequential portion @@ -937,11 +939,11 @@ end else # pairwise portion jmid = ifirst.j + (ilast.j - ifirst.j) >> 1 - v1 = mapreduce_impl(f, op, A, ifirst, SCI(K,jmid), blksize) - v2 = mapreduce_impl(f, op, A, SCI(1,jmid+1), ilast, blksize) + v1 = mapreduce_impl(f, op, A, init, ifirst, SCI(K,jmid), blksize) + v2 = mapreduce_impl(f, op, A, init, SCI(1,jmid+1), ilast, blksize) return op(v1, v2) end end -mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, ifirst::SCartesianIndex2, ilast::SCartesianIndex2) where {F,OP} = - mapreduce_impl(f, op, A, ifirst, ilast, pairwise_blocksize(f, op)) +mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, init, ifirst::SCartesianIndex2, ilast::SCartesianIndex2) where {F,OP} = + mapreduce_impl(f, op, A, init, ifirst, ilast, pairwise_blocksize(f, op)) diff --git a/contrib/juliac-buildscript.jl b/contrib/juliac-buildscript.jl index 0549afc0e1508..36d5900b79f90 100644 --- a/contrib/juliac-buildscript.jl +++ b/contrib/juliac-buildscript.jl @@ -106,10 +106,10 @@ end reduce(op, map(f, A...); kw...) _mapreduce_dim(f::F, op::F2, nt, A::AbstractArrayOrBroadcasted, ::Colon) where {F, F2} = - mapfoldl_impl(f, op, nt, A) + _mapreduce(f, op, IndexStyle(A), A, nt) - _mapreduce_dim(f::F, op::F2, ::_InitialValue, A::AbstractArrayOrBroadcasted, ::Colon) where {F, F2} = - _mapreduce(f, op, IndexStyle(A), A) + _mapreduce_dim(f::F, op::F2, nt::_InitialValue, A::AbstractArrayOrBroadcasted, ::Colon) where {F, F2} = + _mapreduce(f, op, IndexStyle(A), A, nt) _mapreduce_dim(f::F, op::F2, nt, A::AbstractArrayOrBroadcasted, dims) where {F, F2} = mapreducedim!(f, op, reducedim_initarray(A, dims, nt), A) @@ -121,7 +121,7 @@ end reduce_empty_iter(MappingRF(f, op), itr, ItrEltype) mapreduce_first(f::F, op::F2, x) where {F,F2} = reduce_first(op, f(x)) - _mapreduce(f::F, op::F2, A::AbstractArrayOrBroadcasted) where {F,F2} = _mapreduce(f, op, IndexStyle(A), A) + _mapreduce(f::F, op::F2, A::AbstractArrayOrBroadcasted, init) where {F,F2} = _mapreduce(f, op, IndexStyle(A), A, init) mapreduce_empty(::typeof(identity), op::F, T) where {F} = reduce_empty(op, T) mapreduce_empty(::typeof(abs), op::F, T) where {F} = abs(reduce_empty(op, T)) mapreduce_empty(::typeof(abs2), op::F, T) where {F} = abs2(reduce_empty(op, T)) diff --git a/test/reducedim.jl b/test/reducedim.jl index 6a6f20214058c..26b31ce6e9f49 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -693,7 +693,8 @@ end @test_throws TypeError count!([1], [1]) end -@test @inferred(count(false:true, dims=:, init=0x0004)) === 0x0005 +@test count(false:true, dims=:, init=0x0004) === 0x0005 +@test_broken @inferred(count(false:true, dims=:, init=0x0004)) === 0x0005 @test @inferred(count(isodd, reshape(1:9, 3, 3), dims=:, init=Int128(0))) === Int128(5) @testset "reduced_index for BigInt (issue #39995)" begin From c07a5f7cbb2fd31f28c7d594f914825e0b13f547 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Sat, 26 Apr 2025 22:07:17 -0400 Subject: [PATCH 02/11] TEMPORARILY USE STDLIB BRANCHES --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 + .../sha512 | 1 + stdlib/SparseArrays.version | 8 ++++---- stdlib/Statistics.version | 8 ++++---- 6 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 create mode 100644 deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 create mode 100644 deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 create mode 100644 deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 diff --git a/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 b/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 new file mode 100644 index 0000000000000..e8cd8f00e5168 --- /dev/null +++ b/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 @@ -0,0 +1 @@ +bf03172d3f93565b1316884f65d1220b diff --git a/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 b/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 new file mode 100644 index 0000000000000..2d2a8c2599a05 --- /dev/null +++ b/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 @@ -0,0 +1 @@ +ff43fb7498283c1efae75af37ee1db548a4b7505c8bd2f0f71b0fdd3db7620e38c74a49042a5b4336e2c82dee3106dd6958dc14dc8565d3841bac28091cf7d69 diff --git a/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 b/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 new file mode 100644 index 0000000000000..f9cec8744f426 --- /dev/null +++ b/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 @@ -0,0 +1 @@ +b10d43cb41f0ddb747ef877b4a739b49 diff --git a/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 b/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 new file mode 100644 index 0000000000000..e6176ca63120b --- /dev/null +++ b/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 @@ -0,0 +1 @@ +29d84fd2a8dc2c1c324cff742f3ef4754de2d3cec88a8bcf83ca42cfdb361b9f5616f5c7dee86972afa93cb045345e2017fabc0ccd39ea9ad1681e8635bc22e0 diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 9498fbe4943f9..6a851675aa6f0 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ -SPARSEARRAYS_BRANCH = main -SPARSEARRAYS_SHA1 = f3610c07fe0403792743d9c9802a25642a5f2d18 -SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git -SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 +SPARSEARRAYS_BRANCH = mb/mapreduceinit +SPARSEARRAYS_SHA1 = f035300524563dd756fbab5f9a017e509ba97ec7 +SPARSEARRAYS_GIT_URL := https://github.com/mbauman/SparseArrays.jl.git +SPARSEARRAYS_TAR_URL = https://api.github.com/repos/mbauman/SparseArrays.jl/tarball/$1 diff --git a/stdlib/Statistics.version b/stdlib/Statistics.version index e6f0a62b3cec5..985b3c9ab78e2 100644 --- a/stdlib/Statistics.version +++ b/stdlib/Statistics.version @@ -1,4 +1,4 @@ -STATISTICS_BRANCH = master -STATISTICS_SHA1 = 77bd5707f143eb624721a7df28ddef470e70ecef -STATISTICS_GIT_URL := https://github.com/JuliaStats/Statistics.jl.git -STATISTICS_TAR_URL = https://api.github.com/repos/JuliaStats/Statistics.jl/tarball/$1 +STATISTICS_BRANCH = mb/mapreduceinit +STATISTICS_SHA1 = 01c1c43c879d31c1a948b30e964cbdbcbc96d958 +STATISTICS_GIT_URL := https://github.com/mbauman/Statistics.jl.git +STATISTICS_TAR_URL = https://api.github.com/repos/mbauman/Statistics.jl/tarball/$1 From 30a6db06f6ca8e2763e8d88f74cb7f7e40121697 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Sat, 26 Apr 2025 22:07:39 -0400 Subject: [PATCH 03/11] better error message for no eltype --- base/reduce.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/base/reduce.jl b/base/reduce.jl index 265ed15f025bf..56620ccc73b83 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -235,7 +235,10 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) ## reduce & mapreduce -_mapreduce_start(f, op, A, ::_InitialValue) = mapreduce_empty(f, op, eltype(A)) +_empty_eltype(x) = _empty_eltype(x, IteratorEltype(x)) +_empty_eltype(x, ::HasEltype) = eltype(x) +_empty_eltype(_, _) = _empty_reduce_error() +_mapreduce_start(f, op, A, ::_InitialValue) = mapreduce_empty(f, op, _empty_eltype(A)) _mapreduce_start(f, op, A, ::_InitialValue, a1) = mapreduce_first(f, op, a1) _mapreduce_start(f, op, A, ::_InitialValue, a1, a2) = op(f(a1), f(a2)) _mapreduce_start(f, op, A, init) = init From fb1d095f8b30ef66c46e3accbb432e8ed14ce941 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Sun, 27 Apr 2025 00:58:00 -0400 Subject: [PATCH 04/11] always use reduce_first? --- base/reduce.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 56620ccc73b83..efe7e33d9f555 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -238,12 +238,19 @@ foldr(op, itr; kw...) = mapfoldr(identity, op, itr; kw...) _empty_eltype(x) = _empty_eltype(x, IteratorEltype(x)) _empty_eltype(x, ::HasEltype) = eltype(x) _empty_eltype(_, _) = _empty_reduce_error() +""" + _mapreduce_start(f, op, A, init, [a1], [a2]) + +Perform the first step in a mapped reduction over `A` with 0, 1, or more elements. +The two element method may be called multiple times within a single reduction at +the start of each new chain of `op` calls. +""" _mapreduce_start(f, op, A, ::_InitialValue) = mapreduce_empty(f, op, _empty_eltype(A)) _mapreduce_start(f, op, A, ::_InitialValue, a1) = mapreduce_first(f, op, a1) -_mapreduce_start(f, op, A, ::_InitialValue, a1, a2) = op(f(a1), f(a2)) +_mapreduce_start(f, op, A, ::_InitialValue, a1, a2) = op(mapreduce_first(f, op, a1), f(a2)) _mapreduce_start(f, op, A, init) = init -_mapreduce_start(f, op, A, init, a1) = op(init, f(a1)) -_mapreduce_start(f, op, A, init, a1, a2) = op(op(init, f(a1)), f(a2)) +_mapreduce_start(f, op, A, init, a1) = op(init, mapreduce_first(f, op, a1)) +_mapreduce_start(f, op, A, init, a1, a2) = op(op(init, mapreduce_first(f, op, a1)), f(a2)) # `mapreduce_impl()` is called by `mapreduce()` (via `_mapreduce()`, when `A` From fa7490a2940e2d0214368ca0cc6bafc8f6f32673 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 28 Apr 2025 11:29:50 -0400 Subject: [PATCH 05/11] fix tests --- base/missing.jl | 2 +- base/reduce.jl | 4 ++-- test/reduce.jl | 2 +- test/reducedim.jl | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index bee872de3ff3d..00a1ba2168f99 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -325,7 +325,7 @@ mapreduce_impl(f, op, A::SkipMissing, init, ifirst::Integer, ilast::Integer) = end ismissing(ai) && return nothing a1 = ai::eltype(itr) - i == typemax(typeof(i)) && return Some(mapreduce_mapreduce_start(f, op, itr, init, a1)) + i == typemax(typeof(i)) && return Some(_mapreduce_start(f, op, itr, init, a1)) i += 1 ai = missing for outer i in i:ilast diff --git a/base/reduce.jl b/base/reduce.jl index efe7e33d9f555..8362bf673ceaf 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -646,8 +646,8 @@ isbadzero(op, x) = false isgoodzero(::typeof(max), x) = isbadzero(min, x) isgoodzero(::typeof(min), x) = isbadzero(max, x) -function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, init, - A::AbstractArrayOrBroadcasted, first::Int, last::Int) +function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, + A::AbstractArrayOrBroadcasted, init, first::Integer, last::Integer) last == first && throw(AssertionError("mapreduce_impl must process at least two elements")) a1 = @inbounds A[first] a2 = @inbounds A[first+1] diff --git a/test/reduce.jl b/test/reduce.jl index f5140c8a34bd9..c8045a6dc89ca 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -571,7 +571,7 @@ struct NonFunctionIsZero end @test count(Iterators.repeated(true, 3), init=0x04) === 0x07 @test count(!=(2), Iterators.take(1:7, 3), init=Int32(0)) === Int32(2) @test count(identity, [true, false], init=Int8(5)) === Int8(6) -@test count(!, [true false; false true], dims=:, init=Int16(0)) === Int16(2) +@test count(!, [true false; false true], dims=:, init=Int16(0)) === 2 @test isequal(count(identity, [true false; false true], dims=2, init=UInt(4)), reshape(UInt[5, 5], 2, 1)) ## cumsum, cummin, cummax diff --git a/test/reducedim.jl b/test/reducedim.jl index 26b31ce6e9f49..7bdbe0d90dca4 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -693,8 +693,8 @@ end @test_throws TypeError count!([1], [1]) end -@test count(false:true, dims=:, init=0x0004) === 0x0005 -@test_broken @inferred(count(false:true, dims=:, init=0x0004)) === 0x0005 +@test count(false:true, dims=:, init=0x0004) === 5 +@test_broken @inferred(count(false:true, dims=:, init=0x0004)) === 5 @test @inferred(count(isodd, reshape(1:9, 3, 3), dims=:, init=Int128(0))) === Int128(5) @testset "reduced_index for BigInt (issue #39995)" begin From 8d6b63c3a6c15e9433fd5a0ff50b3609d9e9eb5e Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Mon, 28 Apr 2025 11:43:16 -0400 Subject: [PATCH 06/11] `count`'s init is initialization, not type assertion --- base/reduce.jl | 6 ++++-- test/reduce.jl | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 8362bf673ceaf..6680d0da0baa0 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -1159,8 +1159,10 @@ count(f, itr; init=0) = _simple_count(f, itr, init) _simple_count(pred, itr, init) = sum(_bool(pred), itr; init) -function _simple_count(::typeof(identity), x::Array{Bool}, init::T=0) where {T} - n::T = init +function _simple_count(::typeof(identity), x::Array{Bool}, init=0) + v0 = _mapreduce_start(identity, Base.add_sum, x, init, false) + T = typeof(v0) + n::T = v0 chunks = length(x) รท sizeof(UInt) mask = 0x0101010101010101 % UInt GC.@preserve x begin diff --git a/test/reduce.jl b/test/reduce.jl index c8045a6dc89ca..37a48178e24d6 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -570,7 +570,8 @@ struct NonFunctionIsZero end @test count(Iterators.repeated(true, 3), init=0x04) === 0x07 @test count(!=(2), Iterators.take(1:7, 3), init=Int32(0)) === Int32(2) -@test count(identity, [true, false], init=Int8(5)) === Int8(6) +@test count(identity, [true, false], init=Int8(5)) === 6 +@test @inferred(count(identity, [true, false], init=Int8(5))) === 6 @test count(!, [true false; false true], dims=:, init=Int16(0)) === 2 @test isequal(count(identity, [true false; false true], dims=2, init=UInt(4)), reshape(UInt[5, 5], 2, 1)) From 57fbe3334df35ce1b17778f7a510dd97bfd38ddd Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 1 May 2025 15:56:51 -0400 Subject: [PATCH 07/11] simplify reduction start to 2*2 cases: (empty/not) * (init/not) --- base/missing.jl | 4 ++-- base/reduce.jl | 20 +++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index 00a1ba2168f99..86a269d2fee60 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -334,9 +334,9 @@ mapreduce_impl(f, op, A::SkipMissing, init, ifirst::Integer, ilast::Integer) = end ismissing(ai) && return Some(_mapreduce_start(f, op, itr, init, a1)) a2 = ai::eltype(itr) - i == typemax(typeof(i)) && return Some(_mapreduce_start(f, op, itr, init, a1, a2)) + i == typemax(typeof(i)) && return Some(op(_mapreduce_start(f, op, itr, init, a1), f(a2))) i += 1 - v = _mapreduce_start(f, op, itr, init, a1, a2) + v = op(_mapreduce_start(f, op, itr, init, a1), f(a2)) @simd for i = i:ilast @inbounds ai = A[i] if !ismissing(ai) diff --git a/base/reduce.jl b/base/reduce.jl index 6680d0da0baa0..7e6555900bf8f 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -239,18 +239,16 @@ _empty_eltype(x) = _empty_eltype(x, IteratorEltype(x)) _empty_eltype(x, ::HasEltype) = eltype(x) _empty_eltype(_, _) = _empty_reduce_error() """ - _mapreduce_start(f, op, A, init, [a1], [a2]) + _mapreduce_start(f, op, A, init, [a1]) -Perform the first step in a mapped reduction over `A` with 0, 1, or more elements. -The two element method may be called multiple times within a single reduction at +Perform the first step in a mapped reduction over `A` with 0 or one or more elements. +The one-element method may be called multiple times within a single reduction at the start of each new chain of `op` calls. """ _mapreduce_start(f, op, A, ::_InitialValue) = mapreduce_empty(f, op, _empty_eltype(A)) _mapreduce_start(f, op, A, ::_InitialValue, a1) = mapreduce_first(f, op, a1) -_mapreduce_start(f, op, A, ::_InitialValue, a1, a2) = op(mapreduce_first(f, op, a1), f(a2)) _mapreduce_start(f, op, A, init) = init _mapreduce_start(f, op, A, init, a1) = op(init, mapreduce_first(f, op, a1)) -_mapreduce_start(f, op, A, init, a1, a2) = op(op(init, mapreduce_first(f, op, a1)), f(a2)) # `mapreduce_impl()` is called by `mapreduce()` (via `_mapreduce()`, when `A` @@ -263,12 +261,12 @@ _mapreduce_start(f, op, A, init, a1, a2) = op(op(init, mapreduce_first(f, op, a1 @noinline function mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, init, ifirst::Integer, ilast::Integer, blksize::Int) if ifirst == ilast - throw(AssertionError("mapreduce_impl must process at least two elements")) + return _mapreduce_start(f, op, A, init, @inbounds(A[ifirst])) elseif ilast - ifirst < blksize # sequential portion @inbounds a1 = A[ifirst] @inbounds a2 = A[ifirst+1] - v = _mapreduce_start(f, op, A, init, a1, a2) + v = op(_mapreduce_start(f, op, A, init, a1), f(a2)) @simd for i = ifirst + 2 : ilast @inbounds ai = A[i] v = op(v, f(ai)) @@ -443,7 +441,7 @@ function _mapreduce(f, op, ::IndexLinear, A::AbstractArrayOrBroadcasted, init) @inbounds i = first(inds) @inbounds a1 = A[i] @inbounds a2 = A[i+=1] - s = _mapreduce_start(f, op, A, init, a1, a2) + s = op(_mapreduce_start(f, op, A, init, a1), f(a2)) while i < last(inds) @inbounds Ai = A[i+=1] s = op(s, f(Ai)) @@ -650,11 +648,11 @@ function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, A::AbstractArrayOrBroadcasted, init, first::Integer, last::Integer) last == first && throw(AssertionError("mapreduce_impl must process at least two elements")) a1 = @inbounds A[first] - a2 = @inbounds A[first+1] - v1 = _mapreduce_start(f, op, A, init, a1, a2) + v1 = _mapreduce_start(f, op, A, init, a1) + last == first && return v1 v2 = v3 = v4 = v1 chunk_len = 256 - start = first + 2 + start = first + 1 simdstop = start + chunk_len - 4 while simdstop <= last - 3 for i in start:4:simdstop From 8d2bc4d40d01c8e038821f196a990c4a09831336 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 1 May 2025 15:57:11 -0400 Subject: [PATCH 08/11] less disruptive internal method argument orderings --- base/missing.jl | 18 ++++++++---------- base/reduce.jl | 23 ++++++++++------------- base/reducedim.jl | 4 ++-- base/reinterpretarray.jl | 14 ++++++-------- 4 files changed, 26 insertions(+), 33 deletions(-) diff --git a/base/missing.jl b/base/missing.jl index 86a269d2fee60..6cd8121a1d464 100644 --- a/base/missing.jl +++ b/base/missing.jl @@ -273,7 +273,7 @@ end mapreduce(f, op, itr::SkipMissing{<:AbstractArray}; init=Base._InitialValue()) = _mapreduce(f, op, IndexStyle(itr.x), eltype(itr.x) >: Missing ? itr : itr.x, init) -function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}, init) +function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}, init=_InitialValue()) A = itr.x ai = missing inds = LinearIndices(A) @@ -294,18 +294,16 @@ function _mapreduce(f, op, ::IndexLinear, itr::SkipMissing{<:AbstractArray}, ini end ismissing(ai) && return _mapreduce_start(f, op, itr, init, a1) # We know A contains at least two non-missing entries: the result cannot be nothing - something(mapreduce_impl(f, op, itr, init, first(inds), last(inds))) + something(mapreduce_impl(f, op, itr, first(inds), last(inds), init)) end -_mapreduce(f, op, ::IndexCartesian, itr::SkipMissing, init) = mapfoldl(f, op, itr; init) - -mapreduce_impl(f, op, A::SkipMissing, init, ifirst::Integer, ilast::Integer) = - mapreduce_impl(f, op, A, init, ifirst, ilast, pairwise_blocksize(f, op)) +_mapreduce(f, op, ::IndexCartesian, itr::SkipMissing, init=_InitialValue()) = mapfoldl(f, op, itr; init) # Returns nothing when the input contains only missing values, and Some(x) otherwise -@noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray}, init, - ifirst::Integer, ilast::Integer, blksize::Int) +@noinline function mapreduce_impl(f, op, itr::SkipMissing{<:AbstractArray}, + ifirst::Integer, ilast::Integer, init=_InitialValue()) A = itr.x + blksize = pairwise_blocksize(f, op) if ifirst > ilast return nothing elseif ifirst == ilast @@ -347,8 +345,8 @@ mapreduce_impl(f, op, A::SkipMissing, init, ifirst::Integer, ilast::Integer) = else # pairwise portion imid = ifirst + (ilast - ifirst) >> 1 - v1 = mapreduce_impl(f, op, itr, init, ifirst, imid, blksize) - v2 = mapreduce_impl(f, op, itr, init, imid+1, ilast, blksize) + v1 = mapreduce_impl(f, op, itr, ifirst, imid, init) + v2 = mapreduce_impl(f, op, itr, imid+1, ilast, init) if v1 === nothing && v2 === nothing return nothing elseif v1 === nothing diff --git a/base/reduce.jl b/base/reduce.jl index 7e6555900bf8f..5aac0778ab16a 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -258,8 +258,9 @@ _mapreduce_start(f, op, A, init, a1) = op(init, mapreduce_first(f, op, a1)) # This is a generic implementation of `mapreduce_impl()`, # certain `op` (e.g. `min` and `max`) may have their own specialized versions. -@noinline function mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, init, - ifirst::Integer, ilast::Integer, blksize::Int) +@noinline function mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, + ifirst::Integer, ilast::Integer, init=_InitialValue()) + blksize = pairwise_blocksize(f, op) if ifirst == ilast return _mapreduce_start(f, op, A, init, @inbounds(A[ifirst])) elseif ilast - ifirst < blksize @@ -275,15 +276,12 @@ _mapreduce_start(f, op, A, init, a1) = op(init, mapreduce_first(f, op, a1)) else # pairwise portion imid = ifirst + (ilast - ifirst) >> 1 - v1 = mapreduce_impl(f, op, A, init, ifirst, imid, blksize) - v2 = mapreduce_impl(f, op, A, init, imid+1, ilast, blksize) + v1 = mapreduce_impl(f, op, A, ifirst, imid, init) + v2 = mapreduce_impl(f, op, A, imid+1, ilast, init) return op(v1, v2) end end -mapreduce_impl(f, op, A::AbstractArrayOrBroadcasted, init, ifirst::Integer, ilast::Integer) = - mapreduce_impl(f, op, A, init, ifirst, ilast, pairwise_blocksize(f, op)) - """ mapreduce(f, op, itrs...; [init]) @@ -427,9 +425,9 @@ The default is `reduce_first(op, f(x))`. """ mapreduce_first(f, op, x) = reduce_first(op, f(x)) -_mapreduce(f, op, A::AbstractArrayOrBroadcasted, init) = _mapreduce(f, op, IndexStyle(A), A, init) +_mapreduce(f, op, A::AbstractArrayOrBroadcasted, init=_InitialValue()) = _mapreduce(f, op, IndexStyle(A), A, init) -function _mapreduce(f, op, ::IndexLinear, A::AbstractArrayOrBroadcasted, init) +function _mapreduce(f, op, ::IndexLinear, A::AbstractArrayOrBroadcasted, init=_InitialValue()) inds = LinearIndices(A) n = length(inds) if n == 0 @@ -448,13 +446,13 @@ function _mapreduce(f, op, ::IndexLinear, A::AbstractArrayOrBroadcasted, init) end return s else - return mapreduce_impl(f, op, A, init, first(inds), last(inds)) + return mapreduce_impl(f, op, A, first(inds), last(inds), init) end end mapreduce(f, op, a::Number; init=Base._InitialValue()) = _mapreduce_start(f, op, a, init, a) -_mapreduce(f, op, ::IndexCartesian, A::AbstractArrayOrBroadcasted, init) = mapfoldl(f, op, A; init) +_mapreduce(f, op, ::IndexCartesian, A::AbstractArrayOrBroadcasted, init=_InitialValue()) = mapfoldl(f, op, A; init) """ reduce(op, itr; [init]) @@ -645,8 +643,7 @@ isgoodzero(::typeof(max), x) = isbadzero(min, x) isgoodzero(::typeof(min), x) = isbadzero(max, x) function mapreduce_impl(f, op::Union{typeof(max), typeof(min)}, - A::AbstractArrayOrBroadcasted, init, first::Integer, last::Integer) - last == first && throw(AssertionError("mapreduce_impl must process at least two elements")) + A::AbstractArrayOrBroadcasted, first::Integer, last::Integer, init) a1 = @inbounds A[first] v1 = _mapreduce_start(f, op, A, init, a1) last == first && return v1 diff --git a/base/reducedim.jl b/base/reducedim.jl index 193f7bab1b604..f3ee6988f0193 100644 --- a/base/reducedim.jl +++ b/base/reducedim.jl @@ -259,7 +259,7 @@ function _mapreducedim!(f, op, R::AbstractArray, A::AbstractArrayOrBroadcasted) nslices = div(length(A), lsiz) ibase = first(LinearIndices(A))-1 for i in eachindex(R) - r = op(@inbounds(R[i]), mapreduce_impl(f, op, A, _InitialValue(), ibase+1, ibase+lsiz)) + r = op(@inbounds(R[i]), mapreduce_impl(f, op, A, ibase+1, ibase+lsiz, _InitialValue())) @inbounds R[i] = r ibase += lsiz end @@ -332,7 +332,7 @@ _mapreduce_dim(f, op, nt, A::AbstractArrayOrBroadcasted, ::Colon) = _mapreduce(f, op, IndexStyle(A), A, nt) _mapreduce_dim(f, op, nt::_InitialValue, A::AbstractArrayOrBroadcasted, ::Colon) = - _mapreduce(f, op, IndexStyle(A), A, nt) + _mapreduce(f, op, IndexStyle(A), A) _mapreduce_dim(f, op, nt, A::AbstractArrayOrBroadcasted, dims) = mapreducedim!(f, op, reducedim_initarray(A, dims, nt), A) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index bceb4b17a67b2..681530bd4fa83 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -905,7 +905,7 @@ end # Reductions with IndexSCartesian2 -function _mapreduce(f::F, op::OP, style::IndexSCartesian2{K}, A::AbstractArrayOrBroadcasted, init) where {F,OP,K} +function _mapreduce(f::F, op::OP, style::IndexSCartesian2{K}, A::AbstractArrayOrBroadcasted, init=_InitialValue()) where {F,OP,K} inds = eachindex(style, A) n = size(inds)[2] if n == 0 @@ -917,8 +917,9 @@ function _mapreduce(f::F, op::OP, style::IndexSCartesian2{K}, A::AbstractArrayOr end end -@noinline function mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, init, - ifirst::SCI, ilast::SCI, blksize::Int) where {F,OP,SCI<:SCartesianIndex2{K}} where K +@noinline function mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, + ifirst::SCI, ilast::SCI, init=_InitialValue()) where {F,OP,SCI<:SCartesianIndex2{K}} where K + blksize = pairwise_blocksize(f, op) if ilast.j - ifirst.j < blksize # sequential portion @inbounds a1 = A[ifirst] @@ -939,11 +940,8 @@ end else # pairwise portion jmid = ifirst.j + (ilast.j - ifirst.j) >> 1 - v1 = mapreduce_impl(f, op, A, init, ifirst, SCI(K,jmid), blksize) - v2 = mapreduce_impl(f, op, A, init, SCI(1,jmid+1), ilast, blksize) + v1 = mapreduce_impl(f, op, A, ifirst, SCI(K,jmid), init) + v2 = mapreduce_impl(f, op, A, SCI(1,jmid+1), ilast, init) return op(v1, v2) end end - -mapreduce_impl(f::F, op::OP, A::AbstractArrayOrBroadcasted, init, ifirst::SCartesianIndex2, ilast::SCartesianIndex2) where {F,OP} = - mapreduce_impl(f, op, A, init, ifirst, ilast, pairwise_blocksize(f, op)) From b71840f18cfb7ccfcf2a3265ab83f8ee71652927 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 1 May 2025 15:57:24 -0400 Subject: [PATCH 09/11] Revert "TEMPORARILY USE STDLIB BRANCHES" This reverts commit c07a5f7cbb2fd31f28c7d594f914825e0b13f547. The Statistics branch is no longer needed; the Sparse branch is still beneficial but not required. --- .../md5 | 1 - .../sha512 | 1 - .../md5 | 1 - .../sha512 | 1 - stdlib/SparseArrays.version | 8 ++++---- stdlib/Statistics.version | 8 ++++---- 6 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 delete mode 100644 deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 delete mode 100644 deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 delete mode 100644 deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 diff --git a/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 b/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 deleted file mode 100644 index e8cd8f00e5168..0000000000000 --- a/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -bf03172d3f93565b1316884f65d1220b diff --git a/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 b/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 deleted file mode 100644 index 2d2a8c2599a05..0000000000000 --- a/deps/checksums/SparseArrays-f035300524563dd756fbab5f9a017e509ba97ec7.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -ff43fb7498283c1efae75af37ee1db548a4b7505c8bd2f0f71b0fdd3db7620e38c74a49042a5b4336e2c82dee3106dd6958dc14dc8565d3841bac28091cf7d69 diff --git a/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 b/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 deleted file mode 100644 index f9cec8744f426..0000000000000 --- a/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -b10d43cb41f0ddb747ef877b4a739b49 diff --git a/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 b/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 deleted file mode 100644 index e6176ca63120b..0000000000000 --- a/deps/checksums/Statistics-01c1c43c879d31c1a948b30e964cbdbcbc96d958.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -29d84fd2a8dc2c1c324cff742f3ef4754de2d3cec88a8bcf83ca42cfdb361b9f5616f5c7dee86972afa93cb045345e2017fabc0ccd39ea9ad1681e8635bc22e0 diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 6a851675aa6f0..9498fbe4943f9 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ -SPARSEARRAYS_BRANCH = mb/mapreduceinit -SPARSEARRAYS_SHA1 = f035300524563dd756fbab5f9a017e509ba97ec7 -SPARSEARRAYS_GIT_URL := https://github.com/mbauman/SparseArrays.jl.git -SPARSEARRAYS_TAR_URL = https://api.github.com/repos/mbauman/SparseArrays.jl/tarball/$1 +SPARSEARRAYS_BRANCH = main +SPARSEARRAYS_SHA1 = f3610c07fe0403792743d9c9802a25642a5f2d18 +SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git +SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 diff --git a/stdlib/Statistics.version b/stdlib/Statistics.version index 985b3c9ab78e2..e6f0a62b3cec5 100644 --- a/stdlib/Statistics.version +++ b/stdlib/Statistics.version @@ -1,4 +1,4 @@ -STATISTICS_BRANCH = mb/mapreduceinit -STATISTICS_SHA1 = 01c1c43c879d31c1a948b30e964cbdbcbc96d958 -STATISTICS_GIT_URL := https://github.com/mbauman/Statistics.jl.git -STATISTICS_TAR_URL = https://api.github.com/repos/mbauman/Statistics.jl/tarball/$1 +STATISTICS_BRANCH = master +STATISTICS_SHA1 = 77bd5707f143eb624721a7df28ddef470e70ecef +STATISTICS_GIT_URL := https://github.com/JuliaStats/Statistics.jl.git +STATISTICS_TAR_URL = https://api.github.com/repos/JuliaStats/Statistics.jl/tarball/$1 From 0d3c9b0bb4b81d703fcedb920a3538d2b254f966 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 1 May 2025 17:06:29 -0400 Subject: [PATCH 10/11] fixup! less disruptive internal method argument orderings --- base/reinterpretarray.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index 681530bd4fa83..ced1311fb098e 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -913,7 +913,7 @@ function _mapreduce(f::F, op::OP, style::IndexSCartesian2{K}, A::AbstractArrayOr elseif n == 1 return _mapreduce_start(f, op, A, init, first(A)) else - return mapreduce_impl(f, op, A, init, first(inds), last(inds)) + return mapreduce_impl(f, op, A, first(inds), last(inds), init) end end From c8e8bbb319a4aad260e91ff82d9395633f19200d Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Fri, 2 May 2025 10:48:19 -0400 Subject: [PATCH 11/11] review uses of init there are still tests that use "illegal" init values but happen to be ok due to the number of elements or somesuch; I am intentionally leaving them as they may be helpful to flag if and when further refactorings change these fraught behaviors. --- base/dict.jl | 2 +- base/reduce.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/base/dict.jl b/base/dict.jl index 1272229c714da..5a69f966adc54 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -728,7 +728,7 @@ end function reduce(::typeof(merge), items::Vector{<:Dict}) K = mapreduce(keytype, promote_type, items) V = mapreduce(valtype, promote_type, items) - return reduce(merge!, items; init=Dict{K,V}()) + return foldl(merge!, items; init=Dict{K,V}()) end function map!(f, iter::ValueIterator{<:Dict}) diff --git a/base/reduce.jl b/base/reduce.jl index 5aac0778ab16a..298b6cc79eb10 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -1144,8 +1144,8 @@ julia> count(i->(4<=i<=6), [2,3,4,5,6]) julia> count([true, false, true, true]) 3 -julia> count(>(3), 1:7, init=0x03) -0x07 +julia> count(>(3), 1:7, init=UInt(0)) +0x0000000000000004 ``` """ count(itr; init=0) = count(identity, itr; init)