Mercurial > repos > public > sbplib_julia
changeset 263:b577b5f64530 boundary_conditions
Add lazy elementwise operations for array with scalar
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Wed, 04 Dec 2019 19:02:18 +0100 |
parents | f1e90a92ad74 |
children | 8ffd9c2e2119 |
files | LazyTensors/src/lazy_operations.jl LazyTensors/test/runtests.jl |
diffstat | 2 files changed, 116 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/LazyTensors/src/lazy_operations.jl Tue Nov 26 08:28:26 2019 -0800 +++ b/LazyTensors/src/lazy_operations.jl Wed Dec 04 19:02:18 2019 +0100 @@ -38,18 +38,15 @@ # TODO: We need to be really careful about good error messages. # For example what happens if you try to multiply LazyTensorMappingApplication with a TensorMapping(wrong order)? - - """ - LazyElementwiseOperation{T,D,Op, T1<:AbstractArray{T,D}, T2 <: AbstractArray{T,D}} <: AbstractArray{T,D} - + LazyElementwiseOperation{T,D,Op,T1,T2} <: LazyArray{T,D} Struct allowing for lazy evaluation of elementwise operations on AbstractArrays. A LazyElementwiseOperation contains two AbstractArrays of equal size, together with an operation. The operations are carried out when the LazyElementwiseOperation is indexed. """ -struct LazyElementwiseOperation{T,D,Op, T1<:AbstractArray{T,D}, T2 <: AbstractArray{T,D}} <: LazyArray{T,D} +struct LazyElementwiseOperation{T,D,Op, T1, T2} <: LazyArray{T,D} a::T1 b::T2 @@ -59,6 +56,14 @@ end return new{T,D,Op,T1,T2}(a,b) end + + @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:AbstractArray{T,D}, T2<:Real} + return new{T,D,Op,T1,T2}(a,b) + end + + @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:Real, T2<:AbstractArray{T,D}} + return new{T,D,Op,T1,T2}(a,b) + end end # TODO: Move Op to be the first parameter? Compare to Binary operations @@ -69,31 +74,90 @@ # vectors in the LazyElementwiseOperation are the same size. If we remove the # size assertion in the constructor we might have to handle # boundschecking differently. -Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:+}, I::Vararg{Int,D}) where {T,D} +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:+,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:AbstractArray{T,D}} @boundscheck if !checkbounds(Bool,leo.a,I...) throw(BoundsError([leo],I...)) end return leo.a[I...] + leo.b[I...] end -Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:-}, I::Vararg{Int,D}) where {T,D} + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:-,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:AbstractArray{T,D}} @boundscheck if !checkbounds(Bool,leo.a,I...) throw(BoundsError([leo],I...)) end return leo.a[I...] - leo.b[I...] end -Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:*}, I::Vararg{Int,D}) where {T,D} + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:*,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:AbstractArray{T,D}} @boundscheck if !checkbounds(Bool,leo.a,I...) throw(BoundsError([leo],I...)) end return leo.a[I...] * leo.b[I...] end -Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:/}, I::Vararg{Int,D}) where {T,D} + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:/,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:AbstractArray{T,D}} @boundscheck if !checkbounds(Bool,leo.a,I...) throw(BoundsError([leo],I...)) end return leo.a[I...] / leo.b[I...] end +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:+,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:Real} + @boundscheck if !checkbounds(Bool,leo.a,I...) + throw(BoundsError([leo],I...)) + end + return leo.a[I...] + leo.b +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:-,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:Real} + @boundscheck if !checkbounds(Bool,leo.a,I...) + throw(BoundsError([leo],I...)) + end + return leo.a[I...] - leo.b +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:*,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:Real} + @boundscheck if !checkbounds(Bool,leo.a,I...) + throw(BoundsError([leo],I...)) + end + return leo.a[I...] * leo.b +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:/,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:AbstractArray{T,D},T2<:Real} + @boundscheck if !checkbounds(Bool,leo.a,I...) + throw(BoundsError([leo],I...)) + end + return leo.a[I...] / leo.b +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:+,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:Real,T2<:AbstractArray{T,D}} + @boundscheck if !checkbounds(Bool,leo.b,I...) + throw(BoundsError([leo],I...)) + end + return leo.a + leo.b[I...] +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:-,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:Real,T2<:AbstractArray{T,D}} + @boundscheck if !checkbounds(Bool,leo.b,I...) + throw(BoundsError([leo],I...)) + end + return leo.a - leo.b[I...] +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:*,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:Real,T2<:AbstractArray{T,D}} + @boundscheck if !checkbounds(Bool,leo.b,I...) + throw(BoundsError([leo],I...)) + end + return leo.a * leo.b[I...] +end + +Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:/,T1,T2}, I::Vararg{Int,D}) where {T,D,T1<:Real,T2<:AbstractArray{T,D}} + @boundscheck if !checkbounds(Bool,leo.b,I...) + throw(BoundsError([leo],I...)) + end + return leo.a / leo.b[I...] +end + # Define lazy operations for AbstractArrays. Operations constructs a LazyElementwiseOperation which # can later be indexed into. Lazy operations are denoted by the usual operator followed by a tilde Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) @@ -101,6 +165,18 @@ Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) +Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) +Base.@propagate_inbounds -̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) +Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) +Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) + +Base.@propagate_inbounds +̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) +Base.@propagate_inbounds -̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) +Base.@propagate_inbounds *̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) +Base.@propagate_inbounds /̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) + + + # NOTE: Är det knas att vi har till exempel * istället för .* ?? # Oklart om det ens går att lösa.. Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b
--- a/LazyTensors/test/runtests.jl Tue Nov 26 08:28:26 2019 -0800 +++ b/LazyTensors/test/runtests.jl Wed Dec 04 19:02:18 2019 +0100 @@ -110,19 +110,40 @@ # Test lazy operations v1 = [1, 2.3, 4] v2 = [1., 2, 3] - r_add = v1 .+ v2 - r_sub = v1 .- v2 - r_times = v1 .* v2 - r_div = v1 ./ v2 + s = 3.4 + r_add_v = v1 .+ v2 + r_sub_v = v1 .- v2 + r_times_v = v1 .* v2 + r_div_v = v1 ./ v2 + r_add_s = v1 .+ s + r_sub_s = v1 .- s + r_times_s = v1 .* s + r_div_s = v1 ./ s @test isa(v1 +̃ v2, LazyArray) @test isa(v1 -̃ v2, LazyArray) @test isa(v1 *̃ v2, LazyArray) @test isa(v1 /̃ v2, LazyArray) + @test isa(v1 +̃ s, LazyArray) + @test isa(v1 -̃ s, LazyArray) + @test isa(v1 *̃ s, LazyArray) + @test isa(v1 /̃ s, LazyArray) + @test isa(s +̃ v1, LazyArray) + @test isa(s -̃ v1, LazyArray) + @test isa(s *̃ v1, LazyArray) + @test isa(s /̃ v1, LazyArray) for i ∈ eachindex(v1) - @test (v1 +̃ v2)[i] == r_add[i] - @test (v1 -̃ v2)[i] == r_sub[i] - @test (v1 *̃ v2)[i] == r_times[i] - @test (v1 /̃ v2)[i] == r_div[i] + @test (v1 +̃ v2)[i] == r_add_v[i] + @test (v1 -̃ v2)[i] == r_sub_v[i] + @test (v1 *̃ v2)[i] == r_times_v[i] + @test (v1 /̃ v2)[i] == r_div_v[i] + @test (v1 +̃ s)[i] == r_add_s[i] + @test (v1 -̃ s)[i] == r_sub_s[i] + @test (v1 *̃ s)[i] == r_times_s[i] + @test (v1 /̃ s)[i] == r_div_s[i] + @test (s +̃ v1)[i] == r_add_s[i] + @test (s -̃ v1)[i] == -r_sub_s[i] + @test (s *̃ v1)[i] == r_times_s[i] + @test (s /̃ v1)[i] == 1/r_div_s[i] end @test_throws BoundsError (v1 +̃ v2)[4] v2 = [1., 2, 3, 4] @@ -137,8 +158,8 @@ @test isa(v1 - v2, LazyArray) @test isa(v2 - v1, LazyArray) for i ∈ eachindex(v2) - @test (v1 + v2)[i] == (v2 + v1)[i] == r_add[i] - @test (v1 - v2)[i] == -(v2 - v1)[i] == r_sub[i] + @test (v1 + v2)[i] == (v2 + v1)[i] == r_add_v[i] + @test (v1 - v2)[i] == -(v2 - v1)[i] == r_sub_v[i] end @test_throws BoundsError (v1 + v2)[4] v2 = [1., 2, 3, 4]