lib_rapid/math/
unit_conversion.rs

1//! Traits and functions for converting between units.
2use super::constants;
3/// SI-Prefixes as used in several fields.
4#[derive(PartialEq, Clone, Copy)]
5pub enum SIPrefix<T> {
6    /// x · 10⁻²⁴.
7    Yocto(T),
8    /// x · 10⁻²¹.
9    Zepto(T),
10    /// x · 10⁻¹⁸.
11    Atto(T),
12    /// x · 10⁻¹⁵.
13    Femto(T),
14    /// x · 10⁻¹².
15    Pico(T),
16    /// x · 10⁻⁹.
17    Nano(T),
18    /// x · 10⁻⁶.
19    Micro(T),
20    /// x · 10⁻³.
21    Milli(T),
22    /// x · 10⁻².
23    Centi(T),
24    /// x · 10⁻¹.
25    Deci(T),
26    /// x · 10⁰.
27    Unity(T),
28    /// x · 10¹.
29    Deca(T),
30    /// x · 10².
31    Hecto(T),
32    /// x · 10³.
33    Kilo(T),
34    /// x · 10⁶.
35    Mega(T),
36    /// x · 10⁹.
37    Giga(T),
38    /// x · 10¹².
39    Tera(T),
40    /// x · 10¹⁵.
41    Peta(T),
42    /// x · 10¹⁸.
43    Exa(T),
44    /// x · 10²¹.
45    Zetta(T),
46    /// x · 10²⁴.
47    Yotta(T)
48}
49/// The conversion algorithm to be chosen. Used by `temp_conversion`.
50pub enum TempConversion {
51    CelsiusToFahrenheit,
52    FahrenheitToCelsius,
53
54    FahrenheitToKelvin,
55    KelvinToFahrenheit,
56
57    CelsiusToKelvin,
58    KelvinToCelsius,
59}
60/// The conversion algorithm to be chosen. Used by `angle_conversion`.
61pub enum AngleConversion {
62    DegreesToRadians,
63    RadiansToDegrees,
64}
65/// Trait for angle conversion.
66pub trait AngleConversionTrait {
67    /// Performs a angle conversion.
68    /// # Arguments
69    /// * `&self` - The value to be converted.
70    /// * `mode` - The mode ( e.g. RadiansToDegrees ).
71    /// # Returns
72    /// A `Self` containing the result.
73    #[must_use = "This returns the result of the operation, without modifying the original."]
74    fn angle_conversion(&self, mode: AngleConversion) -> Self;
75}
76
77/// Trait for temperature conversion.
78pub trait TempConversionTrait {
79    /// Performs a temperature conversion.
80    /// # Arguments
81    /// * `&self` - The value to be converted.
82    /// * `mode` - The mode ( e.g. CelsiusToFahrenheit ).
83    /// # Returns
84    /// A `Self` containing the result.
85    #[must_use = "This returns the result of the operation, without modifying the original."]
86    fn temp_conversion(&self, mode: TempConversion) -> Self;
87}
88
89impl TempConversionTrait for f64 {
90    fn temp_conversion(&self, mode: TempConversion) -> Self {
91        match mode {
92            TempConversion::CelsiusToFahrenheit => {  self * 1.8 + 32.0 }
93            TempConversion::CelsiusToKelvin     => {  self + 273.15 }
94            TempConversion::FahrenheitToCelsius => { (self - 32.0) / 1.8 }
95            TempConversion::FahrenheitToKelvin  => { (self - 32.0) / 1.8 + 273.15 }
96            TempConversion::KelvinToCelsius     => {  self - 273.15 }
97            TempConversion::KelvinToFahrenheit  => { (self - 273.15) * 1.8 + 32.0 }
98        }
99    }
100}
101
102impl TempConversionTrait for f32 {
103    fn temp_conversion(&self, mode: TempConversion) -> Self {
104        match mode {
105            TempConversion::CelsiusToFahrenheit => {  self * 1.8 + 32.0 }
106            TempConversion::CelsiusToKelvin     => {  self + 273.15 }
107            TempConversion::FahrenheitToCelsius => { (self - 32.0) / 1.8 }
108            TempConversion::FahrenheitToKelvin  => { (self - 32.0) / 1.8 + 273.15 }
109            TempConversion::KelvinToCelsius     => {  self - 273.15 }
110            TempConversion::KelvinToFahrenheit  => { (self - 273.15) * 1.8 + 32.0 }
111        }
112    }
113}
114
115impl AngleConversionTrait for f64 {
116    fn angle_conversion(&self, mode: AngleConversion) -> Self {
117        match mode {
118            AngleConversion::RadiansToDegrees => { self * constants::RADDEGRATE }
119            AngleConversion::DegreesToRadians => { self * constants::DEGRADRATE }
120        }
121    }
122}
123
124impl AngleConversionTrait for f32 {
125    fn angle_conversion(&self, mode: AngleConversion) -> Self {
126        match mode {
127            AngleConversion::RadiansToDegrees => { self * constants::RADDEGRATE as f32 }
128            AngleConversion::DegreesToRadians => { self * constants::DEGRADRATE as f32 }
129        }
130    }
131}
132
133impl<T: Into<f64> + Copy> SIPrefix<T> {
134    /// Converts a SI-Prefix value into a regular `f32`.
135    /// # Returns
136    /// A `f32`.
137    /// # Examples
138    /// ```
139    /// use lib_rapid::math::unit_conversion::SIPrefix;
140    /// assert_eq!(0.000_000_000_000_000_000_000_005, SIPrefix::Yocto(5.0).to_decimal_f32());
141    /// assert_eq!(0.5, SIPrefix::Deci(5.0).to_decimal_f32());
142    /// assert_eq!(5000.0, SIPrefix::Kilo(5.0).to_decimal_f32());
143    /// ```
144    #[must_use = "This returns the result of the operation, without modifying the original."]
145    pub fn to_decimal_f32(&self) -> f32 {
146        self.to_decimal_f64() as f32
147    }
148}
149
150impl<T: Into<f64> + Copy> SIPrefix<T> {
151    /// Converts a SI-Prefix value into a regular `f64`.
152    /// # Returns
153    /// A `f64`.
154    /// # Examples
155    /// ```
156    /// use lib_rapid::math::unit_conversion::SIPrefix;
157    /// assert_eq!(0.000_000_000_000_000_000_000_005, SIPrefix::Yocto(5.0).to_decimal_f64());
158    /// assert_eq!(0.5, SIPrefix::Deci(5.0).to_decimal_f64());
159    /// assert_eq!(5000.0, SIPrefix::Kilo(5.0).to_decimal_f64());
160    /// ```
161    pub fn to_decimal_f64(&self) -> f64 {
162        match self {
163            SIPrefix::Yocto(x) => { (*x).into() * SIRATES[0]  },
164            SIPrefix::Zepto(x) => { (*x).into() * SIRATES[1]  },
165            SIPrefix::Atto(x)  => { (*x).into() * SIRATES[2]  },
166            SIPrefix::Femto(x) => { (*x).into() * SIRATES[3]  },
167            SIPrefix::Pico(x)  => { (*x).into() * SIRATES[4]  },
168            SIPrefix::Nano(x)  => { (*x).into() * SIRATES[5]  },
169            SIPrefix::Micro(x) => { (*x).into() * SIRATES[6]  },
170            SIPrefix::Milli(x) => { (*x).into() * SIRATES[7]  },
171            SIPrefix::Centi(x) => { (*x).into() * SIRATES[8]  },
172            SIPrefix::Deci(x)  => { (*x).into() * SIRATES[9]  },
173            SIPrefix::Unity(x) => { (*x).into()               },
174            SIPrefix::Deca(x)  => { (*x).into() * SIRATES[10] },
175            SIPrefix::Hecto(x) => { (*x).into() * SIRATES[11] },
176            SIPrefix::Kilo(x)  => { (*x).into() * SIRATES[12] },
177            SIPrefix::Mega(x)  => { (*x).into() * SIRATES[13] },
178            SIPrefix::Giga(x)  => { (*x).into() * SIRATES[14] },
179            SIPrefix::Tera(x)  => { (*x).into() * SIRATES[15] },
180            SIPrefix::Peta(x)  => { (*x).into() * SIRATES[16] },
181            SIPrefix::Exa(x)   => { (*x).into() * SIRATES[17] },
182            SIPrefix::Zetta(x) => { (*x).into() * SIRATES[18] },
183            SIPrefix::Yotta(x) => { (*x).into() * SIRATES[19] },
184        }
185    }
186}
187
188impl<T: Into<f64> + Copy> Into<f64> for SIPrefix<T> {
189    fn into(self) -> f64 {
190        self.to_decimal_f64()
191    }
192}
193
194impl<T: Into<f64> + Copy> Into<f32> for SIPrefix<T> {
195    fn into(self) -> f32 {
196        self.to_decimal_f32()
197    }
198}
199/// The different rates for converting from a SI prefix to a normalised value.
200pub(crate) const SIRATES: [f64; 20] = [1e-24,
201                                       1e-21,
202                                       1e-18,
203                                       1e-15,
204                                       1e-12,
205                                       1e-9,
206                                       1e-6,
207                                       1e-3,
208                                       0.01,
209                                       0.1,
210                                       10.0,
211                                       1e2,
212                                       1e3,
213                                       1e6,
214                                       1e9,
215                                       1e12,
216                                       1e15,
217                                       1e18,
218                                       1e21,
219                                       1e24];