changeset 205:70e1f3401d82 boundary_conditions

Merge. Throw away tests written by Jonatan
author Jonatan Werpers <jonatan@werpers.com>
date Mon, 24 Jun 2019 14:43:37 +0200
parents 9d9f7b0e514b (current diff) 19e579a5031f (diff)
children 7b0650021b36
files LazyTensors/src/lazy_operations.jl LazyTensors/test/runtests.jl
diffstat 2 files changed, 82 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/LazyTensors/src/lazy_operations.jl	Mon Jun 24 14:04:38 2019 +0200
+++ b/LazyTensors/src/lazy_operations.jl	Mon Jun 24 14:43:37 2019 +0200
@@ -53,7 +53,13 @@
     a::T1
     b::T2
 
-    function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:AbstractArray{T,D}, T2<:AbstractArray{T,D}}
+    @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:AbstractArray{T,D}, T2<:AbstractArray{T,D}}
+        # TODO: Remove boundscheck once assert can be turned off by
+        # optimization flags. Ugly fix.
+        # NOTE: Seems like adding the boundscheck introduces allocations. Can this
+        # be fixed? Since boundscheck is removed when inlined into inbounds this
+        # should not in practise effect performance.
+        @boundscheck @assert size(a)==size(b)
         return new{T,D,Op,T1,T2}(a,b)
     end
 end
@@ -92,29 +98,34 @@
 
 # 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
-@inline +̃(a::AbstractArray{T,D},b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b)
-@inline -̃(a::AbstractArray{T,D},b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b)
-@inline *̃(a::AbstractArray{T,D},b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b)
-@inline /̃(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::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::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.:+(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b
-Base.:+(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a +̃ b
-Base.:+(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b
+Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b
+Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a +̃ b
+Base.@propagate_inbounds Base.:+(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b
 
-Base.:-(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a -̃ b
-Base.:-(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a -̃ b
-Base.:-(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a -̃ b
+Base.@propagate_inbounds Base.:-(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a -̃ b
+Base.@propagate_inbounds Base.:-(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a -̃ b
+Base.@propagate_inbounds Base.:-(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a -̃ b
 
-Base.:*(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a *̃ b
-Base.:*(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a *̃ b
-Base.:*(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a *̃ b
+Base.@propagate_inbounds Base.:*(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a *̃ b
+Base.@propagate_inbounds Base.:*(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a *̃ b
+Base.@propagate_inbounds Base.:*(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a *̃ b
 
 # TODO: / seems to be ambiguous
-# Base.:/(a::LazyArray{T,D},b::AbstractArray{T,D}) where {T,D} = a /̃ b
-# Base.:/(a::AbstractArray{T,D},b::LazyArray{T,D}) where {T,D} = a /̃ b
+Base.@propagate_inbounds Base.:/(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a /̃  b
+Base.@propagate_inbounds Base.:/(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a /̃ b
+Base.@propagate_inbounds Base.:/(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a /̃ b
+
+# NOTE: Need to define (/) for AbstractVectorOrMat and Union of LazyArrays in order to avoid ambiguities
+# with (/) in the LinearAlgebra package. Not sure if it actually could be usefull.
+Base.@propagate_inbounds Base.:/(a::AbstractVecOrMat, b::Union{LazyArray{T,1}, LazyArray{T,2}})  where {T}  = a /̃ b
+Base.@propagate_inbounds Base.:/(a::Union{LazyArray{T,1}, LazyArray{T,2}}, b::AbstractVecOrMat)  where {T}  = a /̃ b
 
 export +̃, -̃, *̃, /̃
 
--- a/LazyTensors/test/runtests.jl	Mon Jun 24 14:04:38 2019 +0200
+++ b/LazyTensors/test/runtests.jl	Mon Jun 24 14:43:37 2019 +0200
@@ -57,29 +57,60 @@
     @test_broken BoundsError == (m*m*v)[7]
 end
 
-
-@testset "Lazy elementwise operations" begin
-    struct DummyLazyArray{D} <: LazyArray{Int,D}
-        size::NTuple{D,Int}
+@testset "LazyArray" begin
+    struct DummyArray{T,D, T1<:AbstractArray{T,D}} <: LazyArray{T,D}
+        data::T1
     end
-    Base.size(a::DummyLazyArray) = a.size
-    Base.getindex(a::DummyLazyArray, I...) = prod(I)
-
-
-    a = DummyLazyArray((3,))
+    Base.size(v::DummyArray) = size(v.data)
+    Base.getindex(v::DummyArray, I...) = v.data[I...]
 
-    @test (a+a)[3] == 6
-    @test (a-a)[3] == 0
-    @test (a*a)[3] == 9
-
-    a = DummyLazyArray((4,))
-    b = [3,2,1,2]
+    # 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
+    @test isa(v1 +̃ v2, LazyArray)
+    @test isa(v1 -̃ v2, LazyArray)
+    @test isa(v1 *̃ v2, LazyArray)
+    @test isa(v1 /̃ v2, 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]
+    end
+    @test_throws BoundsError (v1 +̃  v2)[4]
+    v2 = [1., 2, 3, 4]
+    # Test that size of arrays is asserted when not specified inbounds
+    @test_throws AssertionError v1 +̃ v2
+    # Test that no error checking is performed when specified inbounds
+    res = (v1,v2) -> (@inbounds (v1 +̃ v2)[1] == 2)
+    @test res(v1,v2)
 
-    @test (a+b)[4] == 6
-    @test (a-b)[4] == 2
-    @test (a*b)[4] == 8
-
-    @test (b+a)[4] == 6
-    @test (b-a)[4] == -2
-    @test (b*a)[4] == 8
-end
\ No newline at end of file
+    # Test operations on LazyArray
+    v1 = DummyArray([1, 2.3, 4])
+    v2 = [1., 2, 3]
+    @test isa(v1 + v2, LazyArray)
+    @test isa(v2 + v1, LazyArray)
+    @test isa(v1 - v2, LazyArray)
+    @test isa(v2 - v1, LazyArray)
+    @test isa(v1 * v2, LazyArray)
+    @test isa(v2 * v1, LazyArray)
+    @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_times[i]
+        @test (v1 / v2)[i] == 1/((v2 / v1)[i])  ==  r_div[i]
+    end
+    @test_throws BoundsError (v1 + v2)[4]
+    v2 = [1., 2, 3, 4]
+    # Test that size of arrays is asserted when not specified inbounds
+    @test_throws AssertionError v1 + v2
+    # Test that no error checking is performed when specified inbounds
+    res = (v1,v2) -> (@inbounds (v1 + v2)[1] == 2)
+    @test res(v1,v2)
+end