use num::complex::Complex;
use super::common::{rotate_matrix, Angle, ComplexMatrix, JonesMatrix};
#[cfg(test)]
use proptest::prelude::*;
#[derive(Debug, Copy, Clone)]
pub struct IdentityElement {
mat: ComplexMatrix,
}
impl IdentityElement {
pub fn new() -> Self {
let zero = Complex::new(0_f64, 0_f64);
let one = Complex::new(1_f64, 0_f64);
let mat = ComplexMatrix::new(one, zero, zero, one);
IdentityElement { mat }
}
}
impl JonesMatrix for IdentityElement {
fn rotated(&self, angle: Angle) -> Self {
let mat = rotate_matrix(&self.matrix(), &angle);
IdentityElement { mat }
}
fn rotate(&mut self, angle: Angle) {
self.mat = rotate_matrix(&self.matrix(), &angle);
}
fn matrix(&self) -> ComplexMatrix {
self.mat
}
}
#[cfg(test)]
impl Arbitrary for IdentityElement {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;
fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
Just(IdentityElement::new()).boxed()
}
}
#[cfg(test)]
mod test {
use super::*;
use jones::common::{are_rel_eq, float_angle, Beam, JonesVector};
proptest! {
#[test]
fn test_identity_element_returns_same_beam(beam: Beam) {
let ident = IdentityElement::new();
let beam_after = beam.apply_element(ident);
prop_assert_beam_approx_eq!(beam_after, beam);
}
#[test]
fn test_multiple_identity_elements_preserves_beam(beam: Beam, elems: Vec<IdentityElement>) {
let mut beam_after = beam.clone();
for elem in elems {
beam_after = beam_after.apply_element(elem);
}
prop_assert_beam_approx_eq!(beam_after, beam);
}
#[test]
fn test_identity_preserved_under_rotation(theta in float_angle()) {
let beam = Beam::linear(Angle::Degrees(theta));
let ident = IdentityElement::new().rotated(Angle::Degrees(theta));
let beam_after = beam.apply_element(ident);
prop_assert_beam_approx_eq!(beam_after, beam);
}
}
}