Skip to content

Commit 4e97792

Browse files
committed
Fix cheb2leg accuracy
1 parent 4cc6391 commit 4e97792

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

src/toeplitzhankel.jl

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,36 @@ function hankel_partialchol(v::Vector{T}) where T
102102
C[:,1:r]
103103
end
104104

105+
# cholesky for D .* H .* D'
106+
function hankel_partialchol(v::Vector, D::AbstractVector)
107+
T = promote_type(eltype(v), eltype(D))
108+
# Assumes positive definite
109+
σ = T[]
110+
n = isempty(v) ? 0 : (length(v)+2) ÷ 2
111+
C = Matrix{T}(undef, n, n)
112+
d = v[1:2:end] .* D.^2 # diag of D .* H .* D'
113+
@assert length(v) 2n-1
114+
reltol = maximum(abs,d)*eps(T)*log(n)
115+
r = 0
116+
for k = 1:n
117+
mx,idx = findmax(d)
118+
if mx reltol break end
119+
push!(σ, inv(mx))
120+
C[:,k] .= view(v,idx:n+idx-1) .*D.*D[idx]
121+
for j = 1:k-1
122+
nCjidxσj = -C[idx,j]*σ[j]
123+
LinearAlgebra.axpy!(nCjidxσj, view(C,:,j), view(C,:,k))
124+
end
125+
@inbounds for p=1:n
126+
d[p] -= C[p,k]^2/mx
127+
end
128+
r += 1
129+
end
130+
for k=1:length(σ) rmul!(view(C,:,k), sqrt(σ[k])) end
131+
C[:,1:r]
132+
end
133+
134+
105135

106136
# Diagonally-scaled Toeplitz∘Hankel polynomial transforms
107137

@@ -209,9 +239,10 @@ function _cheb2legTH_TLC(::Type{S}, mn, d) where S
209239
t[1:2:end] = Λ.(0:one(S̃):div(n-2,2), -half(S̃), one(S̃))
210240
end
211241
h = Λ.(1:half(S̃):n-1, zero(S̃), 3half(S̃))
212-
DL = (3half(S̃):n-half(S̃))
213-
DR = -(one(S̃):n-one(S̃))./4
214-
C = hankel_partialchol(h)
242+
D = 1:one(S):n-1
243+
DL = (3half(S̃):n-half(S̃)) ./ D
244+
DR = -(one(S̃):n-one(S̃)) ./ (4 .* D)
245+
C = hankel_partialchol(h, D)
215246
T = plan_uppertoeplitz!(t, (_sub_dim_by_one(d, mn...)..., size(C,2)), d)
216247
T, DL .* C, DR .* C
217248
end

test/toeplitzhankeltests.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import FastTransforms: th_leg2cheb, th_cheb2leg, th_ultra2ultra,th_jac2jac, th_l
44
plan_th_cheb2leg!, plan_th_leg2cheb!
55

66
@testset "ToeplitzHankel" begin
7-
for x in ([1.0], [1.0,2,3,4,5], [1.0+im,2-3im,3+4im,4-5im,5+10im])
7+
for x in ([1.0], [1.0,2,3,4,5], [1.0+im,2-3im,3+4im,4-5im,5+10im], collect(1.0:1000))
88
@test th_leg2cheb(x) lib_leg2cheb(x)
99
@test th_cheb2leg(x) lib_cheb2leg(x)
1010
@test th_leg2chebu(x) lib_ultra2ultra(x, 0.5, 1.0)
@@ -14,6 +14,9 @@ import FastTransforms: th_leg2cheb, th_cheb2leg, th_ultra2ultra,th_jac2jac, th_l
1414

1515
@test all(th_leg2cheb(x) .=== leg2cheb(x))
1616
@test all(th_cheb2leg(x) .=== cheb2leg(x))
17+
18+
@test th_cheb2leg(th_leg2cheb(x)) x atol=1E-9
19+
@test th_leg2leg(th_cheb2cheb(x)) x atol=1E-11
1720
end
1821

1922
for X in (randn(5,4), randn(5,4) + im*randn(5,4))
@@ -37,4 +40,13 @@ import FastTransforms: th_leg2cheb, th_cheb2leg, th_ultra2ultra,th_jac2jac, th_l
3740
@test leg2cheb(x) lib_leg2cheb(x)
3841
@test cheb2leg(x) lib_cheb2leg(x)
3942
end
43+
44+
@testset "jishnub example" begin
45+
x = chebyshevpoints(4096);
46+
f = x -> cospi(1000x);
47+
y = f.(x);
48+
v = cheb2leg(chebyshevtransform(y))
49+
@test norm(v - cheb2leg(leg2cheb(v)), Inf)  1E-13
50+
@test norm(v - cheb2leg(leg2cheb(v)))/norm(v) 1E-14
51+
end
4052
end

0 commit comments

Comments
 (0)