#![cfg(not(feature = "no_float"))] #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ fmt, hash::{Hash, Hasher}, ops::{Deref, DerefMut}, str::FromStr, }; use num_traits::float::FloatCore as Float; /// A type that wraps a floating-point number and implements [`Hash`]. /// /// Not available under `no_float`. #[derive(Clone, Copy, Eq, PartialEq, PartialOrd)] #[must_use] pub struct FloatWrapper(F); impl Hash for FloatWrapper { #[inline] fn hash(&self, state: &mut H) { self.0.to_ne_bytes().hash(state); } } impl AsRef for FloatWrapper { #[inline(always)] #[must_use] fn as_ref(&self) -> &F { &self.0 } } impl AsMut for FloatWrapper { #[inline(always)] #[must_use] fn as_mut(&mut self) -> &mut F { &mut self.0 } } impl Deref for FloatWrapper { type Target = F; #[inline(always)] fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for FloatWrapper { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl fmt::Debug for FloatWrapper { #[cold] #[inline(never)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.0, f) } } impl> fmt::Display for FloatWrapper { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let abs = self.0.abs(); if abs.is_zero() { f.write_str("0.0") } else if abs > Self::MAX_NATURAL_FLOAT_FOR_DISPLAY.into() || abs < Self::MIN_NATURAL_FLOAT_FOR_DISPLAY.into() { write!(f, "{:e}", self.0) } else { fmt::Display::fmt(&self.0, f)?; if abs.fract().is_zero() { f.write_str(".0")?; } Ok(()) } } } impl From for FloatWrapper { #[inline(always)] fn from(value: F) -> Self { Self::new(value) } } impl FromStr for FloatWrapper { type Err = ::Err; #[inline] fn from_str(s: &str) -> Result { F::from_str(s).map(Into::into) } } impl FloatWrapper { /// Maximum floating-point number for natural display before switching to scientific notation. pub const MAX_NATURAL_FLOAT_FOR_DISPLAY: f32 = 10_000_000_000_000.0; /// Minimum floating-point number for natural display before switching to scientific notation. pub const MIN_NATURAL_FLOAT_FOR_DISPLAY: f32 = 0.000_000_000_000_1; /// Create a new [`FloatWrapper`]. #[inline(always)] pub const fn new(value: F) -> Self { Self(value) } }