Skip to content

Commit 45bb03f

Browse files
committed
Optimized the use of Durbin algorithm
1 parent 4a25d3a commit 45bb03f

File tree

3 files changed

+42
-21
lines changed

3 files changed

+42
-21
lines changed

src/signalcorr.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,12 +549,14 @@ function pacf_regress!(r::AbstractMatrix, X::AbstractMatrix, lags::IntegerVector
549549
end
550550

551551
function pacf_yulewalker!(r::AbstractMatrix, X::AbstractMatrix, lags::IntegerVector, mk::Integer)
552-
tmp = Vector{eltype(X)}(undef, mk)
552+
p = Vector{eltype(X)}(undef, mk)
553+
y = Vector{eltype(X)}(undef, mk)
553554
for j = 1 : size(X,2)
554555
acfs = autocor(X[:,j], 1:mk)
556+
tmp = durbin!(acfs, p, y)
555557
for i = 1 : length(lags)
556558
l = lags[i]
557-
r[i,j] = l == 0 ? 1 : l == 1 ? acfs[i] : -durbin!(view(acfs, 1:l), tmp)[l]
559+
r[i,j] = l == 0 ? 1 : -p[l]
558560
end
559561
end
560562
end

src/toeplitzsolvers.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Symmetric Toeplitz solver
2-
function durbin!(r::AbstractVector{T}, y::AbstractVector{T}) where T
2+
function durbin!(r::AbstractVector{T}, p::AbstractVector{T}, y::AbstractVector{T}) where T
33
n = length(r)
4-
n <= length(y) || throw(DimensionMismatch("Auxiliary vector cannot be shorter than data vector"))
4+
n <= length(p) || n <= length(y) || throw(DimensionMismatch("Auxiliary vectors cannot be shorter than data vector"))
55
y[1] = -r[1]
6+
p[1] = -r[1]
67
β = one(T)
78
α = -r[1]
89
for k = 1:n-1
@@ -19,10 +20,11 @@ function durbin!(r::AbstractVector{T}, y::AbstractVector{T}) where T
1920
end
2021
if isodd(k) y[div(k,2)+1] += α*conj(y[div(k,2)+1]) end
2122
y[k+1] = α
23+
p[k+1] = α
2224
end
23-
return y
25+
return p
2426
end
25-
durbin(r::AbstractVector{T}) where T = durbin!(r, zeros(T, length(r)))
27+
durbin(r::AbstractVector{T}) where T = durbin!(r, zeros(T, length(r)), zeros(T, length(r)))
2628

2729
function levinson!(r::AbstractVector{T}, b::AbstractVector{T}, x::AbstractVector{T}) where T<:BlasReal
2830
n = length(b)

test/signalcorr.jl

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,35 @@ c22 = crosscor(x2, x2)
103103
@test crosscor(x, x) cat([c11 c21], [c12 c22], dims=3)
104104

105105

106-
## pacf
107-
108-
pacfr = [-1.598495044296996e-03 - 2.915104118351207e-01im
109-
-5.560162016912027e-01 + 2.950837739894279e-01im
110-
-2.547001916363494e-02 + 2.326084658014266e-01im
111-
-5.427443903358727e-01 + 3.146715147305132e-01im];
112-
113-
@test pacf(x1, 1:4) pacfr[1:4]
114-
115-
pacfy = [-1.598495044296996e-03 - 2.915104118351207e-01im
116-
-5.560162016912027e-01 + 2.950837739894279e-01im
117-
-2.547001916363494e-02 + 2.326084658014266e-01im
118-
-5.427443903358727e-01 + 3.146715147305132e-01im];
119-
120-
@test pacf(x1, 1:4, method=:yulewalker) pacfy
106+
## pacf least squares
107+
pacf_ls = [-1.598495044296996e-03 - 2.915104118351207e-01im
108+
-5.560162016912027e-01 + 2.950837739894279e-01im
109+
-2.547001916363494e-02 + 2.326084658014266e-01im
110+
-5.427443903358727e-01 + 3.146715147305132e-01im]
111+
112+
@test pacf(x1, 1:4) pacf_ls[1:4]
113+
114+
## pacf Yule-Walker
115+
116+
function yulewalker_qr(v::AbstractVector)
117+
A = toeplitz(v)
118+
b = v[2:end]
119+
x =-A\b
120+
end
121+
function toeplitz(v::AbstractVector{T}) where T
122+
N=length(v)
123+
A = zeros(T, N - 1, N - 1)
124+
for n in 1:N-1
125+
A[n, n + 1:end] = conj(v[2:N-n])
126+
A[n, 1:n] = reverse(v[1:n])
127+
end
128+
return A
129+
end
130+
# durbin solver
131+
acf = autocor(x1)
132+
p = [yulewalker_qr(acf[1:n])[n-1] for n in 2:length(acf)]
133+
@test p StatsBase.durbin(acf[2:end])
134+
135+
pacfy = [];
136+
137+
@test pacf(x1, 1:4, method=:yulewalker) -p[1:4]

0 commit comments

Comments
 (0)