Last active
May 11, 2024 05:46
-
-
Save MikuroXina/f525a7925e138cd68fe112912a26fbb2 to your computer and use it in GitHub Desktop.
NonNanF64, the floating-point number which will not be NaN in Rust.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[derive(Debug, Clone, Copy, PartialEq)] | |
| pub struct NonNanF64(f64); | |
| impl NonNanF64 { | |
| /// # Safety | |
| /// | |
| /// The value must not be `NaN`. | |
| pub const unsafe fn new_unchecked(f: f64) -> Self { | |
| // SAFETY: this is guaranteed to be safe by the caller. | |
| Self(f) | |
| } | |
| /// # Panics | |
| /// | |
| /// Panics if `f` is a `NaN`. | |
| pub fn new(f: f64) -> Self { | |
| assert!(!f.is_nan()); | |
| Self(f) | |
| } | |
| pub fn new_checked(f: f64) -> Option<Self> { | |
| if f.is_nan() { | |
| None | |
| } else { | |
| Some(Self(f)) | |
| } | |
| } | |
| pub const fn get(self) -> f64 { | |
| self.0 | |
| } | |
| } | |
| impl std::cmp::Eq for NonNanF64 {} | |
| impl std::cmp::PartialOrd for NonNanF64 { | |
| fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { | |
| self.0.partial_cmp(&other.0) | |
| } | |
| } | |
| impl std::cmp::Ord for NonNanF64 { | |
| fn cmp(&self, other: &Self) -> std::cmp::Ordering { | |
| self.0.partial_cmp(&other.0).unwrap() | |
| } | |
| } | |
| impl From<NonNanF64> for f64 { | |
| fn from(value: NonNanF64) -> Self { | |
| value.get() | |
| } | |
| } | |
| impl TryFrom<f64> for NonNanF64 { | |
| type Error = (); | |
| fn try_from(value: f64) -> Result<Self, Self::Error> { | |
| Self::new(value).ok_or(()) | |
| } | |
| } | |
| impl NonNanF64 { | |
| pub fn map<F>(self, f: F) -> Option<Self> | |
| where | |
| F: FnOnce(f64) -> f64 | |
| { | |
| Self::new(f(self.0)) | |
| } | |
| } | |
| impl NonNanF64 { | |
| pub fn checked_add(self, other: Self) -> Option<Self> { | |
| Self::new(self.0 + other.0) | |
| } | |
| pub fn checked_sub(self, other: Self) -> Option<Self> { | |
| Self::new(self.0 - other.0) | |
| } | |
| pub fn checked_mul(self, other: Self) -> Option<Self> { | |
| Self::new(self.0 * other.0) | |
| } | |
| pub fn checked_div(self, other: Self) -> Option<Self> { | |
| Self::new(self.0 / other.0) | |
| } | |
| pub fn checked_powi(self, exp: i32) -> Option<Self> { | |
| Self::new(self.0.powi(exp)) | |
| } | |
| pub fn checked_powf(self, exp: impl Into<f64>) -> Option<Self> { | |
| Self::new(self.0.powf(exp.into())) | |
| } | |
| pub fn checked_sqrt(self) -> Option<Self> { | |
| Self::new(self.0.sqrt()) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment