pub struct NotNan<T: NotNanFloat>(/* private fields */);Expand description
A transparent wrapper around f64 and friends with total ordering.
Comparison, equality, and hashing all agree with total_cmp after zero normalization.
Every value except NaN is legal, including +infinity and -infinity.
§Basic Usage
use range_set_blaze::{RangeSetBlaze, NotNanF64, NotNanF32};
let set = RangeSetBlaze::from_iter([NotNanF64::new(3.0)..=NotNanF64::new(5.0)]);
assert!(set.contains(NotNanF64::new(3.1)));
assert!(!set.contains(NotNanF64::new(2.9)));
let set = RangeSetBlaze::from(NotNanF64::from_primitive_range(3.0..=5.0));
assert!(set.contains(NotNanF64::new(4.9)));
assert!(!set.contains(NotNanF64::new(5.1)));
let set = RangeSetBlaze::from_iter(NotNanF32::from_primitive_ranges([3.0..=5.0, 7.0..=9.0]));
assert!(set.contains(NotNanF32::new(4.0)));
assert!(!set.contains(NotNanF32::new(6.0)));§The Full Non-NaN Domain
The primitive -∞..=+∞ range converts to NotNanF64::MIN..=NotNanF64::MAX,
the complete ordered domain of legal values: every non-NaN f64, including
both infinities, is in the range.
use range_set_blaze::{NotNanF64, RangeSetBlaze};
assert_eq!(NotNanF64::MIN, NotNanF64::new(f64::NEG_INFINITY));
assert_eq!(NotNanF64::MAX, NotNanF64::new(f64::INFINITY));
let primitive_domain =
NotNanF64::from_primitive_range(f64::NEG_INFINITY..=f64::INFINITY);
let full_domain = NotNanF64::MIN..=NotNanF64::MAX;
assert_eq!(primitive_domain, full_domain);
let full_domain = RangeSetBlaze::from(full_domain);
assert!(full_domain.contains(NotNanF64::new(f64::NEG_INFINITY)));
assert!(full_domain.contains(NotNanF64::new(-42.0)));
assert!(full_domain.contains(NotNanF64::new(0.0)));
assert!(full_domain.contains(NotNanF64::new(42.0)));
assert!(full_domain.contains(NotNanF64::new(f64::INFINITY)));The stable NotNanF32 and NotNanF64 types are available by default.
On nightly, enable float_nightly_experimental to also use the
NotNanF16 and NotNanF128 types.
Implementations§
Source§impl<T: NotNanFloat> NotNan<T>
impl<T: NotNanFloat> NotNan<T>
Sourcepub const MIN: Self
pub const MIN: Self
The minimum value that can be represented by the type: negative infinity.
Maps directly to crate::Integer::min_value()
§Examples
use range_set_blaze::NotNanF64;
assert_eq!(NotNanF64::MIN, NotNanF64::new(f64::NEG_INFINITY));Sourcepub const MAX: Self
pub const MAX: Self
The maximum value that can be represented by the type: positive infinity.
Maps directly to crate::Integer::max_value()
§Examples
use range_set_blaze::NotNanF64;
assert_eq!(NotNanF64::MAX, NotNanF64::new(f64::INFINITY));Sourcepub const MAX_SIZE: T::SafeLen = T::MAX_SIZE
pub const MAX_SIZE: T::SafeLen = T::MAX_SIZE
The maximum possible size of a range, i.e. the size if [MIN..=MAX]
For NotNan types, this is unusual because NaN values are excluded, and
-0.0 and +0.0 share one slot after normalization.
§Examples
use range_set_blaze::NotNanF32;
assert_eq!(NotNanF32::MAX_SIZE, 0xFF00_0000_u32 + 1);Sourcepub fn try_new(x: T) -> Option<Self>
pub fn try_new(x: T) -> Option<Self>
Creates a new NotNan from a primitive float.
Returns None if the float is NaN.
§Examples
use range_set_blaze::NotNanF64;
assert_eq!(NotNanF64::try_new(1.0), Some(NotNanF64::new(1.0)));
assert_eq!(NotNanF64::try_new(f64::INFINITY), Some(NotNanF64::new(f64::INFINITY)));
assert_eq!(NotNanF64::try_new(f64::NAN), None);Sourcepub const unsafe fn new_unchecked(x: T) -> Self
pub const unsafe fn new_unchecked(x: T) -> Self
Creates a new NotNan from a primitive float without validating it.
This is the unchecked building block every validating constructor in this module
(new, try_new, from_primitive_range, values,
from_primitive_slice, …) is defined in terms
of. Prefer those; only reach for this when you have already independently established
the safety precondition below and need to skip the redundant check.
§Safety
The caller must guarantee that:
xis not NaN.xis not-0.0: zero must already be canonicalized to+0.0.
NotNan has a public type invariant (“only non-NaN values, with zero canonicalized to
+0.0, are legal”). Even though today’s implementation would only produce incorrect
results (wrong MAX_SIZE, a duplicated zero slot, after/before landing somewhere
unexpected) rather than immediate undefined behavior if this precondition is violated,
safe code must never be able to construct a value that breaks it. This preserves the
option for this crate, and downstream code, to rely on the invariant in future
(potentially unsafe) abstractions without an audit of every safe caller.
Sourcepub fn inclusive_end_from_start(self, b: T::SafeLen) -> Self
pub fn inclusive_end_from_start(self, b: T::SafeLen) -> Self
Computes self + (b - 1) where b is of type SafeLen.
§Panics
Panics if b is not small enough that the result stays within range for T
(checked unconditionally, in both debug and release builds, so safe code can
never construct a NotNan value that breaks its invariant this way).
Sourcepub fn start_from_inclusive_end(self, b: T::SafeLen) -> Self
pub fn start_from_inclusive_end(self, b: T::SafeLen) -> Self
Computes self - (b - 1) where b is of type SafeLen.
§Panics
Panics if b is not small enough that the result stays within range for T
(checked unconditionally, in both debug and release builds, so safe code can
never construct a NotNan value that breaks its invariant this way).
Sourcepub const fn into_inner(self) -> T
pub const fn into_inner(self) -> T
Returns the wrapped value.
§Examples
use range_set_blaze::NotNanF64;
assert_eq!(NotNanF64::new(42.0).into_inner(), 42.0);Sourcepub fn after(self) -> Self
pub fn after(self) -> Self
Returns the next float, in total order.
§Examples
use range_set_blaze::NotNanF64;
assert_eq!(NotNanF64::new(42.0).after().before().into_inner(), 42.0);§Panics
Panics if self is the maximum value (checked unconditionally, in both debug
and release builds, so safe code can never construct a NotNan value that
breaks its invariant this way).
Sourcepub fn before(self) -> Self
pub fn before(self) -> Self
Returns the previous float, in total order.
§Examples
use range_set_blaze::NotNanF64;
assert_eq!(NotNanF64::new(42.0).before().after().into_inner(), 42.0);§Panics
Panics if self is the minimum value (checked unconditionally, in both debug
and release builds, so safe code can never construct a NotNan value that
breaks its invariant this way).
Sourcepub fn checked_after(self) -> Option<Self>
pub fn checked_after(self) -> Option<Self>
Sourcepub fn checked_before(self) -> Option<Self>
pub fn checked_before(self) -> Option<Self>
Sourcepub fn from_primitive_range(range: RangeInclusive<T>) -> RangeInclusive<Self> ⓘ
pub fn from_primitive_range(range: RangeInclusive<T>) -> RangeInclusive<Self> ⓘ
Converts an inclusive primitive range into an inclusive NotNan range.
“Primitive” here means Rust’s built-in float type (e.g. f64).
§Examples
use range_set_blaze::{RangeSetBlaze, NotNanF64};
let short = RangeSetBlaze::from(NotNanF64::from_primitive_range(3.0..=5.0));
let long = RangeSetBlaze::from(NotNanF64::new(3.0)..=NotNanF64::new(5.0));
assert_eq!(short, long);§Panics
Panics if start or end is NaN.
Sourcepub fn from_primitive_ranges<I>(
ranges: I,
) -> impl Iterator<Item = RangeInclusive<Self>>where
I: IntoIterator<Item = RangeInclusive<T>>,
pub fn from_primitive_ranges<I>(
ranges: I,
) -> impl Iterator<Item = RangeInclusive<Self>>where
I: IntoIterator<Item = RangeInclusive<T>>,
Converts inclusive primitive ranges into inclusive NotNan ranges.
“Primitive” here means Rust’s built-in float type (e.g. f64).
§Examples
use range_set_blaze::{RangeSetBlaze, NotNanF64};
let short = RangeSetBlaze::from_iter(NotNanF64::from_primitive_ranges([1.0..=2.0, 3.0..=4.0]));
let long = RangeSetBlaze::from_iter([NotNanF64::new(1.0)..=NotNanF64::new(2.0), NotNanF64::new(3.0)..=NotNanF64::new(4.0)]);
assert_eq!(short, long);§Panics
Panics when the returned iterator is consumed if any range endpoint is NaN.
Sourcepub fn values<I>(values: I) -> impl Iterator<Item = Self>where
I: IntoIterator<Item = T>,
pub fn values<I>(values: I) -> impl Iterator<Item = Self>where
I: IntoIterator<Item = T>,
Convenience method to convert primitive values into ordered NotNan values.
§Examples
use range_set_blaze::{RangeSetBlaze, NotNanF64};
let short = RangeSetBlaze::from_iter(NotNanF64::values([1.0, 2.0, 3.0, 4.0]));
let long = RangeSetBlaze::from_iter([NotNanF64::new(1.0), NotNanF64::new(2.0), NotNanF64::new(3.0), NotNanF64::new(4.0)]);
assert_eq!(short, long);§Panics
Panics (when iterated) if any value is NaN.
Sourcepub fn from_primitive_slice(values: &[T]) -> &[Self]
pub fn from_primitive_slice(values: &[T]) -> &[Self]
Views primitive values as ordered NotNan values, validating as it goes.
“Primitive” here means Rust’s built-in float type (e.g. f64).
This runs in O(n) (to validate every element) and does not allocate.
§Examples
use range_set_blaze::{RangeSetBlaze, NotNanF64};
let short = RangeSetBlaze::from_iter(NotNanF64::from_primitive_slice(&[1.0, 2.0, 3.0, 4.0]));
let long = RangeSetBlaze::from_iter([NotNanF64::new(1.0), NotNanF64::new(2.0), NotNanF64::new(3.0), NotNanF64::new(4.0)]);
assert_eq!(short, long);§Panics
Panics if any element is NaN, or is -0.0 (which can’t be normalized to +0.0
without copying — see NotNan::from_primitive_slice_unchecked if you need a true
zero-copy view and can guarantee your data already satisfies NotNan’s invariant).
Sourcepub const unsafe fn from_primitive_slice_unchecked(values: &[T]) -> &[Self]
pub const unsafe fn from_primitive_slice_unchecked(values: &[T]) -> &[Self]
Views primitive values as ordered NotNan values, without validating them.
“Primitive” here means Rust’s built-in float type (e.g. f64).
This runs in O(1) and does not allocate.
§Safety
The caller must guarantee that every element of values is not NaN and not -0.0
(zero must already be canonicalized to +0.0). Because the returned slice is a live
view over the same memory (not a copy), there is no opportunity to normalize -0.0
even if the caller wanted to; the data must already be clean.
NotNan has a public type invariant that safe code must never be able to break, even
though violating it today would only produce incorrect results (see
NotNan::new_unchecked for the full rationale).
Trait Implementations§
impl<T: Copy + NotNanFloat> Copy for NotNan<T>
impl<T: NotNanFloat> Eq for NotNan<T>
Source§impl<T: NotNanFloat> Integer for NotNan<T>
impl<T: NotNanFloat> Integer for NotNan<T>
Source§type SafeLen = <T as NotNanFloat>::SafeLen
type SafeLen = <T as NotNanFloat>::SafeLen
RangeSetBlaze. For example, the length of a RangeSetBlaze<u8> is u16 to handle ranges up to 256 elements.
For larger types like u128, this is represented by a custom type UIntPlusOne<u128>. Read moreSource§fn checked_add_one(self) -> Option<Self>
fn checked_add_one(self) -> Option<Self>
None if the operation would overflow.Source§fn add_one(self) -> Self
fn add_one(self) -> Self
Source§fn sub_one(self) -> Self
fn sub_one(self) -> Self
Source§fn assign_sub_one(&mut self)
fn assign_sub_one(&mut self)
self.Source§fn range_next(range: &mut RangeInclusive<Self>) -> Option<Self>
fn range_next(range: &mut RangeInclusive<Self>) -> Option<Self>
None if the range is exhausted. Read moreSource§fn range_next_back(range: &mut RangeInclusive<Self>) -> Option<Self>
fn range_next_back(range: &mut RangeInclusive<Self>) -> Option<Self>
None if the range is exhausted. Read moreSource§fn min_value() -> Self
fn min_value() -> Self
Source§fn max_value() -> Self
fn max_value() -> Self
Source§fn from_slice(slice: impl AsRef<[Self]>) -> RangeSetBlaze<Self>
fn from_slice(slice: impl AsRef<[Self]>) -> RangeSetBlaze<Self>
from_slice only.RangeSetBlaze from a slice, specific to the integer type.Source§fn safe_len(r: &RangeInclusive<Self>) -> Self::SafeLen
fn safe_len(r: &RangeInclusive<Self>) -> Self::SafeLen
Source§fn safe_len_to_f64_lossy(len: Self::SafeLen) -> f64
fn safe_len_to_f64_lossy(len: Self::SafeLen) -> f64
Integer::SafeLen to f64, potentially losing precision for large values.Source§fn f64_to_safe_len_lossy(f: f64) -> Self::SafeLen
fn f64_to_safe_len_lossy(f: f64) -> Self::SafeLen
f64 to Integer::SafeLen using the formula f as Self::SafeLen. For large integer types, this will result in a loss of precision.Source§fn inclusive_end_from_start(self, b: Self::SafeLen) -> Self
fn inclusive_end_from_start(self, b: Self::SafeLen) -> Self
Source§fn start_from_inclusive_end(self, b: Self::SafeLen) -> Self
fn start_from_inclusive_end(self, b: Self::SafeLen) -> Self
Source§fn exhausted_range() -> RangeInclusive<Self> ⓘ
fn exhausted_range() -> RangeInclusive<Self> ⓘ
Source§impl<T: NotNanFloat> Ord for NotNan<T>
impl<T: NotNanFloat> Ord for NotNan<T>
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl<T: NotNanFloat> PartialOrd for NotNan<T>
impl<T: NotNanFloat> PartialOrd for NotNan<T>
Auto Trait Implementations§
impl<T> Freeze for NotNan<T>where
T: Freeze,
impl<T> RefUnwindSafe for NotNan<T>where
T: RefUnwindSafe,
impl<T> Send for NotNan<T>
impl<T> Sync for NotNan<T>
impl<T> Unpin for NotNan<T>where
T: Unpin,
impl<T> UnsafeUnpin for NotNan<T>where
T: UnsafeUnpin,
impl<T> UnwindSafe for NotNan<T>where
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more