askew 0.1.0

Angles (degrees, radians, and turns)
Documentation
#[cfg(all(feature = "libm", not(feature = "std")))]
mod impl_libm;

#[cfg(all(feature = "libm", not(feature = "std")))]
#[allow(unused_imports)]
pub use impl_libm::*;

#[cfg(feature = "std")]
mod impl_std;

#[cfg(feature = "std")]
pub use impl_std::*;

/// An implementation of `rem_euclid` that is const-compatible.
#[inline]
pub const fn rem_euclid_f32_const(x: f32, y: f32) -> f32 {
    let r = x % y;
    if r < 0.0 { r + y.abs() } else { r }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[track_caller]
    fn compare_v_stdlib(x: f32, y: f32) {
        let expected = x.rem_euclid(y);
        let actual = rem_euclid_f32_const(x, y);
        assert!(
            (expected - actual).abs() < f32::EPSILON,
            "Expected: {expected}, Actual: {actual}"
        );
    }

    #[test]
    #[allow(clippy::float_cmp)]
    fn test_rem_euclid_f32_const() {
        compare_v_stdlib(5.0, 2.0);
        compare_v_stdlib(-1.0, 3.0);
        compare_v_stdlib(7.0, 4.0);
        compare_v_stdlib(-5.0, 3.0);

        // Test with negative y values
        compare_v_stdlib(3.0, -2.0);
        compare_v_stdlib(-3.0, -2.0);
        compare_v_stdlib(5.0, -3.0);
        compare_v_stdlib(-5.0, -3.0);

        // Test with zero
        compare_v_stdlib(0.0, 3.0);
        compare_v_stdlib(0.0, -3.0);

        // Test with y = 1 and y = -1
        compare_v_stdlib(7.0, 1.0);
        compare_v_stdlib(7.0, -1.0);

        // Test with x = y and x = -y
        compare_v_stdlib(2.0, 2.0);
        compare_v_stdlib(-2.0, 2.0);
        compare_v_stdlib(2.0, -2.0);
        compare_v_stdlib(-2.0, -2.0);
    }
}