Mercurial > repos > public > sbplib_julia
comparison LazyTensors/src/lazy_array.jl @ 267:634453a4e1d8 boundary_conditions
Restructure code in LazyTensors
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Thu, 05 Dec 2019 09:28:04 +0100 |
parents | |
children | 41c3c25e4e3b |
comparison
equal
deleted
inserted
replaced
266:9ad447176ba1 | 267:634453a4e1d8 |
---|---|
1 """ | |
2 LazyArray{T,D} <: AbstractArray{T,D} | |
3 | |
4 Array which is calcualted lazily when indexing. | |
5 | |
6 A subtype of `LazyArray` will use lazy version of `+`, `-`, `*`, `/`. | |
7 """ | |
8 abstract type LazyArray{T,D} <: AbstractArray{T,D} end | |
9 export LazyArray | |
10 | |
11 """ | |
12 LazyElementwiseOperation{T,D,Op,T1,T2} <: LazyArray{T,D} | |
13 Struct allowing for lazy evaluation of elementwise operations on AbstractArrays. | |
14 | |
15 A LazyElementwiseOperation contains two datatypes T1, and T2, together with an operation, | |
16 where at least one of T1 and T2 is an AbstractArray, and one may be a Real. | |
17 The operations are carried out when the LazyElementwiseOperation is indexed. | |
18 """ | |
19 struct LazyElementwiseOperation{T,D,Op,T1,T2} <: LazyArray{T,D} | |
20 a::T1 | |
21 b::T2 | |
22 | |
23 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op,T1<:AbstractArray{T,D},T2<:AbstractArray{T,D}} | |
24 @boundscheck if size(a) != size(b) | |
25 throw(DimensionMismatch("dimensions must match")) | |
26 end | |
27 return new{T,D,Op,T1,T2}(a,b) | |
28 end | |
29 | |
30 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op,T1<:AbstractArray{T,D},T2<:Real} | |
31 return new{T,D,Op,T1,T2}(a,b) | |
32 end | |
33 | |
34 @inline function LazyElementwiseOperation{T,D,Op}(a::T1,b::T2) where {T,D,Op,T1<:Real,T2<:AbstractArray{T,D}} | |
35 return new{T,D,Op,T1,T2}(a,b) | |
36 end | |
37 end | |
38 # TODO: Move Op to be the first parameter? Compare to Binary operations | |
39 | |
40 Base.size(v::LazyElementwiseOperation) = size(v.a) | |
41 | |
42 # TODO: Make sure boundschecking is done properly and that the lenght of the vectors are equal | |
43 # NOTE: Boundschecking in getindex functions now assumes that the size of the | |
44 # vectors in the LazyElementwiseOperation are the same size. If we remove the | |
45 # size assertion in the constructor we might have to handle | |
46 # boundschecking differently. | |
47 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}} | |
48 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
49 throw(BoundsError([leo],I...)) | |
50 end | |
51 return leo.a[I...] + leo.b[I...] | |
52 end | |
53 | |
54 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}} | |
55 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
56 throw(BoundsError([leo],I...)) | |
57 end | |
58 return leo.a[I...] - leo.b[I...] | |
59 end | |
60 | |
61 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}} | |
62 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
63 throw(BoundsError([leo],I...)) | |
64 end | |
65 return leo.a[I...] * leo.b[I...] | |
66 end | |
67 | |
68 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}} | |
69 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
70 throw(BoundsError([leo],I...)) | |
71 end | |
72 return leo.a[I...] / leo.b[I...] | |
73 end | |
74 | |
75 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} | |
76 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
77 throw(BoundsError([leo],I...)) | |
78 end | |
79 return leo.a[I...] + leo.b | |
80 end | |
81 | |
82 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} | |
83 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
84 throw(BoundsError([leo],I...)) | |
85 end | |
86 return leo.a[I...] - leo.b | |
87 end | |
88 | |
89 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} | |
90 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
91 throw(BoundsError([leo],I...)) | |
92 end | |
93 return leo.a[I...] * leo.b | |
94 end | |
95 | |
96 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} | |
97 @boundscheck if !checkbounds(Bool,leo.a,I...) | |
98 throw(BoundsError([leo],I...)) | |
99 end | |
100 return leo.a[I...] / leo.b | |
101 end | |
102 | |
103 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}} | |
104 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
105 throw(BoundsError([leo],I...)) | |
106 end | |
107 return leo.a + leo.b[I...] | |
108 end | |
109 | |
110 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}} | |
111 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
112 throw(BoundsError([leo],I...)) | |
113 end | |
114 return leo.a - leo.b[I...] | |
115 end | |
116 | |
117 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}} | |
118 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
119 throw(BoundsError([leo],I...)) | |
120 end | |
121 return leo.a * leo.b[I...] | |
122 end | |
123 | |
124 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}} | |
125 @boundscheck if !checkbounds(Bool,leo.b,I...) | |
126 throw(BoundsError([leo],I...)) | |
127 end | |
128 return leo.a / leo.b[I...] | |
129 end | |
130 | |
131 # Define lazy operations for AbstractArrays. Operations constructs a LazyElementwiseOperation which | |
132 # can later be indexed into. Lazy operations are denoted by the usual operator followed by a tilde | |
133 Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) | |
134 Base.@propagate_inbounds -̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) | |
135 Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) | |
136 Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) | |
137 | |
138 Base.@propagate_inbounds +̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) | |
139 Base.@propagate_inbounds -̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) | |
140 Base.@propagate_inbounds *̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) | |
141 Base.@propagate_inbounds /̃(a::AbstractArray{T,D}, b::Real) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) | |
142 | |
143 Base.@propagate_inbounds +̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:+}(a,b) | |
144 Base.@propagate_inbounds -̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:-}(a,b) | |
145 Base.@propagate_inbounds *̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:*}(a,b) | |
146 Base.@propagate_inbounds /̃(a::Real, b::AbstractArray{T,D}) where {T,D} = LazyElementwiseOperation{T,D,:/}(a,b) | |
147 | |
148 | |
149 | |
150 # NOTE: Är det knas att vi har till exempel * istället för .* ?? | |
151 # Oklart om det ens går att lösa.. | |
152 Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b | |
153 Base.@propagate_inbounds Base.:+(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a +̃ b | |
154 Base.@propagate_inbounds Base.:+(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a +̃ b | |
155 | |
156 Base.@propagate_inbounds Base.:-(a::LazyArray{T,D}, b::LazyArray{T,D}) where {T,D} = a -̃ b | |
157 Base.@propagate_inbounds Base.:-(a::LazyArray{T,D}, b::AbstractArray{T,D}) where {T,D} = a -̃ b | |
158 Base.@propagate_inbounds Base.:-(a::AbstractArray{T,D}, b::LazyArray{T,D}) where {T,D} = a -̃ b | |
159 | |
160 # Element wise operation for `*` and `\` are not overloaded due to conflicts with the behavior | |
161 # of regular `*` and `/` for AbstractArrays. Use tilde versions instead. | |
162 | |
163 export +̃, -̃, *̃, /̃ |