From 4c6f9b17575e516a36ea8cab6fd1b5140fca87c1 Mon Sep 17 00:00:00 2001 From: Mike Boutin Date: Fri, 15 Dec 2017 17:55:01 -0500 Subject: [PATCH] Organize tests based on support by underlying storage type. Part of #29. --- src/tests.rs | 1130 ++++++++++++++++++++++++++------------------------ 1 file changed, 598 insertions(+), 532 deletions(-) diff --git a/src/tests.rs b/src/tests.rs index 77d3199e..4eda9799 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,3 +1,13 @@ +use stdlib::marker::PhantomData; +#[allow(unused_imports)] +use num::{Float, FromPrimitive, One, Signed, Zero}; +use quickcheck::TestResult; +use typenum::{N1, P1, P2, P3, Z0}; +#[allow(unused_imports)] +use {Conversion, ConversionFactor}; +use self::length::{kilometer, meter}; +use self::mass::kilogram; + #[macro_use] mod length { quantity! { @@ -32,68 +42,59 @@ system! { } } -storage_types! { - types: Float; +mod quantities { + Q!(tests); +} - use super::*; +mod quantity_macro { + use tests::*; + + // Module level constant to verify that creation is possible. + #[allow(dead_code)] + #[allow(trivial_numeric_casts)] + #[cfg(feature ="f32")] + const LENGTH: quantities::Length = Quantity { + dimension: PhantomData, + units: PhantomData, + value: 1.0, + }; + + #[test] + fn description() { + assert_eq!("length", length::description()); + assert_eq!("mass", mass::description()); + } - const EPSILON: V = 0.00001; + #[test] + fn abbreviation() { + assert_eq!("km", kilometer::abbreviation()); + assert_eq!("m", meter::abbreviation()); + assert_eq!("kg", kilogram::abbreviation()); + } - mod f { - Q!(tests, super::V); + #[test] + fn singular() { + assert_eq!("kilometer", kilometer::singular()); + assert_eq!("meter", meter::singular()); + assert_eq!("kilogram", kilogram::singular()); } - mod km { - Q!(tests, super::V, (kilometer, kilogram)); + #[test] + fn plural() { + assert_eq!("kilometers", kilometer::plural()); + assert_eq!("meters", meter::plural()); + assert_eq!("kilograms", kilogram::plural()); } - mod quantity_macro { - use num::One; - use Conversion; - use super::*; - use super::f::*; - use super::length::{kilometer, meter}; - use super::mass::kilogram; - - // Module level constant to verify that creation is possible. - #[allow(dead_code)] - const LENGTH: Quantity, U, V> = Quantity { - dimension: ::stdlib::marker::PhantomData, - units: ::stdlib::marker::PhantomData, - value: 1.0, - }; + storage_types! { + types: Float; - #[test] - fn description() { - assert_eq!("length", length::description()); - assert_eq!("mass", mass::description()); - } + use tests::*; - #[test] - fn abbreviation() { - assert_eq!("km", kilometer::abbreviation()); - assert_eq!("m", meter::abbreviation()); - assert_eq!("kg", kilogram::abbreviation()); - } - - #[test] - fn singular() { - assert_eq!("kilometer", kilometer::singular()); - assert_eq!("meter", meter::singular()); - assert_eq!("kilogram", kilogram::singular()); - } - - #[test] - fn plural() { - assert_eq!("kilometers", kilometer::plural()); - assert_eq!("meters", meter::plural()); - assert_eq!("kilograms", kilogram::plural()); - } + Q!(tests, V); #[test] fn struct_literal() { - use stdlib::marker::PhantomData; - let l = Length { dimension: PhantomData, units: PhantomData, value: V::one(), }; let m = Mass { dimension: PhantomData, units: PhantomData, value: V::one(), }; @@ -125,111 +126,6 @@ storage_types! { assert_eq!(V::one(), m1.get(kilogram)); } - #[test] - fn floor() { - let l1 = Length::new::(3.9999); - let l2 = Length::new::(3.0001); - let l3 = Length::new::(3.9999); - let l4 = Length::new::(3.0001); - let m1 = Mass::new::(3.9999); - let m2 = Mass::new::(3.0001); - - assert_eq!(3.0, l1.floor(kilometer).get(kilometer)); - assert_eq!(3999.0, l1.floor(meter).get(meter)); - assert_eq!(3.0, l2.floor(kilometer).get(kilometer)); - assert_eq!(3000.0, l2.floor(meter).get(meter)); - assert_eq!(0.0, l3.floor(kilometer).get(kilometer)); - assert_eq!(3.0, l3.floor(meter).get(meter)); - assert_eq!(0.0, l4.floor(kilometer).get(kilometer)); - assert_eq!(3.0, l4.floor(meter).get(meter)); - assert_eq!(3.0, m1.floor(kilogram).get(kilogram)); - assert_eq!(3.0, m2.floor(kilogram).get(kilogram)); - } - - #[test] - fn ceil() { - let l1 = Length::new::(3.9999); - let l2 = Length::new::(3.0001); - let l3 = Length::new::(3.9999); - let l4 = Length::new::(3.0001); - let m1 = Mass::new::(3.9999); - let m2 = Mass::new::(3.0001); - - assert_eq!(4.0, l1.ceil(kilometer).get(kilometer)); - assert_eq!(4000.0, l1.ceil(meter).get(meter)); - assert_eq!(4.0, l2.ceil(kilometer).get(kilometer)); - assert_eq!(3001.0, l2.ceil(meter).get(meter)); - assert_eq!(V::one(), l3.ceil(kilometer).get(kilometer)); - assert_eq!(4.0, l3.ceil(meter).get(meter)); - assert_eq!(1.0, l4.ceil(kilometer).get(kilometer)); - assert_eq!(4.0, l4.ceil(meter).get(meter)); - assert_eq!(4.0, m1.ceil(kilogram).get(kilogram)); - assert_eq!(4.0, m2.ceil(kilogram).get(kilogram)); - } - - #[test] - fn round() { - let l1 = Length::new::(3.3); - let l2 = Length::new::(3.5); - let l3 = Length::new::(3.3); - let l4 = Length::new::(3.5); - let m1 = Mass::new::(3.3); - let m2 = Mass::new::(3.5); - - assert_eq!(3.0, l1.round(kilometer).get(kilometer)); - assert_eq!(3300.0, l1.round(meter).get(meter)); - assert_eq!(4.0, l2.round(kilometer).get(kilometer)); - assert_eq!(3500.0, l2.round(meter).get(meter)); - assert_eq!(0.0, l3.round(kilometer).get(kilometer)); - assert_eq!(3.0, l3.round(meter).get(meter)); - assert_eq!(0.0, l4.round(kilometer).get(kilometer)); - assert_eq!(4.0, l4.round(meter).get(meter)); - assert_eq!(3.0, m1.round(kilogram).get(kilogram)); - assert_eq!(4.0, m2.round(kilogram).get(kilogram)); - } - - #[test] - fn trunc() { - let l1 = Length::new::(3.3); - let l2 = Length::new::(3.5); - let l3 = Length::new::(3.3); - let l4 = Length::new::(3.5); - let m1 = Mass::new::(3.3); - let m2 = Mass::new::(3.5); - - assert_eq!(3.0, l1.trunc(kilometer).get(kilometer)); - assert_eq!(3300.0, l1.trunc(meter).get(meter)); - assert_eq!(3.0, l2.trunc(kilometer).get(kilometer)); - assert_eq!(3500.0, l2.trunc(meter).get(meter)); - assert_eq!(0.0, l3.trunc(kilometer).get(kilometer)); - assert_eq!(3.0, l3.trunc(meter).get(meter)); - assert_eq!(0.0, l4.trunc(kilometer).get(kilometer)); - assert_eq!(3.0, l4.trunc(meter).get(meter)); - assert_eq!(3.0, m1.trunc(kilogram).get(kilogram)); - assert_eq!(3.0, m2.trunc(kilogram).get(kilogram)); - } - - #[test] - fn fract() { - let l1 = Length::new::(3.3); - let l2 = Length::new::(3.5); - let l3 = Length::new::(3.3); - let l4 = Length::new::(3.5); - let m1 = Mass::new::(3.3); - let m2 = Mass::new::(3.5); - - assert_ulps_eq!(0.3, l1.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.0, l1.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.5, l2.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.0, l2.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.0033, l3.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.3, l3.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.0035, l4.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.5, l4.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.3, m1.fract(kilogram).get(kilogram), epsilon = EPSILON); - assert_ulps_eq!(0.5, m2.fract(kilogram).get(kilogram), epsilon = EPSILON); - } - #[test] fn conversion() { assert_eq!(1000.0, >::conversion()); @@ -255,531 +151,701 @@ storage_types! { } } - mod system_macro { - use num::{Float, Zero}; - use super::*; - use super::f::*; - use super::length::{kilometer, meter}; - use super::mass::kilogram; - use quickcheck::TestResult; - use typenum::{N1, P1, P2, P3, Z0}; - - #[test] - fn fp_categories() { - assert!(!Length::new::(V::infinity()).is_finite()); - assert!(!Length::new::(V::neg_infinity()).is_finite()); - assert!(Length::new::(V::infinity()).is_infinite()); - assert!(Length::new::(V::neg_infinity()).is_infinite()); - assert!(Length::new::(V::min_positive_value()).is_normal()); - assert!(Length::new::(V::max_value()).is_normal()); - assert!(!Length::new::(V::zero()).is_normal()); - assert!(!Length::new::(V::nan()).is_normal()); - assert!(!Length::new::(V::infinity()).is_normal()); + mod float { + storage_types! { + types: Float; + + use tests::*; + + const EPSILON: V = 0.00001; + + Q!(tests, V); + + #[test] + fn floor() { + let l1 = Length::new::(3.9999); + let l2 = Length::new::(3.0001); + let l3 = Length::new::(3.9999); + let l4 = Length::new::(3.0001); + let m1 = Mass::new::(3.9999); + let m2 = Mass::new::(3.0001); + + assert_eq!(3.0, l1.floor(kilometer).get(kilometer)); + assert_eq!(3999.0, l1.floor(meter).get(meter)); + assert_eq!(3.0, l2.floor(kilometer).get(kilometer)); + assert_eq!(3000.0, l2.floor(meter).get(meter)); + assert_eq!(0.0, l3.floor(kilometer).get(kilometer)); + assert_eq!(3.0, l3.floor(meter).get(meter)); + assert_eq!(0.0, l4.floor(kilometer).get(kilometer)); + assert_eq!(3.0, l4.floor(meter).get(meter)); + assert_eq!(3.0, m1.floor(kilogram).get(kilogram)); + assert_eq!(3.0, m2.floor(kilogram).get(kilogram)); + } + + #[test] + fn ceil() { + let l1 = Length::new::(3.9999); + let l2 = Length::new::(3.0001); + let l3 = Length::new::(3.9999); + let l4 = Length::new::(3.0001); + let m1 = Mass::new::(3.9999); + let m2 = Mass::new::(3.0001); + + assert_eq!(4.0, l1.ceil(kilometer).get(kilometer)); + assert_eq!(4000.0, l1.ceil(meter).get(meter)); + assert_eq!(4.0, l2.ceil(kilometer).get(kilometer)); + assert_eq!(3001.0, l2.ceil(meter).get(meter)); + assert_eq!(V::one(), l3.ceil(kilometer).get(kilometer)); + assert_eq!(4.0, l3.ceil(meter).get(meter)); + assert_eq!(1.0, l4.ceil(kilometer).get(kilometer)); + assert_eq!(4.0, l4.ceil(meter).get(meter)); + assert_eq!(4.0, m1.ceil(kilogram).get(kilogram)); + assert_eq!(4.0, m2.ceil(kilogram).get(kilogram)); + } + + #[test] + fn round() { + let l1 = Length::new::(3.3); + let l2 = Length::new::(3.5); + let l3 = Length::new::(3.3); + let l4 = Length::new::(3.5); + let m1 = Mass::new::(3.3); + let m2 = Mass::new::(3.5); + + assert_eq!(3.0, l1.round(kilometer).get(kilometer)); + assert_eq!(3300.0, l1.round(meter).get(meter)); + assert_eq!(4.0, l2.round(kilometer).get(kilometer)); + assert_eq!(3500.0, l2.round(meter).get(meter)); + assert_eq!(0.0, l3.round(kilometer).get(kilometer)); + assert_eq!(3.0, l3.round(meter).get(meter)); + assert_eq!(0.0, l4.round(kilometer).get(kilometer)); + assert_eq!(4.0, l4.round(meter).get(meter)); + assert_eq!(3.0, m1.round(kilogram).get(kilogram)); + assert_eq!(4.0, m2.round(kilogram).get(kilogram)); + } + + #[test] + fn trunc() { + let l1 = Length::new::(3.3); + let l2 = Length::new::(3.5); + let l3 = Length::new::(3.3); + let l4 = Length::new::(3.5); + let m1 = Mass::new::(3.3); + let m2 = Mass::new::(3.5); + + assert_eq!(3.0, l1.trunc(kilometer).get(kilometer)); + assert_eq!(3300.0, l1.trunc(meter).get(meter)); + assert_eq!(3.0, l2.trunc(kilometer).get(kilometer)); + assert_eq!(3500.0, l2.trunc(meter).get(meter)); + assert_eq!(0.0, l3.trunc(kilometer).get(kilometer)); + assert_eq!(3.0, l3.trunc(meter).get(meter)); + assert_eq!(0.0, l4.trunc(kilometer).get(kilometer)); + assert_eq!(3.0, l4.trunc(meter).get(meter)); + assert_eq!(3.0, m1.trunc(kilogram).get(kilogram)); + assert_eq!(3.0, m2.trunc(kilogram).get(kilogram)); + } + + #[test] + fn fract() { + let l1 = Length::new::(3.3); + let l2 = Length::new::(3.5); + let l3 = Length::new::(3.3); + let l4 = Length::new::(3.5); + let m1 = Mass::new::(3.3); + let m2 = Mass::new::(3.5); + + assert_ulps_eq!(0.3, l1.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.0, l1.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.5, l2.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.0, l2.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.0033, l3.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.3, l3.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.0035, l4.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.5, l4.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.3, m1.fract(kilogram).get(kilogram), epsilon = EPSILON); + assert_ulps_eq!(0.5, m2.fract(kilogram).get(kilogram), epsilon = EPSILON); + } } + } +} + +mod system_macro { + storage_types! { + types: Float; + + use tests::*; + + const EPSILON: V = 0.00001; + + Q!(tests, V); quickcheck! { #[allow(trivial_casts)] fn from_base(v: V) -> bool { - use ConversionFactor; - type MeterKilogram = Units; type KilometerKilogram = Units; // meter -> meter. ulps_eq!(v, - super::from_base::(&v), - epsilon = EPSILON) + ::tests::from_base::(&v), + epsilon = EPSILON) // kilometer -> kilometer. && ulps_eq!(v, - super::from_base::(&v), + ::tests::from_base::(&v), epsilon = EPSILON) // meter -> kilometer. && ulps_eq!(v / >::conversion().value(), - super::from_base::(&v), + ::tests::from_base::(&v), epsilon = EPSILON) // kilometer -> meter. && ulps_eq!(v * >::conversion().value(), - super::from_base::(&v), + ::tests::from_base::(&v), epsilon = EPSILON) } #[allow(trivial_casts)] fn to_base(v: V) -> bool { - use ConversionFactor; - type MeterKilogram = Units; type KilometerKilogram = Units; // meter -> meter. ulps_eq!(v, - super::to_base::(&v), - epsilon = EPSILON) + ::tests::to_base::(&v), + epsilon = EPSILON) // kilometer -> kilometer. && ulps_eq!(v, - super::to_base::(&v), + ::tests::to_base::(&v), epsilon = EPSILON) // kilometer -> meter. && ulps_eq!(v * >::conversion().value(), - super::to_base::(&v), + ::tests::to_base::(&v), epsilon = EPSILON) // meter -> kilometer. && ulps_eq!(v / >::conversion().value(), - super::to_base::(&v), + ::tests::to_base::(&v), epsilon = EPSILON) } #[allow(trivial_casts)] fn change_base(v: V) -> bool { - use ConversionFactor; - type MeterKilogram = Units; type KilometerKilogram = Units; // meter -> meter. ulps_eq!(v, - super::change_base::(&v), - epsilon = EPSILON) + ::tests::change_base::(&v), + epsilon = EPSILON) // kilometer -> kilometer. && ulps_eq!(v, - super::change_base::(&v), + ::tests::change_base::(&v), epsilon = EPSILON) // kilometer -> meter. && ulps_eq!(v * >::conversion().value(), - super::change_base::(&v), + ::tests::change_base::(&v), epsilon = EPSILON) // meter -> kilometer. && ulps_eq!(v / >::conversion().value(), - super::change_base::(&v), + ::tests::change_base::(&v), epsilon = EPSILON) } #[allow(trivial_casts)] - fn is_nan(v: V) -> bool { - v.is_nan() == Length::new::(v).is_nan() + fn add(l: V, r: V) -> bool { + (l + r) == (Length::new::(l) + Length::new::(r)).get(meter) } #[allow(trivial_casts)] - fn is_infinite(v: V) -> bool { - v.is_infinite() == Length::new::(v).is_infinite() + fn sub(l: V, r: V) -> bool { + (l - r) == (Length::new::(l) - Length::new::(r)).get(meter) } #[allow(trivial_casts)] - fn is_finite(v: V) -> bool { - v.is_finite() == Length::new::(v).is_finite() + fn mul_quantity(l: V, r: V) -> bool { + // TODO Use `.get(square_meter)` + (l * r) == (Length::new::(l) * Length::new::(r)).value } #[allow(trivial_casts)] - fn is_normal(v: V) -> bool { - v.is_normal() == Length::new::(v).is_normal() + fn mul_v(l: V, r: V) -> bool { + (l * r) == (Length::new::(l) * r).get(meter) + //&& (l * r) == (l * Length::new::(r)).get(meter) } #[allow(trivial_casts)] - fn classify(v: V) -> bool { - v.classify() == Length::new::(v).classify() + fn div_quantity(l: V, r: V) -> bool { + // TODO Use `.get(?)` + (l / r) == (Length::new::(l) / Length::new::(r)).value } #[allow(trivial_casts)] - fn cbrt(v: V) -> bool { - let l: Quantity, U, V> = Quantity::, U, V> { - dimension: ::stdlib::marker::PhantomData, - units: ::stdlib::marker::PhantomData, - value: v, - }.cbrt(); - - v.cbrt() == l.value + fn div_v(l: V, r: V) -> bool { + // TODO Use `get(meter^-1)` + (l / r) == (Length::new::(l) / r).get(meter) + //&& (l / r) == (l / Length::new::(r)).value } #[allow(trivial_casts)] - fn abs(v: V) -> bool { - v.abs() == Length::new::(v).abs().get(meter) + fn rem(l: V, r: V) -> bool { + (l % r) == (Length::new::(l) % Length::new::(r)).get(meter) } + } + } - #[allow(trivial_casts)] - fn signum(v: V) -> bool { - v.signum() == Length::new::(v).signum().get(meter) - } + mod float { + storage_types! { + types: Float; - #[allow(trivial_casts)] - fn is_sign_positive(v: V) -> bool { - v.is_sign_positive() == Length::new::(v).is_sign_positive() - } + use tests::*; - #[allow(trivial_casts)] - fn is_sign_negative(v: V) -> bool { - v.is_sign_negative() == Length::new::(v).is_sign_negative() + Q!(tests, V); + + #[test] + fn fp_categories() { + assert!(!Length::new::(V::infinity()).is_finite()); + assert!(!Length::new::(V::neg_infinity()).is_finite()); + assert!(Length::new::(V::infinity()).is_infinite()); + assert!(Length::new::(V::neg_infinity()).is_infinite()); + assert!(Length::new::(V::min_positive_value()).is_normal()); + assert!(Length::new::(V::max_value()).is_normal()); + assert!(!Length::new::(V::zero()).is_normal()); + assert!(!Length::new::(V::nan()).is_normal()); + assert!(!Length::new::(V::infinity()).is_normal()); } - #[allow(trivial_casts)] - fn mul_add(s: V, a: V, b: V) -> bool { - let r: Quantity, U, V> = Length::new::(s).mul_add( - Length::new::(a), - Quantity::, U, V> { - dimension: ::stdlib::marker::PhantomData, - units: ::stdlib::marker::PhantomData, - value: b - }); + quickcheck! { + #[allow(trivial_casts)] + fn is_nan(v: V) -> bool { + v.is_nan() == Length::new::(v).is_nan() + } - s.mul_add(a, b) == r.value - } + #[allow(trivial_casts)] + fn is_infinite(v: V) -> bool { + v.is_infinite() == Length::new::(v).is_infinite() + } - #[allow(trivial_casts)] - fn recip(v: V) -> bool { - let a: Quantity, U, V> = Quantity::, U, V> { - dimension: ::stdlib::marker::PhantomData, - units: ::stdlib::marker::PhantomData, - value: v, - }.recip(); - - v.recip() == a.value - } + #[allow(trivial_casts)] + fn is_finite(v: V) -> bool { + v.is_finite() == Length::new::(v).is_finite() + } - #[allow(trivial_casts)] - fn powi(v: V) -> bool { - v.powi(3) == Length::new::(v).powi(P3::new()).value - } + #[allow(trivial_casts)] + fn is_normal(v: V) -> bool { + v.is_normal() == Length::new::(v).is_normal() + } - #[allow(trivial_casts)] - fn sqrt(v: V) -> TestResult { - if v < 0.0 { - return TestResult::discard(); + #[allow(trivial_casts)] + fn classify(v: V) -> bool { + v.classify() == Length::new::(v).classify() } - let l: Quantity, U, V> = Quantity::, U, V> { - dimension: ::stdlib::marker::PhantomData, - units: ::stdlib::marker::PhantomData, - value: v, - }.sqrt(); + #[allow(trivial_casts)] + fn cbrt(v: V) -> bool { + let l: Quantity, U, V> = Quantity::, U, V> { + dimension: ::stdlib::marker::PhantomData, + units: ::stdlib::marker::PhantomData, + value: v, + }.cbrt(); - TestResult::from_bool(v.sqrt() == l.value) - } + v.cbrt() == l.value + } - #[allow(trivial_casts)] - fn max(l: V, r: V) -> bool { - l.max(r) == Length::new::(l).max(Length::new::(r)).get(meter) - } + #[allow(trivial_casts)] + fn is_sign_positive(v: V) -> bool { + v.is_sign_positive() == Length::new::(v).is_sign_positive() + } - #[allow(trivial_casts)] - fn min(l: V, r: V) -> bool { - l.min(r) == Length::new::(l).min(Length::new::(r)).get(meter) - } + #[allow(trivial_casts)] + fn is_sign_negative(v: V) -> bool { + v.is_sign_negative() == Length::new::(v).is_sign_negative() + } - #[allow(trivial_casts)] - fn add(l: V, r: V) -> bool { - (l + r) == (Length::new::(l) + Length::new::(r)).get(meter) - } + #[allow(trivial_casts)] + fn mul_add(s: V, a: V, b: V) -> bool { + let r: Quantity, U, V> = Length::new::(s).mul_add( + Length::new::(a), + Quantity::, U, V> { + dimension: ::stdlib::marker::PhantomData, + units: ::stdlib::marker::PhantomData, + value: b + }); + + s.mul_add(a, b) == r.value + } - #[allow(trivial_casts)] - fn add_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = Length::new::(l); + #[allow(trivial_casts)] + fn recip(v: V) -> bool { + let a: Quantity, U, V> = Quantity::, U, V> { + dimension: ::stdlib::marker::PhantomData, + units: ::stdlib::marker::PhantomData, + value: v, + }.recip(); - f += r; - v += Length::new::(r); + v.recip() == a.value + } - f == v.get(meter) - } + #[allow(trivial_casts)] + fn powi(v: V) -> bool { + v.powi(3) == Length::new::(v).powi(P3::new()).value + } - #[allow(trivial_casts)] - fn sub(l: V, r: V) -> bool { - (l - r) == (Length::new::(l) - Length::new::(r)).get(meter) - } + #[allow(trivial_casts)] + fn sqrt(v: V) -> TestResult { + if v < 0.0 { + return TestResult::discard(); + } - #[allow(trivial_casts)] - fn sub_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = Length::new::(l); + let l: Quantity, U, V> = Quantity::, U, V> { + dimension: ::stdlib::marker::PhantomData, + units: ::stdlib::marker::PhantomData, + value: v, + }.sqrt(); - f -= r; - v -= Length::new::(r); + TestResult::from_bool(v.sqrt() == l.value) + } - f == v.get(meter) - } + #[allow(trivial_casts)] + fn max(l: V, r: V) -> bool { + l.max(r) == Length::new::(l).max(Length::new::(r)).get(meter) + } - #[allow(trivial_casts)] - fn mul_quantity(l: V, r: V) -> bool { - // TODO Use `.get(square_meter)` - (l * r) == (Length::new::(l) * Length::new::(r)).value + #[allow(trivial_casts)] + fn min(l: V, r: V) -> bool { + l.min(r) == Length::new::(l).min(Length::new::(r)).get(meter) + } } + } + } - #[allow(trivial_casts)] - fn mul_float(l: V, r: V) -> bool { - (l * r) == (Length::new::(l) * r).get(meter) - //&& (l * r) == (l * Length::new::(r)).get(meter) - } + mod signed { + storage_types! { + types: Float; - #[allow(trivial_casts)] - fn mul_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = Length::new::(l); + use tests::*; - f *= r; - v *= r; + Q!(tests, V); - f == v.get(meter) - } + quickcheck! { + #[allow(trivial_casts)] + fn abs(v: V) -> bool { + v.abs() == Length::new::(v).abs().get(meter) + } - #[allow(trivial_casts)] - fn div_quantity(l: V, r: V) -> bool { - // TODO Use `.get(?)` - (l / r) == (Length::new::(l) / Length::new::(r)).value - } + #[allow(trivial_casts)] + fn signum(v: V) -> bool { + v.signum() == Length::new::(v).signum().get(meter) + } - #[allow(trivial_casts)] - fn div_float(l: V, r: V) -> bool { - // TODO Use `get(meter^-1)` - (l / r) == (Length::new::(l) / r).get(meter) - //&& (l / r) == (l / Length::new::(r)).value + #[allow(trivial_casts)] + fn neg(l: V) -> bool { + -l == -Length::new::(l).get(meter) + } } + } + } - #[allow(trivial_casts)] - fn div_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = Length::new::(l); + mod op_assign { + storage_types! { + types: Float, PrimInt; - f /= r; - v /= r; + use tests::*; - f == v.get(meter) - } + Q!(tests, V); - #[allow(trivial_casts)] - fn neg(l: V) -> bool { - -l == -Length::new::(l).get(meter) - } + quickcheck! { + #[allow(trivial_casts)] + fn add_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = Length::new::(l); - #[allow(trivial_casts)] - fn rem(l: V, r: V) -> bool { - (l % r) == (Length::new::(l) % Length::new::(r)).get(meter) - } + f += r; + v += Length::new::(r); - #[allow(trivial_casts)] - fn rem_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = Length::new::(l); + f == v.get(meter) + } - f %= r; - v %= Length::new::(r); + #[allow(trivial_casts)] + fn sub_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = Length::new::(l); - f == v.get(meter) - } - } - } + f -= r; + v -= Length::new::(r); - mod quantities_macro { - use num::One; - use super::*; - use super::f; - use super::km as k; - use super::length::{kilometer, meter}; - use super::mass::kilogram; + f == v.get(meter) + } - #[test] - fn new() { - let l1 = k::Length::new::(V::one()); - let l2 = k::Length::new::(V::one()); - let m1 = k::Mass::new::(V::one()); + #[allow(trivial_casts)] + fn mul_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = Length::new::(l); - assert_eq!(V::one(), l1.value); - assert_eq!(1.0_E-3, l2.value); - assert_eq!(V::one(), m1.value); - } + f *= r; + v *= r; - #[test] - fn get() { - let l1 = k::Length::new::(V::one()); - let l2 = k::Length::new::(V::one()); - let m1 = k::Mass::new::(V::one()); - - assert_ulps_eq!(1000.0, l1.get(meter)); - assert_ulps_eq!(V::one(), l2.get(meter)); - assert_ulps_eq!(V::one(), l1.get(kilometer)); - assert_ulps_eq!(0.001, l2.get(kilometer)); - assert_ulps_eq!(V::one(), m1.get(kilogram)); - } + f == v.get(meter) + } - #[test] - fn floor() { - let l1 = k::Length::new::(3.9999); - let l2 = k::Length::new::(3.0001); - let l3 = k::Length::new::(3.9999); - let l4 = k::Length::new::(3.0001); - let m1 = k::Mass::new::(3.9999); - let m2 = k::Mass::new::(3.0001); - - assert_eq!(3.0, l1.floor(kilometer).get(kilometer)); - assert_eq!(3999.0, l1.floor(meter).get(meter)); - assert_eq!(3.0, l2.floor(kilometer).get(kilometer)); - assert_eq!(3000.0, l2.floor(meter).get(meter)); - assert_eq!(0.0, l3.floor(kilometer).get(kilometer)); - assert_eq!(3.0, l3.floor(meter).get(meter)); - assert_eq!(0.0, l4.floor(kilometer).get(kilometer)); - assert_eq!(3.0, l4.floor(meter).get(meter)); - assert_eq!(3.0, m1.floor(kilogram).get(kilogram)); - assert_eq!(3.0, m2.floor(kilogram).get(kilogram)); - } + #[allow(trivial_casts)] + fn div_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = Length::new::(l); - #[test] - fn ceil() { - let l1 = k::Length::new::(3.9999); - let l2 = k::Length::new::(3.0001); - let l3 = k::Length::new::(3.9999); - let l4 = k::Length::new::(3.0001); - let m1 = k::Mass::new::(3.9999); - let m2 = k::Mass::new::(3.0001); - - assert_eq!(4.0, l1.ceil(kilometer).get(kilometer)); - assert_eq!(4000.0, l1.ceil(meter).get(meter)); - assert_eq!(4.0, l2.ceil(kilometer).get(kilometer)); - assert_eq!(3001.0, l2.ceil(meter).get(meter)); - assert_eq!(V::one(), l3.ceil(kilometer).get(kilometer)); - assert_eq!(4.0, l3.ceil(meter).get(meter)); - assert_eq!(V::one(), l4.ceil(kilometer).get(kilometer)); - assert_eq!(4.0, l4.ceil(meter).get(meter)); - assert_eq!(4.0, m1.ceil(kilogram).get(kilogram)); - assert_eq!(4.0, m2.ceil(kilogram).get(kilogram)); - } + f /= r; + v /= r; - #[test] - fn round() { - let l1 = k::Length::new::(3.3); - let l2 = k::Length::new::(3.5); - let l3 = k::Length::new::(3.3); - let l4 = k::Length::new::(3.5); - let m1 = k::Mass::new::(3.3); - let m2 = k::Mass::new::(3.5); - - assert_eq!(3.0, l1.round(kilometer).get(kilometer)); - assert_eq!(3300.0, l1.round(meter).get(meter)); - assert_eq!(4.0, l2.round(kilometer).get(kilometer)); - assert_eq!(3500.0, l2.round(meter).get(meter)); - assert_eq!(0.0, l3.round(kilometer).get(kilometer)); - assert_eq!(3.0, l3.round(meter).get(meter)); - assert_eq!(0.0, l4.round(kilometer).get(kilometer)); - assert_eq!(4.0, l4.round(meter).get(meter)); - assert_eq!(3.0, m1.round(kilogram).get(kilogram)); - assert_eq!(4.0, m2.round(kilogram).get(kilogram)); - } + f == v.get(meter) + } - #[test] - fn trunc() { - let l1 = k::Length::new::(3.3); - let l2 = k::Length::new::(3.5); - let l3 = k::Length::new::(3.3); - let l4 = k::Length::new::(3.5); - let m1 = k::Mass::new::(3.3); - let m2 = k::Mass::new::(3.5); - - assert_eq!(3.0, l1.trunc(kilometer).get(kilometer)); - assert_eq!(3300.0, l1.trunc(meter).get(meter)); - assert_eq!(3.0, l2.trunc(kilometer).get(kilometer)); - assert_eq!(3500.0, l2.trunc(meter).get(meter)); - assert_eq!(0.0, l3.trunc(kilometer).get(kilometer)); - assert_eq!(3.0, l3.trunc(meter).get(meter)); - assert_eq!(0.0, l4.trunc(kilometer).get(kilometer)); - assert_eq!(3.0, l4.trunc(meter).get(meter)); - assert_eq!(3.0, m1.trunc(kilogram).get(kilogram)); - assert_eq!(3.0, m2.trunc(kilogram).get(kilogram)); - } + #[allow(trivial_casts)] + fn rem_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = Length::new::(l); - #[test] - fn fract() { - let l1 = k::Length::new::(3.3); - let l2 = k::Length::new::(3.5); - let l3 = k::Length::new::(3.3); - let l4 = k::Length::new::(3.5); - let m1 = k::Mass::new::(3.3); - let m2 = k::Mass::new::(3.5); - - assert_ulps_eq!(0.3, l1.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.0, l1.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.5, l2.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.0, l2.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.0033, l3.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.3, l3.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.0035, l4.fract(kilometer).get(kilometer), epsilon = EPSILON); - assert_ulps_eq!(0.5, l4.fract(meter).get(meter), epsilon = EPSILON); - assert_ulps_eq!(0.3, m1.fract(kilogram).get(kilogram), epsilon = EPSILON); - assert_ulps_eq!(0.5, m2.fract(kilogram).get(kilogram), epsilon = EPSILON); - } + f %= r; + v %= Length::new::(r); - quickcheck! { - #[allow(trivial_casts)] - fn add(l: V, r: V) -> bool { - ulps_eq!(l + r, - (k::Length::new::(l) + f::Length::new::(r)).get(meter), - epsilon = EPSILON) + f == v.get(meter) + } } + } + } +} - #[allow(trivial_casts)] - fn add_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = k::Length::new::(l); +mod quantities_macro { + mod fractional { + storage_types! { + types: Float; - f += r; - v += f::Length::new::(r); + use tests::*; - ulps_eq!(f, v.get(meter), epsilon = EPSILON) - } + const EPSILON: V = 0.00001; - #[allow(trivial_casts)] - fn sub(l: V, r: V) -> bool { - ulps_eq!((l - r), - (k::Length::new::(l) - f::Length::new::(r)).get(meter), - epsilon = EPSILON) - } + mod f { Q!(tests, super::V); } + mod k { Q!(tests, super::V, (kilometer, kilogram)); } - #[allow(trivial_casts)] - fn sub_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = k::Length::new::(l); + #[test] + fn new() { + let l1 = k::Length::new::(V::one()); + let l2 = k::Length::new::(V::one()); + let m1 = k::Mass::new::(V::one()); - f -= r; - v -= f::Length::new::(r); + assert_eq!(V::one(), l1.value); + assert_eq!(1.0_E-3, l2.value); + assert_eq!(V::one(), m1.value); + } + + #[test] + fn get() { + let l1 = k::Length::new::(V::one()); + let l2 = k::Length::new::(V::one()); + let m1 = k::Mass::new::(V::one()); - ulps_eq!(f, v.get(meter), epsilon = EPSILON) + assert_ulps_eq!(1000.0, l1.get(meter)); + assert_ulps_eq!(V::one(), l2.get(meter)); + assert_ulps_eq!(V::one(), l1.get(kilometer)); + assert_ulps_eq!(0.001, l2.get(kilometer)); + assert_ulps_eq!(V::one(), m1.get(kilogram)); } - #[allow(trivial_casts)] - fn mul_quantity(l: V, r: V) -> bool { - // TODO Use `.get(square_meter)` - ulps_eq!(l * r, - (f::Length::new::(l) * k::Length::new::(r)).value, + quickcheck! { + #[allow(trivial_casts)] + fn add(l: V, r: V) -> bool { + ulps_eq!(l + r, + (k::Length::new::(l) + f::Length::new::(r)).get(meter), epsilon = EPSILON) - && ulps_eq!(l * r, - (f::Length::new::(l) * k::Mass::new::(r)).value, + } + + #[allow(trivial_casts)] + fn sub(l: V, r: V) -> bool { + ulps_eq!((l - r), + (k::Length::new::(l) - f::Length::new::(r)).get(meter), + epsilon = EPSILON) + } + + #[allow(trivial_casts)] + fn mul_quantity(l: V, r: V) -> bool { + // TODO Use `.get(square_meter)` + ulps_eq!(l * r, + (f::Length::new::(l) * k::Length::new::(r)).value, + epsilon = EPSILON) + && ulps_eq!(l * r, + (f::Length::new::(l) * k::Mass::new::(r)).value, + epsilon = EPSILON) + && ulps_eq!(l * r, + (k::Length::new::(l) * f::Mass::new::(r)).value, + epsilon = EPSILON) + } + + #[allow(trivial_casts)] + fn div_quantity(l: V, r: V) -> bool { + // TODO Use `.get(?)` + ulps_eq!(l / r, + (k::Length::new::(l) / f::Length::new::(r)).value, epsilon = EPSILON) - && ulps_eq!(l * r, - (k::Length::new::(l) * f::Mass::new::(r)).value, + } + + #[allow(trivial_casts)] + fn rem(l: V, r: V) -> bool { + ulps_eq!(l % r, + (k::Length::new::(l) % f::Length::new::(r)).get(meter), epsilon = EPSILON) + } } + } + } - #[allow(trivial_casts)] - fn div_quantity(l: V, r: V) -> bool { - // TODO Use `.get(?)` - ulps_eq!(l / r, - (k::Length::new::(l) / f::Length::new::(r)).value, - epsilon = EPSILON) - } + mod float { + storage_types! { + types: Float; - #[allow(trivial_casts)] - fn rem(l: V, r: V) -> bool { - ulps_eq!(l % r, - (k::Length::new::(l) % f::Length::new::(r)).get(meter), - epsilon = EPSILON) - } + use tests::*; - #[allow(trivial_casts)] - fn rem_assign(l: V, r: V) -> bool { - let mut f = l; - let mut v = k::Length::new::(l); + const EPSILON: V = 0.00001; + + mod f { Q!(tests, super::V); } + mod k { Q!(tests, super::V, (kilometer, kilogram)); } + + quickcheck! { + #[allow(trivial_casts)] + fn add_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = k::Length::new::(l); + + f += r; + v += f::Length::new::(r); + + ulps_eq!(f, v.get(meter), epsilon = EPSILON) + } + + #[allow(trivial_casts)] + fn sub_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = k::Length::new::(l); - f %= r; - v %= f::Length::new::(r); + f -= r; + v -= f::Length::new::(r); + + ulps_eq!(f, v.get(meter), epsilon = EPSILON) + } + + #[allow(trivial_casts)] + fn rem_assign(l: V, r: V) -> bool { + let mut f = l; + let mut v = k::Length::new::(l); + + f %= r; + v %= f::Length::new::(r); + + ulps_eq!(f, v.get(meter), epsilon = EPSILON) + } + } - ulps_eq!(f, v.get(meter), epsilon = EPSILON) + #[test] + fn floor() { + let l1 = k::Length::new::(3.9999); + let l2 = k::Length::new::(3.0001); + let l3 = k::Length::new::(3.9999); + let l4 = k::Length::new::(3.0001); + let m1 = k::Mass::new::(3.9999); + let m2 = k::Mass::new::(3.0001); + + assert_eq!(3.0, l1.floor(kilometer).get(kilometer)); + assert_eq!(3999.0, l1.floor(meter).get(meter)); + assert_eq!(3.0, l2.floor(kilometer).get(kilometer)); + assert_eq!(3000.0, l2.floor(meter).get(meter)); + assert_eq!(0.0, l3.floor(kilometer).get(kilometer)); + assert_eq!(3.0, l3.floor(meter).get(meter)); + assert_eq!(0.0, l4.floor(kilometer).get(kilometer)); + assert_eq!(3.0, l4.floor(meter).get(meter)); + assert_eq!(3.0, m1.floor(kilogram).get(kilogram)); + assert_eq!(3.0, m2.floor(kilogram).get(kilogram)); + } + + #[test] + fn ceil() { + let l1 = k::Length::new::(3.9999); + let l2 = k::Length::new::(3.0001); + let l3 = k::Length::new::(3.9999); + let l4 = k::Length::new::(3.0001); + let m1 = k::Mass::new::(3.9999); + let m2 = k::Mass::new::(3.0001); + + assert_eq!(4.0, l1.ceil(kilometer).get(kilometer)); + assert_eq!(4000.0, l1.ceil(meter).get(meter)); + assert_eq!(4.0, l2.ceil(kilometer).get(kilometer)); + assert_eq!(3001.0, l2.ceil(meter).get(meter)); + assert_eq!(V::one(), l3.ceil(kilometer).get(kilometer)); + assert_eq!(4.0, l3.ceil(meter).get(meter)); + assert_eq!(V::one(), l4.ceil(kilometer).get(kilometer)); + assert_eq!(4.0, l4.ceil(meter).get(meter)); + assert_eq!(4.0, m1.ceil(kilogram).get(kilogram)); + assert_eq!(4.0, m2.ceil(kilogram).get(kilogram)); + } + + #[test] + fn round() { + let l1 = k::Length::new::(3.3); + let l2 = k::Length::new::(3.5); + let l3 = k::Length::new::(3.3); + let l4 = k::Length::new::(3.5); + let m1 = k::Mass::new::(3.3); + let m2 = k::Mass::new::(3.5); + + assert_eq!(3.0, l1.round(kilometer).get(kilometer)); + assert_eq!(3300.0, l1.round(meter).get(meter)); + assert_eq!(4.0, l2.round(kilometer).get(kilometer)); + assert_eq!(3500.0, l2.round(meter).get(meter)); + assert_eq!(0.0, l3.round(kilometer).get(kilometer)); + assert_eq!(3.0, l3.round(meter).get(meter)); + assert_eq!(0.0, l4.round(kilometer).get(kilometer)); + assert_eq!(4.0, l4.round(meter).get(meter)); + assert_eq!(3.0, m1.round(kilogram).get(kilogram)); + assert_eq!(4.0, m2.round(kilogram).get(kilogram)); + } + + #[test] + fn trunc() { + let l1 = k::Length::new::(3.3); + let l2 = k::Length::new::(3.5); + let l3 = k::Length::new::(3.3); + let l4 = k::Length::new::(3.5); + let m1 = k::Mass::new::(3.3); + let m2 = k::Mass::new::(3.5); + + assert_eq!(3.0, l1.trunc(kilometer).get(kilometer)); + assert_eq!(3300.0, l1.trunc(meter).get(meter)); + assert_eq!(3.0, l2.trunc(kilometer).get(kilometer)); + assert_eq!(3500.0, l2.trunc(meter).get(meter)); + assert_eq!(0.0, l3.trunc(kilometer).get(kilometer)); + assert_eq!(3.0, l3.trunc(meter).get(meter)); + assert_eq!(0.0, l4.trunc(kilometer).get(kilometer)); + assert_eq!(3.0, l4.trunc(meter).get(meter)); + assert_eq!(3.0, m1.trunc(kilogram).get(kilogram)); + assert_eq!(3.0, m2.trunc(kilogram).get(kilogram)); + } + + #[test] + fn fract() { + let l1 = k::Length::new::(3.3); + let l2 = k::Length::new::(3.5); + let l3 = k::Length::new::(3.3); + let l4 = k::Length::new::(3.5); + let m1 = k::Mass::new::(3.3); + let m2 = k::Mass::new::(3.5); + + assert_ulps_eq!(0.3, l1.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.0, l1.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.5, l2.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.0, l2.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.0033, l3.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.3, l3.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.0035, l4.fract(kilometer).get(kilometer), epsilon = EPSILON); + assert_ulps_eq!(0.5, l4.fract(meter).get(meter), epsilon = EPSILON); + assert_ulps_eq!(0.3, m1.fract(kilogram).get(kilogram), epsilon = EPSILON); + assert_ulps_eq!(0.5, m2.fract(kilogram).get(kilogram), epsilon = EPSILON); } } }