Skip to main content

elements_rs/isotopes/
tennessine.rs

1//! Isotopes of the element Tennessine
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
5/// Isotopes of the element Tennessine
6pub enum TennessineIsotope {
7    /// Isotope Ts291 of Tennessine
8    Ts291,
9    /// Isotope Ts292 of Tennessine
10    Ts292,
11    /// Isotope Ts293 of Tennessine
12    Ts293,
13    /// Isotope Ts294 of Tennessine
14    Ts294,
15}
16impl super::RelativeAtomicMass for TennessineIsotope {
17    #[inline]
18    fn relative_atomic_mass(&self) -> f64 {
19        match self {
20            Self::Ts291 => 291.20553f64,
21            Self::Ts292 => 292.20746f64,
22            Self::Ts293 => 293.20824f64,
23            Self::Ts294 => 294.21046f64,
24        }
25    }
26}
27impl super::ElementVariant for TennessineIsotope {
28    #[inline]
29    fn element(&self) -> crate::Element {
30        crate::Element::Ts
31    }
32}
33impl super::MassNumber for TennessineIsotope {
34    #[inline]
35    fn mass_number(&self) -> u16 {
36        match self {
37            Self::Ts291 => 291u16,
38            Self::Ts292 => 292u16,
39            Self::Ts293 => 293u16,
40            Self::Ts294 => 294u16,
41        }
42    }
43}
44impl super::IsotopicComposition for TennessineIsotope {
45    #[inline]
46    fn isotopic_composition(&self) -> Option<f64> {
47        None
48    }
49}
50impl super::MostAbundantIsotope for TennessineIsotope {
51    fn most_abundant_isotope() -> Self {
52        Self::Ts294
53    }
54}
55impl From<TennessineIsotope> for crate::Isotope {
56    fn from(isotope: TennessineIsotope) -> Self {
57        crate::Isotope::Ts(isotope)
58    }
59}
60impl From<TennessineIsotope> for crate::Element {
61    fn from(_isotope: TennessineIsotope) -> Self {
62        crate::Element::Ts
63    }
64}
65impl TryFrom<u64> for TennessineIsotope {
66    type Error = crate::errors::Error;
67    fn try_from(value: u64) -> Result<Self, Self::Error> {
68        match value {
69            291u64 => Ok(Self::Ts291),
70            292u64 => Ok(Self::Ts292),
71            293u64 => Ok(Self::Ts293),
72            294u64 => Ok(Self::Ts294),
73            _ => Err(crate::errors::Error::Isotope(crate::Element::Ts, value)),
74        }
75    }
76}
77impl TryFrom<u8> for TennessineIsotope {
78    type Error = crate::errors::Error;
79    fn try_from(value: u8) -> Result<Self, Self::Error> {
80        Self::try_from(u64::from(value))
81    }
82}
83impl TryFrom<u16> for TennessineIsotope {
84    type Error = crate::errors::Error;
85    fn try_from(value: u16) -> Result<Self, Self::Error> {
86        Self::try_from(u64::from(value))
87    }
88}
89impl TryFrom<u32> for TennessineIsotope {
90    type Error = crate::errors::Error;
91    fn try_from(value: u32) -> Result<Self, Self::Error> {
92        Self::try_from(u64::from(value))
93    }
94}
95impl core::fmt::Display for TennessineIsotope {
96    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
97        match self {
98            Self::Ts291 => write!(f, "Ts291"),
99            Self::Ts292 => write!(f, "Ts292"),
100            Self::Ts293 => write!(f, "Ts293"),
101            Self::Ts294 => write!(f, "Ts294"),
102        }
103    }
104}
105#[cfg(test)]
106mod tests {
107    use strum::IntoEnumIterator;
108
109    use super::*;
110    use crate::isotopes::{
111        ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
112    };
113    #[test]
114    fn test_relative_atomic_mass() {
115        for isotope in TennessineIsotope::iter() {
116            let mass = isotope.relative_atomic_mass();
117            assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
118        }
119    }
120    #[test]
121    fn test_element() {
122        for isotope in TennessineIsotope::iter() {
123            let element = isotope.element();
124            assert_eq!(element, crate::Element::Ts, "Element should be correct for {isotope:?}");
125        }
126    }
127    #[test]
128    fn test_mass_number() {
129        for isotope in TennessineIsotope::iter() {
130            let mass_number = isotope.mass_number();
131            assert!(
132                mass_number > 0 && mass_number < 300,
133                "Mass number should be reasonable for {isotope:?}"
134            );
135        }
136    }
137    #[test]
138    fn test_isotopic_composition() {
139        for isotope in TennessineIsotope::iter() {
140            let comp = isotope.isotopic_composition();
141            if let Some(c) = comp {
142                assert!(
143                    (0.0..=1.0).contains(&c),
144                    "Composition should be between 0 and 1 for {isotope:?}"
145                );
146            }
147        }
148    }
149    #[test]
150    fn test_most_abundant() {
151        let most_abundant = TennessineIsotope::most_abundant_isotope();
152        let _ = most_abundant.relative_atomic_mass();
153    }
154    #[test]
155    fn test_from_isotope() {
156        for isotope in TennessineIsotope::iter() {
157            let iso: crate::Isotope = isotope.into();
158            match iso {
159                crate::Isotope::Ts(i) => assert_eq!(i, isotope),
160                _ => panic!("Wrong isotope type"),
161            }
162        }
163    }
164    #[test]
165    fn test_from_element() {
166        for isotope in TennessineIsotope::iter() {
167            let elem: crate::Element = isotope.into();
168            assert_eq!(elem, crate::Element::Ts);
169        }
170    }
171    #[test]
172    fn test_try_from_mass_number() {
173        for isotope in TennessineIsotope::iter() {
174            let mass = isotope.mass_number();
175            let iso = TennessineIsotope::try_from(mass).unwrap();
176            assert_eq!(iso, isotope);
177            let iso_u32 = TennessineIsotope::try_from(u32::from(mass)).unwrap();
178            assert_eq!(iso_u32, isotope);
179            if let Ok(mass_u8) = u8::try_from(mass) {
180                let iso_u8 = TennessineIsotope::try_from(mass_u8).unwrap();
181                assert_eq!(iso_u8, isotope);
182            }
183        }
184        assert!(TennessineIsotope::try_from(0_u16).is_err());
185        assert!(TennessineIsotope::try_from(1000_u16).is_err());
186        assert!(TennessineIsotope::try_from(0_u32).is_err());
187        assert!(TennessineIsotope::try_from(1000_u32).is_err());
188        assert!(TennessineIsotope::try_from(0_u8).is_err());
189    }
190    #[test]
191    fn test_display() {
192        for isotope in TennessineIsotope::iter() {
193            let s = alloc::format!("{isotope}");
194            assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
195        }
196    }
197}