Skip to content

Commit

Permalink
Add mappedarrayreduce
Browse files Browse the repository at this point in the history
  • Loading branch information
jishnub committed Nov 24, 2020
1 parent 90c6fce commit ce551d9
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,16 @@ julia> arraysT = map(A->of_eltype(Float64, A), arrays)
This construct is inferrable (type-stable), so it can be a useful
means to "coerce" arrays to a common type. This can sometimes solve
type-stability problems without requiring that one copy the data.

### mappedarrayreduce

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`.

Note that `mappedarrayreduce` follows the same signature as `mapreduce`, and does not accept an inverse function.

An example of its usage:

```julia
julia> mappedarrayreduce(x -> x^2, +, 1:3) # == 1^2 + 2^2 + 3^2
14
```
23 changes: 22 additions & 1 deletion src/MappedArrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module MappedArrays

using Base: @propagate_inbounds

export AbstractMappedArray, MappedArray, ReadonlyMappedArray, mappedarray, of_eltype
export AbstractMappedArray, MappedArray, ReadonlyMappedArray, mappedarray, of_eltype, mappedarrayreduce

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


# mapreduce

"""
mappedarrayreduce(f, op, A...; kw...)
Perform a "lazy" `mapreduce` without allocating an intermediate array. This might
be more performant than a standard `mapreduce`. Functionally this is equivalent to
`reduce(op, mappedarray(f, A...); kw...)`.
# Examples
```jldoctest
julia> mappedarrayreduce(x -> x^2, +, 1:10) # == 1^2 + 2^2 + 3^2
385
```
"""
mappedarrayreduce(f, op, A...; kw...) = reduce(op, mappedarray(f, A...); kw...)
mappedarrayreduce(f, finv::Function, op::Function, A...; kw...) = error(
"mappedarrayreduce does not support an inverse function, "*
"please use the signature mappedarrayreduce(f, op, A...; kw...)")

end # module
22 changes: 22 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,25 @@ end
str = String(take!(io))
@test occursin("x1 + x2", str)
end

@testset "mapreduce" begin
for T in [Int, Float64]
x = rand(T, 10); y = similar(x);

f = x->x^2; op = +
@test mapreduce(f, op, x) == mappedarrayreduce(f, op, x)
@test mapreduce(f, op, x, init = zero(T)) == mappedarrayreduce(f, op, x, init = zero(T))
@test mapreduce(f, op, x, init = zero(T), dims = 1) == mappedarrayreduce(f, op, x, init = zero(T), dims = 1)
@test mapreduce(f, op, x, init = zero(T), dims = :) == mappedarrayreduce(f, op, x, init = zero(T), dims = :)

@test_throws Exception mappedarrayreduce(x->x^2, sqrt, op, x)

if VERSION >= v"1.2"
f = ==; op = +
@test mapreduce(f, op, x, y) == mappedarrayreduce(f, op, x, y)
@test mapreduce(f, op, x, y, init = 0) == mappedarrayreduce(f, op, x, y, init = 0)
@test mapreduce(f, op, x, y, init = 0, dims = 1) == mappedarrayreduce(f, op, x, y, init = 0, dims = 1)
@test mapreduce(f, op, x, y, init = 0, dims = :) == mappedarrayreduce(f, op, x, y, init = 0, dims = :)
end
end
end

0 comments on commit ce551d9

Please sign in to comment.