elements_rs/isotopes/
potassium.rs

1//! Isotopes of the element Potassium
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4/// Isotopes of the element Potassium
5pub enum PotassiumIsotope {
6    /// Isotope K32 of Potassium
7    K32,
8    /// Isotope K33 of Potassium
9    K33,
10    /// Isotope K34 of Potassium
11    K34,
12    /// Isotope K35 of Potassium
13    K35,
14    /// Isotope K36 of Potassium
15    K36,
16    /// Isotope K37 of Potassium
17    K37,
18    /// Isotope K38 of Potassium
19    K38,
20    /// Isotope K39 of Potassium
21    K39,
22    /// Isotope K40 of Potassium
23    K40,
24    /// Isotope K41 of Potassium
25    K41,
26    /// Isotope K42 of Potassium
27    K42,
28    /// Isotope K43 of Potassium
29    K43,
30    /// Isotope K44 of Potassium
31    K44,
32    /// Isotope K45 of Potassium
33    K45,
34    /// Isotope K46 of Potassium
35    K46,
36    /// Isotope K47 of Potassium
37    K47,
38    /// Isotope K48 of Potassium
39    K48,
40    /// Isotope K49 of Potassium
41    K49,
42    /// Isotope K50 of Potassium
43    K50,
44    /// Isotope K51 of Potassium
45    K51,
46    /// Isotope K52 of Potassium
47    K52,
48    /// Isotope K53 of Potassium
49    K53,
50    /// Isotope K54 of Potassium
51    K54,
52    /// Isotope K55 of Potassium
53    K55,
54    /// Isotope K56 of Potassium
55    K56,
56}
57impl super::RelativeAtomicMass for PotassiumIsotope {
58    #[inline]
59    fn relative_atomic_mass(&self) -> f64 {
60        match self {
61            Self::K32 => 32.02265f64,
62            Self::K33 => 33.00756f64,
63            Self::K34 => 33.99869f64,
64            Self::K35 => 34.98800541f64,
65            Self::K36 => 35.98130201f64,
66            Self::K37 => 36.97337589f64,
67            Self::K38 => 37.96908112f64,
68            Self::K39 => 38.9637064864f64,
69            Self::K40 => 39.963998166f64,
70            Self::K41 => 40.9618252579f64,
71            Self::K42 => 41.96240231f64,
72            Self::K43 => 42.9607347f64,
73            Self::K44 => 43.96158699f64,
74            Self::K45 => 44.96069149f64,
75            Self::K46 => 45.96198159f64,
76            Self::K47 => 46.9616616f64,
77            Self::K48 => 47.96534119f64,
78            Self::K49 => 48.96821075f64,
79            Self::K50 => 49.97238f64,
80            Self::K51 => 50.975828f64,
81            Self::K52 => 51.98224f64,
82            Self::K53 => 52.98746f64,
83            Self::K54 => 53.99463f64,
84            Self::K55 => 55.00076f64,
85            Self::K56 => 56.00851f64,
86        }
87    }
88}
89impl super::ElementVariant for PotassiumIsotope {
90    #[inline]
91    fn element(&self) -> crate::Element {
92        crate::Element::K
93    }
94}
95impl super::MassNumber for PotassiumIsotope {
96    #[inline]
97    fn mass_number(&self) -> u16 {
98        match self {
99            Self::K32 => 32u16,
100            Self::K33 => 33u16,
101            Self::K34 => 34u16,
102            Self::K35 => 35u16,
103            Self::K36 => 36u16,
104            Self::K37 => 37u16,
105            Self::K38 => 38u16,
106            Self::K39 => 39u16,
107            Self::K40 => 40u16,
108            Self::K41 => 41u16,
109            Self::K42 => 42u16,
110            Self::K43 => 43u16,
111            Self::K44 => 44u16,
112            Self::K45 => 45u16,
113            Self::K46 => 46u16,
114            Self::K47 => 47u16,
115            Self::K48 => 48u16,
116            Self::K49 => 49u16,
117            Self::K50 => 50u16,
118            Self::K51 => 51u16,
119            Self::K52 => 52u16,
120            Self::K53 => 53u16,
121            Self::K54 => 54u16,
122            Self::K55 => 55u16,
123            Self::K56 => 56u16,
124        }
125    }
126}
127impl super::IsotopicComposition for PotassiumIsotope {
128    #[inline]
129    fn isotopic_composition(&self) -> Option<f64> {
130        match self {
131            Self::K39 => Some(0.932581f64),
132            Self::K40 => Some(0.000117f64),
133            Self::K41 => Some(0.067302f64),
134            _ => None,
135        }
136    }
137}
138impl super::MostAbundantIsotope for PotassiumIsotope {
139    fn most_abundant_isotope() -> Self {
140        Self::K39
141    }
142}
143impl From<PotassiumIsotope> for crate::Isotope {
144    fn from(isotope: PotassiumIsotope) -> Self {
145        crate::Isotope::K(isotope)
146    }
147}
148impl From<PotassiumIsotope> for crate::Element {
149    fn from(_isotope: PotassiumIsotope) -> Self {
150        crate::Element::K
151    }
152}
153impl TryFrom<u64> for PotassiumIsotope {
154    type Error = crate::errors::Error;
155    fn try_from(value: u64) -> Result<Self, Self::Error> {
156        match value {
157            32u64 => Ok(Self::K32),
158            33u64 => Ok(Self::K33),
159            34u64 => Ok(Self::K34),
160            35u64 => Ok(Self::K35),
161            36u64 => Ok(Self::K36),
162            37u64 => Ok(Self::K37),
163            38u64 => Ok(Self::K38),
164            39u64 => Ok(Self::K39),
165            40u64 => Ok(Self::K40),
166            41u64 => Ok(Self::K41),
167            42u64 => Ok(Self::K42),
168            43u64 => Ok(Self::K43),
169            44u64 => Ok(Self::K44),
170            45u64 => Ok(Self::K45),
171            46u64 => Ok(Self::K46),
172            47u64 => Ok(Self::K47),
173            48u64 => Ok(Self::K48),
174            49u64 => Ok(Self::K49),
175            50u64 => Ok(Self::K50),
176            51u64 => Ok(Self::K51),
177            52u64 => Ok(Self::K52),
178            53u64 => Ok(Self::K53),
179            54u64 => Ok(Self::K54),
180            55u64 => Ok(Self::K55),
181            56u64 => Ok(Self::K56),
182            _ => Err(crate::errors::Error::Isotope(crate::Element::K, value)),
183        }
184    }
185}
186impl TryFrom<u8> for PotassiumIsotope {
187    type Error = crate::errors::Error;
188    fn try_from(value: u8) -> Result<Self, Self::Error> {
189        Self::try_from(u64::from(value))
190    }
191}
192impl TryFrom<u16> for PotassiumIsotope {
193    type Error = crate::errors::Error;
194    fn try_from(value: u16) -> Result<Self, Self::Error> {
195        Self::try_from(u64::from(value))
196    }
197}
198impl TryFrom<u32> for PotassiumIsotope {
199    type Error = crate::errors::Error;
200    fn try_from(value: u32) -> Result<Self, Self::Error> {
201        Self::try_from(u64::from(value))
202    }
203}
204impl core::fmt::Display for PotassiumIsotope {
205    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
206        match self {
207            Self::K32 => write!(f, "K32"),
208            Self::K33 => write!(f, "K33"),
209            Self::K34 => write!(f, "K34"),
210            Self::K35 => write!(f, "K35"),
211            Self::K36 => write!(f, "K36"),
212            Self::K37 => write!(f, "K37"),
213            Self::K38 => write!(f, "K38"),
214            Self::K39 => write!(f, "K39"),
215            Self::K40 => write!(f, "K40"),
216            Self::K41 => write!(f, "K41"),
217            Self::K42 => write!(f, "K42"),
218            Self::K43 => write!(f, "K43"),
219            Self::K44 => write!(f, "K44"),
220            Self::K45 => write!(f, "K45"),
221            Self::K46 => write!(f, "K46"),
222            Self::K47 => write!(f, "K47"),
223            Self::K48 => write!(f, "K48"),
224            Self::K49 => write!(f, "K49"),
225            Self::K50 => write!(f, "K50"),
226            Self::K51 => write!(f, "K51"),
227            Self::K52 => write!(f, "K52"),
228            Self::K53 => write!(f, "K53"),
229            Self::K54 => write!(f, "K54"),
230            Self::K55 => write!(f, "K55"),
231            Self::K56 => write!(f, "K56"),
232        }
233    }
234}
235#[cfg(test)]
236mod tests {
237    use strum::IntoEnumIterator;
238
239    use super::*;
240    use crate::isotopes::{
241        ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
242    };
243    #[test]
244    fn test_relative_atomic_mass() {
245        for isotope in PotassiumIsotope::iter() {
246            let mass = isotope.relative_atomic_mass();
247            assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
248        }
249    }
250    #[test]
251    fn test_element() {
252        for isotope in PotassiumIsotope::iter() {
253            let element = isotope.element();
254            assert_eq!(element, crate::Element::K, "Element should be correct for {isotope:?}");
255        }
256    }
257    #[test]
258    fn test_mass_number() {
259        for isotope in PotassiumIsotope::iter() {
260            let mass_number = isotope.mass_number();
261            assert!(
262                mass_number > 0 && mass_number < 300,
263                "Mass number should be reasonable for {isotope:?}"
264            );
265        }
266    }
267    #[test]
268    fn test_isotopic_composition() {
269        for isotope in PotassiumIsotope::iter() {
270            let comp = isotope.isotopic_composition();
271            if let Some(c) = comp {
272                assert!(
273                    (0.0..=1.0).contains(&c),
274                    "Composition should be between 0 and 1 for {isotope:?}"
275                );
276            }
277        }
278    }
279    #[test]
280    fn test_most_abundant() {
281        let most_abundant = PotassiumIsotope::most_abundant_isotope();
282        let _ = most_abundant.relative_atomic_mass();
283    }
284    #[test]
285    fn test_from_isotope() {
286        for isotope in PotassiumIsotope::iter() {
287            let iso: crate::Isotope = isotope.into();
288            match iso {
289                crate::Isotope::K(i) => assert_eq!(i, isotope),
290                _ => panic!("Wrong isotope type"),
291            }
292        }
293    }
294    #[test]
295    fn test_from_element() {
296        for isotope in PotassiumIsotope::iter() {
297            let elem: crate::Element = isotope.into();
298            assert_eq!(elem, crate::Element::K);
299        }
300    }
301    #[test]
302    fn test_try_from_mass_number() {
303        for isotope in PotassiumIsotope::iter() {
304            let mass = isotope.mass_number();
305            let iso = PotassiumIsotope::try_from(mass).unwrap();
306            assert_eq!(iso, isotope);
307            let iso_u32 = PotassiumIsotope::try_from(u32::from(mass)).unwrap();
308            assert_eq!(iso_u32, isotope);
309            if let Ok(mass_u8) = u8::try_from(mass) {
310                let iso_u8 = PotassiumIsotope::try_from(mass_u8).unwrap();
311                assert_eq!(iso_u8, isotope);
312            }
313        }
314        assert!(PotassiumIsotope::try_from(0_u16).is_err());
315        assert!(PotassiumIsotope::try_from(1000_u16).is_err());
316        assert!(PotassiumIsotope::try_from(0_u32).is_err());
317        assert!(PotassiumIsotope::try_from(1000_u32).is_err());
318        assert!(PotassiumIsotope::try_from(0_u8).is_err());
319    }
320    #[test]
321    fn test_display() {
322        for isotope in PotassiumIsotope::iter() {
323            let s = alloc::format!("{isotope}");
324            assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
325        }
326    }
327}