mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
59 lines
2.5 KiB
Rust
59 lines
2.5 KiB
Rust
use crate::*;
|
|
|
|
/// A unit of time, represented as an atomic 64-bit float.
|
|
///
|
|
/// According to https://stackoverflow.com/a/873367, as per IEEE754,
|
|
/// every integer between 1 and 2^53 can be represented exactly.
|
|
/// This should mean that, even at 192kHz sampling rate, over 1 year of audio
|
|
/// can be clocked in microseconds with f64 without losing precision.
|
|
pub trait TimeUnit: InteriorMutable<f64> {}
|
|
|
|
/// Implement an arithmetic operation for a unit of time
|
|
#[macro_export] macro_rules! impl_op {
|
|
($T:ident, $Op:ident, $method:ident, |$a:ident,$b:ident|{$impl:expr}) => {
|
|
impl $Op<Self> for $T {
|
|
type Output = Self; #[inline] fn $method (self, other: Self) -> Self::Output {
|
|
let $a = self.get(); let $b = other.get(); Self($impl.into())
|
|
}
|
|
}
|
|
impl $Op<usize> for $T {
|
|
type Output = Self; #[inline] fn $method (self, other: usize) -> Self::Output {
|
|
let $a = self.get(); let $b = other as f64; Self($impl.into())
|
|
}
|
|
}
|
|
impl $Op<f64> for $T {
|
|
type Output = Self; #[inline] fn $method (self, other: f64) -> Self::Output {
|
|
let $a = self.get(); let $b = other; Self($impl.into())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Define and implement a unit of time
|
|
#[macro_export] macro_rules! impl_time_unit {
|
|
($T:ident) => {
|
|
impl Gettable<f64> for $T {
|
|
fn get (&self) -> f64 { self.0.load(Relaxed) }
|
|
}
|
|
impl InteriorMutable<f64> for $T {
|
|
fn set (&self, value: f64) -> f64 {
|
|
let old = self.get();
|
|
self.0.store(value, Relaxed);
|
|
old
|
|
}
|
|
}
|
|
impl TimeUnit for $T {}
|
|
impl_op!($T, Add, add, |a, b|{a + b});
|
|
impl_op!($T, Sub, sub, |a, b|{a - b});
|
|
impl_op!($T, Mul, mul, |a, b|{a * b});
|
|
impl_op!($T, Div, div, |a, b|{a / b});
|
|
impl_op!($T, Rem, rem, |a, b|{a % b});
|
|
impl From<f64> for $T { fn from (value: f64) -> Self { Self(value.into()) } }
|
|
impl From<usize> for $T { fn from (value: usize) -> Self { Self((value as f64).into()) } }
|
|
impl From<$T> for f64 { fn from (value: $T) -> Self { value.get() } }
|
|
impl From<$T> for usize { fn from (value: $T) -> Self { value.get() as usize } }
|
|
impl From<&$T> for f64 { fn from (value: &$T) -> Self { value.get() } }
|
|
impl From<&$T> for usize { fn from (value: &$T) -> Self { value.get() as usize } }
|
|
impl Clone for $T { fn clone (&self) -> Self { Self(self.get().into()) } }
|
|
}
|
|
}
|