Merge #618
618: time: optimize math by reducing fractions at compile time. r=Dirbaio a=Dirbaio For example, `as_micros`, `from_micros` now are noops if tick rate is 1MHz. See: https://godbolt.org/z/fE1bf3ecP Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| use core::fmt; | ||||
| use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; | ||||
|  | ||||
| use super::TICKS_PER_SECOND; | ||||
| use super::{GCD_1K, GCD_1M, TICKS_PER_SECOND}; | ||||
|  | ||||
| #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| @@ -28,12 +28,12 @@ impl Duration { | ||||
|  | ||||
|     /// Convert the `Duration` to milliseconds, rounding down. | ||||
|     pub const fn as_millis(&self) -> u64 { | ||||
|         self.ticks * 1000 / TICKS_PER_SECOND | ||||
|         self.ticks * (1000 / GCD_1K) / (TICKS_PER_SECOND / GCD_1K) | ||||
|     } | ||||
|  | ||||
|     /// Convert the `Duration` to microseconds, rounding down. | ||||
|     pub const fn as_micros(&self) -> u64 { | ||||
|         self.ticks * 1_000_000 / TICKS_PER_SECOND | ||||
|         self.ticks * (1_000_000 / GCD_1M) / (TICKS_PER_SECOND / GCD_1M) | ||||
|     } | ||||
|  | ||||
|     /// Creates a duration from the specified number of clock ticks | ||||
| @@ -51,7 +51,7 @@ impl Duration { | ||||
|     /// Creates a duration from the specified number of milliseconds | ||||
|     pub const fn from_millis(millis: u64) -> Duration { | ||||
|         Duration { | ||||
|             ticks: millis * TICKS_PER_SECOND / 1000, | ||||
|             ticks: millis * (TICKS_PER_SECOND / GCD_1K) / (1000 / GCD_1K), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -59,7 +59,7 @@ impl Duration { | ||||
|     /// NOTE: Delays this small may be inaccurate. | ||||
|     pub const fn from_micros(micros: u64) -> Duration { | ||||
|         Duration { | ||||
|             ticks: micros * TICKS_PER_SECOND / 1_000_000, | ||||
|             ticks: micros * (TICKS_PER_SECOND / GCD_1M) / (1_000_000 / GCD_1M), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| use core::fmt; | ||||
| use core::ops::{Add, AddAssign, Sub, SubAssign}; | ||||
|  | ||||
| use super::{driver, Duration, TICKS_PER_SECOND}; | ||||
| use super::{driver, Duration, GCD_1K, GCD_1M, TICKS_PER_SECOND}; | ||||
|  | ||||
| #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] | ||||
| #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||||
| @@ -31,14 +31,14 @@ impl Instant { | ||||
|     /// Create an Instant from a microsecond count since system boot. | ||||
|     pub const fn from_micros(micros: u64) -> Self { | ||||
|         Self { | ||||
|             ticks: micros * TICKS_PER_SECOND / 1_000_000, | ||||
|             ticks: micros * (TICKS_PER_SECOND / GCD_1M) / (1_000_000 / GCD_1M), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Create an Instant from a millisecond count since system boot. | ||||
|     pub const fn from_millis(millis: u64) -> Self { | ||||
|         Self { | ||||
|             ticks: millis * TICKS_PER_SECOND / 1000, | ||||
|             ticks: millis * (TICKS_PER_SECOND / GCD_1K) / (1000 / GCD_1K), | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -61,12 +61,12 @@ impl Instant { | ||||
|  | ||||
|     /// Milliseconds since system boot. | ||||
|     pub const fn as_millis(&self) -> u64 { | ||||
|         self.ticks * 1000 / TICKS_PER_SECOND | ||||
|         self.ticks * (1000 / GCD_1K) / (TICKS_PER_SECOND / GCD_1K) | ||||
|     } | ||||
|  | ||||
|     /// Microseconds since system boot. | ||||
|     pub const fn as_micros(&self) -> u64 { | ||||
|         self.ticks * 1_000_000 / TICKS_PER_SECOND | ||||
|         self.ticks * (1_000_000 / GCD_1M) / (TICKS_PER_SECOND / GCD_1M) | ||||
|     } | ||||
|  | ||||
|     /// Duration between this Instant and another Instant | ||||
|   | ||||
| @@ -75,3 +75,14 @@ const TPS: u64 = 1_000_000; | ||||
| /// allow you to choose a tick rate with Cargo features of their own. You should not | ||||
| /// set the `time-tick-*` features for embassy yourself as an end user. | ||||
| pub const TICKS_PER_SECOND: u64 = TPS; | ||||
|  | ||||
| const fn gcd(a: u64, b: u64) -> u64 { | ||||
|     if b == 0 { | ||||
|         a | ||||
|     } else { | ||||
|         gcd(b, a % b) | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub(crate) const GCD_1K: u64 = gcd(TICKS_PER_SECOND, 1_000); | ||||
| pub(crate) const GCD_1M: u64 = gcd(TICKS_PER_SECOND, 1_000_000); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user