diff --git a/src/quantity.rs b/src/quantity.rs index 03dadf4c..4ccbdf78 100644 --- a/src/quantity.rs +++ b/src/quantity.rs @@ -137,6 +137,8 @@ macro_rules! quantity { where V: $crate::Conversion, { + #[cfg(test)] + fn is_valid() -> bool; } unit! { diff --git a/src/si/acceleration.rs b/src/si/acceleration.rs index be8a24cf..431737d8 100644 --- a/src/si/acceleration.rs +++ b/src/si/acceleration.rs @@ -114,9 +114,11 @@ mod tests { test::(); fn test, T: t::Conversion, A: a::Conversion>() { - Test::assert_eq(&Acceleration::new::(V::one()), - &(Length::new::(V::one()) / - (Time::new::(V::one()) * Time::new::(V::one())))); + if A::is_valid() { + Test::assert_eq(&Acceleration::new::(V::one()), + &(Length::new::(V::one()) / + (Time::new::(V::one()) * Time::new::(V::one())))); + } } } } diff --git a/src/si/area.rs b/src/si/area.rs index 58a5cccf..fb405c37 100644 --- a/src/si/area.rs +++ b/src/si/area.rs @@ -71,7 +71,6 @@ quantity! { #[cfg(test)] mod tests { storage_types! { - use crate::lib::any::TypeId; use crate::num::One; use crate::si::area as a; use crate::si::length as l; @@ -87,12 +86,8 @@ mod tests { // #392: Disable tests on ARM until issues with floating point behavior can be resolved. #[cfg(not(target_arch = "arm"))] fn check_units() { - // Values too large for f32. - if TypeId::of::() == TypeId::of::() { - test::(); - test::(); - } - + test(l::yottameter, a::square_yottameter); + test(l::zettameter, a::square_zettameter); test::(); test::(); test::(); @@ -111,16 +106,13 @@ mod tests { test::(); test::(); test::(); - - // Values too small for f32. - if TypeId::of::() == TypeId::of::() { - test::(); - } + test(l::yoctometer, a::square_yoctometer); fn test, A: a::Conversion>() { - Test::assert_eq(&Area::new::(V::one()), - &(Length::new::(V::one()) * Length::new::(V::one()))); - } + if A::is_valid() { + Test::assert_eq(&Area::new::(V::one()), + &(Length::new::(V::one()) * Length::new::(V::one()))); + } } } } } diff --git a/src/si/force.rs b/src/si/force.rs index e4173d39..06102cdd 100644 --- a/src/si/force.rs +++ b/src/si/force.rs @@ -122,10 +122,12 @@ mod tests { T: t::Conversion, F: f::Conversion>() { - Test::assert_approx_eq(&Force::new::(V::one()), - &((Mass::new::(V::one()) - * Length::new::(V::one())) - / (Time::new::(V::one()) * Time::new::(V::one())))); + if F::is_valid() && T::is_valid() { + Test::assert_approx_eq(&Force::new::(V::one()), + &((Mass::new::(V::one()) + * Length::new::(V::one())) + / (Time::new::(V::one()) * Time::new::(V::one())))); + } } } } diff --git a/src/si/frequency.rs b/src/si/frequency.rs index 1a7ee541..2b0400c2 100644 --- a/src/si/frequency.rs +++ b/src/si/frequency.rs @@ -89,11 +89,15 @@ mod tests { test::(); fn test, F: f::Conversion>() { - Test::assert_approx_eq(&(V::one() / Time::new::(V::one())), - &Frequency::new::(V::one())); - Test::assert_approx_eq(&Time::new::(V::one()), - &(V::one() / Frequency::new::(V::one()))); - } + if T::is_valid() { + Test::assert_approx_eq(&(V::one() / Time::new::(V::one())), + &Frequency::new::(V::one())); + } + + if F::is_valid() { + Test::assert_approx_eq(&Time::new::(V::one()), + &(V::one() / Frequency::new::(V::one()))); + } } } } } diff --git a/src/si/velocity.rs b/src/si/velocity.rs index 5f662268..1b368e31 100644 --- a/src/si/velocity.rs +++ b/src/si/velocity.rs @@ -132,8 +132,10 @@ mod test { test::(); fn test, T: t::Conversion, E: v::Conversion>() { - Test::assert_eq(&Velocity::new::(V::one()), - &(Length::new::(V::one()) / Time::new::(V::one()))); + if E::is_valid() { + Test::assert_eq(&Velocity::new::(V::one()), + &(Length::new::(V::one()) / Time::new::(V::one()))); + } } } } diff --git a/src/si/volume.rs b/src/si/volume.rs index 4939e878..df79d6ff 100644 --- a/src/si/volume.rs +++ b/src/si/volume.rs @@ -106,7 +106,6 @@ quantity! { #[cfg(test)] mod tests { storage_types! { - use crate::lib::any::TypeId; use crate::num::{FromPrimitive, One}; use crate::si::area as a; use crate::si::length as l; @@ -160,14 +159,10 @@ mod tests { // #392: Disable tests on ARM until issues with floating point behavior can be resolved. #[cfg(not(target_arch = "arm"))] fn check_units() { - // Values too large for f32. - if TypeId::of::() == TypeId::of::() { - test::(); - test::(); - test::(); - test::(); - } - + test(l::yottameter, v::cubic_yottameter); + test(l::zettameter, v::cubic_zettameter); + test(l::exameter, v::cubic_exameter); + test(l::petameter, v::cubic_petameter); test::(); test::(); test::(); @@ -182,19 +177,17 @@ mod tests { test::(); test::(); test::(); - - // Values too small for f32. - if TypeId::of::() == TypeId::of::() { - test::(); - test::(); - test::(); - } + test(l::attometer, v::cubic_attometer); + test(l::zeptometer, v::cubic_zeptometer); + test(l::yoctometer, v::cubic_yoctometer); fn test, O: v::Conversion>() { - Test::assert_eq(&Volume::new::(V::one()), - &(Length::new::(V::one()) - * Length::new::(V::one()) - * Length::new::(V::one()))); + if O::is_valid() { + Test::assert_eq(&Volume::new::(V::one()), + &(Length::new::(V::one()) + * Length::new::(V::one()) + * Length::new::(V::one()))); + } } } } diff --git a/src/unit.rs b/src/unit.rs index b6251243..ba34b4cd 100644 --- a/src/unit.rs +++ b/src/unit.rs @@ -160,7 +160,16 @@ macro_rules! unit { } } - impl super::Conversion for super::$unit {})+ + impl super::Conversion for super::$unit { + #[cfg(test)] + #[inline(always)] + fn is_valid() -> bool { + use $crate::num::ToPrimitive; + + Some(unit!(@coefficient $($conversion),+)) == >::conversion() + .to_f64() + } + })+ } storage_types! { @@ -187,7 +196,26 @@ macro_rules! unit { } } - impl super::Conversion for super::$unit {})+ + impl super::Conversion for super::$unit { + #[cfg(test)] + #[inline(always)] + fn is_valid() -> bool { + use $crate::num::{FromPrimitive, ToPrimitive}; + + if let Some(conversion) = Self::T::from_f64(unit!(@coefficient $($conversion),+)) { + // Fractional conversion factors will end up being truncated. + if conversion.numer() >= conversion.denom() { + if let Some(numer) = conversion.numer().to_f64() { + if let Some(denom) = conversion.denom().to_f64() { + return $conversion == numer / denom + } + } + } + } + + false + } + })+ } storage_types! { @@ -219,7 +247,25 @@ macro_rules! unit { } } - impl super::Conversion for super::$unit {})+ + impl super::Conversion for super::$unit { + #[cfg(test)] + #[inline(always)] + fn is_valid() -> bool { + use $crate::num::{FromPrimitive, ToPrimitive}; + + if let Some(conversion) = $crate::num::rational::Ratio::<$crate::num::BigInt>::from_f64(unit!(@coefficient $($conversion),+)) { + if conversion.numer() >= conversion.denom() { + if let Some(numer) = conversion.numer().to_f64() { + if let Some(denom) = conversion.denom().to_f64() { + return $conversion == numer / denom + } + } + } + } + + false + } + })+ } storage_types! { @@ -245,7 +291,26 @@ macro_rules! unit { } } - impl super::Conversion for super::$unit {})+ + impl super::Conversion for super::$unit { + #[cfg(test)] + #[inline(always)] + fn is_valid() -> bool { + use $crate::num::{FromPrimitive, ToPrimitive}; + + if let Some(conversion) = Self::T::from_f64(unit!(@coefficient $($conversion),+)) { + // Factional conversion factors will end up being truncated. + if conversion.numer() >= conversion.denom() { + if let Some(numer) = conversion.numer().to_f64() { + if let Some(denom) = conversion.denom().to_f64() { + return $conversion == numer / denom + } + } + } + } + + false + } + })+ } storage_types! {