@@ -35,10 +35,91 @@ pub use force::Force;
3535pub mod area;
3636pub use area:: Area ;
3737
38- pub fn duration_as_f64 ( duration : std:: time:: Duration ) -> f64 {
39- duration. as_secs ( ) as f64 + ( ( duration. subsec_nanos ( ) as f64 ) * 1e-9 )
38+ /// For given types A, B and C, implement, using base units:
39+ /// - A = B * C
40+ /// - A = C * B
41+ /// - B = A / C
42+ /// - C = A / B
43+ macro_rules! impl_maths {
44+ ( $a: ty, $b: ty) => {
45+ impl :: std:: ops:: Mul <$b> for $b {
46+ type Output = $a;
47+
48+ fn mul( self , rhs: $b) -> Self :: Output {
49+ Self :: Output :: from_base_units( self . get_base_units( ) * rhs. get_base_units( ) )
50+ }
51+ }
52+
53+ impl :: std:: ops:: Div <$b> for $a {
54+ type Output = $b;
55+
56+ fn div( self , rhs: $b) -> Self :: Output {
57+ Self :: Output :: from_base_units( self . get_base_units( ) / rhs. get_base_units( ) )
58+ }
59+ }
60+ } ;
61+
62+ ( $a: ty, $b: ty, $c: ty) => {
63+ impl :: std:: ops:: Mul <$b> for $c {
64+ type Output = $a;
65+
66+ fn mul( self , rhs: $b) -> Self :: Output {
67+ Self :: Output :: from_base_units( self . get_base_units( ) * rhs. get_base_units( ) )
68+ }
69+ }
70+
71+ impl :: std:: ops:: Mul <$c> for $b {
72+ type Output = $a;
73+
74+ fn mul( self , rhs: $c) -> Self :: Output {
75+ Self :: Output :: from_base_units( self . get_base_units( ) * rhs. get_base_units( ) )
76+ }
77+ }
78+
79+ impl :: std:: ops:: Div <$c> for $a {
80+ type Output = $b;
81+
82+ fn div( self , rhs: $c) -> Self :: Output {
83+ Self :: Output :: from_base_units( self . get_base_units( ) / rhs. get_base_units( ) )
84+ }
85+ }
86+
87+ impl :: std:: ops:: Div <$b> for $a {
88+ type Output = $c;
89+
90+ fn div( self , rhs: $b) -> Self :: Output {
91+ Self :: Output :: from_base_units( self . get_base_units( ) / rhs. get_base_units( ) )
92+ }
93+ }
94+ }
95+ }
96+
97+ impl Measurement for std:: time:: Duration {
98+ fn get_base_units ( & self ) -> f64 {
99+ self . as_secs ( ) as f64 + ( ( self . subsec_nanos ( ) as f64 ) * 1e-9 )
100+ }
101+
102+ fn from_base_units ( units : f64 ) -> Self {
103+ let subsec_nanos = ( ( units * 1e9 ) % 1e9 ) as u32 ;
104+ let secs = units as u64 ;
105+ std:: time:: Duration :: new ( secs, subsec_nanos)
106+ }
107+
108+ fn get_base_units_name ( & self ) -> & ' static str {
109+ "s"
110+ }
40111}
41112
113+ impl_maths ! ( Area , Length ) ;
114+ impl_maths ! ( Energy , Force , Length ) ;
115+ impl_maths ! ( Energy , std:: time:: Duration , Power ) ;
116+ impl_maths ! ( Force , Mass , Acceleration ) ;
117+ impl_maths ! ( Force , Pressure , Area ) ;
118+ impl_maths ! ( Length , std:: time:: Duration , Speed ) ;
119+ impl_maths ! ( Power , Force , Speed ) ;
120+ impl_maths ! ( Speed , std:: time:: Duration , Acceleration ) ;
121+ impl_maths ! ( Volume , Length , Area ) ;
122+
42123// Include when running tests, but don't export them
43124#[ cfg( test) ]
44125#[ allow( dead_code) ]
0 commit comments