Mercurial > repos > public > sbplib_julia
comparison LazyTensor/src/LazyTensor.jl @ 187:156bb18a2252 boundary_conditions
Merge with tip
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Thu, 20 Jun 2019 21:22:44 +0200 |
parents | b7397ae8afaf |
children |
comparison
equal
deleted
inserted
replaced
178:64b9751b3cb2 | 187:156bb18a2252 |
---|---|
1 module LazyTensor | |
2 | |
3 | |
4 """ | |
5 Mapping{T,R,D} | |
6 | |
7 Describes a mapping of a D dimension tensor to an R dimension tensor. | |
8 The action of the mapping is implemented through the method | |
9 | |
10 apply(t::Mapping{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {R,D,T} | |
11 | |
12 The size of range tensor should be dependent on the size of the domain tensor | |
13 and the type should implement the methods | |
14 | |
15 range_size(::Mapping{T,R,D}, domain_size::NTuple{D,Integer}) where {T,R,D} | |
16 domain_size(::Mapping{T,R,D}, range_size::NTuple{R,Integer}) where {T,R,D} | |
17 | |
18 to allow querying for one or the other. | |
19 | |
20 Optionally the action of the transpose may be defined through | |
21 apply_transpose(t::Mapping{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {R,D,T} | |
22 """ | |
23 abstract type Mapping{T,R,D} end | |
24 | |
25 """ | |
26 apply(t::Mapping{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {R,D,T} | |
27 | |
28 Return the result of the mapping for a given index. | |
29 """ | |
30 function apply end | |
31 export apply | |
32 | |
33 """ | |
34 apply_transpose(t::Mapping{T,R,D}, v::AbstractArray{T,R}, I::Vararg) where {R,D,T} | |
35 | |
36 Return the result of the transposed mapping for a given index. | |
37 """ | |
38 function apply_transpose end | |
39 export apply_transpose | |
40 | |
41 """ | |
42 Return the dimension of the range space of a given mapping | |
43 """ | |
44 range_dim(::Mapping{T,R,D}) where {T,R,D} = R | |
45 | |
46 """ | |
47 Return the dimension of the domain space of a given mapping | |
48 """ | |
49 domain_dim(::Mapping{T,R,D}) where {T,R,D} = D | |
50 | |
51 export range_dim, domain_dim | |
52 | |
53 """ | |
54 range_size(M::Mapping, domain_size) | |
55 | |
56 Return the resulting range size for the mapping applied to a given domain_size | |
57 """ | |
58 function range_size end | |
59 | |
60 """ | |
61 domain_size(M::Mapping, range_size) | |
62 | |
63 Return the resulting domain size for the mapping applied to a given range_size | |
64 """ | |
65 function domain_size end | |
66 | |
67 export range_size, domain_size | |
68 # TODO: Think about boundschecking! | |
69 | |
70 | |
71 """ | |
72 Operator{T,D} | |
73 | |
74 A `Mapping{T,D,D}` where the range and domain tensor have the same number of | |
75 dimensions and the same size. | |
76 """ | |
77 abstract type Operator{T,D} <: Mapping{T,D,D} end | |
78 domain_size(::Operator{T,D}, range_size::NTuple{D,Integer}) where {T,D} = range_size | |
79 range_size(::Operator{T,D}, domain_size::NTuple{D,Integer}) where {T,D} = domain_size | |
80 | |
81 | |
82 | |
83 """ | |
84 MappingTranspose{T,R,D} <: Mapping{T,D,R} | |
85 | |
86 Struct for lazy transpose of a Mapping. | |
87 | |
88 If a mapping implements the the `apply_transpose` method this allows working with | |
89 the transpose of mapping `m` by using `m'`. `m'` will work as a regular Mapping lazily calling | |
90 the appropriate methods of `m`. | |
91 """ | |
92 struct MappingTranspose{T,R,D} <: Mapping{T,D,R} | |
93 tm::Mapping{T,R,D} | |
94 end | |
95 | |
96 # # TBD: Should this be implemented on a type by type basis or through a trait to provide earlier errors? | |
97 Base.adjoint(t::Mapping) = MappingTranspose(t) | |
98 Base.adjoint(t::MappingTranspose) = t.tm | |
99 | |
100 apply(tm::MappingTranspose{T,R,D}, v::AbstractArray{T,R}, I::Vararg) where {T,R,D} = apply_transpose(tm.tm, v, I...) | |
101 apply_transpose(tm::MappingTranspose{T,R,D}, v::AbstractArray{T,D}, I::Vararg) where {T,R,D} = apply(tm.tm, v, I...) | |
102 | |
103 range_size(tmt::MappingTranspose{T,R,D}, d_size::NTuple{R,Integer}) where {T,R,D} = domain_size(tmt.tm, domain_size) | |
104 domain_size(tmt::MappingTranspose{T,R,D}, r_size::NTuple{D,Integer}) where {T,R,D} = range_size(tmt.tm, range_size) | |
105 | |
106 | |
107 """ | |
108 Application{T,R,D} <: AbstractArray{T,R} | |
109 | |
110 Struct for lazy application of a Mapping. Created using `*`. | |
111 | |
112 Allows the result of a `Mapping` applied to a vector to be treated as an `AbstractArray`. | |
113 With a mapping `m` and a vector `v` the Application object can be created by `m*v`. | |
114 The actual result will be calcualted when indexing into `m*v`. | |
115 """ | |
116 struct Application{T,R,D} <: AbstractArray{T,R} | |
117 t::Mapping{T,R,D} | |
118 o::AbstractArray{T,D} | |
119 end | |
120 | |
121 Base.:*(tm::Mapping{T,R,D}, o::AbstractArray{T,D}) where {T,R,D} = Application(tm,o) | |
122 | |
123 Base.getindex(ta::Application{T,R,D}, I::Vararg) where {T,R,D} = apply(ta.t, ta.o, I...) | |
124 Base.size(ta::Application{T,R,D}) where {T,R,D} = range_size(ta.t,size(ta.o)) | |
125 # TODO: What else is needed to implement the AbstractArray interface? | |
126 | |
127 | |
128 # # We need the associativity to be a→b→c = a→(b→c), which is the case for '→' | |
129 Base.:*(args::Union{Mapping{T}, AbstractArray{T}}...) where T = foldr(*,args) | |
130 # # Should we overload some other infix binary operator? | |
131 # →(tm::Mapping{T,R,D}, o::AbstractArray{T,D}) where {T,R,D} = Application(tm,o) | |
132 # TODO: We need to be really careful about good error messages. | |
133 # For example what happens if you try to multiply Application with a Mapping(wrong order)? | |
134 | |
135 | |
136 | |
137 # struct TensorMappingComposition{T,R,K,D} <: Mapping{T,R,D} | |
138 # t1::Mapping{T,R,K} | |
139 # t2::Mapping{T,K,D} | |
140 # end | |
141 | |
142 # Base.:∘(s::Mapping{T,R,K}, t::Mapping{T,K,D}) where {T,R,K,D} = TensorMappingComposition(s,t) | |
143 | |
144 # function range_size(tm::TensorMappingComposition{T,R,K,D}, domain_size::NTuple{D,Integer}) where {T,R,K,D} | |
145 # range_size(tm.t1, domain_size(tm.t2, domain_size)) | |
146 # end | |
147 | |
148 # function domain_size(tm::TensorMappingComposition{T,R,K,D}, range_size::NTuple{R,Integer}) where {T,R,K,D} | |
149 # domain_size(tm.t1, domain_size(tm.t2, range_size)) | |
150 # end | |
151 | |
152 # function apply(c::TensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::Vararg) where {T,R,K,D} | |
153 # apply(c.t1, Application(c.t2,v), I...) | |
154 # end | |
155 | |
156 # function apply_transpose(c::TensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::Vararg) where {T,R,K,D} | |
157 # apply_transpose(c.t2, Application(c.t1',v), I...) | |
158 # end | |
159 | |
160 # # Have i gone too crazy with the type parameters? Maybe they aren't all needed? | |
161 | |
162 # export → | |
163 | |
164 | |
165 end # module |