macro_rules! gen_tests_for_float {
($float_name: ident, $mod_name: ident, $assert_is_close: path, $assert_is_close_float: path) => {
mod $mod_name {
use crate::example_system::constants::{
SOLAR_MASS, SOLAR_MASS_AWKWARD, SOLAR_MASS_GRAMS,
};
use crate::example_system::dimensions::{
Dimensionless, Energy, Force, Length, Mass, Time, Velocity,
};
use crate::example_system::units;
use crate::make_annotated_unit_constructor;
use $assert_is_close as assert_is_close;
use $assert_is_close_float as assert_is_close_float;
make_annotated_unit_constructor!(meters, Length<$float_name>, $float_name);
make_annotated_unit_constructor!(kilometers, Length<$float_name>, $float_name);
make_annotated_unit_constructor!(seconds, Time<$float_name>, $float_name);
make_annotated_unit_constructor!(kilograms, Mass<$float_name>, $float_name);
make_annotated_unit_constructor!(
dimensionless,
Dimensionless<$float_name>,
$float_name
);
make_annotated_unit_constructor!(meters_per_second, Velocity<$float_name>, $float_name);
make_annotated_unit_constructor!(newtons, Force<$float_name>, $float_name);
make_annotated_unit_constructor!(joules, Energy<$float_name>, $float_name);
#[test]
fn add_same_unit() {
let x = meters(1.0);
let y = meters(10.0);
assert_is_close(x + y, meters(11.0));
}
#[test]
fn add_different_units() {
let x = meters(1.0);
let y = kilometers(10.0);
assert_is_close(x + y, meters(10001.0));
}
#[test]
fn add_quantity_ref() {
let x = meters(1.0);
let y = meters(10.0);
assert_is_close(x + &y, meters(11.0));
}
#[test]
fn add_ref_quantity() {
let x = meters(1.0);
let y = meters(10.0);
assert_is_close(&x + y, meters(11.0));
}
#[test]
fn add_ref_ref() {
let x = meters(1.0);
let y = meters(10.0);
assert_is_close(&x + &y, meters(11.0));
}
#[test]
fn add_quantity_type() {
let x = dimensionless(1.0);
let y = 10.0;
assert_is_close(x + y, dimensionless(11.0));
}
#[test]
fn add_type_quantity() {
let x = dimensionless(1.0);
let y = 10.0;
assert_is_close(y + x, dimensionless(11.0));
}
#[test]
fn add_ref_type() {
let x = &dimensionless(1.0);
let y = 10.0;
assert_is_close(x + y, dimensionless(11.0));
}
#[test]
fn add_quantity_reftype() {
let x = dimensionless(1.0);
let y = &10.0;
assert_is_close(x + y, dimensionless(11.0));
}
#[test]
fn add_ref_reftype() {
let x = &dimensionless(1.0);
let y = &10.0;
assert_is_close(x + y, dimensionless(11.0));
}
#[test]
fn add_assign_quantity_quantity() {
let mut x = meters(1.0);
let y = kilometers(10.0);
x += y;
assert_is_close(x, meters(10001.0));
}
#[test]
fn add_assign_quantity_ref() {
let mut x = meters(1.0);
let y = kilometers(10.0);
x += &y;
assert_is_close(x, meters(10001.0));
}
#[test]
fn add_assign_ref_ref() {
let mut x = &mut meters(1.0);
let y = kilometers(10.0);
x += &y;
assert_is_close(*x, meters(10001.0));
}
#[test]
fn add_assign_quantity_type() {
let mut x = dimensionless(1.0);
let y = 10.0;
x += y;
assert_is_close(x, dimensionless(11.0));
}
#[test]
fn add_assign_type_quantity() {
let x = dimensionless(1.0);
let mut y = 10.0;
y += x;
assert_is_close_float(y, 11.0);
}
#[test]
fn add_assign_ref_type() {
let mut x = &mut dimensionless(1.0);
let y = 10.0;
x += y;
assert_is_close(*x, dimensionless(11.0));
}
#[test]
fn sum_quantity_type() {
let items = [meters(3.0), kilometers(3.0), meters(9.0), kilometers(1.0)];
assert_is_close(items.into_iter().sum(), meters(4012.0));
}
#[test]
fn sub_different_units() {
let x = meters(1.0);
let y = kilometers(10.0);
assert_is_close(x - y, meters(-9999.0));
}
#[test]
fn sub_quantity_ref() {
let x = meters(1.0);
let y = meters(10.0);
assert_is_close(x - &y, meters(-9.0));
}
#[test]
fn sub_ref_ref() {
let x = meters(1.0);
let y = meters(10.0);
assert_is_close(&x - &y, meters(-9.0));
}
#[test]
fn sub_quantity_type() {
let x = dimensionless(1.0);
let y = 10.0;
assert_is_close(x - y, dimensionless(-9.0));
}
#[test]
fn sub_type_quantity() {
let x = dimensionless(1.0);
let y = 10.0;
assert_is_close(y - x, dimensionless(9.0));
}
#[test]
fn sub_ref_type() {
let x = &dimensionless(1.0);
let y = 10.0;
assert_is_close(x - y, dimensionless(-9.0));
}
#[test]
fn sub_quantity_reftype() {
let x = dimensionless(1.0);
let y = &10.0;
assert_is_close(x - y, dimensionless(-9.0));
}
#[test]
fn sub_ref_reftype() {
let x = &dimensionless(1.0);
let y = &10.0;
assert_is_close(x - y, dimensionless(-9.0));
}
#[test]
fn sub_assign_quantity_quantity() {
let mut x = meters(1.0);
let y = kilometers(10.0);
x -= y;
assert_is_close(x, meters(-9999.0));
}
#[test]
fn sub_assign_quantity_ref() {
let mut x = meters(1.0);
let y = kilometers(10.0);
x -= &y;
assert_is_close(x, meters(-9999.0));
}
#[test]
fn sub_assign_ref_quantity() {
let mut x = &mut meters(1.0);
let y = kilometers(10.0);
x -= y;
assert_is_close(*x, meters(-9999.0));
}
#[test]
fn sub_assign_ref_ref() {
let mut x = &mut meters(1.0);
let y = kilometers(10.0);
x -= &y;
assert_is_close(*x, meters(-9999.0));
}
#[test]
fn sub_assign_quantity_type() {
let mut x = dimensionless(1.0);
let y = 10.0;
x -= y;
assert_is_close(x, dimensionless(-9.0));
}
#[test]
fn sub_assign_type_quantity() {
let x = dimensionless(1.0);
let mut y = 10.0;
y -= x;
assert_is_close_float(y, 9.0);
}
#[test]
fn sub_assign_ref_type() {
let mut x = &mut dimensionless(1.0);
let y = 10.0;
x -= y;
assert_is_close(*x, dimensionless(-9.0));
}
#[test]
fn neg_quantity() {
let x = meters(5.0);
let y = meters(2.0);
assert_is_close(x + (-y), meters(3.0));
assert_is_close(x - y, meters(3.0));
}
#[test]
fn mul_quantity_quantity() {
let x = newtons(2.0);
let y = meters(3.0);
assert_is_close(x * y, joules(6.0));
}
#[test]
fn mul_quantity_ref() {
let x = newtons(2.0);
let y = meters(3.0);
assert_is_close(x * &y, joules(6.0));
}
#[test]
fn mul_ref_quantity() {
let x = newtons(2.0);
let y = meters(3.0);
assert_is_close(&x * y, joules(6.0));
}
#[test]
fn mul_ref_ref() {
let x = newtons(2.0);
let y = meters(3.0);
assert_is_close(&x * &y, joules(6.0));
}
#[test]
fn mul_quantity_type() {
let x = newtons(2.0);
let y = 3.0;
assert_is_close(x * y, newtons(6.0));
}
#[test]
fn mul_type_quantity() {
let x = 3.0;
let y = newtons(2.0);
assert_is_close(x * y, newtons(6.0));
}
#[test]
fn mul_quantity_typeref() {
let x = newtons(2.0);
let y = &3.0;
assert_is_close(x * y, newtons(6.0));
}
#[test]
fn mul_ref_type() {
let x = &newtons(2.0);
let y = 3.0;
assert_is_close(x * y, newtons(6.0));
}
#[test]
fn mul_ref_typeref() {
let x = &newtons(2.0);
let y = &3.0;
assert_is_close(x * y, newtons(6.0));
}
#[test]
fn mul_assign_quantity_quantity() {
let mut x = newtons(2.0);
let y = dimensionless(3.0);
x *= y;
assert_is_close(x, newtons(6.0));
}
#[test]
fn mul_assign_quantity_ref() {
let mut x = newtons(2.0);
let y = dimensionless(3.0);
x *= &y;
assert_is_close(x, newtons(6.0));
}
#[test]
fn mul_assign_ref_quantity() {
let mut x = &mut newtons(2.0);
let y = dimensionless(3.0);
x *= y;
assert_is_close(*x, newtons(6.0));
}
#[test]
fn mul_assign_ref_ref() {
let mut x = &mut newtons(2.0);
let y = dimensionless(3.0);
x *= &y;
assert_is_close(*x, newtons(6.0));
}
#[test]
fn mul_assign_quantity_type() {
let mut x = newtons(2.0);
let y = 3.0;
x *= y;
assert_is_close(x, newtons(6.0));
}
#[test]
fn mul_assign_type_quantity() {
let mut x = 3.0;
let y = dimensionless(2.0);
x *= y;
assert_is_close_float(x, 6.0);
}
#[test]
fn mul_assign_type_ref() {
let mut x = 3.0;
let y = &dimensionless(2.0);
x *= y;
assert_is_close_float(x, 6.0);
}
#[test]
fn div_quantity_quantity() {
let x = meters(6.0);
let y = seconds(2.0);
assert_is_close(x / y, meters_per_second(3.0));
}
#[test]
fn div_quantity_ref() {
let x = meters(6.0);
let y = seconds(2.0);
assert_is_close(x / &y, meters_per_second(3.0));
}
#[test]
fn div_ref_quantity() {
let x = meters(6.0);
let y = seconds(2.0);
assert_is_close(&x / y, meters_per_second(3.0));
}
#[test]
fn div_ref_ref() {
let x = meters(6.0);
let y = seconds(2.0);
assert_is_close(&x / &y, meters_per_second(3.0));
}
#[test]
fn div_assign_quantity_quantity() {
let mut x = newtons(2.0);
let y = dimensionless(4.0);
x /= y;
assert_is_close(x, newtons(0.5));
}
#[test]
fn div_assign_quantity_ref() {
let mut x = newtons(2.0);
let y = dimensionless(4.0);
x /= &y;
assert_is_close(x, newtons(0.5));
}
#[test]
fn div_assign_ref_quantity() {
let mut x = &mut newtons(2.0);
let y = dimensionless(4.0);
x /= y;
assert_is_close(*x, newtons(0.5));
}
#[test]
fn div_assign_ref_ref() {
let mut x = &mut newtons(2.0);
let y = dimensionless(4.0);
x /= &y;
assert_is_close(*x, newtons(0.5));
}
#[test]
fn div_quantity_type() {
let x = meters(6.0);
let y = 2.0;
assert_is_close(x / y, meters(3.0));
}
#[test]
fn div_quantity_reftype() {
let x = meters(6.0);
let y = &2.0;
assert_is_close(x / y, meters(3.0));
}
#[test]
fn div_ref_type() {
let x = &meters(6.0);
let y = 2.0;
assert_is_close(x / y, meters(3.0));
}
#[test]
fn div_ref_reftype() {
let x = &meters(6.0);
let y = &2.0;
assert_is_close(x / y, meters(3.0));
}
#[test]
fn div_assign_quantity_type() {
let mut x = meters(6.0);
let y = 2.0;
x /= y;
assert_is_close(x, meters(3.0));
}
#[test]
fn div_type_quantity() {
let x = 2.0;
let y = meters_per_second(6.0);
assert_is_close(x / y, seconds(2.0) / meters(6.0));
}
#[test]
fn div_assign_type_quantity() {
let mut x = 6.0;
let y = dimensionless(2.0);
x /= y;
assert_is_close_float(x, 3.0);
}
#[cfg(any(feature = "std", feature = "num-traits-libm"))]
#[test]
fn sqrt_float_quantity() {
let x = meters(6.0).powi::<2>();
let y = seconds(2.0).powi::<2>();
assert_is_close((x / y).sqrt(), meters_per_second(3.0));
}
#[cfg(any(feature = "std", feature = "num-traits-libm"))]
#[test]
fn cbrt_float_quantity() {
let x = meters(4.0).powi::<3>();
let y = seconds(1.0).powi::<3>();
assert_is_close((x / y).cbrt(), meters_per_second(4.0));
}
#[test]
fn constant() {
assert_is_close((1.0 as $float_name) * SOLAR_MASS, kilograms(1.988477e30));
assert_is_close(
(1.0 as $float_name) * SOLAR_MASS_GRAMS,
kilograms(1.988477e30),
);
assert_is_close(
(1.0 as $float_name) * SOLAR_MASS_AWKWARD,
kilograms(1.988477e30),
);
}
#[cfg(any(feature = "std", feature = "num-traits-libm"))]
#[test]
fn log2() {
let x = dimensionless(128.0);
assert_is_close(x.log2(), dimensionless(7.0));
}
#[test]
fn deref_dimensionless() {
let x = dimensionless(128.3);
assert_eq!(x.round(), 128.0);
}
#[test]
fn partial_eq_quantity_quantity() {
let x = meters(50.0);
let y = meters(50.0);
assert!(x == y);
}
#[test]
fn partial_eq_quantity_ref() {
let x = meters(50.0);
let y = meters(50.0);
assert!(x == &y);
}
#[test]
fn partial_eq_ref_quantity() {
let x = meters(50.0);
let y = meters(50.0);
assert!(&x == y);
}
#[test]
fn partial_eq_ref_ref() {
let x = meters(50.0);
let y = meters(50.0);
assert!(&x == &y);
}
#[test]
fn partial_eq_quantity_type() {
let x = dimensionless(50.0);
let y = 50.0;
assert!(x == y);
}
#[test]
fn partial_eq_type_quantity() {
let x = 50.0;
let y = dimensionless(50.0);
assert!(x == y);
}
#[test]
fn partial_ord_quantity_quantity() {
let x = meters(50.0);
let y = meters(49.0);
assert!(x > y);
}
#[test]
fn partial_ord_quantity_type() {
let x = dimensionless(50.0);
let y = 49.0;
assert!(x >= y);
}
#[test]
fn partial_ord_type_quantity() {
let x = 50.0;
let y = dimensionless(49.0);
assert!(x > y);
}
#[test]
fn clamp_quantity_quantity() {
let x = meters(10.0);
let y = kilometers(20.0);
assert!(meters(1.0).clamp(x, y) == x);
assert!(meters(50.0).clamp(x, y) == meters(50.0));
assert!(meters(50000.0).clamp(x, y) == y);
}
#[test]
fn clamp_quantity_type() {
let x = 10.0;
let y = 20.0;
assert!(dimensionless(5.0).clamp(x, y) == x);
assert!(dimensionless(15.0).clamp(x, y) == dimensionless(15.0));
assert!(dimensionless(50.0).clamp(x, y) == y);
}
#[test]
fn max_quantity_quantity() {
let x = meters(10.0);
assert!(meters(5.0).max(x) == x);
assert!(meters(15.0).max(x) == meters(15.0));
}
#[test]
fn max_quantity_type() {
let x = 10.0;
assert!(dimensionless(5.0).max(x) == x);
assert!(dimensionless(15.0).max(x) == dimensionless(15.0));
}
#[test]
fn min_quantity_quantity() {
let x = meters(10.0);
assert!(meters(5.0).min(x) == meters(5.0));
assert!(meters(15.0).min(x) == x);
}
#[test]
fn min_quantity_type() {
let x = 10.0;
assert!(dimensionless(5.0).min(x) == dimensionless(5.0));
assert!(dimensionless(15.0).min(x) == x);
}
}
};
}
#[cfg(feature = "f32")]
gen_tests_for_float!(
f32,
f32,
crate::utils::assert_is_close_f32,
crate::utils::assert_is_close_float_f32
);
#[cfg(feature = "f64")]
gen_tests_for_float!(
f64,
f64,
crate::utils::assert_is_close_f64,
crate::utils::assert_is_close_float_f64
);