1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum PromethiumIsotope {
6 Pm126,
8 Pm127,
10 Pm128,
12 Pm129,
14 Pm130,
16 Pm131,
18 Pm132,
20 Pm133,
22 Pm134,
24 Pm135,
26 Pm136,
28 Pm137,
30 Pm138,
32 Pm139,
34 Pm140,
36 Pm141,
38 Pm142,
40 Pm143,
42 Pm144,
44 Pm145,
46 Pm146,
48 Pm147,
50 Pm148,
52 Pm149,
54 Pm150,
56 Pm151,
58 Pm152,
60 Pm153,
62 Pm154,
64 Pm155,
66 Pm156,
68 Pm157,
70 Pm158,
72 Pm159,
74 Pm160,
76 Pm161,
78 Pm162,
80 Pm163,
82}
83impl super::RelativeAtomicMass for PromethiumIsotope {
84 #[inline]
85 fn relative_atomic_mass(&self) -> f64 {
86 match self {
87 Self::Pm126 => 125.95792f64,
88 Self::Pm127 => 126.95192f64,
89 Self::Pm128 => 127.9487f64,
90 Self::Pm129 => 128.94323f64,
91 Self::Pm130 => 129.94053f64,
92 Self::Pm131 => 130.93567f64,
93 Self::Pm132 => 131.93384f64,
94 Self::Pm133 => 132.929782f64,
95 Self::Pm134 => 133.928353f64,
96 Self::Pm135 => 134.924823f64,
97 Self::Pm136 => 135.923585f64,
98 Self::Pm137 => 136.92048f64,
99 Self::Pm138 => 137.919548f64,
100 Self::Pm139 => 138.9168f64,
101 Self::Pm140 => 139.91604f64,
102 Self::Pm141 => 140.913555f64,
103 Self::Pm142 => 141.91289f64,
104 Self::Pm143 => 142.9109383f64,
105 Self::Pm144 => 143.9125964f64,
106 Self::Pm145 => 144.9127559f64,
107 Self::Pm146 => 145.9147024f64,
108 Self::Pm147 => 146.915145f64,
109 Self::Pm148 => 147.9174819f64,
110 Self::Pm149 => 148.9183423f64,
111 Self::Pm150 => 149.920991f64,
112 Self::Pm151 => 150.9212175f64,
113 Self::Pm152 => 151.923506f64,
114 Self::Pm153 => 152.9241567f64,
115 Self::Pm154 => 153.926472f64,
116 Self::Pm155 => 154.928137f64,
117 Self::Pm156 => 155.9311175f64,
118 Self::Pm157 => 156.9331214f64,
119 Self::Pm158 => 157.936565f64,
120 Self::Pm159 => 158.939287f64,
121 Self::Pm160 => 159.9431f64,
122 Self::Pm161 => 160.94607f64,
123 Self::Pm162 => 161.95022f64,
124 Self::Pm163 => 162.95357f64,
125 }
126 }
127}
128impl super::ElementVariant for PromethiumIsotope {
129 #[inline]
130 fn element(&self) -> crate::Element {
131 crate::Element::Pm
132 }
133}
134impl super::MassNumber for PromethiumIsotope {
135 #[inline]
136 fn mass_number(&self) -> u16 {
137 match self {
138 Self::Pm126 => 126u16,
139 Self::Pm127 => 127u16,
140 Self::Pm128 => 128u16,
141 Self::Pm129 => 129u16,
142 Self::Pm130 => 130u16,
143 Self::Pm131 => 131u16,
144 Self::Pm132 => 132u16,
145 Self::Pm133 => 133u16,
146 Self::Pm134 => 134u16,
147 Self::Pm135 => 135u16,
148 Self::Pm136 => 136u16,
149 Self::Pm137 => 137u16,
150 Self::Pm138 => 138u16,
151 Self::Pm139 => 139u16,
152 Self::Pm140 => 140u16,
153 Self::Pm141 => 141u16,
154 Self::Pm142 => 142u16,
155 Self::Pm143 => 143u16,
156 Self::Pm144 => 144u16,
157 Self::Pm145 => 145u16,
158 Self::Pm146 => 146u16,
159 Self::Pm147 => 147u16,
160 Self::Pm148 => 148u16,
161 Self::Pm149 => 149u16,
162 Self::Pm150 => 150u16,
163 Self::Pm151 => 151u16,
164 Self::Pm152 => 152u16,
165 Self::Pm153 => 153u16,
166 Self::Pm154 => 154u16,
167 Self::Pm155 => 155u16,
168 Self::Pm156 => 156u16,
169 Self::Pm157 => 157u16,
170 Self::Pm158 => 158u16,
171 Self::Pm159 => 159u16,
172 Self::Pm160 => 160u16,
173 Self::Pm161 => 161u16,
174 Self::Pm162 => 162u16,
175 Self::Pm163 => 163u16,
176 }
177 }
178}
179impl super::IsotopicComposition for PromethiumIsotope {
180 #[inline]
181 fn isotopic_composition(&self) -> Option<f64> {
182 None
183 }
184}
185impl super::MostAbundantIsotope for PromethiumIsotope {
186 fn most_abundant_isotope() -> Self {
187 Self::Pm163
188 }
189}
190impl From<PromethiumIsotope> for crate::Isotope {
191 fn from(isotope: PromethiumIsotope) -> Self {
192 crate::Isotope::Pm(isotope)
193 }
194}
195impl From<PromethiumIsotope> for crate::Element {
196 fn from(_isotope: PromethiumIsotope) -> Self {
197 crate::Element::Pm
198 }
199}
200impl TryFrom<u64> for PromethiumIsotope {
201 type Error = crate::errors::Error;
202 fn try_from(value: u64) -> Result<Self, Self::Error> {
203 match value {
204 126u64 => Ok(Self::Pm126),
205 127u64 => Ok(Self::Pm127),
206 128u64 => Ok(Self::Pm128),
207 129u64 => Ok(Self::Pm129),
208 130u64 => Ok(Self::Pm130),
209 131u64 => Ok(Self::Pm131),
210 132u64 => Ok(Self::Pm132),
211 133u64 => Ok(Self::Pm133),
212 134u64 => Ok(Self::Pm134),
213 135u64 => Ok(Self::Pm135),
214 136u64 => Ok(Self::Pm136),
215 137u64 => Ok(Self::Pm137),
216 138u64 => Ok(Self::Pm138),
217 139u64 => Ok(Self::Pm139),
218 140u64 => Ok(Self::Pm140),
219 141u64 => Ok(Self::Pm141),
220 142u64 => Ok(Self::Pm142),
221 143u64 => Ok(Self::Pm143),
222 144u64 => Ok(Self::Pm144),
223 145u64 => Ok(Self::Pm145),
224 146u64 => Ok(Self::Pm146),
225 147u64 => Ok(Self::Pm147),
226 148u64 => Ok(Self::Pm148),
227 149u64 => Ok(Self::Pm149),
228 150u64 => Ok(Self::Pm150),
229 151u64 => Ok(Self::Pm151),
230 152u64 => Ok(Self::Pm152),
231 153u64 => Ok(Self::Pm153),
232 154u64 => Ok(Self::Pm154),
233 155u64 => Ok(Self::Pm155),
234 156u64 => Ok(Self::Pm156),
235 157u64 => Ok(Self::Pm157),
236 158u64 => Ok(Self::Pm158),
237 159u64 => Ok(Self::Pm159),
238 160u64 => Ok(Self::Pm160),
239 161u64 => Ok(Self::Pm161),
240 162u64 => Ok(Self::Pm162),
241 163u64 => Ok(Self::Pm163),
242 _ => Err(crate::errors::Error::Isotope(crate::Element::Pm, value)),
243 }
244 }
245}
246impl TryFrom<u8> for PromethiumIsotope {
247 type Error = crate::errors::Error;
248 fn try_from(value: u8) -> Result<Self, Self::Error> {
249 Self::try_from(u64::from(value))
250 }
251}
252impl TryFrom<u16> for PromethiumIsotope {
253 type Error = crate::errors::Error;
254 fn try_from(value: u16) -> Result<Self, Self::Error> {
255 Self::try_from(u64::from(value))
256 }
257}
258impl TryFrom<u32> for PromethiumIsotope {
259 type Error = crate::errors::Error;
260 fn try_from(value: u32) -> Result<Self, Self::Error> {
261 Self::try_from(u64::from(value))
262 }
263}
264impl core::fmt::Display for PromethiumIsotope {
265 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
266 match self {
267 Self::Pm126 => write!(f, "Pm126"),
268 Self::Pm127 => write!(f, "Pm127"),
269 Self::Pm128 => write!(f, "Pm128"),
270 Self::Pm129 => write!(f, "Pm129"),
271 Self::Pm130 => write!(f, "Pm130"),
272 Self::Pm131 => write!(f, "Pm131"),
273 Self::Pm132 => write!(f, "Pm132"),
274 Self::Pm133 => write!(f, "Pm133"),
275 Self::Pm134 => write!(f, "Pm134"),
276 Self::Pm135 => write!(f, "Pm135"),
277 Self::Pm136 => write!(f, "Pm136"),
278 Self::Pm137 => write!(f, "Pm137"),
279 Self::Pm138 => write!(f, "Pm138"),
280 Self::Pm139 => write!(f, "Pm139"),
281 Self::Pm140 => write!(f, "Pm140"),
282 Self::Pm141 => write!(f, "Pm141"),
283 Self::Pm142 => write!(f, "Pm142"),
284 Self::Pm143 => write!(f, "Pm143"),
285 Self::Pm144 => write!(f, "Pm144"),
286 Self::Pm145 => write!(f, "Pm145"),
287 Self::Pm146 => write!(f, "Pm146"),
288 Self::Pm147 => write!(f, "Pm147"),
289 Self::Pm148 => write!(f, "Pm148"),
290 Self::Pm149 => write!(f, "Pm149"),
291 Self::Pm150 => write!(f, "Pm150"),
292 Self::Pm151 => write!(f, "Pm151"),
293 Self::Pm152 => write!(f, "Pm152"),
294 Self::Pm153 => write!(f, "Pm153"),
295 Self::Pm154 => write!(f, "Pm154"),
296 Self::Pm155 => write!(f, "Pm155"),
297 Self::Pm156 => write!(f, "Pm156"),
298 Self::Pm157 => write!(f, "Pm157"),
299 Self::Pm158 => write!(f, "Pm158"),
300 Self::Pm159 => write!(f, "Pm159"),
301 Self::Pm160 => write!(f, "Pm160"),
302 Self::Pm161 => write!(f, "Pm161"),
303 Self::Pm162 => write!(f, "Pm162"),
304 Self::Pm163 => write!(f, "Pm163"),
305 }
306 }
307}
308#[cfg(test)]
309mod tests {
310 use strum::IntoEnumIterator;
311
312 use super::*;
313 use crate::isotopes::{
314 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
315 };
316 #[test]
317 fn test_relative_atomic_mass() {
318 for isotope in PromethiumIsotope::iter() {
319 let mass = isotope.relative_atomic_mass();
320 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
321 }
322 }
323 #[test]
324 fn test_element() {
325 for isotope in PromethiumIsotope::iter() {
326 let element = isotope.element();
327 assert_eq!(element, crate::Element::Pm, "Element should be correct for {isotope:?}");
328 }
329 }
330 #[test]
331 fn test_mass_number() {
332 for isotope in PromethiumIsotope::iter() {
333 let mass_number = isotope.mass_number();
334 assert!(
335 mass_number > 0 && mass_number < 300,
336 "Mass number should be reasonable for {isotope:?}"
337 );
338 }
339 }
340 #[test]
341 fn test_isotopic_composition() {
342 for isotope in PromethiumIsotope::iter() {
343 let comp = isotope.isotopic_composition();
344 if let Some(c) = comp {
345 assert!(
346 (0.0..=1.0).contains(&c),
347 "Composition should be between 0 and 1 for {isotope:?}"
348 );
349 }
350 }
351 }
352 #[test]
353 fn test_most_abundant() {
354 let most_abundant = PromethiumIsotope::most_abundant_isotope();
355 let _ = most_abundant.relative_atomic_mass();
356 }
357 #[test]
358 fn test_from_isotope() {
359 for isotope in PromethiumIsotope::iter() {
360 let iso: crate::Isotope = isotope.into();
361 match iso {
362 crate::Isotope::Pm(i) => assert_eq!(i, isotope),
363 _ => panic!("Wrong isotope type"),
364 }
365 }
366 }
367 #[test]
368 fn test_from_element() {
369 for isotope in PromethiumIsotope::iter() {
370 let elem: crate::Element = isotope.into();
371 assert_eq!(elem, crate::Element::Pm);
372 }
373 }
374 #[test]
375 fn test_try_from_mass_number() {
376 for isotope in PromethiumIsotope::iter() {
377 let mass = isotope.mass_number();
378 let iso = PromethiumIsotope::try_from(mass).unwrap();
379 assert_eq!(iso, isotope);
380 let iso_u32 = PromethiumIsotope::try_from(u32::from(mass)).unwrap();
381 assert_eq!(iso_u32, isotope);
382 if let Ok(mass_u8) = u8::try_from(mass) {
383 let iso_u8 = PromethiumIsotope::try_from(mass_u8).unwrap();
384 assert_eq!(iso_u8, isotope);
385 }
386 }
387 assert!(PromethiumIsotope::try_from(0_u16).is_err());
388 assert!(PromethiumIsotope::try_from(1000_u16).is_err());
389 assert!(PromethiumIsotope::try_from(0_u32).is_err());
390 assert!(PromethiumIsotope::try_from(1000_u32).is_err());
391 assert!(PromethiumIsotope::try_from(0_u8).is_err());
392 }
393 #[test]
394 fn test_display() {
395 for isotope in PromethiumIsotope::iter() {
396 let s = alloc::format!("{isotope}");
397 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
398 }
399 }
400}