rinia 0.0.1

Portable scalar abstractions for game and simulation math.
Documentation
use approx::assert_relative_eq;

use super::{FloatScalar, Scalar};

fn scalar_identities<T: Scalar>() -> (T, T) {
    (T::ZERO, T::ONE)
}

fn float_constants<T: FloatScalar>() -> (T, T, T) {
    (T::INFINITY, T::NEG_INFINITY, T::NAN)
}

fn sin_via_floatscalar<T: FloatScalar>(x: T) -> T {
    x.sin()
}

fn round_trip<T: FloatScalar>(value: T) -> T {
    (value + T::ONE) - T::ONE
}

#[test]
fn scalar_constants_match_for_f32_and_f64() {
    assert_eq!(scalar_identities::<f32>(), (0.0, 1.0));
    assert_eq!(scalar_identities::<f64>(), (0.0, 1.0));
}

#[test]
fn float_constants_match_for_f32_and_f64() {
    let (f32_inf, f32_neg_inf, f32_nan) = float_constants::<f32>();
    assert!(f32_inf.is_infinite() && f32_inf.is_sign_positive());
    assert!(f32_neg_inf.is_infinite() && f32_neg_inf.is_sign_negative());
    assert!(f32_nan.is_nan());

    let (f64_inf, f64_neg_inf, f64_nan) = float_constants::<f64>();
    assert!(f64_inf.is_infinite() && f64_inf.is_sign_positive());
    assert!(f64_neg_inf.is_infinite() && f64_neg_inf.is_sign_negative());
    assert!(f64_nan.is_nan());
}

#[test]
fn corefloat_and_approx_work_through_floatscalar_for_f32_and_f64() {
    let sin_zero_f32 = sin_via_floatscalar::<f32>(0.0);
    assert_relative_eq!(sin_zero_f32, 0.0, epsilon = 1.0e-6);

    let sin_zero_f64 = sin_via_floatscalar::<f64>(0.0);
    assert_relative_eq!(sin_zero_f64, 0.0, epsilon = 1.0e-12);
}

#[test]
fn generic_round_trip_works_for_f32_and_f64() {
    let out_f32 = round_trip::<f32>(3.5);
    assert_relative_eq!(out_f32, 3.5, epsilon = 1.0e-6);

    let out_f64 = round_trip::<f64>(3.5);
    assert_relative_eq!(out_f64, 3.5, epsilon = 1.0e-12);
}

#[cfg(feature = "std")]
#[test]
fn std_inherent_sin_matches_floatscalar_path_for_f32_and_f64() {
    let x32 = 0.5_f32;
    let std_sin32 = x32.sin();
    let generic_sin32 = sin_via_floatscalar::<f32>(x32);
    assert_relative_eq!(std_sin32, generic_sin32, epsilon = 1.0e-6);

    let x64 = 0.5_f64;
    let std_sin64 = x64.sin();
    let generic_sin64 = sin_via_floatscalar::<f64>(x64);
    assert_relative_eq!(std_sin64, generic_sin64, epsilon = 1.0e-12);
}

#[cfg(not(feature = "std"))]
#[test]
fn non_std_method_sin_still_works_for_f32_and_f64() {
    let x32 = 0.5_f32;
    let sin32 = x32.sin();
    assert_relative_eq!(sin32, sin_via_floatscalar::<f32>(x32), epsilon = 1.0e-6);

    let x64 = 0.5_f64;
    let sin64 = x64.sin();
    assert_relative_eq!(sin64, sin_via_floatscalar::<f64>(x64), epsilon = 1.0e-12);
}