1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum PotassiumIsotope {
6 K32,
8 K33,
10 K34,
12 K35,
14 K36,
16 K37,
18 K38,
20 K39,
22 K40,
24 K41,
26 K42,
28 K43,
30 K44,
32 K45,
34 K46,
36 K47,
38 K48,
40 K49,
42 K50,
44 K51,
46 K52,
48 K53,
50 K54,
52 K55,
54 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}