@@ -15,46 +15,39 @@ filt{T<:Number}(b::Union(AbstractVector{T}, T), a::Union(AbstractVector{T}, T),
15
15
16
16
# in-place filtering; both the input and filter state are modified in-place
17
17
function filt! {T<:Number} (b:: Union(AbstractVector{T}, T) , a:: Union(AbstractVector{T}, T) ,
18
- x:: AbstractVector{T} , si:: AbstractVector{T} = zeros (T, max ( length (a), length (b)) - 1 ) )
18
+ x:: AbstractVector{T} , si:: Union( AbstractVector{T}, Nothing) = nothing )
19
19
if isempty (b); error (" b must be non-empty" ); end
20
20
if isempty (a); error (" a must be non-empty" ); end
21
21
if a[1 ]== 0 ; error (" a[1] must be nonzero" ); end
22
22
23
23
as = length (a)
24
24
bs = length (b)
25
25
sz = max (as, bs)
26
+ xs = size (x,1 )
26
27
27
- if sz == 1
28
- # Simple scaling without memory; quick exit
29
- return scale! (x, b[1 ]/ a[1 ])
30
- end
31
-
32
- if bs< sz
33
- # Ensure b has at least as many elements as a
34
- newb = zeros (T,sz)
35
- newb[1 : bs] = b
36
- b = newb
37
- end
28
+ # Quick exits
29
+ sz == 1 && return scale! (x, b[1 ]/ a[1 ]) # Simple scaling; no filter state
30
+ xs == 0 && return x # No data; return the same empty array
38
31
39
- xs = size (x,1 )
40
- silen = sz- 1
41
- size (si) == (silen,) || error (" the vector of initial conditions must have exactly max(length(a),length(b))-1 elements" )
32
+ has_denominator = (as > 1 )
33
+ # Make the filter coefficients the same length
34
+ a = copy! (zeros (T, sz), a)
35
+ b = copy! (zeros (T, sz), b)
42
36
43
37
if a[1 ] != 1
44
38
# Normalize the coefficients such that a[1] == 1
45
- norml = a[1 ]
46
- a ./= norml
47
- b ./= norml
39
+ norml = one (T) ./ a[1 ]
40
+ scale! (a, norml)
41
+ scale! (b, norml)
48
42
end
49
43
50
- if as > 1
51
- if as< sz
52
- # Pad a to be the same length as b
53
- newa = zeros (T,sz)
54
- newa[1 : as] = a
55
- a = newa
56
- end
44
+ silen = sz- 1
45
+ if si == nothing
46
+ si = scale! (filt_stepstate (b, a), x[1 ])
47
+ end
48
+ size (si) == (silen,) || error (" the vector of initial conditions must have exactly max(length(a),length(b))-1 elements" )
57
49
50
+ if has_denominator
58
51
@inbounds begin
59
52
for i= 1 : xs
60
53
val = si[1 ] + b[1 ]* x[i]
@@ -80,6 +73,24 @@ function filt!{T<:Number}(b::Union(AbstractVector{T}, T), a::Union(AbstractVecto
80
73
return x
81
74
end
82
75
76
+ # Compute an initial state for filt with coefficients (b,a) such that its
77
+ # response to a step function is steady state.
78
+ function filt_stepstate {T<:Number} (b:: Union(AbstractVector{T}, T) , a:: Union(AbstractVector{T}, T) )
79
+ sz = length (a)
80
+ sz == length (b) || error (" a and b must be the same length" )
81
+ sz > 0 || error (" a and b must have at least one element each" )
82
+ a[1 ] == 1 || error (" a and b must be normalized such that a[1] == 1" )
83
+
84
+ sz == 1 && return T[]
85
+
86
+ # construct the companion matrix A and vector B:
87
+ A = [- a[2 : end ] [eye (T, sz- 2 ); zeros (T, 1 , sz- 2 )]]
88
+ B = b[2 : end ] - a[2 : end ] * b[1 ]
89
+ # Solve si = A*si + B
90
+ # (I - A)*si = B
91
+ return (I - A) \ B
92
+ end
93
+
83
94
function deconv {T} (b:: StridedVector{T} , a:: StridedVector{T} )
84
95
lb = size (b,1 )
85
96
la = size (a,1 )
0 commit comments