elements_rs/isotopes/
magnesium.rs

1//! Isotopes of the element Magnesium
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 Magnesium
5pub enum MagnesiumIsotope {
6    /// Isotope Mg19 of Magnesium
7    Mg19,
8    /// Isotope Mg20 of Magnesium
9    Mg20,
10    /// Isotope Mg21 of Magnesium
11    Mg21,
12    /// Isotope Mg22 of Magnesium
13    Mg22,
14    /// Isotope Mg23 of Magnesium
15    Mg23,
16    /// Isotope Mg24 of Magnesium
17    Mg24,
18    /// Isotope Mg25 of Magnesium
19    Mg25,
20    /// Isotope Mg26 of Magnesium
21    Mg26,
22    /// Isotope Mg27 of Magnesium
23    Mg27,
24    /// Isotope Mg28 of Magnesium
25    Mg28,
26    /// Isotope Mg29 of Magnesium
27    Mg29,
28    /// Isotope Mg30 of Magnesium
29    Mg30,
30    /// Isotope Mg31 of Magnesium
31    Mg31,
32    /// Isotope Mg32 of Magnesium
33    Mg32,
34    /// Isotope Mg33 of Magnesium
35    Mg33,
36    /// Isotope Mg34 of Magnesium
37    Mg34,
38    /// Isotope Mg35 of Magnesium
39    Mg35,
40    /// Isotope Mg36 of Magnesium
41    Mg36,
42    /// Isotope Mg37 of Magnesium
43    Mg37,
44    /// Isotope Mg38 of Magnesium
45    Mg38,
46    /// Isotope Mg39 of Magnesium
47    Mg39,
48    /// Isotope Mg40 of Magnesium
49    Mg40,
50}
51impl super::RelativeAtomicMass for MagnesiumIsotope {
52    #[inline]
53    fn relative_atomic_mass(&self) -> f64 {
54        match self {
55            Self::Mg19 => 19.034169f64,
56            Self::Mg20 => 20.01885f64,
57            Self::Mg21 => 21.011716f64,
58            Self::Mg22 => 21.99957065f64,
59            Self::Mg23 => 22.99412421f64,
60            Self::Mg24 => 23.985041697f64,
61            Self::Mg25 => 24.985836976f64,
62            Self::Mg26 => 25.982592968f64,
63            Self::Mg27 => 26.984340624f64,
64            Self::Mg28 => 27.9838767f64,
65            Self::Mg29 => 28.988617f64,
66            Self::Mg30 => 29.9904629f64,
67            Self::Mg31 => 30.996648f64,
68            Self::Mg32 => 31.9991102f64,
69            Self::Mg33 => 33.0053271f64,
70            Self::Mg34 => 34.008935f64,
71            Self::Mg35 => 35.01679f64,
72            Self::Mg36 => 36.02188f64,
73            Self::Mg37 => 37.03037f64,
74            Self::Mg38 => 38.03658f64,
75            Self::Mg39 => 39.04538f64,
76            Self::Mg40 => 40.05218f64,
77        }
78    }
79}
80impl super::ElementVariant for MagnesiumIsotope {
81    #[inline]
82    fn element(&self) -> crate::Element {
83        crate::Element::Mg
84    }
85}
86impl super::MassNumber for MagnesiumIsotope {
87    #[inline]
88    fn mass_number(&self) -> u16 {
89        match self {
90            Self::Mg19 => 19u16,
91            Self::Mg20 => 20u16,
92            Self::Mg21 => 21u16,
93            Self::Mg22 => 22u16,
94            Self::Mg23 => 23u16,
95            Self::Mg24 => 24u16,
96            Self::Mg25 => 25u16,
97            Self::Mg26 => 26u16,
98            Self::Mg27 => 27u16,
99            Self::Mg28 => 28u16,
100            Self::Mg29 => 29u16,
101            Self::Mg30 => 30u16,
102            Self::Mg31 => 31u16,
103            Self::Mg32 => 32u16,
104            Self::Mg33 => 33u16,
105            Self::Mg34 => 34u16,
106            Self::Mg35 => 35u16,
107            Self::Mg36 => 36u16,
108            Self::Mg37 => 37u16,
109            Self::Mg38 => 38u16,
110            Self::Mg39 => 39u16,
111            Self::Mg40 => 40u16,
112        }
113    }
114}
115impl super::IsotopicComposition for MagnesiumIsotope {
116    #[inline]
117    fn isotopic_composition(&self) -> Option<f64> {
118        match self {
119            Self::Mg24 => Some(0.7899f64),
120            Self::Mg25 => Some(0.1f64),
121            Self::Mg26 => Some(0.1101f64),
122            _ => None,
123        }
124    }
125}
126impl super::MostAbundantIsotope for MagnesiumIsotope {
127    fn most_abundant_isotope() -> Self {
128        Self::Mg24
129    }
130}
131impl From<MagnesiumIsotope> for crate::Isotope {
132    fn from(isotope: MagnesiumIsotope) -> Self {
133        crate::Isotope::Mg(isotope)
134    }
135}
136impl From<MagnesiumIsotope> for crate::Element {
137    fn from(_isotope: MagnesiumIsotope) -> Self {
138        crate::Element::Mg
139    }
140}
141impl TryFrom<u64> for MagnesiumIsotope {
142    type Error = crate::errors::Error;
143    fn try_from(value: u64) -> Result<Self, Self::Error> {
144        match value {
145            19u64 => Ok(Self::Mg19),
146            20u64 => Ok(Self::Mg20),
147            21u64 => Ok(Self::Mg21),
148            22u64 => Ok(Self::Mg22),
149            23u64 => Ok(Self::Mg23),
150            24u64 => Ok(Self::Mg24),
151            25u64 => Ok(Self::Mg25),
152            26u64 => Ok(Self::Mg26),
153            27u64 => Ok(Self::Mg27),
154            28u64 => Ok(Self::Mg28),
155            29u64 => Ok(Self::Mg29),
156            30u64 => Ok(Self::Mg30),
157            31u64 => Ok(Self::Mg31),
158            32u64 => Ok(Self::Mg32),
159            33u64 => Ok(Self::Mg33),
160            34u64 => Ok(Self::Mg34),
161            35u64 => Ok(Self::Mg35),
162            36u64 => Ok(Self::Mg36),
163            37u64 => Ok(Self::Mg37),
164            38u64 => Ok(Self::Mg38),
165            39u64 => Ok(Self::Mg39),
166            40u64 => Ok(Self::Mg40),
167            _ => Err(crate::errors::Error::Isotope(crate::Element::Mg, value)),
168        }
169    }
170}
171impl TryFrom<u8> for MagnesiumIsotope {
172    type Error = crate::errors::Error;
173    fn try_from(value: u8) -> Result<Self, Self::Error> {
174        Self::try_from(u64::from(value))
175    }
176}
177impl TryFrom<u16> for MagnesiumIsotope {
178    type Error = crate::errors::Error;
179    fn try_from(value: u16) -> Result<Self, Self::Error> {
180        Self::try_from(u64::from(value))
181    }
182}
183impl TryFrom<u32> for MagnesiumIsotope {
184    type Error = crate::errors::Error;
185    fn try_from(value: u32) -> Result<Self, Self::Error> {
186        Self::try_from(u64::from(value))
187    }
188}
189impl core::fmt::Display for MagnesiumIsotope {
190    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
191        match self {
192            Self::Mg19 => write!(f, "Mg19"),
193            Self::Mg20 => write!(f, "Mg20"),
194            Self::Mg21 => write!(f, "Mg21"),
195            Self::Mg22 => write!(f, "Mg22"),
196            Self::Mg23 => write!(f, "Mg23"),
197            Self::Mg24 => write!(f, "Mg24"),
198            Self::Mg25 => write!(f, "Mg25"),
199            Self::Mg26 => write!(f, "Mg26"),
200            Self::Mg27 => write!(f, "Mg27"),
201            Self::Mg28 => write!(f, "Mg28"),
202            Self::Mg29 => write!(f, "Mg29"),
203            Self::Mg30 => write!(f, "Mg30"),
204            Self::Mg31 => write!(f, "Mg31"),
205            Self::Mg32 => write!(f, "Mg32"),
206            Self::Mg33 => write!(f, "Mg33"),
207            Self::Mg34 => write!(f, "Mg34"),
208            Self::Mg35 => write!(f, "Mg35"),
209            Self::Mg36 => write!(f, "Mg36"),
210            Self::Mg37 => write!(f, "Mg37"),
211            Self::Mg38 => write!(f, "Mg38"),
212            Self::Mg39 => write!(f, "Mg39"),
213            Self::Mg40 => write!(f, "Mg40"),
214        }
215    }
216}
217#[cfg(test)]
218mod tests {
219    use strum::IntoEnumIterator;
220
221    use super::*;
222    use crate::isotopes::{
223        ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
224    };
225    #[test]
226    fn test_relative_atomic_mass() {
227        for isotope in MagnesiumIsotope::iter() {
228            let mass = isotope.relative_atomic_mass();
229            assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
230        }
231    }
232    #[test]
233    fn test_element() {
234        for isotope in MagnesiumIsotope::iter() {
235            let element = isotope.element();
236            assert_eq!(element, crate::Element::Mg, "Element should be correct for {isotope:?}");
237        }
238    }
239    #[test]
240    fn test_mass_number() {
241        for isotope in MagnesiumIsotope::iter() {
242            let mass_number = isotope.mass_number();
243            assert!(
244                mass_number > 0 && mass_number < 300,
245                "Mass number should be reasonable for {isotope:?}"
246            );
247        }
248    }
249    #[test]
250    fn test_isotopic_composition() {
251        for isotope in MagnesiumIsotope::iter() {
252            let comp = isotope.isotopic_composition();
253            if let Some(c) = comp {
254                assert!(
255                    (0.0..=1.0).contains(&c),
256                    "Composition should be between 0 and 1 for {isotope:?}"
257                );
258            }
259        }
260    }
261    #[test]
262    fn test_most_abundant() {
263        let most_abundant = MagnesiumIsotope::most_abundant_isotope();
264        let _ = most_abundant.relative_atomic_mass();
265    }
266    #[test]
267    fn test_from_isotope() {
268        for isotope in MagnesiumIsotope::iter() {
269            let iso: crate::Isotope = isotope.into();
270            match iso {
271                crate::Isotope::Mg(i) => assert_eq!(i, isotope),
272                _ => panic!("Wrong isotope type"),
273            }
274        }
275    }
276    #[test]
277    fn test_from_element() {
278        for isotope in MagnesiumIsotope::iter() {
279            let elem: crate::Element = isotope.into();
280            assert_eq!(elem, crate::Element::Mg);
281        }
282    }
283    #[test]
284    fn test_try_from_mass_number() {
285        for isotope in MagnesiumIsotope::iter() {
286            let mass = isotope.mass_number();
287            let iso = MagnesiumIsotope::try_from(mass).unwrap();
288            assert_eq!(iso, isotope);
289            let iso_u32 = MagnesiumIsotope::try_from(u32::from(mass)).unwrap();
290            assert_eq!(iso_u32, isotope);
291            if let Ok(mass_u8) = u8::try_from(mass) {
292                let iso_u8 = MagnesiumIsotope::try_from(mass_u8).unwrap();
293                assert_eq!(iso_u8, isotope);
294            }
295        }
296        assert!(MagnesiumIsotope::try_from(0_u16).is_err());
297        assert!(MagnesiumIsotope::try_from(1000_u16).is_err());
298        assert!(MagnesiumIsotope::try_from(0_u32).is_err());
299        assert!(MagnesiumIsotope::try_from(1000_u32).is_err());
300        assert!(MagnesiumIsotope::try_from(0_u8).is_err());
301    }
302    #[test]
303    fn test_display() {
304        for isotope in MagnesiumIsotope::iter() {
305            let s = alloc::format!("{isotope}");
306            assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
307        }
308    }
309}