cert 0.1.4

Uncertainty propagation and manipulation
Documentation
use super::{AbsUncertainty, RelUncertainty, Uncertainty};
use num_traits::Float;
use std::ops::{Add, Div, Mul, Neg, Sub};

impl<N: Float, U: Uncertainty<Float = N>> Add<U> for RelUncertainty<N> {
    type Output = RelUncertainty<N>;
    fn add(self, other: U) -> Self {
        let other: RelUncertainty<N> = other.into();
        Self::new(
            self.mean() + other.mean(),
            (self.uncertainty().powi(2) + other.uncertainty().powi(2)).sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Add<U> for AbsUncertainty<N> {
    type Output = AbsUncertainty<N>;
    fn add(self, other: U) -> Self {
        let other: AbsUncertainty<N> = other.into();
        Self::new(
            self.mean() + other.mean(),
            (self.uncertainty().powi(2) + other.uncertainty().powi(2)).sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Sub<U> for RelUncertainty<N> {
    type Output = RelUncertainty<N>;
    fn sub(self, other: U) -> Self {
        let other: RelUncertainty<N> = other.into();
        Self::new(
            self.mean() - other.mean(),
            (self.uncertainty().powi(2) + other.uncertainty().powi(2)).sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Sub<U> for AbsUncertainty<N> {
    type Output = AbsUncertainty<N>;
    fn sub(self, other: U) -> Self {
        let other: AbsUncertainty<N> = other.into();
        Self::new(
            self.mean() - other.mean(),
            (self.uncertainty().powi(2) + other.uncertainty().powi(2)).sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Mul<U> for RelUncertainty<N> {
    type Output = RelUncertainty<N>;
    fn mul(self, other: U) -> Self {
        let other: RelUncertainty<N> = other.into();
        Self::new(
            self.mean() * other.mean(),
            (self.uncertainty().powi(2) * other.mean().powi(2)
                + other.uncertainty().powi(2) * self.mean().powi(2))
            .sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Mul<U> for AbsUncertainty<N> {
    type Output = AbsUncertainty<N>;
    fn mul(self, other: U) -> Self {
        let other: AbsUncertainty<N> = other.into();
        Self::new(
            self.mean() * other.mean(),
            (self.uncertainty().powi(2) * other.mean().powi(2)
                + other.uncertainty().powi(2) * self.mean().powi(2))
            .sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Div<U> for RelUncertainty<N> {
    type Output = RelUncertainty<N>;
    fn div(self, other: U) -> Self {
        let other: RelUncertainty<N> = other.into();
        Self::new(
            self.mean() / other.mean(),
            (self.uncertainty().powi(2) / other.mean().powi(2)
                + self.mean().powi(2) * (other.uncertainty() * other.mean().powi(2)).abs().powi(2))
            .sqrt(),
        )
    }
}

impl<N: Float, U: Uncertainty<Float = N>> Div<U> for AbsUncertainty<N> {
    type Output = AbsUncertainty<N>;
    fn div(self, other: U) -> Self {
        let other: AbsUncertainty<N> = other.into();
        Self::new(
            self.mean() / other.mean(),
            (self.uncertainty().powi(2) / other.mean().powi(2)
                + self.mean().powi(2) * (other.uncertainty() * other.mean().powi(2)).abs().powi(2))
            .sqrt(),
        )
    }
}

impl<N: Float> Neg for AbsUncertainty<N> {
    type Output = Self;
    fn neg(self) -> Self::Output {
        Self::new(-self.mean(), self.uncertainty())
    }
}

impl<N: Float> Neg for RelUncertainty<N> {
    type Output = Self;
    fn neg(self) -> Self::Output {
        Self::new(-self.mean(), self.uncertainty())
    }
}