Skip to main content

space_units/quantities/
waves.rs

1use super::DisplayWithUnit;
2use super::Length;
3use super::Time;
4
5/// Speed of light in vacuum (m/s), used for wavelength calculations.
6const SPEED_OF_LIGHT_MPS: f64 = 299_792_458.0;
7
8// -------------------------
9// Frequency
10// -------------------------
11
12/// A frequency quantity, stored internally in hertz (Hz).
13///
14/// # Construction
15/// ```
16/// # use space_units::Frequency;
17/// let f = Frequency::from_ghz(2.4);
18/// ```
19///
20/// # Typed arithmetic
21/// Supports [`.period()`](Frequency::period) → [`Time`] and [`.wavelength()`](Frequency::wavelength) → [`Length`] (vacuum).
22#[must_use]
23#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
24pub struct Frequency(pub(crate) f64);
25
26/// Display/conversion units for [`Frequency`].
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum FrequencyUnit {
29    /// Hertz (Hz).
30    Hertz,
31    /// Kilohertz (kHz).
32    KiloHertz,
33    /// Megahertz (MHz).
34    MegaHertz,
35    /// Gigahertz (GHz).
36    GigaHertz,
37    /// Terahertz (THz).
38    TeraHertz,
39    /// Revolutions per minute (rpm). 1 rpm = 1/60 Hz.
40    Rpm,
41}
42
43impl FrequencyUnit {
44    const fn symbol(self) -> &'static str {
45        match self {
46            Self::Hertz => "Hz",
47            Self::KiloHertz => "kHz",
48            Self::MegaHertz => "MHz",
49            Self::GigaHertz => "GHz",
50            Self::TeraHertz => "THz",
51            Self::Rpm => "rpm",
52        }
53    }
54
55    const fn hz_per_unit(self) -> f64 {
56        match self {
57            Self::Hertz => 1.0,
58            Self::KiloHertz => 1e3,
59            Self::MegaHertz => 1e6,
60            Self::GigaHertz => 1e9,
61            Self::TeraHertz => 1e12,
62            Self::Rpm => 1.0 / 60.0,
63        }
64    }
65}
66
67impl Frequency {
68    /// Create from hertz (canonical unit).
69    pub const fn from_hz(val: f64) -> Self {
70        Self(val)
71    }
72
73    /// Create from kilohertz. 1 kHz = 1e3 Hz.
74    pub const fn from_khz(val: f64) -> Self {
75        Self(val * 1e3)
76    }
77
78    /// Create from megahertz. 1 MHz = 1e6 Hz.
79    pub const fn from_mhz(val: f64) -> Self {
80        Self(val * 1e6)
81    }
82
83    /// Create from gigahertz. 1 GHz = 1e9 Hz.
84    pub const fn from_ghz(val: f64) -> Self {
85        Self(val * 1e9)
86    }
87
88    /// Create from terahertz. 1 THz = 1e12 Hz.
89    pub const fn from_thz(val: f64) -> Self {
90        Self(val * 1e12)
91    }
92
93    /// Create from revolutions per minute. 1 rpm = 1/60 Hz.
94    pub const fn from_rpm(val: f64) -> Self {
95        Self(val / 60.0)
96    }
97
98    /// Get value in hertz.
99    pub const fn in_hz(self) -> f64 {
100        self.0
101    }
102
103    /// Get value in kilohertz.
104    pub const fn in_khz(self) -> f64 {
105        self.0 / 1e3
106    }
107
108    /// Get value in megahertz.
109    pub const fn in_mhz(self) -> f64 {
110        self.0 / 1e6
111    }
112
113    /// Get value in gigahertz.
114    pub const fn in_ghz(self) -> f64 {
115        self.0 / 1e9
116    }
117
118    /// Get value in terahertz.
119    pub const fn in_thz(self) -> f64 {
120        self.0 / 1e12
121    }
122
123    /// Get value in revolutions per minute.
124    pub const fn in_rpm(self) -> f64 {
125        self.0 * 60.0
126    }
127
128    /// Get value in the specified [`FrequencyUnit`].
129    pub fn in_unit(self, unit: FrequencyUnit) -> f64 {
130        self.0 / unit.hz_per_unit()
131    }
132
133    /// Return a display wrapper that formats this frequency in the given unit.
134    pub fn display_as(self, unit: FrequencyUnit) -> DisplayWithUnit {
135        DisplayWithUnit {
136            value: self.in_unit(unit),
137            symbol: unit.symbol(),
138        }
139    }
140
141    /// Compute the period (1/f) as a [`Time`].
142    pub fn period(self) -> Time {
143        Time::from_s(1.0 / self.0)
144    }
145
146    /// Compute the wavelength in vacuum (c/f) as a [`Length`].
147    pub fn wavelength(self) -> Length {
148        Length::from_m(SPEED_OF_LIGHT_MPS / self.0)
149    }
150
151    /// Return the absolute value of this frequency.
152    pub fn abs(self) -> Self {
153        Self(self.0.abs())
154    }
155}
156
157impl_quantity_display!(Frequency, "Hz");
158
159impl_common_ops!(Frequency);
160
161/// Extend [`Time`] with frequency conversion.
162impl Time {
163    /// Compute the frequency (1/t) as a [`Frequency`].
164    pub fn frequency(self) -> Frequency {
165        Frequency(1.0 / self.0)
166    }
167}
168
169// -------------------------
170// Data rate
171// -------------------------
172
173/// A data rate quantity, stored internally in bits per second (bps).
174///
175/// # Construction
176/// ```
177/// # use space_units::DataRate;
178/// let rate = DataRate::from_mbps(100.0);
179/// ```
180#[must_use]
181#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
182pub struct DataRate(pub(crate) f64);
183
184/// Display/conversion units for [`DataRate`].
185#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186pub enum DataRateUnit {
187    /// Bits per second (bps).
188    BitsPerSecond,
189    /// Kilobits per second (kbps).
190    KiloBitsPerSecond,
191    /// Megabits per second (Mbps).
192    MegaBitsPerSecond,
193    /// Gigabits per second (Gbps).
194    GigaBitsPerSecond,
195    /// Bytes per second (B/s). 1 B/s = 8 bps.
196    BytesPerSecond,
197    /// Kilobytes per second (KB/s). 1 KB/s = 8e3 bps.
198    KiloBytesPerSecond,
199    /// Megabytes per second (MB/s). 1 MB/s = 8e6 bps.
200    MegaBytesPerSecond,
201    /// Gigabytes per second (GB/s). 1 GB/s = 8e9 bps.
202    GigaBytesPerSecond,
203}
204
205impl DataRateUnit {
206    const fn symbol(self) -> &'static str {
207        match self {
208            Self::BitsPerSecond => "bps",
209            Self::KiloBitsPerSecond => "kbps",
210            Self::MegaBitsPerSecond => "Mbps",
211            Self::GigaBitsPerSecond => "Gbps",
212            Self::BytesPerSecond => "B/s",
213            Self::KiloBytesPerSecond => "KB/s",
214            Self::MegaBytesPerSecond => "MB/s",
215            Self::GigaBytesPerSecond => "GB/s",
216        }
217    }
218
219    const fn bps_per_unit(self) -> f64 {
220        match self {
221            Self::BitsPerSecond => 1.0,
222            Self::KiloBitsPerSecond => 1e3,
223            Self::MegaBitsPerSecond => 1e6,
224            Self::GigaBitsPerSecond => 1e9,
225            Self::BytesPerSecond => 8.0,
226            Self::KiloBytesPerSecond => 8e3,
227            Self::MegaBytesPerSecond => 8e6,
228            Self::GigaBytesPerSecond => 8e9,
229        }
230    }
231}
232
233impl DataRate {
234    /// Create from bits per second (canonical unit).
235    pub const fn from_bps(val: f64) -> Self {
236        Self(val)
237    }
238
239    /// Create from kilobits per second. 1 kbps = 1e3 bps.
240    pub const fn from_kbps(val: f64) -> Self {
241        Self(val * 1e3)
242    }
243
244    /// Create from megabits per second. 1 Mbps = 1e6 bps.
245    pub const fn from_mbps(val: f64) -> Self {
246        Self(val * 1e6)
247    }
248
249    /// Create from gigabits per second. 1 Gbps = 1e9 bps.
250    pub const fn from_gbps(val: f64) -> Self {
251        Self(val * 1e9)
252    }
253
254    /// Create from bytes per second. 1 B/s = 8 bps.
255    pub const fn from_bytes_ps(val: f64) -> Self {
256        Self(val * 8.0)
257    }
258
259    /// Create from kilobytes per second. 1 KB/s = 8e3 bps.
260    pub const fn from_kbytes_ps(val: f64) -> Self {
261        Self(val * 8e3)
262    }
263
264    /// Create from megabytes per second. 1 MB/s = 8e6 bps.
265    pub const fn from_mbytes_ps(val: f64) -> Self {
266        Self(val * 8e6)
267    }
268
269    /// Create from gigabytes per second. 1 GB/s = 8e9 bps.
270    pub const fn from_gbytes_ps(val: f64) -> Self {
271        Self(val * 8e9)
272    }
273
274    /// Get value in bits per second.
275    pub const fn in_bps(self) -> f64 {
276        self.0
277    }
278
279    /// Get value in kilobits per second.
280    pub const fn in_kbps(self) -> f64 {
281        self.0 / 1e3
282    }
283
284    /// Get value in megabits per second.
285    pub const fn in_mbps(self) -> f64 {
286        self.0 / 1e6
287    }
288
289    /// Get value in gigabits per second.
290    pub const fn in_gbps(self) -> f64 {
291        self.0 / 1e9
292    }
293
294    /// Get value in bytes per second.
295    pub const fn in_bytes_ps(self) -> f64 {
296        self.0 / 8.0
297    }
298
299    /// Get value in kilobytes per second.
300    pub const fn in_kbytes_ps(self) -> f64 {
301        self.0 / 8e3
302    }
303
304    /// Get value in megabytes per second.
305    pub const fn in_mbytes_ps(self) -> f64 {
306        self.0 / 8e6
307    }
308
309    /// Get value in gigabytes per second.
310    pub const fn in_gbytes_ps(self) -> f64 {
311        self.0 / 8e9
312    }
313
314    /// Get value in the specified [`DataRateUnit`].
315    pub fn in_unit(self, unit: DataRateUnit) -> f64 {
316        self.0 / unit.bps_per_unit()
317    }
318
319    /// Return a display wrapper that formats this data rate in the given unit.
320    pub fn display_as(self, unit: DataRateUnit) -> DisplayWithUnit {
321        DisplayWithUnit {
322            value: self.in_unit(unit),
323            symbol: unit.symbol(),
324        }
325    }
326
327    /// Return the absolute value of this data rate.
328    pub fn abs(self) -> Self {
329        Self(self.0.abs())
330    }
331}
332
333impl_quantity_display!(DataRate, "bps");
334
335impl_common_ops!(DataRate);