time: optimize math by reducing fractions at compile time.
For example, `as_micros`, `from_micros` now are noops if tick rate is 1MHz.
This commit is contained in:
parent
eb922c4655
commit
640ddc9481
3 changed files with 21 additions and 10 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue