Skip to content

Commit e828c21

Browse files
committed
Eliminate reliance of deconv on filt and move into Convolutions module
1 parent c134edc commit e828c21

File tree

4 files changed

+65
-22
lines changed

4 files changed

+65
-22
lines changed

src/DSP.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module DSP
22

33
using LinearAlgebra: mul!
44

5-
export deconv, filt, filt!
5+
export filt, filt!
66

77
# This function has methods added in `periodograms` but is not exported,
88
# so we define it here so one can do `DSP.allocate_output` instead of

src/convolutions.jl

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using LinearAlgebra: Transpose, mul!
44
using IterTools: subsets
55
using FFTW
66

7-
export conv, conv!, xcorr, nextfastfft
7+
export conv, conv!, deconv, xcorr, nextfastfft
88

99
# Get next fast FFT size for a given signal length
1010
const FAST_FFT_SIZES = (2, 3, 5, 7)
@@ -690,6 +690,67 @@ function dsp_reverse(v::AbstractVector, vaxes::Tuple{AbstractUnitRange})
690690
copyto!(out, reflected_start, Iterators.reverse(v), 1, vsize)
691691
end
692692

693+
"""
694+
deconv(b, a) -> c
695+
696+
Construct vector `c` such that `b = conv(a,c) + r`.
697+
This is equivalent to polynomial division of `b` by `a`.
698+
699+
# Examples
700+
```jldoctest
701+
julia> b = [1.0, 2.0, 3.0, 4.0]; a = [1.0, 1.0];
702+
703+
julia> c = deconv(b, a)
704+
3-element Vector{Float64}:
705+
1.0
706+
1.0
707+
2.0
708+
709+
julia> conv(a, c)
710+
4-element Vector{Float64}:
711+
1.0
712+
2.0
713+
3.0
714+
2.0
715+
```
716+
"""
717+
function deconv(b::StridedVector{T}, a::StridedVector{T}) where T
718+
lb = length(b)
719+
la = length(a)
720+
721+
# If b is shorter than a, return [0] since polynomial division is impossible
722+
if lb < la
723+
return [zero(T)]
724+
end
725+
726+
if iszero(a[1])
727+
throw(ArgumentError("Leading coefficient of divisor must be non-zero"))
728+
end
729+
730+
V = typeof(one(T) / one(T))
731+
c = zeros(V, lb - la + 1)
732+
733+
if la == 1
734+
c .= b ./ a[1]
735+
else
736+
# Initialize remainder with b
737+
r = collect(V, b)
738+
739+
# Polynomial long division algorithm
740+
for i in 1:(lb-la+1)
741+
# Next coefficient is ratio of leading terms
742+
c_i = r[i] / a[1]
743+
c[i] = c_i
744+
745+
# Subtract a * c[i] from remaining terms
746+
for j in 1:la
747+
@inbounds r[i+j-1] -= a[j] * c_i
748+
end
749+
end
750+
end
751+
752+
return c
753+
end
693754

694755
"""
695756
xcorr(u; padmode::Symbol=:none, scaling::Symbol=:none)

src/dspbase.jl

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -152,21 +152,3 @@ function _small_filt_fir!(
152152
_filt_fir!(out, b, x, si, col)
153153
end
154154
end
155-
156-
"""
157-
deconv(b,a) -> c
158-
159-
Construct vector `c` such that `b = conv(a,c) + r`.
160-
Equivalent to polynomial division.
161-
"""
162-
function deconv(b::StridedVector{T}, a::StridedVector{T}) where T
163-
lb = size(b,1)
164-
la = size(a,1)
165-
if lb < la
166-
return [zero(T)]
167-
end
168-
lx = lb-la+1
169-
x = zeros(T, lx)
170-
x[1] = 1
171-
filt(b, a, x)
172-
end

test/dsp.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# This file was formerly a part of Julia. License is MIT: https://julialang.org/license
22
# TODO: parameterize conv tests
33
using Test, OffsetArrays
4-
using DSP: filt, filt!, deconv
5-
using DSP.Convolutions: conv, conv!, xcorr, nextfastfft,
4+
using DSP: filt, filt!
5+
using DSP.Convolutions: conv, conv!, deconv, xcorr, nextfastfft,
66
optimalfftfiltlength, unsafe_conv_kern_os!, _conv_kern_fft!
77

88

0 commit comments

Comments
 (0)