Skip to content

Commit ce551d9

Browse files
committed
Add mappedarrayreduce
1 parent 90c6fce commit ce551d9

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,16 @@ julia> arraysT = map(A->of_eltype(Float64, A), arrays)
210210
This construct is inferrable (type-stable), so it can be a useful
211211
means to "coerce" arrays to a common type. This can sometimes solve
212212
type-stability problems without requiring that one copy the data.
213+
214+
### mappedarrayreduce
215+
216+
This package provides a "lazy" `mapreduce` operation in the form of the function `mappedarrayreduce`, where the `map` is evaluated as a `MappedArray` and is not materialized. This therefore might be more performant than a standard `mapreduce`.
217+
218+
Note that `mappedarrayreduce` follows the same signature as `mapreduce`, and does not accept an inverse function.
219+
220+
An example of its usage:
221+
222+
```julia
223+
julia> mappedarrayreduce(x -> x^2, +, 1:3) # == 1^2 + 2^2 + 3^2
224+
14
225+
```

src/MappedArrays.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module MappedArrays
22

33
using Base: @propagate_inbounds
44

5-
export AbstractMappedArray, MappedArray, ReadonlyMappedArray, mappedarray, of_eltype
5+
export AbstractMappedArray, MappedArray, ReadonlyMappedArray, mappedarray, of_eltype, mappedarrayreduce
66

77
abstract type AbstractMappedArray{T,N} <: AbstractArray{T,N} end
88
abstract type AbstractMultiMappedArray{T,N} <: AbstractMappedArray{T,N} end
@@ -261,4 +261,25 @@ eltypes(A::AbstractArray) = Tuple{eltype(A)}
261261
## Deprecations
262262
@deprecate mappedarray(f_finv::Tuple{Any,Any}, args::AbstractArray...) mappedarray(f_finv[1], f_finv[2], args...)
263263

264+
265+
# mapreduce
266+
267+
"""
268+
mappedarrayreduce(f, op, A...; kw...)
269+
270+
Perform a "lazy" `mapreduce` without allocating an intermediate array. This might
271+
be more performant than a standard `mapreduce`. Functionally this is equivalent to
272+
`reduce(op, mappedarray(f, A...); kw...)`.
273+
274+
# Examples
275+
```jldoctest
276+
julia> mappedarrayreduce(x -> x^2, +, 1:10) # == 1^2 + 2^2 + 3^2
277+
385
278+
```
279+
"""
280+
mappedarrayreduce(f, op, A...; kw...) = reduce(op, mappedarray(f, A...); kw...)
281+
mappedarrayreduce(f, finv::Function, op::Function, A...; kw...) = error(
282+
"mappedarrayreduce does not support an inverse function, "*
283+
"please use the signature mappedarrayreduce(f, op, A...; kw...)")
284+
264285
end # module

test/runtests.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,25 @@ end
177177
str = String(take!(io))
178178
@test occursin("x1 + x2", str)
179179
end
180+
181+
@testset "mapreduce" begin
182+
for T in [Int, Float64]
183+
x = rand(T, 10); y = similar(x);
184+
185+
f = x->x^2; op = +
186+
@test mapreduce(f, op, x) == mappedarrayreduce(f, op, x)
187+
@test mapreduce(f, op, x, init = zero(T)) == mappedarrayreduce(f, op, x, init = zero(T))
188+
@test mapreduce(f, op, x, init = zero(T), dims = 1) == mappedarrayreduce(f, op, x, init = zero(T), dims = 1)
189+
@test mapreduce(f, op, x, init = zero(T), dims = :) == mappedarrayreduce(f, op, x, init = zero(T), dims = :)
190+
191+
@test_throws Exception mappedarrayreduce(x->x^2, sqrt, op, x)
192+
193+
if VERSION >= v"1.2"
194+
f = ==; op = +
195+
@test mapreduce(f, op, x, y) == mappedarrayreduce(f, op, x, y)
196+
@test mapreduce(f, op, x, y, init = 0) == mappedarrayreduce(f, op, x, y, init = 0)
197+
@test mapreduce(f, op, x, y, init = 0, dims = 1) == mappedarrayreduce(f, op, x, y, init = 0, dims = 1)
198+
@test mapreduce(f, op, x, y, init = 0, dims = :) == mappedarrayreduce(f, op, x, y, init = 0, dims = :)
199+
end
200+
end
201+
end

0 commit comments

Comments
 (0)