Skip to content

Commit 34cbc9d

Browse files
author
Jonathan Pallant
committed
Added acceleration.
1 parent 845e688 commit 34cbc9d

File tree

8 files changed

+231
-4
lines changed

8 files changed

+231
-4
lines changed

examples/format_test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use measurements::Pressure;
55
use measurements::Volume;
66
use measurements::Weight;
77
use measurements::Speed;
8+
use measurements::Acceleration;
9+
810
fn main() {
911
for power in -9..9 {
1012
let val: f64 = 123.456 * (10.0f64.powf(power as f64));
@@ -15,5 +17,6 @@ fn main() {
1517
println!("Volume of {0:.3}", Volume::from_litres(val));
1618
println!("Weight of {0:.3}", Weight::from_kilograms(val));
1719
println!("Speed of {0:.3}", Speed::from_meters_per_second(val));
20+
println!("Acceleration of {0:.3}", Acceleration::from_meters_per_second_per_second(val));
1821
}
1922
}

src/acceleration.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
use super::measurement::*;
2+
use super::Speed;
3+
use std::time::Duration;
4+
5+
/// The `Acceleration` struct can be used to deal with Accelerations in a common way.
6+
/// Common metric and imperial units are supported.
7+
///
8+
/// # Example
9+
///
10+
/// ```
11+
/// use measurements::{Acceleration, Length, Speed};
12+
/// use std::time::Duration;
13+
///
14+
/// // Standing quarter mile in 10.0 dead, at 120.0 mph
15+
/// let track = Length::from_miles(0.25);
16+
/// let finish = Speed::from_miles_per_hour(120.0);
17+
/// let time = Duration::new(10, 0);
18+
/// let accel = finish / time;
19+
/// println!("You accelerated over {} at an average of {}", track, accel);
20+
/// ```
21+
#[derive(Copy, Clone, Debug)]
22+
pub struct Acceleration {
23+
meters_per_second_per_second: f64,
24+
}
25+
26+
impl Acceleration {
27+
pub fn from_meters_per_second_per_second(meters_per_second_per_second: f64) -> Acceleration {
28+
Acceleration { meters_per_second_per_second: meters_per_second_per_second }
29+
}
30+
31+
pub fn from_metres_per_second_per_second(metres_per_second_per_second: f64) -> Acceleration {
32+
Acceleration::from_meters_per_second_per_second(metres_per_second_per_second)
33+
}
34+
35+
pub fn as_meters_per_second_per_second(&self) -> f64 {
36+
self.meters_per_second_per_second
37+
}
38+
39+
pub fn as_metres_per_second_per_second(&self) -> f64 {
40+
self.as_meters_per_second_per_second()
41+
}
42+
}
43+
44+
/// Acceleration * Time = Speed
45+
impl ::std::ops::Mul<Duration> for Acceleration {
46+
type Output = Speed;
47+
48+
fn mul(self, rhs: Duration) -> Speed {
49+
// It would be useful if Duration had a method that did this...
50+
let seconds: f64 = rhs.as_secs() as f64 + ((rhs.subsec_nanos() as f64) * 1e-9);
51+
Speed::from_meters_per_second(self.as_meters_per_second_per_second() * seconds)
52+
}
53+
}
54+
55+
/// Time * Acceleration = Speed
56+
impl ::std::ops::Mul<Acceleration> for Duration {
57+
type Output = Speed;
58+
59+
fn mul(self, rhs: Acceleration) -> Speed {
60+
rhs * self
61+
}
62+
}
63+
64+
impl Measurement for Acceleration {
65+
fn get_base_units(&self) -> f64 {
66+
self.meters_per_second_per_second
67+
}
68+
69+
fn from_base_units(units: f64) -> Self {
70+
Self::from_meters_per_second_per_second(units)
71+
}
72+
73+
fn get_base_units_name(&self) -> &'static str {
74+
"m/s\u{00B2}"
75+
}
76+
}
77+
78+
implement_measurement! { Acceleration }

src/length.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::measurement::*;
2+
use std::time::Duration;
3+
use speed::Speed;
24

35
// Constants, metric
46
const METER_NANOMETER_FACTOR: f64 = 1000000000.0;
@@ -208,6 +210,28 @@ impl Length {
208210
}
209211
}
210212

213+
/// Length / Time = Speed
214+
impl ::std::ops::Div<Duration> for Length {
215+
type Output = Speed;
216+
217+
fn div(self, rhs: Duration) -> Speed {
218+
// It would be useful if Duration had a method that did this...
219+
let seconds: f64 = rhs.as_secs() as f64 + ((rhs.subsec_nanos() as f64) * 1e-9);
220+
Speed::from_meters_per_second(self.as_meters() / seconds)
221+
}
222+
}
223+
224+
/// Length / Speed = Time
225+
impl ::std::ops::Div<Speed> for Length {
226+
type Output = Duration;
227+
228+
fn div(self, rhs: Speed) -> Duration {
229+
let seconds = self.as_meters() / rhs.as_meters_per_second();
230+
let nanosecs = (seconds * 1e9) % 1e9;
231+
Duration::new(seconds as u64, nanosecs as u32)
232+
}
233+
}
234+
211235
impl Measurement for Length {
212236
fn get_base_units(&self) -> f64 {
213237
self.meters

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub use pressure::Pressure;
2020
pub mod speed;
2121
pub use speed::Speed;
2222

23+
pub mod acceleration;
24+
pub use acceleration::Acceleration;
25+
2326
// Include when running tests, but don't export them
2427
#[cfg(test)]
2528
#[allow(dead_code)]

src/speed.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::measurement::*;
22
use super::Length;
3+
use super::Acceleration;
34
use std::time::Duration;
45

56
/// The `Speed` struct can be used to deal with speeds in a common way.
@@ -62,13 +63,45 @@ impl Speed {
6263
}
6364
}
6465

65-
impl ::std::ops::Div<Duration> for Length {
66-
type Output = Speed;
66+
/// Speed / Acceleration = Time
67+
impl ::std::ops::Div<Acceleration> for Speed {
68+
type Output = Duration;
6769

68-
fn div(self, rhs: Duration) -> Speed {
70+
fn div(self, rhs: Acceleration) -> Duration {
71+
let seconds = self.as_meters_per_second() / rhs.as_meters_per_second_per_second();
72+
let nanosecs = (seconds * 1e9) % 1e9;
73+
Duration::new(seconds as u64, nanosecs as u32)
74+
}
75+
}
76+
77+
/// Speed / Time = Acceleration
78+
impl ::std::ops::Div<Duration> for Speed {
79+
type Output = Acceleration;
80+
81+
fn div(self, rhs: Duration) -> Acceleration {
82+
// It would be useful if Duration had a method that did this...
83+
let seconds: f64 = rhs.as_secs() as f64 + ((rhs.subsec_nanos() as f64) * 1e-9);
84+
Acceleration::from_meters_per_second_per_second(self.as_meters_per_second() / seconds)
85+
}
86+
}
87+
88+
/// Speed * Time = Length
89+
impl ::std::ops::Mul<Duration> for Speed {
90+
type Output = Length;
91+
92+
fn mul(self, rhs: Duration) -> Length {
6993
// It would be useful if Duration had a method that did this...
7094
let seconds: f64 = rhs.as_secs() as f64 + ((rhs.subsec_nanos() as f64) * 1e-9);
71-
Speed::from_meters_per_second(self.as_meters() / seconds)
95+
Length::from_meters(self.as_meters_per_second() * seconds)
96+
}
97+
}
98+
99+
/// Time * Speed = Length
100+
impl ::std::ops::Mul<Speed> for Duration {
101+
type Output = Length;
102+
103+
fn mul(self, rhs: Speed) -> Length {
104+
rhs * self
72105
}
73106
}
74107

src/tests/acceleration_tests.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use acceleration::*;
2+
use super::assert_almost_eq;
3+
use std::time::Duration;
4+
use speed::Speed;
5+
6+
// Metric
7+
#[test]
8+
fn speed_over_time() {
9+
let s1 = Speed::from_meters_per_second(10.0);
10+
let t1 = Duration::new(5, 0);
11+
let i1 = s1 / t1;
12+
let r1 = i1.as_meters_per_second_per_second();
13+
assert_almost_eq(r1, 2.0);
14+
}
15+
16+
// Traits
17+
#[test]
18+
fn add() {
19+
let a = Acceleration::from_meters_per_second_per_second(2.0);
20+
let b = Acceleration::from_meters_per_second_per_second(4.0);
21+
let c = a + b;
22+
let d = b + a;
23+
assert_almost_eq(c.as_meters_per_second_per_second(), 6.0);
24+
assert_eq!(c, d);
25+
}
26+
27+
#[test]
28+
fn sub() {
29+
let a = Acceleration::from_meters_per_second_per_second(2.0);
30+
let b = Acceleration::from_meters_per_second_per_second(4.0);
31+
let c = a - b;
32+
assert_almost_eq(c.as_meters_per_second_per_second(), -2.0);
33+
}
34+
35+
#[test]
36+
fn mul() {
37+
let a = Acceleration::from_meters_per_second_per_second(3.0);
38+
let b = a * 2.0;
39+
let c = 2.0 * a;
40+
assert_almost_eq(b.as_meters_per_second_per_second(), 6.0);
41+
assert_eq!(b, c);
42+
}
43+
44+
#[test]
45+
fn div() {
46+
let a = Acceleration::from_meters_per_second_per_second(2.0);
47+
let b = Acceleration::from_meters_per_second_per_second(4.0);
48+
let c = a / b;
49+
let d = a / 2.0;
50+
assert_almost_eq(c, 0.5);
51+
assert_almost_eq(d.as_meters_per_second_per_second(), 1.0);
52+
}
53+
54+
#[test]
55+
fn eq() {
56+
let a = Acceleration::from_meters_per_second_per_second(2.0);
57+
let b = Acceleration::from_meters_per_second_per_second(2.0);
58+
assert_eq!(a == b, true);
59+
}
60+
61+
#[test]
62+
fn neq() {
63+
let a = Acceleration::from_meters_per_second_per_second(2.0);
64+
let b = Acceleration::from_meters_per_second_per_second(4.0);
65+
assert_eq!(a == b, false);
66+
}
67+
68+
#[test]
69+
fn cmp() {
70+
let a = Acceleration::from_meters_per_second_per_second(2.0);
71+
let b = Acceleration::from_meters_per_second_per_second(4.0);
72+
assert_eq!(a < b, true);
73+
assert_eq!(a <= b, true);
74+
assert_eq!(a > b, false);
75+
assert_eq!(a >= b, false);
76+
}

src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod temperature_tests;
33
mod weight_tests;
44
mod volume_tests;
55
mod speed_tests;
6+
mod acceleration_tests;
67

78
const DEFAULT_DELTA: f64 = 0.00001;
89

src/tests/speed_tests.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ fn length_over_time() {
2525
assert_almost_eq(r1, 2.0);
2626
}
2727

28+
#[test]
29+
fn acceleration() {
30+
// To get to 100 m/s at 50 m/s/s takes 2.0 seconds
31+
let s = Length::from_meters(100.0) / Duration::new(1, 0);
32+
let a = Length::from_meters(50.0) / Duration::new(1, 0) / Duration::new(1, 0);
33+
let t = s / a;
34+
assert_eq!(t, Duration::new(2, 0));
35+
}
36+
2837
#[test]
2938
fn kilometres_per_hour() {
3039
let i1 = Speed::from_metres_per_second(100.0);

0 commit comments

Comments
 (0)