Mercurial > repos > public > sbplib_julia
comparison LazyTensors/src/lazy_operations.jl @ 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 | d4cd4882ee9f |
children | 8ffd9c2e2119 |
comparison
equal
deleted
inserted
replaced
262:f1e90a92ad74 | 263:b577b5f64530 |
---|---|
36 # # Should we overload some other infix binary operator? | 36 # # Should we overload some other infix binary operator? |
37 # →(tm::TensorMapping{T,R,D}, o::AbstractArray{T,D}) where {T,R,D} = LazyTensorMappingApplication(tm,o) | 37 # →(tm::TensorMapping{T,R,D}, o::AbstractArray{T,D}) where {T,R,D} = LazyTensorMappingApplication(tm,o) |
38 # TODO: We need to be really careful about good error messages. | 38 # TODO: We need to be really careful about good error messages. |
39 # For example what happens if you try to multiply LazyTensorMappingApplication with a TensorMapping(wrong order)? | 39 # For example what happens if you try to multiply LazyTensorMappingApplication with a TensorMapping(wrong order)? |
40 | 40 |
41 | 41 """ |
42 | 42 LazyElementwiseOperation{T,D,Op,T1,T2} <: LazyArray{T,D} |
43 """ | |
44 LazyElementwiseOperation{T,D,Op, T1<:AbstractArray{T,D}, T2 <: AbstractArray{T,D}} <: AbstractArray{T,D} | |
45 | |
46 Struct allowing for lazy evaluation of elementwise operations on AbstractArrays. | 43 Struct allowing for lazy evaluation of elementwise operations on AbstractArrays. |
47 | 44 |
48 A LazyElementwiseOperation contains two AbstractArrays of equal size, | 45 A LazyElementwiseOperation contains two AbstractArrays of equal size, |
49 together with an operation. The operations are carried out when the | 46 together with an operation. The operations are carried out when the |
50 LazyElementwiseOperation is indexed. | 47 LazyElementwiseOperation is indexed. |
51 """ | 48 """ |
52 struct LazyElementwiseOperation{T,D,Op, T1<:AbstractArray{T,D}, T2 <: AbstractArray{T,D}} <: LazyArray{T,D} | 49 struct LazyElementwiseOperation{T,D,Op, T1, T2} <: LazyArray{T,D} |
53 a::T1 | 50 a::T1 |
54 b::T2 | 51 b::T2 |
55 | 52 |
56 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:AbstractArray{T,D}, T2<:AbstractArray{T,D}} | 53 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:AbstractArray{T,D}, T2<:AbstractArray{T,D}} |
57 @boundscheck if size(a) != size(b) | 54 @boundscheck if size(a) != size(b) |
58 throw(DimensionMismatch("dimensions must match")) | 55 throw(DimensionMismatch("dimensions must match")) |
59 end | 56 end |
60 return new{T,D,Op,T1,T2}(a,b) | 57 return new{T,D,Op,T1,T2}(a,b) |
61 end | 58 end |
59 | |
60 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:AbstractArray{T,D}, T2<:Real} | |
61 return new{T,D,Op,T1,T2}(a,b) | |
62 end | |
63 | |
64 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op, T1<:Real, T2<:AbstractArray{T,D}} | |
65 return new{T,D,Op,T1,T2}(a,b) | |
66 end | |
62 end | 67 end |
63 # TODO: Move Op to be the first parameter? Compare to Binary operations | 68 # TODO: Move Op to be the first parameter? Compare to Binary operations |
64 | 69 |
65 Base.size(v::LazyElementwiseOperation) = size(v.a) | 70 Base.size(v::LazyElementwiseOperation) = size(v.a) |
66 | 71 |
67 # TODO: Make sure boundschecking is done properly and that the lenght of the vectors are equal | 72 # TODO: Make sure boundschecking is done properly and that the lenght of the vectors are equal |
68 # NOTE: Boundschecking in getindex functions now assumes that the size of the | 73 # NOTE: Boundschecking in getindex functions now assumes that the size of the |
69 # vectors in the LazyElementwiseOperation are the same size. If we remove the | 74 # vectors in the LazyElementwiseOperation are the same size. If we remove the |
70 # size assertion in the constructor we might have to handle | 75 # size assertion in the constructor we might have to handle |
71 # boundschecking differently. | 76 # boundschecking differently. |
72 Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:+}, I::Vararg{Int,D}) where {T,D} | 77 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}} |
73 @boundscheck if !checkbounds(Bool,leo.a,I...) | 78 @boundscheck if !checkbounds(Bool,leo.a,I...) |
74 throw(BoundsError([leo],I...)) | 79 throw(BoundsError([leo],I...)) |
75 end | 80 end |
76 return leo.a[I...] + leo.b[I...] | 81 return leo.a[I...] + leo.b[I...] |
77 end | 82 end |
78 Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:-}, I::Vararg{Int,D}) where {T,D} | 83 |
84 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}} | |
79 @boundscheck if !checkbounds(Bool,leo.a,I...) | 85 @boundscheck if !checkbounds(Bool,leo.a,I...) |
80 throw(BoundsError([leo],I...)) | 86 throw(BoundsError([leo],I...)) |
81 end | 87 end |
82 return leo.a[I...] - leo.b[I...] | 88 return leo.a[I...] - leo.b[I...] |
83 end | 89 end |
84 Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:*}, I::Vararg{Int,D}) where {T,D} | 90 |
91 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}} | |
85 @boundscheck if !checkbounds(Bool,leo.a,I...) | 92 @boundscheck if !checkbounds(Bool,leo.a,I...) |
86 throw(BoundsError([leo],I...)) | 93 throw(BoundsError([leo],I...)) |
87 end | 94 end |
88 return leo.a[I...] * leo.b[I...] | 95 return leo.a[I...] * leo.b[I...] |
89 end | 96 end |
90 Base.@propagate_inbounds @inline function Base.getindex(leo::LazyElementwiseOperation{T,D,:/}, I::Vararg{Int,D}) where {T,D} | 97 |
98 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}} | |
91 @boundscheck if !checkbounds(Bool,leo.a,I...) | 99 @boundscheck if !checkbounds(Bool,leo.a,I...) |
92 throw(BoundsError([leo],I...)) | 100 throw(BoundsError([leo],I...)) |
93 end | 101 end |
94 return leo.a[I...] / leo.b[I...] | 102 return leo.a[I...] / leo.b[I...] |
103 end | |
104 | |
105 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} | |
106 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
107 throw(BoundsError([leo],I...)) | |
108 end | |
109 return leo.a[I...] + leo.b | |
110 end | |
111 | |
112 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} | |
113 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
114 throw(BoundsError([leo],I...)) | |
115 end | |
116 return leo.a[I...] - leo.b | |
117 end | |
118 | |
119 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} | |
120 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
121 throw(BoundsError([leo],I...)) | |
122 end | |
123 return leo.a[I...] * leo.b | |
124 end | |
125 | |
126 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} | |
127 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
128 throw(BoundsError([leo],I...)) | |
129 end | |
130 return leo.a[I...] / leo.b | |
131 end | |
132 | |
133 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}} | |
134 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
135 throw(BoundsError([leo],I...)) | |
136 end | |
137 return leo.a + leo.b[I...] | |
138 end | |
139 | |
140 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}} | |
141 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
142 throw(BoundsError([leo],I...)) | |
143 end | |
144 return leo.a - leo.b[I...] | |
145 end | |
146 | |
147 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}} | |
148 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
149 throw(BoundsError([leo],I...)) | |
150 end | |
151 return leo.a * leo.b[I...] | |
152 end | |
153 | |
154 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}} | |
155 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
156 throw(BoundsError([leo],I...)) | |
157 end | |
158 return leo.a / leo.b[I...] | |
95 end | 159 end |
96 | 160 |
97 # Define lazy operations for AbstractArrays. Operations constructs a LazyElementwiseOperation which | 161 # Define lazy operations for AbstractArrays. Operations constructs a LazyElementwiseOperation which |
98 # can later be indexed into. Lazy operations are denoted by the usual operator followed by a tilde | 162 # can later be indexed into. Lazy operations are denoted by the usual operator followed by a tilde |
99 Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) | 163 Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) |
100 Base.@propagate_inbounds -̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) | 164 Base.@propagate_inbounds -̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) |
101 Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) | 165 Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) |
102 Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) | 166 Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) |
103 | 167 |
168 Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) | |
169 Base.@propagate_inbounds -̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) | |
170 Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) | |
171 Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) | |
172 | |
173 Base.@propagate_inbounds +̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) | |
174 Base.@propagate_inbounds -̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) | |
175 Base.@propagate_inbounds *̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) | |
176 Base.@propagate_inbounds /̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) | |
177 | |
178 | |
179 | |
104 # NOTE: Är det knas att vi har till exempel * istället för .* ?? | 180 # NOTE: Är det knas att vi har till exempel * istället för .* ?? |
105 # Oklart om det ens går att lösa.. | 181 # Oklart om det ens går att lösa.. |
106 Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b | 182 Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b |
107 Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a +̃ b | 183 Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a +̃ b |
108 Base.@propagate_inbounds Base.:+(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b | 184 Base.@propagate_inbounds Base.:+(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b |