From b5707b9bb5af47b6f19b8eeec70e1febc222b580 Mon Sep 17 00:00:00 2001 From: fverdugo Date: Fri, 7 Jun 2019 19:42:42 +0200 Subject: [PATCH] Defined apply on Map --- src/ArrayOperations.jl | 32 +++++--- src/CellwiseValues.jl | 3 + src/Kernels.jl | 16 ++++ src/MapOperations.jl | 161 +++++++++++++++++++++++++++++++++++++ src/NumberOperations.jl | 2 +- test/MapOperationsTests.jl | 31 +++++++ test/runtests.jl | 2 + 7 files changed, 233 insertions(+), 14 deletions(-) create mode 100644 src/MapOperations.jl create mode 100644 test/MapOperationsTests.jl diff --git a/src/ArrayOperations.jl b/src/ArrayOperations.jl index 38771ff..84028b7 100644 --- a/src/ArrayOperations.jl +++ b/src/ArrayOperations.jl @@ -33,31 +33,37 @@ end function CellArrayFromKernel(k::ArrayKernel,v::Vararg{<:CellValue}) _checks(v) - T = _compute_type(k,v) - N = _compute_N(v) + T = _compute_T(k,v) + N = _compute_N(k,v) K = typeof(k) V = typeof(v) CellArrayFromKernel{T,N,K,V}(k,v) end -function _compute_type(k,v) +function _compute_T(k,v) t = tuple([ _eltype(vi) for vi in v ]...) T = compute_type(k,t...) @assert T <: NumberLike T end -function _compute_N(v) - n = 0 - for vi in v - n = max(n,_ndims(vi)) - end - n +function _compute_N(k,v) + d = _compute_ndims(v...) + compute_ndim(k,d...) end -_ndims(v::CellNumber) = 0 +_nd(v::CellNumber) = 0 -_ndims(v::CellArray{T,N}) where {T,N} = N +_nd(v::CellArray{T,N}) where {T,N} = N + +# TODO use a generated function here +_compute_ndims(v...) = @notimplemented +_compute_ndims(v1) = (_nd(v1),) +_compute_ndims(v1,v2) = (_nd(v1),_nd(v2)) +_compute_ndims(v1,v2,v3) = (_nd(v1),_nd(v2),_nd(v3)) +_compute_ndims(v1,v2,v3,v4) = (_nd(v1),_nd(v2),_nd(v3),_nd(v4)) +_compute_ndims(v1,v2,v3,v4,v5) = (_nd(v1),_nd(v2),_nd(v3),_nd(v4),_nd(v5)) +_compute_ndims(v1,v2,v3,v4,v5,v6) = (_nd(v1),_nd(v2),_nd(v3),_nd(v4),_nd(v5),_nd(v6)) _eltype(v::CellNumber{T}) where T = T @@ -111,8 +117,8 @@ end function IndexCellArrayFromKernel(k::ArrayKernel,v::Vararg{<:CellValue}) _checks(v) - T = _compute_type(k,v) - N = _compute_N(v) + T = _compute_T(k,v) + N = _compute_N(k,v) K = typeof(k) V = typeof(v) cache = CachedArray(T,N) diff --git a/src/CellwiseValues.jl b/src/CellwiseValues.jl index 10d313f..9ff354c 100644 --- a/src/CellwiseValues.jl +++ b/src/CellwiseValues.jl @@ -35,4 +35,7 @@ include("CachedArrays.jl") include("ArrayOperations.jl") @reexport using CellwiseValues.ArrayOperations +include("MapOperations.jl") +@reexport using CellwiseValues.MapOperations + end # module diff --git a/src/Kernels.jl b/src/Kernels.jl index 83732cf..48df043 100644 --- a/src/Kernels.jl +++ b/src/Kernels.jl @@ -11,6 +11,7 @@ export compute_type export compute_value export compute_value! export compute_size +export compute_ndim export test_number_kernel export test_array_kernel @@ -32,6 +33,10 @@ function compute_type(::ArrayKernel,::Vararg{<:Type})::Type{<:NumberLike} @abstractmethod end +function compute_ndim(::ArrayKernel,::Vararg{Int})::Int + @abstractmethod +end + function compute_size(::ArrayKernel,::Vararg{<:NTuple})::NTuple @abstractmethod end @@ -58,6 +63,9 @@ function test_array_kernel( s = [ _size_for_broadcast(ii) for ii in i ] si = compute_size(k,s...) @test size(o) == si + d = [length(si) for si in s] + n = compute_ndim(k,d...) + @test n == length(si) r = Array{T,N}(undef,si) compute_value!(r,k,i...) @test r == o @@ -102,4 +110,12 @@ function compute_value!( broadcast!(k.fun,v,a...) end +function compute_ndim(::ArrayKernelFromBroadcastedFunction,d::Vararg{Int}) + n = 0 + for di in d + n = max(n,di) + end + n +end + end # module Kernels diff --git a/src/MapOperations.jl b/src/MapOperations.jl new file mode 100644 index 0000000..8cd32c0 --- /dev/null +++ b/src/MapOperations.jl @@ -0,0 +1,161 @@ +module MapOperations + +using CellwiseValues +using CellwiseValues.ArrayOperations: _compute_N, _compute_T + +import CellwiseValues.ArrayOperations: _nd, _eltype +import CellwiseValues: apply +import CellwiseValues: evaluate! +import CellwiseValues: return_size + +function apply(k::ArrayKernel,m::Map,v::Vararg) + MapFromKernel(k,m,v...) +end + +struct MapFromKernel{S,M,T,N,K,V,C} <: Map{S,M,T,N} + kernel::K + inputs::V + caches::C +end + +function MapFromKernel(k::ArrayKernel,v::Vararg) + S = _compute_S(v) + M = _compute_M(v) + T = _compute_T(k,v) + N = _compute_N(k,v) + K = typeof(k) + V = typeof(v) + c = _create_caches(v) + C = typeof(c) + MapFromKernel{S,M,T,N,K,V,C}(k,v,c) +end + +function evaluate!( + m::MapFromKernel{S,M,T,N}, + points::AbstractArray{S,M}, + v::AbstractArray{T,N}) where {S,M,T,N} + _evaluate_inputs!(points,m.caches...,m.inputs...) + compute_value!(v,m.kernel,m.caches...) +end + +function return_size(m::MapFromKernel{S,M},s::NTuple{M,Int}) where {S,M} + z = _return_sizes(s,m.inputs...) + compute_size(m.kernel,z...) +end + +function _create_caches(v) + tuple([_cache(vi) for vi in v]...) +end + +_cache(v::Map{S,M,T,N}) where {S,M,T,N} = CachedArray(T,N) + +_cache(v::AbstractArray{T,N}) where {T,N} = CachedArray(T,N) + +function _compute_S(v) + @assert length(v) > 0 + v1, = v + S = _stype(v1) + @assert S != nothing + @assert all([ (_stype(vi)==S || _stype(vi)==nothing ) for vi in v ]) + S +end + +function _compute_M(v) + @assert length(v) > 0 + v1, = v + M = _m(v1) + @assert M != nothing + @assert all([ (_m(vi)==M || _m(vi)==nothing ) for vi in v ]) + M +end + +_stype(v::Map{S}) where S = S + +_stype(v::AbstractArray) = nothing + +_m(v::Map{S,M}) where {S,M} = M + +_m(v::AbstractArray) = nothing + +_eltype(v::Map{S,M,T}) where {S,M,T} = T + +_eltype(v::AbstractArray{T}) where T = T + +_nd(v::Map{S,M,T,N}) where {S,M,T,N} = N + +_nd(v::AbstractArray{T,N}) where {T,N} = N + +_rz(s,i) = @unreachable + +_rz(s,i::Map) = return_size(i,s) + +_rz(s,i::AbstractArray) = size(i) + +# TODO also with a generated function +_return_sizes(s,i...) = @notimplemented +_return_sizes(s,i1) = (_rz(s,i1),) +_return_sizes(s,i1,i2) = (_rz(s,i1),_rz(s,i2)) +_return_sizes(s,i1,i2,i3) = (_rz(s,i1),_rz(s,i2),_rz(s,i3)) +_return_sizes(s,i1,i2,i3,i4) = (_rz(s,i1),_rz(s,i2),_rz(s,i3),_rz(s,i4)) +_return_sizes(s,i1,i2,i3,i4,i5) = (_rz(s,i1),_rz(s,i2),_rz(s,i3),_rz(s,i4),_rz(s,i5)) +_return_sizes(s,i1,i2,i3,i4,i5,i6) = (_rz(s,i1),_rz(s,i2),_rz(s,i3),_rz(s,i4),_rz(s,i5),_rz(s,i6)) + +_ev!(p,c,i) = @unreachable + +function _ev!(p,c,i::Map) + s = return_size(i,size(p)) + setsize!(c,s) + evaluate!(i,p,c) +end + +function _ev!(p,c,i::AbstractArray) + s = size(i) + setsize!(c,s) + for k in eachindex(i) + @inbounds c[k] = i[k] + end +end + +# TODO also with a generated function +_evaluate_inputs!(p,ci...) = @notimplemented + +function _evaluate_inputs!(p,c1,i1) + _ev!(p,c1,i1) +end + +function _evaluate_inputs!(p,c1,c2,i1,i2) + _ev!(p,c1,i1) + _ev!(p,c2,i2) +end + +function _evaluate_inputs!(p,c1,c2,c3,i1,i2,i3) + _ev!(p,c1,i1) + _ev!(p,c2,i2) + _ev!(p,c3,i3) +end + +function _evaluate_inputs!(p,c1,c2,c3,c4,i1,i2,i3,i4) + _ev!(p,c1,i1) + _ev!(p,c2,i2) + _ev!(p,c3,i3) + _ev!(p,c4,i4) +end + +function _evaluate_inputs!(p,c1,c2,c3,c4,c5,i1,i2,i3,i4,i5) + _ev!(p,c1,i1) + _ev!(p,c2,i2) + _ev!(p,c3,i3) + _ev!(p,c4,i4) + _ev!(p,c5,i5) +end + +function _evaluate_inputs!(p,c1,c2,c3,c4,c5,c6,i1,i2,i3,i4,i5,i6) + _ev!(p,c1,i1) + _ev!(p,c2,i2) + _ev!(p,c3,i3) + _ev!(p,c4,i4) + _ev!(p,c5,i5) + _ev!(p,c6,i6) +end + +end # module MapOperations diff --git a/src/NumberOperations.jl b/src/NumberOperations.jl index de88be8..422512e 100644 --- a/src/NumberOperations.jl +++ b/src/NumberOperations.jl @@ -17,7 +17,7 @@ function apply(k::NumberKernel,v::Vararg{<:IndexCellValue}) IndexCellNumberFromKernel(k,v...) end -function apply(f::Function,v::Vararg{<:CellValue};broadcast=false) +function apply(f::Function,v::Vararg;broadcast=false) _apply(f,v,Val(broadcast)) end diff --git a/test/MapOperationsTests.jl b/test/MapOperationsTests.jl new file mode 100644 index 0000000..7676363 --- /dev/null +++ b/test/MapOperationsTests.jl @@ -0,0 +1,31 @@ +module MapOperationsTests + +using Test +using CellwiseValues +using TensorValues + +using ..MapsMocks + +a = VectorValue(10,10) +b = VectorValue(15,20) +p1 = VectorValue(1,1) +p2 = VectorValue(2,2) +p3 = VectorValue(3,3) +p = [p1,p2,p3] +m = MockMap(a) + +m2 = apply(-,m,broadcast=true) + +r = evaluate(m,p) +r2 = -r +test_map(m2,p,r2) + +m3 = apply(-,m,m2,broadcast=true) +r3 = r .- r2 +test_map(m3,p,r3) + +m3 = apply(-,m,p,broadcast=true) +r3 = r .- p +test_map(m3,p,r3) + +end # module MapOperationsTests diff --git a/test/runtests.jl b/test/runtests.jl index e7ea5c2..b919cf5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,4 +21,6 @@ include("MapsMocks.jl") @time @testset "ArrayOperations" begin include("ArrayOperationsTests.jl") end +@time @testset "MapOperations" begin include("MapOperationsTests.jl") end + end # module CellwiseValuesTests