Skip to content

Instantly share code, notes, and snippets.

@MikuroXina
Last active May 11, 2024 05:46
Show Gist options
  • Select an option

  • Save MikuroXina/f525a7925e138cd68fe112912a26fbb2 to your computer and use it in GitHub Desktop.

Select an option

Save MikuroXina/f525a7925e138cd68fe112912a26fbb2 to your computer and use it in GitHub Desktop.
NonNanF64, the floating-point number which will not be NaN in Rust.
#[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