@@ -16,75 +16,42 @@ so that `L[:,k] = DL*C[:,k]` and `R[:,k] = DR*C[:,k]`.
1616This allows a Cholesky decomposition in 𝒪(K²N) operations and 𝒪(KN) storage, K = log N log ɛ⁻¹.
1717The tuple storage allows plans applied to each dimension.
1818"""
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 }
2626 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)
2828 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,))
3129end
3230
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)
3531
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)
3835
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)
4136
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... ))
6745end
6846
6947
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)
7651 end
7752 v
7853end
7954
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
8855
8956# partial cholesky for a Hankel matrix
9057
@@ -166,9 +133,9 @@ function *(P::ChebyshevToLegendrePlanTH, v::AbstractVector{S}) where S
166133 v
167134end
168135
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)))
172139 ret = zero (S)
173140 @inbounds for k = 1 : 2 : m
174141 ret += - V[k,j]/ (k* (k- 2 ))
@@ -178,24 +145,15 @@ function _cheb2leg_rescale1!(V::AbstractMatrix{S}) where S
178145 V
179146end
180147
148+ _dropfirstdim (d:: Int ) = ()
149+ _dropfirstdim (d:: Int , m, szs... ) = ((d == 1 ? 2 : 1 ): m, _dropfirstdim (d- 1 , szs... )... )
181150
182- function * (P:: ChebyshevToLegendrePlanTH , V:: AbstractMatrix )
151+ function * (P:: ChebyshevToLegendrePlanTH , V:: AbstractArray{<:Any,N} ) where N
183152 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)
199157 end
200158 V
201159end
@@ -226,18 +184,14 @@ function _leg2chebuTH_TLC(::Type{S}, mn, d) where {S}
226184 (T, (1 : n) .* C, C)
227185end
228186
229-
230187for f in (:leg2cheb , :leg2chebu )
231188 plan = Symbol (" plan_th_" , f, " !" )
232189 TLC = Symbol (" _" , f, " TH_TLC" )
233190 @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)
241195 end
242196 end
243197end
@@ -265,13 +219,11 @@ function _cheb2legTH_TLC(::Type{S}, mn, d) where S
265219 T, DL .* C, DR .* C
266220end
267221
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))
269223
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))
275227end
276228
277229
@@ -337,7 +289,7 @@ _good_plan_th_ultra2ultra!(::Type{S}, mn, λ₁, λ₂, dims::Int) where S = Toe
337289function _good_plan_th_ultra2ultra! (:: Type{S} , mn:: NTuple{2,Int} , λ₁, λ₂, dims:: NTuple{2,Int} ) where S
338290 T1,L1,C1 = _ultra2ultraTH_TLC (S, mn, λ₁, λ₂, 1 )
339291 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)
341293end
342294
343295
@@ -515,7 +467,7 @@ _good_plan_th_jac2jac!(::Type{S}, mn, α, β, γ, δ, dims::Int) where S = Toepl
515467function _good_plan_th_jac2jac! (:: Type{S} , mn:: NTuple{2,Int} , α, β, γ, δ, dims:: NTuple{2,Int} ) where S
516468 T1,L1,C1 = _jac2jacTH_TLC (S, mn, α, β, γ, δ, 1 )
517469 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)
519471end
520472
521473
685637for f in (:th_leg2cheb , :th_cheb2leg , :th_leg2chebu )
686638 plan = Symbol (" plan_" , f, " !" )
687639 @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 ))
691640 $ 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)))
692642 $ f (v, dims... ) = $ plan (eltype (v), size (v), dims... )* copy (v)
693643 end
694644end
0 commit comments