1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub enum GermaniumIsotope {
6 Ge58,
8 Ge59,
10 Ge60,
12 Ge61,
14 Ge62,
16 Ge63,
18 Ge64,
20 Ge65,
22 Ge66,
24 Ge67,
26 Ge68,
28 Ge69,
30 Ge70,
32 Ge71,
34 Ge72,
36 Ge73,
38 Ge74,
40 Ge75,
42 Ge76,
44 Ge77,
46 Ge78,
48 Ge79,
50 Ge80,
52 Ge81,
54 Ge82,
56 Ge83,
58 Ge84,
60 Ge85,
62 Ge86,
64 Ge87,
66 Ge88,
68 Ge89,
70 Ge90,
72}
73impl super::RelativeAtomicMass for GermaniumIsotope {
74 #[inline]
75 fn relative_atomic_mass(&self) -> f64 {
76 match self {
77 Self::Ge58 => 57.99172f64,
78 Self::Ge59 => 58.98249f64,
79 Self::Ge60 => 59.97036f64,
80 Self::Ge61 => 60.96379f64,
81 Self::Ge62 => 61.95502f64,
82 Self::Ge63 => 62.949628f64,
83 Self::Ge64 => 63.9416899f64,
84 Self::Ge65 => 64.9393681f64,
85 Self::Ge66 => 65.9338621f64,
86 Self::Ge67 => 66.9327339f64,
87 Self::Ge68 => 67.9280953f64,
88 Self::Ge69 => 68.9279645f64,
89 Self::Ge70 => 69.92424875f64,
90 Self::Ge71 => 70.92495233f64,
91 Self::Ge72 => 71.922075826f64,
92 Self::Ge73 => 72.923458956f64,
93 Self::Ge74 => 73.921177761f64,
94 Self::Ge75 => 74.92285837f64,
95 Self::Ge76 => 75.921402726f64,
96 Self::Ge77 => 76.923549843f64,
97 Self::Ge78 => 77.9228529f64,
98 Self::Ge79 => 78.92536f64,
99 Self::Ge80 => 79.9253508f64,
100 Self::Ge81 => 80.9288329f64,
101 Self::Ge82 => 81.929774f64,
102 Self::Ge83 => 82.9345391f64,
103 Self::Ge84 => 83.9375751f64,
104 Self::Ge85 => 84.9429697f64,
105 Self::Ge86 => 85.94658f64,
106 Self::Ge87 => 86.95268f64,
107 Self::Ge88 => 87.95691f64,
108 Self::Ge89 => 88.96379f64,
109 Self::Ge90 => 89.96863f64,
110 }
111 }
112}
113impl super::ElementVariant for GermaniumIsotope {
114 #[inline]
115 fn element(&self) -> crate::Element {
116 crate::Element::Ge
117 }
118}
119impl super::MassNumber for GermaniumIsotope {
120 #[inline]
121 fn mass_number(&self) -> u16 {
122 match self {
123 Self::Ge58 => 58u16,
124 Self::Ge59 => 59u16,
125 Self::Ge60 => 60u16,
126 Self::Ge61 => 61u16,
127 Self::Ge62 => 62u16,
128 Self::Ge63 => 63u16,
129 Self::Ge64 => 64u16,
130 Self::Ge65 => 65u16,
131 Self::Ge66 => 66u16,
132 Self::Ge67 => 67u16,
133 Self::Ge68 => 68u16,
134 Self::Ge69 => 69u16,
135 Self::Ge70 => 70u16,
136 Self::Ge71 => 71u16,
137 Self::Ge72 => 72u16,
138 Self::Ge73 => 73u16,
139 Self::Ge74 => 74u16,
140 Self::Ge75 => 75u16,
141 Self::Ge76 => 76u16,
142 Self::Ge77 => 77u16,
143 Self::Ge78 => 78u16,
144 Self::Ge79 => 79u16,
145 Self::Ge80 => 80u16,
146 Self::Ge81 => 81u16,
147 Self::Ge82 => 82u16,
148 Self::Ge83 => 83u16,
149 Self::Ge84 => 84u16,
150 Self::Ge85 => 85u16,
151 Self::Ge86 => 86u16,
152 Self::Ge87 => 87u16,
153 Self::Ge88 => 88u16,
154 Self::Ge89 => 89u16,
155 Self::Ge90 => 90u16,
156 }
157 }
158}
159impl super::IsotopicComposition for GermaniumIsotope {
160 #[inline]
161 fn isotopic_composition(&self) -> Option<f64> {
162 match self {
163 Self::Ge70 => Some(0.2057f64),
164 Self::Ge72 => Some(0.2745f64),
165 Self::Ge73 => Some(0.0775f64),
166 Self::Ge74 => Some(0.365f64),
167 Self::Ge76 => Some(0.0773f64),
168 _ => None,
169 }
170 }
171}
172impl super::MostAbundantIsotope for GermaniumIsotope {
173 fn most_abundant_isotope() -> Self {
174 Self::Ge74
175 }
176}
177impl From<GermaniumIsotope> for crate::Isotope {
178 fn from(isotope: GermaniumIsotope) -> Self {
179 crate::Isotope::Ge(isotope)
180 }
181}
182impl From<GermaniumIsotope> for crate::Element {
183 fn from(_isotope: GermaniumIsotope) -> Self {
184 crate::Element::Ge
185 }
186}
187impl TryFrom<u64> for GermaniumIsotope {
188 type Error = crate::errors::Error;
189 fn try_from(value: u64) -> Result<Self, Self::Error> {
190 match value {
191 58u64 => Ok(Self::Ge58),
192 59u64 => Ok(Self::Ge59),
193 60u64 => Ok(Self::Ge60),
194 61u64 => Ok(Self::Ge61),
195 62u64 => Ok(Self::Ge62),
196 63u64 => Ok(Self::Ge63),
197 64u64 => Ok(Self::Ge64),
198 65u64 => Ok(Self::Ge65),
199 66u64 => Ok(Self::Ge66),
200 67u64 => Ok(Self::Ge67),
201 68u64 => Ok(Self::Ge68),
202 69u64 => Ok(Self::Ge69),
203 70u64 => Ok(Self::Ge70),
204 71u64 => Ok(Self::Ge71),
205 72u64 => Ok(Self::Ge72),
206 73u64 => Ok(Self::Ge73),
207 74u64 => Ok(Self::Ge74),
208 75u64 => Ok(Self::Ge75),
209 76u64 => Ok(Self::Ge76),
210 77u64 => Ok(Self::Ge77),
211 78u64 => Ok(Self::Ge78),
212 79u64 => Ok(Self::Ge79),
213 80u64 => Ok(Self::Ge80),
214 81u64 => Ok(Self::Ge81),
215 82u64 => Ok(Self::Ge82),
216 83u64 => Ok(Self::Ge83),
217 84u64 => Ok(Self::Ge84),
218 85u64 => Ok(Self::Ge85),
219 86u64 => Ok(Self::Ge86),
220 87u64 => Ok(Self::Ge87),
221 88u64 => Ok(Self::Ge88),
222 89u64 => Ok(Self::Ge89),
223 90u64 => Ok(Self::Ge90),
224 _ => Err(crate::errors::Error::Isotope(crate::Element::Ge, value)),
225 }
226 }
227}
228impl TryFrom<u8> for GermaniumIsotope {
229 type Error = crate::errors::Error;
230 fn try_from(value: u8) -> Result<Self, Self::Error> {
231 Self::try_from(u64::from(value))
232 }
233}
234impl TryFrom<u16> for GermaniumIsotope {
235 type Error = crate::errors::Error;
236 fn try_from(value: u16) -> Result<Self, Self::Error> {
237 Self::try_from(u64::from(value))
238 }
239}
240impl TryFrom<u32> for GermaniumIsotope {
241 type Error = crate::errors::Error;
242 fn try_from(value: u32) -> Result<Self, Self::Error> {
243 Self::try_from(u64::from(value))
244 }
245}
246impl core::fmt::Display for GermaniumIsotope {
247 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248 match self {
249 Self::Ge58 => write!(f, "Ge58"),
250 Self::Ge59 => write!(f, "Ge59"),
251 Self::Ge60 => write!(f, "Ge60"),
252 Self::Ge61 => write!(f, "Ge61"),
253 Self::Ge62 => write!(f, "Ge62"),
254 Self::Ge63 => write!(f, "Ge63"),
255 Self::Ge64 => write!(f, "Ge64"),
256 Self::Ge65 => write!(f, "Ge65"),
257 Self::Ge66 => write!(f, "Ge66"),
258 Self::Ge67 => write!(f, "Ge67"),
259 Self::Ge68 => write!(f, "Ge68"),
260 Self::Ge69 => write!(f, "Ge69"),
261 Self::Ge70 => write!(f, "Ge70"),
262 Self::Ge71 => write!(f, "Ge71"),
263 Self::Ge72 => write!(f, "Ge72"),
264 Self::Ge73 => write!(f, "Ge73"),
265 Self::Ge74 => write!(f, "Ge74"),
266 Self::Ge75 => write!(f, "Ge75"),
267 Self::Ge76 => write!(f, "Ge76"),
268 Self::Ge77 => write!(f, "Ge77"),
269 Self::Ge78 => write!(f, "Ge78"),
270 Self::Ge79 => write!(f, "Ge79"),
271 Self::Ge80 => write!(f, "Ge80"),
272 Self::Ge81 => write!(f, "Ge81"),
273 Self::Ge82 => write!(f, "Ge82"),
274 Self::Ge83 => write!(f, "Ge83"),
275 Self::Ge84 => write!(f, "Ge84"),
276 Self::Ge85 => write!(f, "Ge85"),
277 Self::Ge86 => write!(f, "Ge86"),
278 Self::Ge87 => write!(f, "Ge87"),
279 Self::Ge88 => write!(f, "Ge88"),
280 Self::Ge89 => write!(f, "Ge89"),
281 Self::Ge90 => write!(f, "Ge90"),
282 }
283 }
284}
285#[cfg(test)]
286mod tests {
287 use strum::IntoEnumIterator;
288
289 use super::*;
290 use crate::isotopes::{
291 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
292 };
293 #[test]
294 fn test_relative_atomic_mass() {
295 for isotope in GermaniumIsotope::iter() {
296 let mass = isotope.relative_atomic_mass();
297 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
298 }
299 }
300 #[test]
301 fn test_element() {
302 for isotope in GermaniumIsotope::iter() {
303 let element = isotope.element();
304 assert_eq!(element, crate::Element::Ge, "Element should be correct for {isotope:?}");
305 }
306 }
307 #[test]
308 fn test_mass_number() {
309 for isotope in GermaniumIsotope::iter() {
310 let mass_number = isotope.mass_number();
311 assert!(
312 mass_number > 0 && mass_number < 300,
313 "Mass number should be reasonable for {isotope:?}"
314 );
315 }
316 }
317 #[test]
318 fn test_isotopic_composition() {
319 for isotope in GermaniumIsotope::iter() {
320 let comp = isotope.isotopic_composition();
321 if let Some(c) = comp {
322 assert!(
323 (0.0..=1.0).contains(&c),
324 "Composition should be between 0 and 1 for {isotope:?}"
325 );
326 }
327 }
328 }
329 #[test]
330 fn test_most_abundant() {
331 let most_abundant = GermaniumIsotope::most_abundant_isotope();
332 let _ = most_abundant.relative_atomic_mass();
333 }
334 #[test]
335 fn test_from_isotope() {
336 for isotope in GermaniumIsotope::iter() {
337 let iso: crate::Isotope = isotope.into();
338 match iso {
339 crate::Isotope::Ge(i) => assert_eq!(i, isotope),
340 _ => panic!("Wrong isotope type"),
341 }
342 }
343 }
344 #[test]
345 fn test_from_element() {
346 for isotope in GermaniumIsotope::iter() {
347 let elem: crate::Element = isotope.into();
348 assert_eq!(elem, crate::Element::Ge);
349 }
350 }
351 #[test]
352 fn test_try_from_mass_number() {
353 for isotope in GermaniumIsotope::iter() {
354 let mass = isotope.mass_number();
355 let iso = GermaniumIsotope::try_from(mass).unwrap();
356 assert_eq!(iso, isotope);
357 let iso_u32 = GermaniumIsotope::try_from(u32::from(mass)).unwrap();
358 assert_eq!(iso_u32, isotope);
359 if let Ok(mass_u8) = u8::try_from(mass) {
360 let iso_u8 = GermaniumIsotope::try_from(mass_u8).unwrap();
361 assert_eq!(iso_u8, isotope);
362 }
363 }
364 assert!(GermaniumIsotope::try_from(0_u16).is_err());
365 assert!(GermaniumIsotope::try_from(1000_u16).is_err());
366 assert!(GermaniumIsotope::try_from(0_u32).is_err());
367 assert!(GermaniumIsotope::try_from(1000_u32).is_err());
368 assert!(GermaniumIsotope::try_from(0_u8).is_err());
369 }
370 #[test]
371 fn test_display() {
372 for isotope in GermaniumIsotope::iter() {
373 let s = alloc::format!("{isotope}");
374 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
375 }
376 }
377}