num-valid 0.3.3

A robust numerical library providing validated types for real and complex numbers to prevent common floating-point errors like NaN propagation. Features a generic, layered architecture with support for native f64 and optional arbitrary-precision arithmetic.
Documentation
#![deny(rustdoc::broken_intra_doc_links)]

//! Validation traits and marker traits for scalar types.
//!
//! This module provides traits for floating-point classification checks and
//! marker traits that guarantee certain properties of validated types.

use crate::kernels::{RawComplexTrait, RawRealTrait, RawScalarTrait};
use duplicate::duplicate_item;
use num::Complex;
use try_create::ValidationPolicy;

/// Provides a set of fundamental floating-point classification checks.
///
/// This trait defines common methods to determine the characteristics of a numerical value,
/// such as whether it is finite, infinite, NaN (Not a Number), or normal.
/// It is implemented for standard floating-point types (`f64`), complex numbers
/// (`num::Complex<f64>`), and their arbitrary-precision counterparts from the `rug`
/// library (via `RealRugStrictFinite<P>` and `ComplexRugStrictFinite<P>` which internally use [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html)
/// and [`rug::Complex`](https://docs.rs/rug/latest/rug/struct.Complex.html)) when the "rug" feature is enabled.
///
/// `FpChecks` is often used as a supertrait for more general numerical traits like
/// [`FpScalar`](crate::FpScalar), ensuring that types representing floating-point
/// scalars can be queried for these basic properties. This is essential for
/// validation policies and writing robust numerical algorithms.
///
/// Note that this trait focuses on these specific classifications. For more detailed
/// categorization (like distinguishing subnormals or zero explicitly through this trait),
/// types may provide other methods (e.g., `classify()` for `f64` and [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html),
/// or `is_zero()` from [`FpScalar`](crate::FpScalar)).
pub trait FpChecks {
    /// Returns [`true`] if `self` is finite (i.e., not infinite and not NaN).
    ///
    /// For complex numbers, this typically means both the real and imaginary parts are finite.
    fn is_finite(&self) -> bool;

    /// Returns [`true`] if `self` is positive infinity or negative infinity.
    ///
    /// For complex numbers, this typically means at least one part is infinite,
    /// and no part is NaN.
    fn is_infinite(&self) -> bool;

    /// Returns [`true`] if `self` is NaN (Not a Number).
    ///
    /// For complex numbers, this typically means at least one part is NaN.
    fn is_nan(&self) -> bool;

    /// Returns [`true`] if `self` is a *normal* number.
    ///
    /// A normal number is a finite, non-zero number that is not subnormal.
    /// For complex numbers, this typically means both real and imaginary parts are normal
    /// numbers (and thus individually finite, non-zero, and not subnormal).
    fn is_normal(&self) -> bool;
}

#[duplicate_item(
    T;
    [f64];
    [Complex::<f64>];
)]
impl FpChecks for T {
    #[inline(always)]
    fn is_finite(&self) -> bool {
        T::is_finite(*self)
    }

    #[inline(always)]
    fn is_infinite(&self) -> bool {
        T::is_infinite(*self)
    }

    #[inline(always)]
    fn is_nan(&self) -> bool {
        T::is_nan(*self)
    }

    #[inline(always)]
    fn is_normal(&self) -> bool {
        T::is_normal(*self)
    }
}
//------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------
/// A marker for policies that apply to real types.
///
/// This trait refines the generic [`ValidationPolicy`] for types that implement
/// [`RawRealTrait`]. It adds two key constraints:
///
/// 1.  It associates a `const PRECISION` with the policy, essential for backends
///     like `rug`.
/// 2.  It enforces that the policy's `Error` type must be the same as the canonical
///     `ValidationErrors` type defined on the raw scalar itself. This architectural
///     choice ensures consistent error handling throughout the library.
pub trait ValidationPolicyReal:
    ValidationPolicy<
        Value: RawRealTrait,
        Error = <<Self as ValidationPolicy>::Value as RawScalarTrait>::ValidationErrors,
    >
{
    /// The precision (in bits) of the validated real type.
    ///
    /// For IEEE 754 double-precision (`f64`), this is 53 bits.
    /// For arbitrary-precision types like `rug::Float`, this can be any positive integer.
    const PRECISION: u32;
}

/// A marker for policies that apply to complex types.
///
/// This trait refines the generic [`ValidationPolicy`] for types that implement
/// [`RawComplexTrait`]. It adds two key constraints:
///
/// 1.  It associates a `const PRECISION` with the policy, essential for backends
///     like `rug`.
/// 2.  It enforces that the policy's `Error` type must be the same as the canonical
///     `ValidationErrors` type defined on the raw scalar itself. This architectural
///     choice ensures consistent error handling throughout the library.
pub trait ValidationPolicyComplex:
    ValidationPolicy<
        Value: RawComplexTrait,
        Error = <<Self as ValidationPolicy>::Value as RawScalarTrait>::ValidationErrors,
    >
{
    /// The precision (in bits) of the validated complex type's components.
    ///
    /// For IEEE 754 double-precision (`Complex<f64>`), this is 53 bits.
    /// For arbitrary-precision types like `rug::Complex`, this can be any positive integer.
    const PRECISION: u32;
}

/// A marker trait for validation policies that guarantee finite real values.
///
/// This trait serves as a compile-time marker to identify policies that ensure
/// all validated real values are always finite (never NaN or infinite). It enables
/// the implementation of full equality ([`Eq`]) and hashing ([`Hash`]) for
/// validated types, allowing them to be used as keys in hash-based collections
/// like [`HashMap`](std::collections::HashMap) and [`HashSet`](std::collections::HashSet).
///
/// ## Enabled Features
///
/// When a validation policy implements this trait, the corresponding validated types
/// (like [`RealValidated<K>`](crate::RealValidated)) automatically gain:
///
/// - **Full Equality ([`Eq`])**: Equality becomes reflexive, symmetric, and transitive
///   since NaN values (which violate these properties) are excluded.
/// - **Total Ordering ([`Ord`])**: Enables total ordering for validated types, allowing
///   use in sorted collections like [`BTreeMap`](std::collections::BTreeMap) and [`BTreeSet`](std::collections::BTreeSet),
///   and enabling standard library sorting operations.
/// - **Hashing ([`Hash`])**: Combined with [`Eq`], this allows validated types to be
///   used as keys in hash-based collections like [`HashMap`](std::collections::HashMap) and [`HashSet`](std::collections::HashSet).
///
/// ## Hashing Implementation Details
///
/// The [`Hash`] implementation for validated types:
/// - Delegates to the underlying raw type's [`RawScalarTrait::compute_hash`] method
/// - Handles IEEE 754 floating-point edge cases correctly (e.g., signed zeros)
/// - Maintains the contract that `a == b` implies `hash(a) == hash(b)`
/// - Works with both native `f64`/`Complex<f64>` and arbitrary-precision `rug` types
///
/// ## Comparison and Ordering
///
/// Validated types with finite value guarantees support multiple comparison mechanisms:
/// 1. **Partial Ordering ([`PartialOrd`])**: Always available, efficient for comparisons
/// 2. **Total Ordering ([`Ord`])**: Available when this trait is implemented, enables sorted collections
/// 3. **Reference-based comparison**: The library's [`Max`](crate::functions::Max)/[`Min`](crate::functions::Min)
///    traits provide `max_by_ref()`/`min_by_ref()` methods that avoid unnecessary cloning
///
/// ## Use Cases
///
/// This marker trait enables validated numerical types to be used in contexts that
/// require [`Eq`], [`Hash`], and [`Ord`]:
///
/// ```rust
/// use num_valid::{RealNative64StrictFinite, functions::Max};
/// use std::collections::{HashMap, HashSet, BTreeMap, BTreeSet};
/// use try_create::TryNew;
///
/// // Use as HashMap keys (requires Eq + Hash)
/// let mut scores = HashMap::new();
/// let player1 = RealNative64StrictFinite::try_new(1.5).unwrap();
/// scores.insert(player1, 100);
///
/// // Use in HashSet (requires Eq + Hash)
/// let mut unique_values = HashSet::new();
/// unique_values.insert(RealNative64StrictFinite::try_new(3.14).unwrap());
///
/// // Use in BTreeMap (requires Ord)
/// let mut sorted_scores = BTreeMap::new();
/// sorted_scores.insert(RealNative64StrictFinite::try_new(1.5).unwrap(), 100);
///
/// // Comparison works with both PartialOrd and Ord
/// let a = RealNative64StrictFinite::try_new(1.0).unwrap();
/// let b = RealNative64StrictFinite::try_new(2.0).unwrap();
/// assert!(a < b);  // Uses PartialOrd
/// assert_eq!(a.clone().max(b.clone()), b);  // Uses Ord::max from std (consumes values)
/// assert_eq!(a.max_by_ref(&b), &b);  // Uses library's Max trait (avoids cloning)
/// ```
///
/// ## Hash Collision Considerations
///
/// The hashing implementation ensures:
/// - Consistent hashes for mathematically equal values
/// - Proper handling of floating-point edge cases
/// - Compatibility with both native and arbitrary-precision backends
/// - No hash collisions due to NaN values (which are excluded by design)
///
/// ## Currently Implemented By
///
/// - [`StrictFinitePolicy<T, P>`](crate::core::policies::StrictFinitePolicy): The primary policy that
///   rejects NaN, infinity, and subnormal values.
/// - [`DebugValidationPolicy<StrictFinitePolicy<T, P>>`](crate::core::policies::DebugValidationPolicy):
///   A wrapper that applies strict validation only in debug builds.
///
/// ## Safety and Correctness
///
/// This trait should only be implemented by validation policies that genuinely
/// guarantee finite values. Incorrect implementation could lead to hash collisions
/// or violated equality contracts in the methods that rely on this guarantee.
///
/// The trait is designed as a marker trait (no methods) to emphasize that it's
/// purely a compile-time contract rather than runtime functionality.
pub trait GuaranteesFiniteRealValues: ValidationPolicyReal {}

/// Marker trait indicating that a validation policy guarantees finite complex values.
///
/// This trait serves as a compile-time indicator that a validation policy for
/// complex numbers ensures all validated values have finite real and imaginary components
/// (i.e., neither component is NaN or infinity). This guarantee enables the
/// implementation of [`Eq`] and [`Hash`] for [`ComplexValidated`](crate::core::types::ComplexValidated) types, allowing
/// them to be used as keys in hash-based collections like [`HashMap`](std::collections::HashMap)
/// and [`HashSet`](std::collections::HashSet).
///
/// ## Purpose
///
/// Complex numbers can have NaN or infinite components, making equality comparison
/// problematic (NaN != NaN). By guaranteeing finiteness at the policy level,
/// this trait allows:
/// - Full equality ([`Eq`]) implementation for complex validated types
/// - Consistent hashing ([`Hash`]) for use in hash-based collections
/// - Compile-time verification of these properties
///
/// ## Design Rationale
///
/// This trait works in tandem with [`GuaranteesFiniteRealValues`] for real numbers:
/// - [`GuaranteesFiniteRealValues`]: For real number policies
/// - [`GuaranteesFiniteComplexValues`]: For complex number policies
///
/// This separation allows different validation strategies for real and complex
/// components while maintaining type safety.
///
/// ## Currently Implemented By
///
/// - [`StrictFinitePolicy<T, P>`](crate::core::policies::StrictFinitePolicy): Validates both real and imaginary
///   components for finiteness and non-subnormal values.
/// - [`DebugValidationPolicy<StrictFinitePolicy<T, P>>`](crate::core::policies::DebugValidationPolicy):
///   Applies strict validation only in debug builds.
///
/// ## Safety and Correctness
///
/// This trait should only be implemented by validation policies that genuinely
/// guarantee finite values in both components. Incorrect implementation could lead
/// to hash collisions or violated equality contracts.
pub trait GuaranteesFiniteComplexValues: ValidationPolicyComplex {}