@@ -156,13 +156,12 @@ _grid(::WeightedBasisLayouts, P) = grid(unweighted(P))
156
156
grid (P) = _grid (MemoryLayout (P), P)
157
157
158
158
159
- struct TransformFactorization{T,Grid,Plan,IPlan } <: Factorization{T}
159
+ struct TransformFactorization{T,Grid,Plan} <: Factorization{T}
160
160
grid:: Grid
161
161
plan:: Plan
162
- iplan:: IPlan
163
162
end
164
163
165
- TransformFactorization {T} (grid, plan) where T = TransformFactorization {T,typeof(grid),typeof(plan),Nothing } (grid, plan, nothing )
164
+ TransformFactorization {T} (grid, plan) where T = TransformFactorization {T,typeof(grid),typeof(plan)} (grid, plan)
166
165
167
166
"""
168
167
TransformFactorization(grid, plan)
@@ -173,44 +172,84 @@ associates a planned transform with a grid. That is, if `F` is a `TransformFacto
173
172
TransformFactorization (grid, plan) = TransformFactorization {promote_type(eltype(eltype(grid)),eltype(plan))} (grid, plan)
174
173
175
174
176
- TransformFactorization {T} (grid, :: Nothing , iplan) where T = TransformFactorization {T,typeof(grid),Nothing,typeof(iplan)} (grid, nothing , iplan)
177
-
178
- """
179
- TransformFactorization(grid, nothing, iplan)
180
-
181
- associates a planned inverse transform with a grid. That is, if `F` is a `TransformFactorization`, then
182
- `F \\ f` is equivalent to `F.iplan \\ f[F.grid]`.
183
- """
184
- TransformFactorization (grid, :: Nothing , iplan) = TransformFactorization {promote_type(eltype(eltype(grid)),eltype(iplan))} (grid, nothing , iplan)
185
175
186
176
grid (T:: TransformFactorization ) = T. grid
187
177
function size (T:: TransformFactorization , k)
188
178
@assert k == 2 # TODO : make consistent
189
179
size (T. plan,1 )
190
180
end
191
181
192
- function size (T:: TransformFactorization{<:Any,<:Any,Nothing} , k)
193
- @assert k == 2 # TODO : make consistent
194
- size (T. iplan,2 )
182
+
183
+ \ (a:: TransformFactorization , b:: AbstractQuasiVector ) = a. plan * convert (Array, b[a. grid])
184
+ \ (a:: TransformFactorization , b:: AbstractQuasiMatrix ) = a. plan * convert (Array, b[a. grid,:])
185
+
186
+ """
187
+ InvPlan(factorization, dims)
188
+
189
+ Takes a factorization and supports it applied to different dimensions.
190
+ """
191
+ struct InvPlan{T, Fact, Dims} # <: Plan{T} We don't depend on AbstractFFTs
192
+ factorization:: Fact
193
+ dims:: Dims
195
194
end
196
195
196
+ InvPlan (fact, dims) = InvPlan {eltype(fact), typeof(fact), typeof(dims)} (fact, dims)
197
197
198
- \ (a:: TransformFactorization{<:Any,<:Any,Nothing} , b:: AbstractQuasiVector{T} ) where T = a. iplan \ convert (Array{T}, b[a. grid])
199
- \ (a:: TransformFactorization , b:: AbstractQuasiVector ) = a. plan * convert (Array, b[a. grid])
200
- \ (a:: TransformFactorization{<:Any,<:Any,Nothing} , b:: AbstractVector ) = a. iplan \ b
201
- \ (a:: TransformFactorization , b:: AbstractVector ) = a. plan * b
202
- ldiv! (ret:: AbstractVecOrMat , a:: TransformFactorization , b:: AbstractVecOrMat ) = mul! (ret, a. plan, b)
203
- ldiv! (ret:: AbstractVecOrMat , a:: TransformFactorization{<:Any,<:Any,Nothing} , b:: AbstractVecOrMat ) = ldiv! (ret, a. iplan, b)
198
+ size (F:: InvPlan , k... ) = size (F. factorization, k... )
199
+
200
+
201
+ function * (P:: InvPlan{<:Any,<:Any,Int} , x:: AbstractVector )
202
+ @assert P. dims == 1
203
+ P. factorization \ x
204
+ end
205
+
206
+ function * (P:: InvPlan{<:Any,<:Any,Int} , X:: AbstractMatrix )
207
+ if P. dims == 1
208
+ P. factorization \ X
209
+ else
210
+ @assert P. dims == 2
211
+ permutedims (P. factorization \ permutedims (X))
212
+ end
213
+ end
204
214
205
- \ (a:: TransformFactorization{<:Any,<:Any,Nothing} , b:: AbstractQuasiMatrix{T} ) where T = a \ convert (Array{T}, b[a. grid,:])
206
- \ (a:: TransformFactorization , b:: AbstractQuasiMatrix ) = a \ convert (Array, b[a. grid,:])
207
- \ (a:: TransformFactorization , b:: AbstractMatrix ) = ldiv! (Array {promote_type(eltype(a),eltype(b))} (undef,size (a,2 ),size (b,2 )), a, b)
215
+ function * (P:: InvPlan{<:Any,<:Any,Int} , X:: AbstractArray{<:Any,3} )
216
+ Y = similar (X)
217
+ if P. dims == 1
218
+ for j in axes (X,3 )
219
+ Y[:,:,j] = P. factorization \ X[:,:,j]
220
+ end
221
+ elseif P. dims == 2
222
+ for k in axes (X,1 )
223
+ Y[k,:,:] = P. factorization \ X[k,:,:]
224
+ end
225
+ else
226
+ @assert P. dims == 3
227
+ for k in axes (X,1 ), j in axes (X,2 )
228
+ Y[k,j,:] = P. factorization \ X[k,j,:]
229
+ end
230
+ end
231
+ Y
232
+ end
208
233
209
- function _factorize (:: AbstractBasisLayout , L, dims... ; kws... )
234
+ function * (P:: InvPlan , X:: AbstractArray )
235
+ for d in P. dims
236
+ X = InvPlan (P. factorization, d) * X
237
+ end
238
+ X
239
+ end
240
+
241
+
242
+ function plan_grid_transform (L, arr, dims= 1 : ndims (arr))
210
243
p = grid (L)
211
- TransformFactorization ( p, nothing , factorize (L[p,:]))
244
+ p, InvPlan ( factorize (L[p,:]), dims )
212
245
end
213
246
247
+ plan_transform (P, arr, dims... ) = plan_grid_transform (P, arr, dims... )[2 ]
248
+
249
+ _factorize (:: AbstractBasisLayout , L, dims... ; kws... ) =
250
+ TransformFactorization (plan_grid_transform (L, Array {eltype(L)} (undef, size (L,2 ), dims... ), 1 )... )
251
+
252
+
214
253
215
254
"""
216
255
ProjectionFactorization(F, inds)
225
264
226
265
\ (a:: ProjectionFactorization , b:: AbstractQuasiVector ) = (a. F \ b)[a. inds]
227
266
\ (a:: ProjectionFactorization , b:: AbstractQuasiMatrix ) = (a. F \ b)[a. inds,:]
228
- \ (a:: ProjectionFactorization , b:: AbstractVector ) = (a. F \ b)[a. inds]
229
267
230
- _factorize (:: SubBasisLayout , L, dims... ; kws... ) = ProjectionFactorization (factorize (parent (L), dims... ; kws... ), parentindices (L)[2 ])
268
+
269
+
270
+ # if parent is finite dimensional default to its transform and project down
271
+ _sub_factorize (:: Tuple{Any,Int} , (kr,jr), L, dims... ; kws... ) = ProjectionFactorization (factorize (parent (L), dims... ; kws... ), jr)
272
+ _sub_factorize (:: Tuple{Any,Int} , (kr,jr):: Tuple{Any,OneTo} , L, dims... ; kws... ) = ProjectionFactorization (factorize (parent (L), dims... ; kws... ), jr)
273
+
274
+ # ∞-dimensional parents need to use transforms. For now we assume the size of the transform is equal to the size of the truncation
275
+ _sub_factorize (:: Tuple{Any,Any} , (kr,jr):: Tuple{Any,OneTo} , L, dims... ; kws... ) =
276
+ TransformFactorization (plan_grid_transform (parent (L), Array {eltype(L)} (undef, last (jr), dims... ), 1 )... )
277
+
278
+ # If jr is not OneTo we project
279
+ _sub_factorize (:: Tuple{Any,Any} , (kr,jr), L, dims... ; kws... ) =
280
+ ProjectionFactorization (factorize (parent (L)[:,OneTo (maximum (jr))]), jr)
281
+
282
+ _factorize (:: SubBasisLayout , L, dims... ; kws... ) = _sub_factorize (size (parent (L)), parentindices (L), L, dims... ; kws... )
231
283
232
284
233
285
"""
@@ -260,6 +312,29 @@ plan_ldiv(A, B::AbstractQuasiMatrix) = factorize(A, size(B,2))
260
312
transform_ldiv (A:: AbstractQuasiArray{T} , B:: AbstractQuasiArray{V} , _) where {T,V} = plan_ldiv (A, B) \ B
261
313
transform_ldiv (A, B) = transform_ldiv (A, B, size (A))
262
314
315
+
316
+ """
317
+ transform(A, f)
318
+
319
+ finds the coefficients of a function `f` expanded in a basis defined as the columns of a quasi matrix `A`.
320
+ It is equivalent to
321
+ ```
322
+ A \\ f.(axes(A,1))
323
+ ```
324
+ """
325
+ transform (A, f) = A \ f .(axes (A,1 ))
326
+
327
+ """
328
+ expand(A, f)
329
+
330
+ expands a function `f` im a basis defined as the columns of a quasi matrix `A`.
331
+ It is equivalent to
332
+ ```
333
+ A / A \\ f.(axes(A,1))
334
+ ```
335
+ """
336
+ expand (A, f) = A * transform (A, f)
337
+
263
338
copy (L:: Ldiv{<:AbstractBasisLayout} ) = transform_ldiv (L. A, L. B)
264
339
# TODO : redesign to use simplifiable(\, A, B)
265
340
copy (L:: Ldiv{<:AbstractBasisLayout,ApplyLayout{typeof(*)},<:Any,<:AbstractQuasiVector} ) = transform_ldiv (L. A, L. B)
573
648
__sum (:: ExpansionLayout , A, dims) = __sum (ApplyLayout {typeof(*)} (), A, dims)
574
649
__cumsum (:: ExpansionLayout , A, dims) = __cumsum (ApplyLayout {typeof(*)} (), A, dims)
575
650
651
+ include (" basisconcat.jl" )
652
+ include (" basiskron.jl" )
576
653
include (" splines.jl" )
0 commit comments