#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "mem_size", derive(mem_dbg::MemSize))]
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg))]
#[cfg_attr(feature = "mem_size", mem_size(flat))]
pub enum TungstenIsotope {
W157,
W158,
W159,
W160,
W161,
W162,
W163,
W164,
W165,
W166,
W167,
W168,
W169,
W170,
W171,
W172,
W173,
W174,
W175,
W176,
W177,
W178,
W179,
W180,
W181,
W182,
W183,
W184,
W185,
W186,
W187,
W188,
W189,
W190,
W191,
W192,
W193,
W194,
W195,
W196,
W197,
}
impl super::RelativeAtomicMass for TungstenIsotope {
#[inline]
fn relative_atomic_mass(&self) -> f64 {
match self {
Self::W157 => 156.97884f64,
Self::W158 => 157.97456f64,
Self::W159 => 158.97264f64,
Self::W160 => 159.96846f64,
Self::W161 => 160.9672f64,
Self::W162 => 161.963499f64,
Self::W163 => 162.962524f64,
Self::W164 => 163.958961f64,
Self::W165 => 164.958281f64,
Self::W166 => 165.955031f64,
Self::W167 => 166.954805f64,
Self::W168 => 167.951806f64,
Self::W169 => 168.951779f64,
Self::W170 => 169.949232f64,
Self::W171 => 170.949451f64,
Self::W172 => 171.947292f64,
Self::W173 => 172.947689f64,
Self::W174 => 173.946079f64,
Self::W175 => 174.946717f64,
Self::W176 => 175.945634f64,
Self::W177 => 176.946643f64,
Self::W178 => 177.945883f64,
Self::W179 => 178.947077f64,
Self::W180 => 179.9467108f64,
Self::W181 => 180.9481978f64,
Self::W182 => 181.94820394f64,
Self::W183 => 182.95022275f64,
Self::W184 => 183.95093092f64,
Self::W185 => 184.95341897f64,
Self::W186 => 185.9543628f64,
Self::W187 => 186.9571588f64,
Self::W188 => 187.9584862f64,
Self::W189 => 188.961763f64,
Self::W190 => 189.963091f64,
Self::W191 => 190.966531f64,
Self::W192 => 191.96817f64,
Self::W193 => 192.97178f64,
Self::W194 => 193.97367f64,
Self::W195 => 194.977735f64,
Self::W196 => 195.979882f64,
Self::W197 => 196.984036f64,
}
}
}
impl super::ElementVariant for TungstenIsotope {
#[inline]
fn element(&self) -> crate::Element {
crate::Element::W
}
}
impl super::MassNumber for TungstenIsotope {
#[inline]
fn mass_number(&self) -> u16 {
match self {
Self::W157 => 157u16,
Self::W158 => 158u16,
Self::W159 => 159u16,
Self::W160 => 160u16,
Self::W161 => 161u16,
Self::W162 => 162u16,
Self::W163 => 163u16,
Self::W164 => 164u16,
Self::W165 => 165u16,
Self::W166 => 166u16,
Self::W167 => 167u16,
Self::W168 => 168u16,
Self::W169 => 169u16,
Self::W170 => 170u16,
Self::W171 => 171u16,
Self::W172 => 172u16,
Self::W173 => 173u16,
Self::W174 => 174u16,
Self::W175 => 175u16,
Self::W176 => 176u16,
Self::W177 => 177u16,
Self::W178 => 178u16,
Self::W179 => 179u16,
Self::W180 => 180u16,
Self::W181 => 181u16,
Self::W182 => 182u16,
Self::W183 => 183u16,
Self::W184 => 184u16,
Self::W185 => 185u16,
Self::W186 => 186u16,
Self::W187 => 187u16,
Self::W188 => 188u16,
Self::W189 => 189u16,
Self::W190 => 190u16,
Self::W191 => 191u16,
Self::W192 => 192u16,
Self::W193 => 193u16,
Self::W194 => 194u16,
Self::W195 => 195u16,
Self::W196 => 196u16,
Self::W197 => 197u16,
}
}
}
impl super::IsotopicComposition for TungstenIsotope {
#[inline]
fn isotopic_composition(&self) -> Option<f64> {
match self {
Self::W180 => Some(0.0012f64),
Self::W182 => Some(0.265f64),
Self::W183 => Some(0.1431f64),
Self::W184 => Some(0.3064f64),
Self::W186 => Some(0.2843f64),
_ => None,
}
}
}
impl super::MostAbundantIsotope for TungstenIsotope {
fn most_abundant_isotope() -> Self {
Self::W184
}
}
impl From<TungstenIsotope> for crate::Isotope {
fn from(isotope: TungstenIsotope) -> Self {
crate::Isotope::W(isotope)
}
}
impl From<TungstenIsotope> for crate::Element {
fn from(_isotope: TungstenIsotope) -> Self {
crate::Element::W
}
}
impl TryFrom<u64> for TungstenIsotope {
type Error = crate::errors::Error;
fn try_from(value: u64) -> Result<Self, Self::Error> {
match value {
157u64 => Ok(Self::W157),
158u64 => Ok(Self::W158),
159u64 => Ok(Self::W159),
160u64 => Ok(Self::W160),
161u64 => Ok(Self::W161),
162u64 => Ok(Self::W162),
163u64 => Ok(Self::W163),
164u64 => Ok(Self::W164),
165u64 => Ok(Self::W165),
166u64 => Ok(Self::W166),
167u64 => Ok(Self::W167),
168u64 => Ok(Self::W168),
169u64 => Ok(Self::W169),
170u64 => Ok(Self::W170),
171u64 => Ok(Self::W171),
172u64 => Ok(Self::W172),
173u64 => Ok(Self::W173),
174u64 => Ok(Self::W174),
175u64 => Ok(Self::W175),
176u64 => Ok(Self::W176),
177u64 => Ok(Self::W177),
178u64 => Ok(Self::W178),
179u64 => Ok(Self::W179),
180u64 => Ok(Self::W180),
181u64 => Ok(Self::W181),
182u64 => Ok(Self::W182),
183u64 => Ok(Self::W183),
184u64 => Ok(Self::W184),
185u64 => Ok(Self::W185),
186u64 => Ok(Self::W186),
187u64 => Ok(Self::W187),
188u64 => Ok(Self::W188),
189u64 => Ok(Self::W189),
190u64 => Ok(Self::W190),
191u64 => Ok(Self::W191),
192u64 => Ok(Self::W192),
193u64 => Ok(Self::W193),
194u64 => Ok(Self::W194),
195u64 => Ok(Self::W195),
196u64 => Ok(Self::W196),
197u64 => Ok(Self::W197),
_ => Err(crate::errors::Error::Isotope(crate::Element::W, value)),
}
}
}
impl TryFrom<u8> for TungstenIsotope {
type Error = crate::errors::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
Self::try_from(u64::from(value))
}
}
impl TryFrom<u16> for TungstenIsotope {
type Error = crate::errors::Error;
fn try_from(value: u16) -> Result<Self, Self::Error> {
Self::try_from(u64::from(value))
}
}
impl TryFrom<u32> for TungstenIsotope {
type Error = crate::errors::Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
Self::try_from(u64::from(value))
}
}
impl core::fmt::Display for TungstenIsotope {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::W157 => write!(f, "W157"),
Self::W158 => write!(f, "W158"),
Self::W159 => write!(f, "W159"),
Self::W160 => write!(f, "W160"),
Self::W161 => write!(f, "W161"),
Self::W162 => write!(f, "W162"),
Self::W163 => write!(f, "W163"),
Self::W164 => write!(f, "W164"),
Self::W165 => write!(f, "W165"),
Self::W166 => write!(f, "W166"),
Self::W167 => write!(f, "W167"),
Self::W168 => write!(f, "W168"),
Self::W169 => write!(f, "W169"),
Self::W170 => write!(f, "W170"),
Self::W171 => write!(f, "W171"),
Self::W172 => write!(f, "W172"),
Self::W173 => write!(f, "W173"),
Self::W174 => write!(f, "W174"),
Self::W175 => write!(f, "W175"),
Self::W176 => write!(f, "W176"),
Self::W177 => write!(f, "W177"),
Self::W178 => write!(f, "W178"),
Self::W179 => write!(f, "W179"),
Self::W180 => write!(f, "W180"),
Self::W181 => write!(f, "W181"),
Self::W182 => write!(f, "W182"),
Self::W183 => write!(f, "W183"),
Self::W184 => write!(f, "W184"),
Self::W185 => write!(f, "W185"),
Self::W186 => write!(f, "W186"),
Self::W187 => write!(f, "W187"),
Self::W188 => write!(f, "W188"),
Self::W189 => write!(f, "W189"),
Self::W190 => write!(f, "W190"),
Self::W191 => write!(f, "W191"),
Self::W192 => write!(f, "W192"),
Self::W193 => write!(f, "W193"),
Self::W194 => write!(f, "W194"),
Self::W195 => write!(f, "W195"),
Self::W196 => write!(f, "W196"),
Self::W197 => write!(f, "W197"),
}
}
}
#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
use super::*;
use crate::isotopes::{
ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
};
#[test]
fn test_relative_atomic_mass() {
for isotope in TungstenIsotope::iter() {
let mass = isotope.relative_atomic_mass();
assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
}
}
#[test]
fn test_element() {
for isotope in TungstenIsotope::iter() {
let element = isotope.element();
assert_eq!(element, crate::Element::W, "Element should be correct for {isotope:?}");
}
}
#[test]
fn test_mass_number() {
for isotope in TungstenIsotope::iter() {
let mass_number = isotope.mass_number();
assert!(
mass_number > 0 && mass_number < 300,
"Mass number should be reasonable for {isotope:?}"
);
}
}
#[test]
fn test_isotopic_composition() {
for isotope in TungstenIsotope::iter() {
let comp = isotope.isotopic_composition();
if let Some(c) = comp {
assert!(
(0.0..=1.0).contains(&c),
"Composition should be between 0 and 1 for {isotope:?}"
);
}
}
}
#[test]
fn test_most_abundant() {
let most_abundant = TungstenIsotope::most_abundant_isotope();
let _ = most_abundant.relative_atomic_mass();
}
#[test]
fn test_from_isotope() {
for isotope in TungstenIsotope::iter() {
let iso: crate::Isotope = isotope.into();
match iso {
crate::Isotope::W(i) => assert_eq!(i, isotope),
_ => panic!("Wrong isotope type"),
}
}
}
#[test]
fn test_from_element() {
for isotope in TungstenIsotope::iter() {
let elem: crate::Element = isotope.into();
assert_eq!(elem, crate::Element::W);
}
}
#[test]
fn test_try_from_mass_number() {
for isotope in TungstenIsotope::iter() {
let mass = isotope.mass_number();
let iso = TungstenIsotope::try_from(mass).unwrap();
assert_eq!(iso, isotope);
let iso_u32 = TungstenIsotope::try_from(u32::from(mass)).unwrap();
assert_eq!(iso_u32, isotope);
if let Ok(mass_u8) = u8::try_from(mass) {
let iso_u8 = TungstenIsotope::try_from(mass_u8).unwrap();
assert_eq!(iso_u8, isotope);
}
}
assert!(TungstenIsotope::try_from(0_u16).is_err());
assert!(TungstenIsotope::try_from(1000_u16).is_err());
assert!(TungstenIsotope::try_from(0_u32).is_err());
assert!(TungstenIsotope::try_from(1000_u32).is_err());
assert!(TungstenIsotope::try_from(0_u8).is_err());
}
#[test]
fn test_display() {
for isotope in TungstenIsotope::iter() {
let s = alloc::format!("{isotope}");
assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
}
}
}