zng_unit/
frequency.rs

1use std::{fmt, ops};
2
3use crate::Factor;
4
5/// Extension methods for initializing [`Frequency`] values.
6pub trait FrequencyUnits {
7    /// Millihertz.
8    ///
9    /// See [`Frequency::from_millihertz`] for more details.
10    fn millihertz(self) -> Frequency;
11
12    /// Hertz.
13    ///
14    /// See [`Frequency::from_hertz`] for more details.
15    fn hertz(self) -> Frequency;
16
17    /// Megahertz.
18    ///
19    /// See [`Frequency::from_megahertz`] for more details.
20    fn megahertz(self) -> Frequency;
21
22    /// Gigahertz.
23    ///
24    /// See [`Frequency::from_gigahertz`] for more details.
25    fn gigahertz(self) -> Frequency;
26
27    /// Terahertz.
28    ///
29    /// See [`Frequency::from_terahertz`] for more details.
30    fn terahertz(self) -> Frequency;
31}
32impl FrequencyUnits for u64 {
33    fn millihertz(self) -> Frequency {
34        Frequency::from_millihertz(self)
35    }
36
37    fn hertz(self) -> Frequency {
38        Frequency::from_hertz(self as _)
39    }
40
41    fn megahertz(self) -> Frequency {
42        Frequency::from_megahertz(self as _)
43    }
44
45    fn gigahertz(self) -> Frequency {
46        Frequency::from_gigahertz(self as _)
47    }
48
49    fn terahertz(self) -> Frequency {
50        Frequency::from_terahertz(self as _)
51    }
52}
53impl FrequencyUnits for f64 {
54    fn millihertz(self) -> Frequency {
55        Frequency::from_millihertz(self.round() as _)
56    }
57
58    fn hertz(self) -> Frequency {
59        Frequency::from_hertz(self)
60    }
61
62    fn megahertz(self) -> Frequency {
63        Frequency::from_megahertz(self)
64    }
65
66    fn gigahertz(self) -> Frequency {
67        Frequency::from_gigahertz(self)
68    }
69
70    fn terahertz(self) -> Frequency {
71        Frequency::from_terahertz(self)
72    }
73}
74
75/// A unit of frequency.
76#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, serde::Serialize, serde::Deserialize)]
77#[serde(transparent)]
78pub struct Frequency(u64);
79impl ops::Add for Frequency {
80    type Output = Self;
81
82    fn add(self, rhs: Self) -> Self::Output {
83        Self(self.0 + rhs.0)
84    }
85}
86impl ops::AddAssign for Frequency {
87    fn add_assign(&mut self, rhs: Self) {
88        self.0 += rhs.0;
89    }
90}
91impl ops::Sub for Frequency {
92    type Output = Self;
93
94    fn sub(self, rhs: Self) -> Self::Output {
95        Self(self.0 - rhs.0)
96    }
97}
98impl ops::SubAssign for Frequency {
99    fn sub_assign(&mut self, rhs: Self) {
100        self.0 -= rhs.0;
101    }
102}
103impl ops::Mul<Factor> for Frequency {
104    type Output = Frequency;
105
106    fn mul(mut self, rhs: Factor) -> Self::Output {
107        self.0 *= rhs;
108        self
109    }
110}
111impl ops::Div<Factor> for Frequency {
112    type Output = Frequency;
113
114    fn div(mut self, rhs: Factor) -> Self::Output {
115        self.0 /= rhs;
116        self
117    }
118}
119impl ops::MulAssign<Factor> for Frequency {
120    fn mul_assign(&mut self, rhs: Factor) {
121        self.0 *= rhs;
122    }
123}
124impl ops::DivAssign<Factor> for Frequency {
125    fn div_assign(&mut self, rhs: Factor) {
126        self.0 /= rhs;
127    }
128}
129impl Frequency {
130    /// Frequency in millihertz.
131    pub const fn millihertz(&self) -> u64 {
132        self.0
133    }
134
135    /// Frequency in hertz.
136    pub const fn hertz(&self) -> f64 {
137        self.0 as f64 / 1000.0
138    }
139
140    /// Frequency in kilohertz.
141    pub const fn kilohertz(&self) -> f64 {
142        self.hertz() / 1000.0
143    }
144
145    /// Frequency in megahertz.
146    pub const fn megahertz(&self) -> f64 {
147        self.kilohertz() / 1000.0
148    }
149
150    /// Frequency in gigahertz.
151    pub const fn gigahertz(&self) -> f64 {
152        self.megahertz() / 1000.0
153    }
154
155    /// Frequency in terahertz.
156    pub const fn terahertz(&self) -> f64 {
157        self.gigahertz() / 1000.0
158    }
159
160    /// Interval of one cycle at the frequency.
161    pub const fn period(&self) -> std::time::Duration {
162        if self.0 == 0 {
163            return std::time::Duration::MAX;
164        }
165        let nanos = (1_000_000_000_000u128 / self.0 as u128) as u64;
166        std::time::Duration::from_nanos(nanos)
167    }
168}
169impl Frequency {
170    /// From millihertz.
171    pub const fn from_millihertz(z: u64) -> Self {
172        Self(z)
173    }
174
175    /// From hertz.
176    pub const fn from_hertz(z: f64) -> Self {
177        Self::from_millihertz((z * 1000.0).round() as _)
178    }
179
180    /// From kilohertz.
181    pub const fn from_kilohertz(z: f64) -> Self {
182        Self::from_hertz(z * 1000.0)
183    }
184
185    /// From megahertz.
186    pub const fn from_megahertz(z: f64) -> Self {
187        Self::from_kilohertz(z * 1000.0)
188    }
189
190    /// From gigahertz.
191    pub const fn from_gigahertz(z: f64) -> Self {
192        Self::from_megahertz(z * 1000.0)
193    }
194
195    /// From terahertz.
196    pub const fn from_terahertz(z: f64) -> Self {
197        Self::from_gigahertz(z * 1000.0)
198    }
199
200    /// From interval of one cycle at the frequency.
201    pub const fn from_period(p: std::time::Duration) -> Self {
202        let nanos = p.as_nanos();
203        if nanos == 0 {
204            return Self(0);
205        }
206        let mhz = 1_000_000_000_000u128 / nanos;
207        Self(mhz as u64)
208    }
209}
210impl fmt::Display for Frequency {
211    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212        let z = self.0;
213        if z >= 1_000_000_000_000_000 {
214            write!(f, "{:.2}THz", self.terahertz())
215        } else if z >= 1_000_000_000_000 {
216            write!(f, "{:.2}GHz", self.gigahertz())
217        } else if z >= 1_000_000_000 {
218            write!(f, "{:.2}MHz", self.megahertz())
219        } else if z >= 1_000_000 {
220            write!(f, "{:.2}kHz", self.kilohertz())
221        } else if z >= 1_000 {
222            write!(f, "{:.2}Hz", self.hertz())
223        } else {
224            write!(f, "{z}mHz")
225        }
226    }
227}
228impl fmt::Debug for Frequency {
229    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230        if f.alternate() {
231            f.debug_tuple("Frequency").field(&self.0).finish()
232        } else {
233            write!(f, "Frequency({self})")
234        }
235    }
236}