autofloat 1.0.4

Pure Rust library for efficient automatic differentiation
Documentation
use num_traits::Zero;
use simba::scalar::{SubsetOf, SupersetOf};

use crate::{autofloat::unary_op, AutoFloat};

impl<T, const N: usize> SubsetOf<AutoFloat<T, N>> for AutoFloat<T, N>
where
    T: SubsetOf<T> + Clone,
{
    fn to_superset(&self) -> Self {
        AutoFloat {
            x: self.x.to_superset(),
            dx: unary_op(self.dx.clone(), |v| v.to_superset()),
        }
    }
    fn from_superset_unchecked(element: &AutoFloat<T, N>) -> Self {
        AutoFloat {
            x: T::from_superset_unchecked(&element.x),
            dx: unary_op(element.dx.clone(), |v| T::from_superset_unchecked(&v)),
        }
    }
    fn is_in_subset(element: &AutoFloat<T, N>) -> bool {
        T::is_in_subset(&element.x) && element.dx.iter().all(T::is_in_subset)
    }
}

impl<T, const N: usize> SubsetOf<T> for AutoFloat<T, N>
where
    T: SubsetOf<T> + Zero + Clone,
{
    fn to_superset(&self) -> T {
        self.x.to_superset()
    }
    fn from_superset_unchecked(element: &T) -> Self {
        AutoFloat::constant(T::from_superset_unchecked(&element))
    }
    fn is_in_subset(element: &T) -> bool {
        T::is_in_subset(element)
    }
}

impl<T, const N: usize> SupersetOf<f32> for AutoFloat<T, N>
where
    T: SupersetOf<f32> + Zero + Clone,
{
    fn is_in_subset(&self) -> bool {
        self.dx.iter().all(T::is_zero) && self.x.is_in_subset()
    }

    fn to_subset_unchecked(&self) -> f32 {
        self.x.to_subset_unchecked()
    }

    fn from_subset(element: &f32) -> Self {
        Self::constant(T::from_subset(element))
    }
}

impl<T, const N: usize> SupersetOf<f64> for AutoFloat<T, N>
where
    T: SupersetOf<f64> + Zero + Clone,
{
    fn is_in_subset(&self) -> bool {
        self.dx.iter().all(T::is_zero) && self.x.is_in_subset()
    }

    fn to_subset_unchecked(&self) -> f64 {
        self.x.to_subset_unchecked()
    }

    fn from_subset(element: &f64) -> Self {
        Self::constant(T::from_subset(element))
    }
}

#[cfg(test)]
mod test {
    use simba::scalar::SupersetOf;

    use crate::AutoFloat;

    macro_rules! create_superset_of_test {
        ($scalar: ty,  $name: ident) => {
            #[test]
            fn $name() {
                let v = AutoFloat::<$scalar, 2>::variable(2.3, 0);
                let c = AutoFloat::<$scalar, 2>::constant(4.1);

                assert!(!SupersetOf::<$scalar>::is_in_subset(&v));
                assert_eq!(None, SupersetOf::<$scalar>::to_subset(&v));

                assert!(SupersetOf::<$scalar>::is_in_subset(&c));
                assert_eq!(Some(c.x), SupersetOf::<$scalar>::to_subset(&c));

                let from_subset: AutoFloat<$scalar, 2> = SupersetOf::<$scalar>::from_subset(&3.1);
                assert_eq!(3.1, from_subset.x);
                assert_eq!([0.0, 0.0], from_subset.dx);
            }
        };
    }

    create_superset_of_test!(f32, superset_of_f32);
    create_superset_of_test!(f64, superset_of_f64);
}