|
1 | 1 | # Filter types and conversions |
2 | 2 |
|
| 3 | +using Base: uabs |
| 4 | + |
3 | 5 | abstract type FilterCoefficients{Domain} end |
4 | 6 |
|
5 | 7 | Base.convert(::Type{T}, f::FilterCoefficients) where {T<:FilterCoefficients} = T(f) |
@@ -45,11 +47,9 @@ Base.promote_rule(::Type{ZeroPoleGain{D,Z1,P1,K1}}, ::Type{ZeroPoleGain{D,Z2,P2, |
45 | 47 | Base.inv(f::ZeroPoleGain{D}) where {D} = ZeroPoleGain{D}(f.p, f.z, inv(f.k)) |
46 | 48 |
|
47 | 49 | function Base.:^(f::ZeroPoleGain{D}, e::Integer) where {D} |
48 | | - if e < 0 |
49 | | - return inv(f^-e) |
50 | | - else |
51 | | - return ZeroPoleGain{D}(repeat(f.z, e), repeat(f.p, e), f.k^e) |
52 | | - end |
| 50 | + ae = uabs(e) |
| 51 | + z, p = repeat(f.z, ae), repeat(f.p, ae) |
| 52 | + return e < 0 ? ZeroPoleGain{D}(p, z, inv(f.k)^ae) : ZeroPoleGain{D}(z, p, f.k^ae) |
53 | 53 | end |
54 | 54 |
|
55 | 55 | # |
@@ -184,11 +184,12 @@ end |
184 | 184 | Base.inv(f::PolynomialRatio{D}) where {D} = PolynomialRatio{D}(f.a, f.b) |
185 | 185 |
|
186 | 186 | function Base.:^(f::PolynomialRatio{D,T}, e::Integer) where {D,T} |
| 187 | + ae = uabs(e) |
| 188 | + b, a = f.b^ae, f.a^ae |
187 | 189 | if e < 0 |
188 | | - return PolynomialRatio{D}(f.a^-e, f.b^-e) |
189 | | - else |
190 | | - return PolynomialRatio{D}(f.b^e, f.a^e) |
| 190 | + b, a = a, b |
191 | 191 | end |
| 192 | + return PolynomialRatio{D}(b, a) |
192 | 193 | end |
193 | 194 |
|
194 | 195 | coef_s(p::LaurentPolynomial) = p[end:-1:0] |
@@ -304,7 +305,49 @@ Base.promote_rule(::Type{SecondOrderSections{D,T1,G1}}, ::Type{SecondOrderSectio |
304 | 305 |
|
305 | 306 | SecondOrderSections{D,T,G}(f::SecondOrderSections) where {D,T,G} = |
306 | 307 | SecondOrderSections{D,T,G}(f.biquads, f.g) |
| 308 | +SecondOrderSections{D,T,G}(f::Biquad{D}) where {D,T,G} = SecondOrderSections{D,T,G}([f], one(G)) |
| 309 | + |
307 | 310 | SecondOrderSections{D}(f::SecondOrderSections{D,T,G}) where {D,T,G} = SecondOrderSections{D,T,G}(f) |
| 311 | +SecondOrderSections{D}(f::Biquad{D,T}) where {D,T} = SecondOrderSections{D,T,Int}(f) |
| 312 | + |
| 313 | +*(f::SecondOrderSections{D}, g::Number) where {D} = SecondOrderSections{D}(f.biquads, f.g * g) |
| 314 | +*(g::Number, f::SecondOrderSections{D}) where {D} = SecondOrderSections{D}(f.biquads, f.g * g) |
| 315 | +*(f1::SecondOrderSections{D}, f2::SecondOrderSections{D}) where {D} = |
| 316 | + SecondOrderSections{D}([f1.biquads; f2.biquads], f1.g * f2.g) |
| 317 | +*(f1::SecondOrderSections{D}, fs::SecondOrderSections{D}...) where {D} = |
| 318 | + SecondOrderSections{D}(vcat(f1.biquads, map(f -> f.biquads, fs)...), f1.g * prod(f.g for f in fs)) |
| 319 | + |
| 320 | +*(f1::Biquad{D}, f2::Biquad{D}) where {D} = SecondOrderSections{D}([f1, f2], 1) |
| 321 | +*(f1::Biquad{D}, fs::Biquad{D}...) where {D} = SecondOrderSections{D}([f1, fs...], 1) |
| 322 | +*(f1::SecondOrderSections{D}, f2::Biquad{D}) where {D} = |
| 323 | + SecondOrderSections{D}([f1.biquads; f2], f1.g) |
| 324 | +*(f1::Biquad{D}, f2::SecondOrderSections{D}) where {D} = |
| 325 | + SecondOrderSections{D}([f1; f2.biquads], f2.g) |
| 326 | + |
| 327 | +Base.inv(f::SecondOrderSections{D}) where {D} = SecondOrderSections{D}(inv.(f.biquads), inv(f.g)) |
| 328 | + |
| 329 | +function Base.:^(f::SecondOrderSections{D}, e::Integer) where {D} |
| 330 | + ae = uabs(e) |
| 331 | + if e < 0 |
| 332 | + inv_f = inv(f) |
| 333 | + return SecondOrderSections{D}(repeat(inv_f.biquads, ae), inv_f.g^ae) |
| 334 | + else |
| 335 | + return SecondOrderSections{D}(repeat(f.biquads, ae), f.g^ae) |
| 336 | + end |
| 337 | +end |
| 338 | + |
| 339 | +function Base.:^(f::Biquad{D}, e::Integer) where {D} |
| 340 | + ae = uabs(e) |
| 341 | + return SecondOrderSections{D}(fill(e < 0 ? inv(f) : f, ae), 1) |
| 342 | +end |
| 343 | + |
| 344 | +function Biquad{D,T}(f::SecondOrderSections{D}) where {D,T} |
| 345 | + if length(f.biquads) != 1 |
| 346 | + throw(ArgumentError("only a single second order section may be converted to a biquad")) |
| 347 | + end |
| 348 | + Biquad{D,T}(f.biquads[1] * f.g) |
| 349 | +end |
| 350 | +Biquad{D}(f::SecondOrderSections{D,T,G}) where {D,T,G} = Biquad{D,promote_type(T, G)}(f) |
308 | 351 |
|
309 | 352 | function ZeroPoleGain{D,Z,P,K}(f::SecondOrderSections{D}) where {D,Z,P,K} |
310 | 353 | z = Z[] |
|
321 | 364 | ZeroPoleGain{D}(f::SecondOrderSections{D,T,G}) where {D,T,G} = |
322 | 365 | ZeroPoleGain{D,complex(T),complex(T),G}(f) |
323 | 366 |
|
324 | | -function Biquad{D,T}(f::SecondOrderSections{D}) where {D,T} |
325 | | - if length(f.biquads) != 1 |
326 | | - throw(ArgumentError("only a single second order section may be converted to a biquad")) |
327 | | - end |
328 | | - Biquad{D,T}(f.biquads[1] * f.g) |
329 | | -end |
330 | | -Biquad{D}(f::SecondOrderSections{D,T,G}) where {D,T,G} = Biquad{D,promote_type(T,G)}(f) |
331 | | - |
332 | 367 | PolynomialRatio{D,T}(f::SecondOrderSections{D}) where {D,T} = PolynomialRatio{D,T}(ZeroPoleGain(f)) |
333 | 368 | PolynomialRatio{D}(f::SecondOrderSections{D}) where {D} = PolynomialRatio{D}(ZeroPoleGain(f)) |
334 | 369 |
|
|
447 | 482 | SecondOrderSections{D}(f::ZeroPoleGain{D,Z,P,K}) where {D,Z,P,K} = |
448 | 483 | SecondOrderSections{D,promote_type(real(Z), real(P)), K}(f) |
449 | 484 |
|
450 | | - |
451 | | -SecondOrderSections{D,T,G}(f::Biquad{D}) where {D,T,G} = SecondOrderSections{D,T,G}([f], one(G)) |
452 | | -SecondOrderSections{D}(f::Biquad{D,T}) where {D,T} = SecondOrderSections{D,T,Int}(f) |
453 | 485 | SecondOrderSections{D}(f::FilterCoefficients{D}) where {D} = SecondOrderSections{D}(ZeroPoleGain(f)) |
454 | | - |
455 | | -*(f::SecondOrderSections{D}, g::Number) where {D} = SecondOrderSections{D}(f.biquads, f.g * g) |
456 | | -*(g::Number, f::SecondOrderSections{D}) where {D} = SecondOrderSections{D}(f.biquads, f.g * g) |
457 | | -*(f1::SecondOrderSections{D}, f2::SecondOrderSections{D}) where {D} = |
458 | | - SecondOrderSections{D}([f1.biquads; f2.biquads], f1.g * f2.g) |
459 | | -*(f1::SecondOrderSections{D}, fs::SecondOrderSections{D}...) where {D} = |
460 | | - SecondOrderSections{D}(vcat(f1.biquads, map(f -> f.biquads, fs)...), f1.g * prod(f.g for f in fs)) |
461 | | - |
462 | | -*(f1::Biquad{D}, f2::Biquad{D}) where {D} = SecondOrderSections{D}([f1, f2], 1) |
463 | | -*(f1::Biquad{D}, fs::Biquad{D}...) where {D} = SecondOrderSections{D}([f1, fs...], 1) |
464 | | -*(f1::SecondOrderSections{D}, f2::Biquad{D}) where {D} = |
465 | | - SecondOrderSections{D}([f1.biquads; f2], f1.g) |
466 | | -*(f1::Biquad{D}, f2::SecondOrderSections{D}) where {D} = |
467 | | - SecondOrderSections{D}([f1; f2.biquads], f2.g) |
468 | | - |
469 | | -Base.inv(f::SecondOrderSections{D}) where {D} = SecondOrderSections{D}(inv.(f.biquads), inv(f.g)) |
470 | | - |
471 | | -function Base.:^(f::SecondOrderSections{D}, e::Integer) where {D} |
472 | | - if e < 0 |
473 | | - return inv(f)^-e |
474 | | - else |
475 | | - return SecondOrderSections{D}(repeat(f.biquads, e), f.g^e) |
476 | | - end |
477 | | -end |
478 | | - |
479 | | -function Base.:^(f::Biquad{D}, e::Integer) where {D} |
480 | | - if e < 0 |
481 | | - return inv(f)^-e |
482 | | - else |
483 | | - return SecondOrderSections{D}(fill(f, e), 1) |
484 | | - end |
485 | | -end |
0 commit comments