6
6
7
7
8
8
# # PolynomialRatio
9
- _zerosi (f:: PolynomialRatio{:z,T} , x :: AbstractArray{S} ) where {T,S} =
9
+ _zerosi (f:: PolynomialRatio{:z,T} , :: AbstractArray{S} ) where {T,S} =
10
10
zeros (promote_type (T, S), max (- firstindex (f. a), - firstindex (f. b)))
11
11
12
12
"""
@@ -35,7 +35,7 @@ selected based on the data and filter length.
35
35
filt (f:: PolynomialRatio{:z} , x, si= _zerosi (f, x)) = filt (coefb (f), coefa (f), x, si)
36
36
37
37
# # SecondOrderSections
38
- _zerosi (f:: SecondOrderSections{:z,T,G} , x :: AbstractArray{S} ) where {T,G,S} =
38
+ _zerosi (f:: SecondOrderSections{:z,T,G} , :: AbstractArray{S} ) where {T,G,S} =
39
39
zeros (promote_type (T, G, S), 2 , length (f. biquads))
40
40
41
41
# filt! algorithm (no checking, returns si)
@@ -44,14 +44,14 @@ function _filt!(out::AbstractArray, si::AbstractArray{S,N}, f::SecondOrderSectio
44
44
g = f. g
45
45
biquads = f. biquads
46
46
n = length (biquads)
47
- @inbounds for i = 1 : size (x, 1 )
47
+ @inbounds for i in axes (x, 1 )
48
48
yi = x[i, col]
49
49
for fi = 1 : n
50
50
biquad = biquads[fi]
51
51
xi = yi
52
- yi = si[1 , fi] + biquad . b0 * xi
53
- si[1 , fi] = si[ 2 , fi] + biquad. b1* xi - biquad . a1 * yi
54
- si[2 , fi] = biquad. b2* xi - biquad. a2* yi
52
+ yi = muladd (biquad . b0, xi, si[1 , fi])
53
+ si[1 , fi] = muladd (biquad . a1, - yi, muladd ( biquad. b1, xi, si[ 2 , fi]))
54
+ si[2 , fi] = muladd ( biquad. b2, xi, - biquad. a2 * yi)
55
55
end
56
56
out[i, col] = yi* g
57
57
end
@@ -80,17 +80,17 @@ filt(f::SecondOrderSections{:z,T,G}, x::AbstractArray{S}, si=_zerosi(f, x)) wher
80
80
filt! (Array {promote_type(T, G, S)} (undef, size (x)), f, x, si)
81
81
82
82
# # Biquad
83
- _zerosi (f :: Biquad{:z,T} , x :: AbstractArray{S} ) where {T,S} =
83
+ _zerosi (:: Biquad{:z,T} , :: AbstractArray{S} ) where {T,S} =
84
84
zeros (promote_type (T, S), 2 )
85
85
86
86
# filt! algorithm (no checking, returns si)
87
87
function _filt! (out:: AbstractArray , si1:: Number , si2:: Number , f:: Biquad{:z} ,
88
88
x:: AbstractArray , col:: Int )
89
- @inbounds for i = 1 : size (x, 1 )
89
+ @inbounds for i in axes (x, 1 )
90
90
xi = x[i, col]
91
- yi = si1 + f. b0* xi
92
- si1 = si2 + f . b1 * xi - f . a1 * yi
93
- si2 = f. b2* xi - f. a2* yi
91
+ yi = muladd ( f. b0, xi, si1)
92
+ si1 = muladd (f . a1, - yi, muladd (f . b1, xi, si2))
93
+ si2 = muladd ( f. b2, xi, - f. a2 * yi)
94
94
out[i, col] = yi
95
95
end
96
96
(si1, si2)
@@ -105,9 +105,8 @@ function filt!(out::AbstractArray, f::Biquad{:z}, x::AbstractArray,
105
105
(size (si, 1 ) != 2 || (N > 1 && Base. trailingsize (si, 2 ) != ncols)) &&
106
106
error (" si must have two rows and 1 or nsignals columns" )
107
107
108
- initial_si = si
109
108
for col = 1 : ncols
110
- _filt! (out, initial_si [1 , N > 1 ? col : 1 ], initial_si [2 , N > 1 ? col : 1 ], f, x, col)
109
+ _filt! (out, si [1 , N > 1 ? col : 1 ], si [2 , N > 1 ? col : 1 ], f, x, col)
111
110
end
112
111
out
113
112
end
@@ -170,13 +169,13 @@ function filt!(out::AbstractVector, f::DF2TFilter{<:PolynomialRatio,<:Vector}, x
170
169
if n == 1
171
170
mul! (out, x, b[1 ])
172
171
else
173
- @inbounds for i= 1 : length (x )
172
+ @inbounds for i in eachindex (x, out )
174
173
xi = x[i]
175
- val = si [1 ] + b [1 ]* xi
174
+ val = muladd (b [1 ], xi, si [1 ])
176
175
for j= 2 : n- 1
177
- si[j- 1 ] = si [j] + b[j]* xi - a [j]* val
176
+ si[j- 1 ] = muladd (a [j], - val, muladd ( b[j], xi, si [j]))
178
177
end
179
- si[n- 1 ] = b[n]* xi - a[n]* val
178
+ si[n- 1 ] = muladd ( b[n], xi, - a[n] * val)
180
179
out[i] = val
181
180
end
182
181
end
@@ -200,13 +199,13 @@ DF2TFilter(coef::Biquad{:z,T}, state::Vector{S}=zeros(T, 2)) where {T,S} =
200
199
function filt! (out:: AbstractVector , f:: DF2TFilter{<:Biquad,<:Vector} , x:: AbstractVector )
201
200
length (x) != length (out) && throw (ArgumentError (" out size must match x" ))
202
201
si = f. state
203
- (si[1 ], si[2 ]) = _filt! (out, si[1 ], si[2 ], f. coef, x, 1 )
202
+ (si[1 ], si[2 ]) = _filt! (out, si[1 ], si[2 ], f. coef, x, 1 )
204
203
out
205
204
end
206
205
207
206
# Variant that allocates the output
208
- filt (f:: DF2TFilter{<:FilterCoefficients{:z},S} , x:: AbstractVector ) where {S <: Array } =
209
- filt! (Vector {eltype(S) } (undef, length (x)), f, x)
207
+ filt (f:: DF2TFilter{<:FilterCoefficients{:z},<:Array{T}} , x:: AbstractVector ) where {T } =
208
+ filt! (Vector {T } (undef, length (x)), f, x)
210
209
211
210
# Fall back to SecondOrderSections
212
211
DF2TFilter (coef:: FilterCoefficients{:z} ) = DF2TFilter (convert (SecondOrderSections, coef))
@@ -346,7 +345,7 @@ filtfilt(f::PolynomialRatio{:z}, x) = filtfilt(coefb(f), coefa(f), x)
346
345
# response to a step function is steady state.
347
346
function filt_stepstate (b:: Union{AbstractVector{T}, T} , a:: Union{AbstractVector{T}, T} ) where T<: Number
348
347
scale_factor = a[1 ]
349
- if scale_factor != 1.0
348
+ if ! isone (scale_factor)
350
349
a = a ./ scale_factor
351
350
b = b ./ scale_factor
352
351
end
@@ -362,8 +361,8 @@ function filt_stepstate(b::Union{AbstractVector{T}, T}, a::Union{AbstractVector{
362
361
as< sz && (a = copyto! (zeros (eltype (a), sz), a))
363
362
364
363
# construct the companion matrix A and vector B:
365
- A = [- a[2 : end ] [I; zeros (T, 1 , sz- 2 )] ]
366
- B = b[ 2 : end ] - a[2 : end ] * b[1 ]
364
+ A = [- a[2 : end ] Matrix {T} (I, sz - 1 , sz- 2 )]
365
+ B = @views @. muladd ( a[2 : end ], - b[1 ], b[ 2 : end ])
367
366
# Solve si = A*si + B
368
367
# (I - A)*si = B
369
368
scale_factor \ (I - A) \ B
@@ -375,18 +374,18 @@ function filt_stepstate(f::SecondOrderSections{:z,T}) where T
375
374
y = one (T)
376
375
for i = 1 : length (biquads)
377
376
biquad = biquads[i]
377
+ a1, a2, b0, b1, b2 = biquad. a1, biquad. a2, biquad. b0, biquad. b1, biquad. b2
378
378
379
379
# At steady state, we have:
380
380
# y = s1 + b0*x
381
381
# s1 = s2 + b1*x - a1*y
382
382
# s2 = b2*x - a2*y
383
383
# where x is the input and y is the output. Solving these
384
384
# equations yields the following.
385
- si[1 , i] = (- (biquad. a1 + biquad. a2)* biquad. b0 + biquad. b1 + biquad. b2)/
386
- (1 + biquad. a1 + biquad. a2)* y
387
- si[2 , i] = (biquad. a1* biquad. b2 - biquad. a2* (biquad. b0 + biquad. b1) + biquad. b2)/
388
- (1 + biquad. a1 + biquad. a2)* y
389
- y *= (biquad. b0 + biquad. b1 + biquad. b2)/ (1 + biquad. a1 + biquad. a2)
385
+ den = (1 + a1 + a2)
386
+ si[1 , i] = muladd ((a1 + a2), - b0, b1 + b2) / den * y
387
+ si[2 , i] = muladd (a1, b2, muladd (- a2, (b0 + b1), b2)) / den * y
388
+ y *= (b0 + b1 + b2) / den
390
389
end
391
390
si
392
391
end
397
396
Apply filter or filter coefficients `h` along the first dimension
398
397
of array `x` using a naïve time-domain algorithm
399
398
"""
400
- function tdfilt (h:: AbstractVector , x:: AbstractArray{T} ) where T<: Real
401
- filt! ( Array {T} (undef, size (x)), h, ones ( eltype (h), 1 ), x)
399
+ function tdfilt (h:: AbstractVector{H} , x:: AbstractArray{T} ) where {H, T<: Real }
400
+ filt ( h, one (H ), x)
402
401
end
403
402
404
403
"""
@@ -407,12 +406,12 @@ end
407
406
Like `tdfilt`, but writes the result into array `out`. Output array `out` may
408
407
not be an alias of `x`, i.e. filtering may not be done in place.
409
408
"""
410
- function tdfilt! (out:: AbstractArray , h:: AbstractVector , x:: AbstractArray )
411
- filt! (out, h, ones ( eltype (h), 1 ), x)
409
+ function tdfilt! (out:: AbstractArray , h:: AbstractVector{H} , x:: AbstractArray ) where H
410
+ filt! (out, h, one (H ), x)
412
411
end
413
412
414
- filt (h:: AbstractArray , x:: AbstractArray ) =
415
- filt! (Array {eltype(x )} (undef, size (x)), h, x)
413
+ filt (h:: AbstractVector{H} , x:: AbstractArray{T} ) where {H,T} =
414
+ filt! (Array {promote_type(H, T )} (undef, size (x)), h, x)
416
415
417
416
#
418
417
# fftfilt and filt
@@ -447,48 +446,44 @@ end
447
446
# Like fftfilt! but does not check if out and x are the same size
448
447
function _fftfilt! (
449
448
out:: AbstractArray{<:Real} ,
450
- b:: AbstractVector{<:Real } ,
449
+ b:: AbstractVector{H } ,
451
450
x:: AbstractArray{T} ,
452
451
nfft:: Integer
453
- ) where T<: Real
452
+ ) where { T<: Real ,H <: Real }
454
453
nb = length (b)
455
454
nx = size (x, 1 )
456
- normfactor = 1 / nfft
455
+ normfactor = nfft
456
+ W = promote_type (H, T)
457
457
458
458
L = min (nx, nfft - (nb - 1 ))
459
- tmp1 = Vector {T } (undef, nfft)
460
- tmp2 = Vector {Complex{T }} (undef, nfft >> 1 + 1 )
459
+ tmp1 = Vector {W } (undef, nfft)
460
+ tmp2 = Vector {Complex{W }} (undef, nfft >> 1 + 1 )
461
461
462
462
p1 = plan_rfft (tmp1)
463
463
p2 = plan_brfft (tmp2, nfft)
464
464
465
465
# FFT of filter
466
466
filterft = similar (tmp2)
467
- tmp1[1 : nb] .= b .* normfactor
468
- tmp1[nb+ 1 : end ] .= zero (T )
467
+ tmp1[1 : nb] .= b ./ normfactor
468
+ tmp1[nb+ 1 : end ] .= zero (W )
469
469
mul! (filterft, p1, tmp1)
470
470
471
471
# FFT of chunks
472
- for colstart = 0 : nx: length (x)- 1
473
- off = 1
474
- while off <= nx
475
- npadbefore = max (0 , nb - off)
476
- xstart = off - nb + npadbefore + 1
477
- n = min (nfft - npadbefore, nx - xstart + 1 )
472
+ for colstart = 0 : nx: length (x)- 1 , off = 1 : L: nx
473
+ npadbefore = max (0 , nb - off)
474
+ xstart = off - nb + npadbefore + 1
475
+ n = min (nfft - npadbefore, nx - xstart + 1 )
478
476
479
- tmp1[1 : npadbefore] .= zero (T )
480
- tmp1[npadbefore+ n+ 1 : end ] .= zero (T )
477
+ tmp1[1 : npadbefore] .= zero (W )
478
+ tmp1[npadbefore+ n+ 1 : end ] .= zero (W )
481
479
482
- copyto! (tmp1, npadbefore+ 1 , x, colstart+ xstart, n)
483
- mul! (tmp2, p1, tmp1)
484
- broadcast! (* , tmp2, tmp2, filterft)
485
- mul! (tmp1, p2, tmp2)
480
+ copyto! (tmp1, npadbefore+ 1 , x, colstart+ xstart, n)
481
+ mul! (tmp2, p1, tmp1)
482
+ broadcast! (* , tmp2, tmp2, filterft)
483
+ mul! (tmp1, p2, tmp2)
486
484
487
- # Copy to output
488
- copyto! (out, colstart+ off, tmp1, nb, min (L, nx - off + 1 ))
489
-
490
- off += L
491
- end
485
+ # Copy to output
486
+ copyto! (out, colstart+ off, tmp1, nb, min (L, nx - off + 1 ))
492
487
end
493
488
494
489
out
@@ -524,6 +519,6 @@ function filt_choose_alg!(
524
519
end
525
520
end
526
521
527
- function filt_choose_alg! (out:: AbstractArray , b:: AbstractArray , x:: AbstractArray )
522
+ function filt_choose_alg! (out:: AbstractArray , b:: AbstractVector , x:: AbstractArray )
528
523
tdfilt! (out, b, x)
529
524
end
0 commit comments