demes 0.7.0

rust implementation of demes specification
Documentation
#![macro_use]

macro_rules! impl_newtype_arithmetic {
    ($type: ty, $op: ident, $fn: ident) => {
        impl std::ops::$op for $type {
            type Output = Option<Self>;
            fn $fn(self, value: Self) -> Self::Output {
                Self::try_from(self.0.$fn(value.0)).ok()
            }
        }

        impl std::ops::$op<f64> for $type {
            type Output = Option<Self>;
            fn $fn(self, value: f64) -> Self::Output {
                Self::try_from(self.0.$fn(value)).ok()
            }
        }

        impl std::ops::$op<$type> for f64 {
            type Output = Option<$type>;
            fn $fn(self, value: $type) -> Self::Output {
                <$type>::try_from(self.$fn(value.0)).ok()
            }
        }
    };
}

macro_rules! impl_newtype_traits {
    ($type: ty) => {
        impl From<$type> for f64 {
            fn from(value: $type) -> f64 {
                value.0
            }
        }

        impl PartialOrd<$type> for $type {
            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
                Some(self.cmp(&other))
            }
        }

        impl PartialOrd<$type> for f64 {
            fn partial_cmp(&self, other: &$type) -> Option<std::cmp::Ordering> {
                self.partial_cmp(&other.0)
            }
        }

        impl PartialOrd<f64> for $type {
            fn partial_cmp(&self, other: &f64) -> Option<std::cmp::Ordering> {
                self.0.partial_cmp(other)
            }
        }

        impl Ord for $type {
            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
                match self.0.partial_cmp(&other.0) {
                    Some(ordering) => ordering,
                    None => panic!("invalid f64 snuck in somehow"),
                }
            }
        }

        impl PartialEq for $type {
            fn eq(&self, other: &Self) -> bool {
                self.0 == other.0
            }
        }

        impl PartialEq<$type> for f64 {
            fn eq(&self, other: &$type) -> bool {
                self.eq(&other.0)
            }
        }

        impl PartialEq<f64> for $type {
            fn eq(&self, other: &f64) -> bool {
                self.0.eq(other)
            }
        }

        impl Eq for $type {}

        impl std::fmt::Display for $type {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                write!(f, "{}", self.0)
            }
        }

        impl_newtype_arithmetic!($type, Add, add);
        impl_newtype_arithmetic!($type, Sub, sub);
        impl_newtype_arithmetic!($type, Mul, mul);
        impl_newtype_arithmetic!($type, Div, div);
    };
}

macro_rules! impl_input_newtype_arithmetic {
    ($type: ty, $op: ident, $fn: ident) => {
        impl std::ops::$op for $type {
            type Output = Self;
            fn $fn(self, value: Self) -> Self::Output {
                self.0.$fn(value.0).into()
            }
        }

        impl std::ops::$op<f64> for $type {
            type Output = Self;
            fn $fn(self, value: f64) -> Self::Output {
                self.0.$fn(value).into()
            }
        }

        impl std::ops::$op<$type> for f64 {
            type Output = Self;
            fn $fn(self, value: $type) -> Self::Output {
                self.$fn(value.0).into()
            }
        }
    };
}

macro_rules! impl_input_newtype_traits {
    ($type: ty) => {
        impl From<f64> for $type {
            fn from(value: f64) -> Self {
                Self(value)
            }
        }

        impl From<&f64> for $type {
            fn from(value: &f64) -> Self {
                Self(*value)
            }
        }

        impl From<$type> for f64 {
            fn from(value: $type) -> Self {
                value.0
            }
        }

        impl PartialEq<$type> for f64 {
            fn eq(&self, other: &$type) -> bool {
                self.eq(&other.0)
            }
        }

        impl PartialEq<f64> for $type {
            fn eq(&self, other: &f64) -> bool {
                self.0.eq(other)
            }
        }

        impl_input_newtype_arithmetic!($type, Add, add);
        impl_input_newtype_arithmetic!($type, Sub, sub);
        impl_input_newtype_arithmetic!($type, Mul, mul);
        impl_input_newtype_arithmetic!($type, Div, div);
    };
}