use approx::{assert_abs_diff_eq, assert_relative_eq};
use automatica::{signals::discrete, Ssd, Tfz};
use polynomen::{poly, Poly};
#[test]
fn stability() {
let stable_poles = [-0.3_f64, 0., -0.99];
let den = Poly::new_from_roots(&stable_poles);
assert!(Tfz::new([0.5, 1.5], den).is_stable());
let unstable_poles = [-1.0_f64, 0.3, -5.];
let den2 = Poly::new_from_roots(&unstable_poles);
assert!(!Tfz::new([0.5, 1.5], den2).is_stable());
}
#[test]
fn equilibrium() {
let a = [0.6_f32, 0., 0., 0.4];
let b = [1., 5.];
let c = [1., 3.];
let d = [0.];
let sys = Ssd::new_from_slice(2, 1, 1, &a, &b, &c, &d);
let eq = sys.equilibrium(&[1.]).unwrap();
assert_relative_eq!(2.5, eq.x()[0]);
assert_relative_eq!(8.333_333, eq.x()[1]);
assert_relative_eq!(27.5, eq.y()[0]);
}
#[test]
fn no_equilibrium() {
let a = [0.6_f32, 0., 0., 1.];
let b = [1., 5.];
let c = [1., 3.];
let d = [0.];
let sys = Ssd::new_from_slice(2, 1, 1, &a, &b, &c, &d);
let no_eq = sys.equilibrium(&[1.]);
assert!(no_eq.is_none());
}
#[test]
fn static_gain() {
let tf = Tfz::new([-0.5], poly!(-0.5, 1.) * poly!(-0.5, 1.));
let sys = Ssd::new_observability_realization(&tf).unwrap();
let step = discrete::step_vec(1., 1, 1);
let evo = sys.evolution_fn(30, step, &[0., 0.]);
let last = evo.last().unwrap();
let gain = tf.static_gain();
assert_abs_diff_eq!(gain, last.output()[0], epsilon = 1e-5);
}
#[test]
fn fir_impulse() {
use std::iter::{once, repeat, Iterator};
let num = 1.016_f32 * poly!(0.015, 0.031, 0.063, 0.125, 0.25, 0.5);
let den = [0., 0., 0., 0., 0., 0., 1.];
let g = Tfz::new(num, den);
let mut iter = g.arma_iter(once(1.).chain(repeat(0.)));
assert_abs_diff_eq!(0.000, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.508, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.254, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.127, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.064, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.031, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.015, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.000, iter.next().unwrap(), epsilon = 1e-3); }
#[test]
fn fir_step() {
use std::iter::{repeat, Iterator};
let num = 1.016_f32 * poly!(0.015, 0.031, 0.063, 0.125, 0.25, 0.5);
let den = [0., 0., 0., 0., 0., 0., 1.];
let g = Tfz::new(num, den);
let mut iter = g.arma_iter(repeat(1.));
assert_abs_diff_eq!(0.000, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.508, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.762, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.889, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.953, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(0.985, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(1.000, iter.next().unwrap(), epsilon = 1e-3); assert_abs_diff_eq!(1.000, iter.next().unwrap(), epsilon = 1e-3); }