@@ -16,75 +16,42 @@ so that `L[:,k] = DL*C[:,k]` and `R[:,k] = DR*C[:,k]`.
16
16
This allows a Cholesky decomposition in 𝒪(K²N) operations and 𝒪(KN) storage, K = log N log ɛ⁻¹.
17
17
The tuple storage allows plans applied to each dimension.
18
18
"""
19
- struct ToeplitzHankelPlan{S, N, M, N1 , TP<: ToeplitzPlan{S,N1} } <: Plan{S}
20
- T:: NTuple{M,TP}
21
- L:: NTuple{M,Matrix{S}}
22
- R:: NTuple{M,Matrix{S}}
23
- tmp:: Array{S,N1}
24
- dims:: NTuple{M, Int}
25
- function ToeplitzHankelPlan {S,N,M, N1,TP } (T:: NTuple{M,TP} , L, R, dims) where {S,TP, N,N1,M }
19
+ struct ToeplitzHankelPlan{S, N, N1, LowR , TP, Dims } <: Plan{S}
20
+ T:: TP # A length M Vector or Tuple of ToeplitzPlan
21
+ L:: LowR # A length M Vector or Tuple of Matrices storing low rank factors of L
22
+ R:: LowR # A length M Vector or Tuple of Matrices storing low rank factors of R
23
+ tmp:: Array{S,N1} # A larger dimensional array to transform each scaled array all-at-once
24
+ dims:: Dims # A length M Vector or Tuple of Int storing the dimensions acted on
25
+ function ToeplitzHankelPlan {S,N,N1,LowR,TP,Dims } (T:: TP , L:: LowR , R:: LowR , dims) where {S,N,N1,LowR,TP,Dims }
26
26
tmp = Array {S} (undef, max .(size .(T)... )... )
27
- new {S,N,M, N1,TP } (T, L, R, tmp, dims)
27
+ new {S,N,N1,LowR,TP,Dims } (T, L, R, tmp, dims)
28
28
end
29
- ToeplitzHankelPlan {S,N,M,N1,TP} (T:: NTuple{M,TP} , L, R, dims:: Int ) where {S,TP,N,N1,M} =
30
- ToeplitzHankelPlan {S,N,M,N1,TP} (T, L, R, (dims,))
31
29
end
32
30
33
- ToeplitzHankelPlan (T:: ToeplitzPlan{S,2} , L:: Matrix , R:: Matrix , dims= 1 ) where S =
34
- ToeplitzHankelPlan {S, 1, 1, 2, typeof(T)} ((T,), (L,), (R,), dims)
35
31
36
- ToeplitzHankelPlan (T:: ToeplitzPlan{S,3} , L:: Matrix , R:: Matrix , dims) where S =
37
- ToeplitzHankelPlan {S, 2, 1,3, typeof(T)} ((T,), (L,), (R,), dims)
32
+ ToeplitzHankelPlan {S,N,M} (T:: TP , L:: LowR , R:: LowR , dims:: Dims ) where {S,N,M,LowR,TP,Dims} = ToeplitzHankelPlan {S,N,M,LowR,TP,Dims} (T, L, R, dims)
33
+ ToeplitzHankelPlan {S,N} (T, L, R, dims) where {S,N} = ToeplitzHankelPlan {S,N,N+1} (T, L, R, dims)
34
+ ToeplitzHankelPlan (T:: ToeplitzPlan{S,M} , L:: Matrix , R:: Matrix , dims= 1 ) where {S,M} = ToeplitzHankelPlan {S,M-1,M} ((T,), (L,), (R,), dims)
38
35
39
- ToeplitzHankelPlan (T:: NTuple{2,TP} , L:: Tuple , R:: Tuple , dims) where {S,TP<: ToeplitzPlan{S,3} } =
40
- ToeplitzHankelPlan {S, 2,2,3, TP} (T, L, R, dims)
41
36
42
-
43
- function * (P:: ToeplitzHankelPlan{<:Any,1} , v:: AbstractVector )
44
- (R,),(L,),(T,),tmp = P. R,P. L,P. T,P. tmp
45
- tmp .= R .* v
46
- T * tmp
47
- tmp .= L .* tmp
48
- sum! (v, tmp)
49
- end
50
-
51
- function _th_applymul1! (v, T, L, R, tmp)
52
- N = size (R,2 )
53
- m,n = size (v)
54
- tmp[1 : m,1 : n,1 : N] .= reshape (R,size (R,1 ),1 ,N) .* v
55
- T * view (tmp,1 : m,1 : n,1 : N)
56
- view (tmp,1 : m,1 : n,1 : N) .*= reshape (L,size (L,1 ),1 ,N)
57
- sum! (v, view (tmp,1 : m,1 : n,1 : N))
58
- end
59
-
60
- function _th_applymul2! (v, T, L, R, tmp)
61
- N = size (R,2 )
62
- m,n = size (v)
63
- tmp[1 : m,1 : n,1 : N] .= reshape (R,1 ,size (R,1 ),N) .* v
64
- T * view (tmp,1 : m,1 : n,1 : N)
65
- view (tmp,1 : m,1 : n,1 : N) .*= reshape (L,1 ,size (L,1 ),N)
66
- sum! (v, view (tmp,1 : m,1 : n,1 : N))
37
+ _reshape_broadcast (d, R, :: Val{N} , M) where N = reshape (R,ntuple (k -> k == d ? size (R,1 ) : 1 , Val (N))... ,M)
38
+ function _th_applymul! (d, v:: AbstractArray{<:Any,N} , T, L, R, tmp) where N
39
+ M = size (R,2 )
40
+ ax = (axes (v)... , OneTo (M))
41
+ tmp[ax... ] .= _reshape_broadcast (d, R, Val (N), M) .* v
42
+ T * view (tmp, ax... )
43
+ view (tmp,ax... ) .*= _reshape_broadcast (d, L, Val (N), M)
44
+ sum! (v, view (tmp,ax... ))
67
45
end
68
46
69
47
70
- function * (P:: ToeplitzHankelPlan{<:Any,2,1} , v:: AbstractMatrix )
71
- (R,),(L,),(T,),tmp = P. R,P. L,P. T,P. tmp
72
- if P. dims == (1 ,)
73
- _th_applymul1! (v, T, L, R, tmp)
74
- else
75
- _th_applymul2! (v, T, L, R, tmp)
48
+ function * (P:: ToeplitzHankelPlan{<:Any,N} , v:: AbstractArray{<:Any,N} ) where N
49
+ for (R,L,T,d) in zip (P. R,P. L,P. T,P. dims)
50
+ _th_applymul! (d, v, T, L, R, P. tmp)
76
51
end
77
52
v
78
53
end
79
54
80
- function * (P:: ToeplitzHankelPlan{<:Any,2,2} , v:: AbstractMatrix )
81
- (R1,R2),(L1,L2),(T1,T2),tmp = P. R,P. L,P. T,P. tmp
82
-
83
- _th_applymul1! (v, T1, L1, R1, tmp)
84
- _th_applymul2! (v, T2, L2, R2, tmp)
85
-
86
- v
87
- end
88
55
89
56
# partial cholesky for a Hankel matrix
90
57
@@ -166,9 +133,9 @@ function *(P::ChebyshevToLegendrePlanTH, v::AbstractVector{S}) where S
166
133
v
167
134
end
168
135
169
- function _cheb2leg_rescale1! (V:: AbstractMatrix {S} ) where S
170
- m,n = size (V)
171
- for j = 1 : n
136
+ function _cheb2leg_rescale1! (V:: AbstractArray {S} ) where S
137
+ m = size (V, 1 )
138
+ for j = CartesianIndices ( tail ( axes (V)))
172
139
ret = zero (S)
173
140
@inbounds for k = 1 : 2 : m
174
141
ret += - V[k,j]/ (k* (k- 2 ))
@@ -178,24 +145,15 @@ function _cheb2leg_rescale1!(V::AbstractMatrix{S}) where S
178
145
V
179
146
end
180
147
148
+ _dropfirstdim (d:: Int ) = ()
149
+ _dropfirstdim (d:: Int , m, szs... ) = ((d == 1 ? 2 : 1 ): m, _dropfirstdim (d- 1 , szs... )... )
181
150
182
- function * (P:: ChebyshevToLegendrePlanTH , V:: AbstractMatrix )
151
+ function * (P:: ChebyshevToLegendrePlanTH , V:: AbstractArray{<:Any,N} ) where N
183
152
m,n = size (V)
184
- dims = P. toeplitzhankel. dims
185
- if dims == (1 ,)
186
- _cheb2leg_rescale1! (V)
187
- P. toeplitzhankel* view (V,2 : m,:)
188
- elseif dims == (2 ,)
189
- _cheb2leg_rescale1! (transpose (V))
190
- P. toeplitzhankel* view (V,:,2 : n)
191
- else
192
- @assert dims == (1 ,2 )
193
- (R1,R2),(L1,L2),(T1,T2),tmp = P. toeplitzhankel. R,P. toeplitzhankel. L,P. toeplitzhankel. T,P. toeplitzhankel. tmp
194
-
195
- _cheb2leg_rescale1! (V)
196
- _th_applymul1! (view (V,2 : m,:), T1, L1, R1, tmp)
197
- _cheb2leg_rescale1! (transpose (V))
198
- _th_applymul2! (view (V,:,2 : n), T2, L2, R2, tmp)
153
+ tmp = P. toeplitzhankel. tmp
154
+ for (d,R,L,T) in zip (P. toeplitzhankel. dims,P. toeplitzhankel. R,P. toeplitzhankel. L,P. toeplitzhankel. T)
155
+ _cheb2leg_rescale1! (PermutedDimsArray (V, _permfirst (d, N)))
156
+ _th_applymul! (d, view (V, _dropfirstdim (d, size (V)... )... ), T, L, R, tmp)
199
157
end
200
158
V
201
159
end
@@ -226,18 +184,14 @@ function _leg2chebuTH_TLC(::Type{S}, mn, d) where {S}
226
184
(T, (1 : n) .* C, C)
227
185
end
228
186
229
-
230
187
for f in (:leg2cheb , :leg2chebu )
231
188
plan = Symbol (" plan_th_" , f, " !" )
232
189
TLC = Symbol (" _" , f, " TH_TLC" )
233
190
@eval begin
234
- $ plan (:: Type{S} , mn:: Tuple , dims:: Int ) where {S} = ToeplitzHankelPlan ($ TLC (S, mn, dims)... , dims)
235
-
236
- function $plan (:: Type{S} , mn:: NTuple{2,Int} , dims:: NTuple{2,Int} ) where {S}
237
- @assert dims == (1 ,2 )
238
- T1,L1,C1 = $ TLC (S, mn, 1 )
239
- T2,L2,C2 = $ TLC (S, mn, 2 )
240
- ToeplitzHankelPlan ((T1,T2), (L1,L2), (C1,C2), dims)
191
+ $ plan (:: Type{S} , mn:: NTuple{N,Int} , dims:: Int ) where {S,N} = ToeplitzHankelPlan ($ TLC (S, mn, dims)... , dims)
192
+ function $plan (:: Type{S} , mn:: NTuple{N,Int} , dims) where {S,N}
193
+ TLCs = $ TLC .(S, Ref (mn), dims)
194
+ ToeplitzHankelPlan {S,N} (map (first, TLCs), map (TLC -> TLC[2 ], TLCs), map (last, TLCs), dims)
241
195
end
242
196
end
243
197
end
@@ -265,13 +219,11 @@ function _cheb2legTH_TLC(::Type{S}, mn, d) where S
265
219
T, DL .* C, DR .* C
266
220
end
267
221
268
- plan_th_cheb2leg! (:: Type{S} , mn:: Tuple , dims:: Int ) where {S} = ChebyshevToLegendrePlanTH (ToeplitzHankelPlan (_cheb2legTH_TLC (S, mn, dims)... , dims))
222
+ plan_th_cheb2leg! (:: Type{S} , mn:: NTuple{N,Int} , dims:: Int ) where {S,N } = ChebyshevToLegendrePlanTH (ToeplitzHankelPlan (_cheb2legTH_TLC (S, mn, dims)... , dims))
269
223
270
- function plan_th_cheb2leg! (:: Type{S} , mn:: NTuple{2,Int} , dims:: NTuple{2,Int} ) where {S}
271
- @assert dims == (1 ,2 )
272
- T1,L1,C1 = _cheb2legTH_TLC (S, mn, 1 )
273
- T2,L2,C2 = _cheb2legTH_TLC (S, mn, 2 )
274
- ChebyshevToLegendrePlanTH (ToeplitzHankelPlan ((T1,T2), (L1,L2), (C1,C2), dims))
224
+ function plan_th_cheb2leg! (:: Type{S} , mn:: NTuple{N,Int} , dims) where {S,N}
225
+ TLCs = _cheb2legTH_TLC .(S, Ref (mn), dims)
226
+ ChebyshevToLegendrePlanTH (ToeplitzHankelPlan {S,N} (map (first, TLCs), map (TLC -> TLC[2 ], TLCs), map (last, TLCs), dims))
275
227
end
276
228
277
229
@@ -337,7 +289,7 @@ _good_plan_th_ultra2ultra!(::Type{S}, mn, λ₁, λ₂, dims::Int) where S = Toe
337
289
function _good_plan_th_ultra2ultra! (:: Type{S} , mn:: NTuple{2,Int} , λ₁, λ₂, dims:: NTuple{2,Int} ) where S
338
290
T1,L1,C1 = _ultra2ultraTH_TLC (S, mn, λ₁, λ₂, 1 )
339
291
T2,L2,C2 = _ultra2ultraTH_TLC (S, mn, λ₁, λ₂, 2 )
340
- ToeplitzHankelPlan ((T1,T2), (L1,L2), (C1,C2), dims)
292
+ ToeplitzHankelPlan {S,2} ((T1,T2), (L1,L2), (C1,C2), dims)
341
293
end
342
294
343
295
@@ -515,7 +467,7 @@ _good_plan_th_jac2jac!(::Type{S}, mn, α, β, γ, δ, dims::Int) where S = Toepl
515
467
function _good_plan_th_jac2jac! (:: Type{S} , mn:: NTuple{2,Int} , α, β, γ, δ, dims:: NTuple{2,Int} ) where S
516
468
T1,L1,C1 = _jac2jacTH_TLC (S, mn, α, β, γ, δ, 1 )
517
469
T2,L2,C2 = _jac2jacTH_TLC (S, mn, α, β, γ, δ, 2 )
518
- ToeplitzHankelPlan ((T1,T2), (L1,L2), (C1,C2), dims)
470
+ ToeplitzHankelPlan {S,2} ((T1,T2), (L1,L2), (C1,C2), dims)
519
471
end
520
472
521
473
685
637
for f in (:th_leg2cheb , :th_cheb2leg , :th_leg2chebu )
686
638
plan = Symbol (" plan_" , f, " !" )
687
639
@eval begin
688
- $ plan (:: Type{S} , mn:: NTuple{N,Int} , dims:: UnitRange ) where {N,S} = $ plan (S, mn, tuple (dims... ))
689
- $ plan (:: Type{S} , mn:: Tuple{Int} , dims:: Tuple{Int} = (1 ,)) where {S} = $ plan (S, mn, dims... )
690
- $ plan (:: Type{S} , (m,n):: NTuple{2,Int} ) where {S} = $ plan (S, (m,n), (1 ,2 ))
691
640
$ plan (arr:: AbstractArray{T} , dims... ) where T = $ plan (T, size (arr), dims... )
641
+ $ plan (:: Type{S} , mn:: NTuple{N,Int} ) where {S,N} = $ plan (S, mn, ntuple (identity,Val (N)))
692
642
$ f (v, dims... ) = $ plan (eltype (v), size (v), dims... )* copy (v)
693
643
end
694
644
end
0 commit comments