1use std::{fmt, ops};
2
3use crate::Factor;
4
5pub trait FrequencyUnits {
7 fn millihertz(self) -> Frequency;
11
12 fn hertz(self) -> Frequency;
16
17 fn megahertz(self) -> Frequency;
21
22 fn gigahertz(self) -> Frequency;
26
27 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#[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 pub const fn millihertz(&self) -> u64 {
132 self.0
133 }
134
135 pub const fn hertz(&self) -> f64 {
137 self.0 as f64 / 1000.0
138 }
139
140 pub const fn kilohertz(&self) -> f64 {
142 self.hertz() / 1000.0
143 }
144
145 pub const fn megahertz(&self) -> f64 {
147 self.kilohertz() / 1000.0
148 }
149
150 pub const fn gigahertz(&self) -> f64 {
152 self.megahertz() / 1000.0
153 }
154
155 pub const fn terahertz(&self) -> f64 {
157 self.gigahertz() / 1000.0
158 }
159
160 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 pub const fn from_millihertz(z: u64) -> Self {
172 Self(z)
173 }
174
175 pub const fn from_hertz(z: f64) -> Self {
177 Self::from_millihertz((z * 1000.0).round() as _)
178 }
179
180 pub const fn from_kilohertz(z: f64) -> Self {
182 Self::from_hertz(z * 1000.0)
183 }
184
185 pub const fn from_megahertz(z: f64) -> Self {
187 Self::from_kilohertz(z * 1000.0)
188 }
189
190 pub const fn from_gigahertz(z: f64) -> Self {
192 Self::from_megahertz(z * 1000.0)
193 }
194
195 pub const fn from_terahertz(z: f64) -> Self {
197 Self::from_gigahertz(z * 1000.0)
198 }
199
200 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}