8
8
struct DiskTrav{T, AA<: AbstractMatrix{T} } <: AbstractBlockVector{T}
9
9
matrix:: AA
10
10
function DiskTrav {T, AA} (matrix:: AA ) where {T,AA<: AbstractMatrix{T} }
11
- n,m = size (matrix)
12
- isodd (m ) && n == m ÷ 4 + 1 || throw (ArgumentError (" size must match" ))
11
+ m,n = size (matrix)
12
+ isodd (n ) && m == n ÷ 4 + 1 || throw (ArgumentError (" size must match" ))
13
13
new {T,AA} (matrix)
14
14
end
15
15
end
16
16
17
17
DiskTrav {T} (matrix:: AbstractMatrix{T} ) where T = DiskTrav {T,typeof(matrix)} (matrix)
18
18
DiskTrav (matrix:: AbstractMatrix{T} ) where T = DiskTrav {T} (matrix)
19
19
20
+ function DiskTrav (v:: AbstractVector{T} ) where T
21
+ N = blocksize (v,1 )
22
+ m = N ÷ 2 + 1
23
+ n = 4 (m- 1 ) + 1
24
+ mat = zeros (T, m, n)
25
+ for K in blockaxes (v,1 )
26
+ K̃ = Int (K)
27
+ w = v[K]
28
+ if isodd (K̃)
29
+ mat[K̃÷ 2 + 1 ,1 ] = w[1 ]
30
+ for j = 2 : 2 : K̃- 1
31
+ mat[K̃÷ 2 - j÷ 2 + 1 ,2 (j- 1 )+ 2 ] = w[j]
32
+ mat[K̃÷ 2 - j÷ 2 + 1 ,2 (j- 1 )+ 3 ] = w[j+ 1 ]
33
+ end
34
+ else
35
+ for j = 1 : 2 : K̃
36
+ mat[K̃÷ 2 - j÷ 2 ,2 (j- 1 )+ 2 ] = w[j]
37
+ mat[K̃÷ 2 - j÷ 2 ,2 (j- 1 )+ 3 ] = w[j+ 1 ]
38
+ end
39
+ end
40
+ end
41
+ DiskTrav (mat)
42
+ end
43
+
20
44
axes (A:: DiskTrav ) = (blockedrange (oneto (div (size (A. matrix,2 ),2 ,RoundUp))),)
21
45
22
46
function getindex (A:: DiskTrav , K:: Block{1} )
@@ -165,6 +189,7 @@ function ZernikeTransform{T}(N::Int, a::Number, b::Number) where T<:Real
165
189
ZernikeTransform {T} (N, plan_disk2cxf (T, Ñ, a, b), plan_disk_analysis (T, Ñ, 4 Ñ- 3 ))
166
190
end
167
191
* (P:: ZernikeTransform{T} , f:: Matrix{T} ) where T = DiskTrav (P. disk2cxf \ (P. analysis * f))[Block .(1 : P. N)]
192
+ \ (P:: ZernikeTransform , f:: AbstractVector ) = P. analysis \ (P. disk2cxf * DiskTrav (f). matrix)
168
193
169
194
factorize (S:: FiniteZernike{T} ) where T = TransformFactorization (grid (S), ZernikeTransform {T} (blocksize (S,2 ), parent (S). a, parent (S). b))
170
195
@@ -174,6 +199,9 @@ struct WeightedZernikeLaplacianDiag{T} <: AbstractBlockVector{T} end
174
199
axes (:: WeightedZernikeLaplacianDiag ) = (blockedrange (oneto (∞)),)
175
200
copy (R:: WeightedZernikeLaplacianDiag ) = R
176
201
202
+ MemoryLayout (:: Type{<:WeightedZernikeLaplacianDiag} ) = LazyLayout ()
203
+ Base. BroadcastStyle (:: Type{<:Diagonal{<:Any,<:WeightedZernikeLaplacianDiag}} ) = LazyArrayStyle {2} ()
204
+
177
205
function Base. view (W:: WeightedZernikeLaplacianDiag{T} , K:: Block{1} ) where T
178
206
K̃ = Int (K)
179
207
d = K̃÷ 2 + 1
@@ -197,12 +225,20 @@ end
197
225
"""
198
226
ModalInterlace
199
227
"""
200
- struct ModalInterlace{T} <: AbstractBandedBlockBandedMatrix{T}
228
+ struct ModalInterlace{T, MMNN <: Tuple } <: AbstractBandedBlockBandedMatrix{T}
201
229
ops
230
+ MN:: MMNN
202
231
bandwidths:: NTuple{2,Int}
203
232
end
204
233
205
- axes (Z:: ModalInterlace ) = (blockedrange (oneto (∞)), blockedrange (oneto (∞)))
234
+ ModalInterlace {T} (ops, MN:: NTuple{2,Integer} , bandwidths:: NTuple{2,Int} ) where T =
235
+ ModalInterlace {T,typeof(MN)} (ops, MN, bandwidths)
236
+
237
+ # act like lazy array
238
+ MemoryLayout (:: Type {<: ModalInterlace{<:Any,NTuple{2,InfiniteCardinal{0}}} }) = LazyBandedBlockBandedLayout ()
239
+ Base. BroadcastStyle (:: Type {<: ModalInterlace{<:Any,NTuple{2,InfiniteCardinal{0}}} }) = LazyArrayStyle {2} ()
240
+
241
+ axes (Z:: ModalInterlace ) = blockedrange .(oneto .(Z. MN))
206
242
207
243
blockbandwidths (R:: ModalInterlace ) = R. bandwidths
208
244
subblockbandwidths (:: ModalInterlace ) = (0 ,0 )
@@ -230,18 +266,27 @@ end
230
266
231
267
getindex (R:: ModalInterlace , k:: Integer , j:: Integer ) = R[findblockindex .(axes (R),(k,j))... ]
232
268
269
+ function getindex (R:: ModalInterlace{T} , KR:: BlockOneTo , JR:: BlockOneTo ) where T
270
+ M,N = Int (last (KR)), Int (last (JR))
271
+ ModalInterlace {T} ([R. ops[m][1 : (M- m+ 2 )÷ 2 ,1 : (N- m+ 2 )÷ 2 ] for m= 1 : min (N,M)], (M,N), R. bandwidths)
272
+ end
273
+
233
274
function \ (A:: Zernike{T} , B:: Zernike{V} ) where {T,V}
234
275
TV = promote_type (T,V)
235
276
A. a == B. a && A. b == B. b && return Eye {TV} (∞)
236
277
@assert A. a == 0 && A. b == 1
237
278
@assert B. a == 0 && B. b == 0
238
- ModalInterlace {TV} ((Normalized .(Jacobi {TV} .(1 ,0 : ∞)) .\ Normalized .(Jacobi {TV} .(0 ,0 : ∞))) ./ sqrt (convert (TV, 2 )), (0 ,2 ))
279
+ ModalInterlace {TV} ((Normalized .(Jacobi {TV} .(1 ,0 : ∞)) .\ Normalized .(Jacobi {TV} .(0 ,0 : ∞))) ./ sqrt (convert (TV, 2 )), (ℵ₀,ℵ₀), ( 0 ,2 ))
239
280
end
240
281
241
282
function \ (A:: Zernike{T} , B:: Weighted{V,Zernike{V}} ) where {T,V}
242
283
TV = promote_type (T,V)
243
284
A. a == B. P. a == A. b == B. P. b == 0 && return Eye {TV} (∞)
244
- @assert A. a == A. b == 0
245
- @assert B. P. a == 0 && B. P. b == 1
246
- ModalInterlace {TV} ((Normalized .(Jacobi {TV} .(0 , 0 : ∞)) .\ HalfWeighted {:a} .(Normalized .(Jacobi {TV} .(1 , 0 : ∞)))) ./ sqrt (convert (TV, 2 )), (2 ,0 ))
285
+ if A. a == A. b == 0
286
+ @assert B. P. a == 0 && B. P. b == 1
287
+ ModalInterlace {TV} ((Normalized .(Jacobi {TV} .(0 , 0 : ∞)) .\ HalfWeighted {:a} .(Normalized .(Jacobi {TV} .(1 , 0 : ∞)))) ./ sqrt (convert (TV, 2 )), (ℵ₀,ℵ₀), (2 ,0 ))
288
+ else
289
+ Z = Zernike {TV} ()
290
+ (A \ Z) * (Z \ B)
291
+ end
247
292
end
0 commit comments