meiosis 0.1.0

An evolutionary algorithm library with as many compile time checks as possible.
Documentation
use core::cmp::Ordering;

use crate::fitness::FitnessValue;

/// As required for selection, [`f32`] values can only be compared if they are finite.
/// All other values, differing from the [`f32::total_cmp`] implementation, are considered
/// invalid.
/// # Panics
/// This implementation panics if either value being compared is not finite.
/// To be precise, these invalid values are `+Inf`, `-Inf` and `NaN`.
impl FitnessValue for f32 {
    fn compare(&self, rhs: &Self) -> Ordering {
        assert!(
            self.is_finite() && rhs.is_finite(),
            "values being compared need to be finite. comparing '{}' with '{}'",
            self,
            rhs
        );

        // This is fine as we're checking the value first anyway.
        #[allow(clippy::expect_used)]
        // To make sure that -0.0 and +0.0 are both considered equal, we use `partial_cmp`
        // instead of `total_cmp` and simply expect the result to be valid, as we have
        // checked invalid values above.
        self.partial_cmp(rhs).expect("both values should be finite")
    }
}

/// As required for selection, [`f64`] values can only be compared if they are finite.
/// All other values, differing from the [`f64::total_cmp`] implementation, are considered
/// invalid.
/// # Panics
/// This implementation panics if either value being compared is not finite.
/// To be precise, these invalid values are `+Inf`, `-Inf` and `NaN`.
impl FitnessValue for f64 {
    fn compare(&self, rhs: &Self) -> Ordering {
        assert!(
            self.is_finite() && rhs.is_finite(),
            "values being compared need to be finite. comparing '{}' with '{}'",
            self,
            rhs
        );

        // This is fine as we're checking the value first anyway.
        #[allow(clippy::expect_used)]
        // To make sure that -0.0 and +0.0 are both considered equal, we use `partial_cmp`
        // instead of `total_cmp` and simply expect the result to be valid, as we have
        // checked invalid values above.
        self.partial_cmp(rhs).expect("both values should be finite")
    }
}