pub trait RealScalar:
FpScalar<RealType = Self, InnerType = Self::RawReal>
+ Sign
+ Rounding
+ Constants
+ PartialEq<f64>
+ PartialOrd
+ PartialOrd<f64>
+ Max
+ Min
+ ATan2
+ for<'a> Pow<&'a Self, Error = PowRealBaseRealExponentErrors<Self::RawReal>>
+ Clamp
+ Classify
+ ExpM1
+ Hypot
+ Ln1p
+ TotalCmp {
type RawReal: RawRealTrait;
// Required methods
fn kernel_mul_add_mul_mut(
&mut self,
mul: &Self,
add_mul1: &Self,
add_mul2: &Self,
);
fn kernel_mul_sub_mul_mut(
&mut self,
mul: &Self,
sub_mul1: &Self,
sub_mul2: &Self,
);
fn try_from_f64(value: f64) -> Result<Self, ErrorsTryFromf64<Self::RawReal>>;
// Provided methods
fn from_f64(value: f64) -> Self { ... }
fn truncate_to_usize(
self,
) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>> { ... }
}Expand description
§Trait for scalar real numbers
RealScalar extends the fundamental FpScalar trait, providing an interface
specifically for real (non-complex) floating-point numbers. It introduces
operations and properties that are unique to real numbers, such as ordering,
rounding, and clamping.
This trait is implemented by real scalar types within each numerical kernel,
for example, f64 for the native kernel,
and RealRugStrictFinite for the rug kernel (when the rug feature is enabled).
§Key Design Principles
- Inheritance from
FpScalar: As a sub-trait ofFpScalar, anyRealScalartype automatically gains all the capabilities of a general floating-point number, including basic arithmetic and standard mathematical functions (e.g.,sin,exp,sqrt). - Raw Underlying Type (
RawReal): This associated type specifies the most fundamental, “raw” representation of the real number, which implements theRawRealTrait. This is the type used for low-level, unchecked operations within the library’s internal implementation.- For
f64,RealNative64StrictFiniteandRealNative64StrictFiniteInDebug,RawRealisf64. - For
RealRugStrictFinite<P>,RawRealisrug::Float.
- For
- Reference-Based Operations: Many operations take arguments by reference (
&Self) to avoid unnecessary clones of potentially expensive arbitrary-precision numbers. - Fallible Constructors:
try_from_f64()validates inputs and ensures exact representability for arbitrary-precision types.
§Creating Validated Real Numbers
There are multiple ways to create validated real scalar instances, depending on your source data and use case:
§1. From f64 Values (Most Common)
Use try_from_f64() for fallible conversion with error handling,
or from_f64() for infallible conversion that panics on invalid input:
use num_valid::{RealNative64StrictFinite, RealScalar};
// Fallible conversion (recommended for runtime values)
let x = RealNative64StrictFinite::try_from_f64(3.14)?;
assert_eq!(x.as_ref(), &3.14);
// Panicking conversion (safe for known-valid constants)
let pi = RealNative64StrictFinite::from_f64(std::f64::consts::PI);
let e = RealNative64StrictFinite::from_f64(std::f64::consts::E);
// Error handling for invalid values
let invalid = RealNative64StrictFinite::try_from_f64(f64::NAN);
assert!(invalid.is_err()); // NaN is rejected§2. From Raw Values (Advanced)
Use try_new() when working with the raw underlying type directly:
use num_valid::RealNative64StrictFinite;
use try_create::TryNew;
// For native f64 types
let x = RealNative64StrictFinite::try_new(42.0)?;
// For arbitrary-precision types (with rug feature)
use num_valid::RealRugStrictFinite;
let high_precision = RealRugStrictFinite::<200>::try_new(
rug::Float::with_val(200, 1.5)
)?;§3. Using Constants
Leverage the Constants trait for mathematical constants:
use num_valid::{RealNative64StrictFinite, Constants};
let pi = RealNative64StrictFinite::pi();
let e = RealNative64StrictFinite::e();
let two = RealNative64StrictFinite::two();
let epsilon = RealNative64StrictFinite::epsilon();§4. From Arithmetic Operations
Create values through validated arithmetic on existing validated numbers:
use num_valid::RealNative64StrictFinite;
use try_create::TryNew;
let a = RealNative64StrictFinite::try_new(2.0)?;
let b = RealNative64StrictFinite::try_new(3.0)?;
let sum = a.clone() + b.clone(); // Automatically validated
let product = &a * &b; // Also works with references§5. Using Zero and One Traits
For generic code, use num::Zero and num::One:
use num_valid::RealNative64StrictFinite;
use num::{Zero, One};
let zero = RealNative64StrictFinite::zero();
let one = RealNative64StrictFinite::one();
assert_eq!(*zero.as_ref(), 0.0);
assert_eq!(*one.as_ref(), 1.0);§Choosing the Right Method
| Method | Use When | Panics? | Example |
|---|---|---|---|
from_f64() | Value is guaranteed valid (constants) | Yes | from_f64(PI) |
try_from_f64() | Value might be invalid (user input) | No | try_from_f64(x)? |
try_new() | Working with raw backend types | No | try_new(raw_val)? |
| Constants trait | Need mathematical constants | No | pi(), e() |
| Arithmetic | Deriving from other validated values | No | a + b |
§Type Safety with Validated Types
Real scalars that use validation policies implementing finite value guarantees automatically gain:
- Full Equality (
Eq): Well-defined, symmetric equality comparisons - Hashing (
Hash): Use as keys inHashMapandHashSet - No Total Ordering: The library intentionally avoids
Ordin favor of more efficient reference-basedfunctions::Max/functions::Minoperations
§Mathematical Operations
§Core Arithmetic
All standard arithmetic operations are available through the Arithmetic trait,
supporting both value and reference semantics:
use num_valid::RealNative64StrictFinite;
use try_create::TryNew;
let a = RealNative64StrictFinite::try_new(2.0).unwrap();
let b = RealNative64StrictFinite::try_new(3.0).unwrap();
// All combinations supported: T op T, T op &T, &T op T, &T op &T
let sum1 = a.clone() + b.clone();
let sum2 = &a + &b;
let sum3 = a.clone() + &b;
let sum4 = &a + b.clone();
assert_eq!(sum1, sum2);
assert_eq!(sum2, sum3);
assert_eq!(sum3, sum4);§Advanced Functions
In addition to the functions from FpScalar, RealScalar provides a suite of methods common in real number arithmetic.
Methods prefixed with kernel_ provide direct access to underlying mathematical operations with minimal overhead:
-
Rounding (
Rounding):kernel_ceil(),kernel_floor(),kernel_round(),kernel_round_ties_even(),kernel_trunc(), andkernel_fract(). -
Sign Manipulation (
Sign):kernel_copysign(),kernel_signum(),kernel_is_sign_positive(), andkernel_is_sign_negative(). -
Comparison and Ordering:
- From
functions::Max/functions::Min:max()andmin(). - From
TotalCmp:total_cmp()for a total ordering compliant with IEEE 754. - From
Clamp:clamp().
- From
-
Specialized Functions:
-
Fused Multiply-Add Variants:
kernel_mul_add_mul_mut()andkernel_mul_sub_mul_mut().
§Constants and Utilities
use num_valid::{RealNative64StrictFinite, Constants};
let pi = RealNative64StrictFinite::pi();
let e = RealNative64StrictFinite::e();
let eps = RealNative64StrictFinite::epsilon();
let max_val = RealNative64StrictFinite::max_finite();§Naming Convention for kernel_* Methods
Methods prefixed with kernel_ (e.g., kernel_ceil, kernel_copysign) are
part of the low-level kernel interface. They typically delegate directly to the
most efficient implementation for the underlying type (like f64::ceil) without
adding extra validation layers. They are intended to be fast primitives upon which
safer, higher-level abstractions can be built.
§Critical Trait Bounds
Self: FpScalar<RealType = Self>: This is the defining constraint. It ensures that the type has all basic floating-point capabilities and confirms that its associated real type is itself.Self: PartialOrd + PartialOrd<f64>: These bounds are essential for comparison operations, allowing instances to be compared both with themselves and with nativef64constants.
§Backend-Specific Behavior
§Native f64 Backend
- Direct delegation to standard library functions
- IEEE 754 compliance
- Maximum performance
§Arbitrary-Precision (rug) Backend
- Configurable precision at compile-time
- Exact arithmetic within precision limits
try_from_f64()validates exact representability
§Error Handling
Operations that can fail provide both panicking and non-panicking variants:
use num_valid::{RealNative64StrictFinite, functions::Sqrt};
use try_create::TryNew;
let positive = RealNative64StrictFinite::try_new(4.0).unwrap();
let negative = RealNative64StrictFinite::try_new(-4.0).unwrap();
// Panicking version (use when input validity is guaranteed)
let sqrt_pos = positive.sqrt();
assert_eq!(*sqrt_pos.as_ref(), 2.0);
// Non-panicking version (use for potentially invalid inputs)
let sqrt_neg_result = negative.try_sqrt();
assert!(sqrt_neg_result.is_err());Required Associated Types§
Sourcetype RawReal: RawRealTrait
type RawReal: RawRealTrait
The most fundamental, “raw” representation of this real number.
This type provides the foundation for all mathematical operations and is used to parameterize error types for this scalar.
§Examples
- For
f64:RawReal = f64 - For
RealNative64StrictFinite:RawReal = f64 - For
RealRugStrictFinite<P>:RawReal = rug::Float
Required Methods§
Sourcefn kernel_mul_add_mul_mut(
&mut self,
mul: &Self,
add_mul1: &Self,
add_mul2: &Self,
)
fn kernel_mul_add_mul_mut( &mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self, )
Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
a.kernel_mul_add_mul_mut(&b, &c, &d) produces a result like &a * &b + &c * &d, but stores the result in a using its precision.
Sourcefn kernel_mul_sub_mul_mut(
&mut self,
mul: &Self,
sub_mul1: &Self,
sub_mul2: &Self,
)
fn kernel_mul_sub_mul_mut( &mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self, )
Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
a.kernel_mul_sub_mul_mut(&b, &c, &d) produces a result like &a * &b - &c * &d, but stores the result in a using its precision.
Sourcefn try_from_f64(value: f64) -> Result<Self, ErrorsTryFromf64<Self::RawReal>>
fn try_from_f64(value: f64) -> Result<Self, ErrorsTryFromf64<Self::RawReal>>
Tries to create an instance of Self from a f64.
This conversion is fallible and validates the input value. For rug-based types,
it also ensures that the f64 can be represented exactly at the target precision.
§Errors
Returns ErrorsTryFromf64 if the value is not finite or cannot be
represented exactly by Self.
§Examples
use num_valid::{RealNative64StrictFinite, RealScalar};
// Valid value
let x = RealNative64StrictFinite::try_from_f64(3.14).unwrap();
assert_eq!(x.as_ref(), &3.14);
// Invalid value (NaN)
assert!(RealNative64StrictFinite::try_from_f64(f64::NAN).is_err());Provided Methods§
Sourcefn from_f64(value: f64) -> Self
fn from_f64(value: f64) -> Self
Creates an instance of Self from a f64, panicking if the value is invalid.
This is a convenience method for cases where you know the value is valid (e.g., constants).
For error handling without panics, use try_from_f64.
§Panics
Panics if the input value fails validation (e.g., NaN, infinity, or subnormal for strict policies).
§Examples
use num_valid::{RealNative64StrictFinite, RealScalar};
// Valid constants - cleaner syntax without unwrap()
let pi = RealNative64StrictFinite::from_f64(std::f64::consts::PI);
let e = RealNative64StrictFinite::from_f64(std::f64::consts::E);
let sqrt2 = RealNative64StrictFinite::from_f64(std::f64::consts::SQRT_2);
assert_eq!(pi.as_ref(), &std::f64::consts::PI);use num_valid::{RealNative64StrictFinite, RealScalar};
// This will panic because NaN is invalid
let invalid = RealNative64StrictFinite::from_f64(f64::NAN);Sourcefn truncate_to_usize(
self,
) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>>
fn truncate_to_usize( self, ) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>>
Safely converts the truncated value to usize.
Truncates toward zero and validates the result is a valid usize.
§Returns
Ok(usize): If truncated value is in0..=usize::MAXErr(_): If value is not finite or out of range
§Examples
use num_valid::{RealNative64StrictFinite, RealScalar};
use try_create::TryNew;
let x = RealNative64StrictFinite::try_new(42.9)?;
assert_eq!(x.truncate_to_usize()?, 42);
let neg = RealNative64StrictFinite::try_new(-1.0)?;
assert!(neg.truncate_to_usize().is_err());Detailed Behavior and Edge Cases
§Truncation Rules
The fractional part is discarded, moving toward zero:
3.7→3-2.9→-20.9→0
§Error Conditions
NotFinite: Value isNaNor±∞OutOfRange: Value is negative or >usize::MAX
§Additional Examples
use num_valid::{RealNative64StrictFinite, RealScalar, validation::ErrorsRawRealToInteger};
use try_create::TryNew;
// Zero
let zero = RealNative64StrictFinite::try_new(0.0)?;
assert_eq!(zero.truncate_to_usize()?, 0);
// Large valid values
let large = RealNative64StrictFinite::try_new(1_000_000.7)?;
assert_eq!(large.truncate_to_usize()?, 1_000_000);
// Values too large for usize
let too_large = RealNative64StrictFinite::try_new(1e20)?;
assert!(matches!(too_large.truncate_to_usize(), Err(ErrorsRawRealToInteger::OutOfRange { .. })));§Practical Usage
use num_valid::{RealNative64StrictFinite, RealScalar};
use try_create::TryNew;
fn create_vector_with_size<T: Default + Clone>(
size_float: RealNative64StrictFinite
) -> Result<Vec<T>, Box<dyn std::error::Error>> {
let size = size_float.truncate_to_usize()?;
Ok(vec![T::default(); size])
}
let size = RealNative64StrictFinite::try_new(10.7)?;
let vec: Vec<i32> = create_vector_with_size(size)?;
assert_eq!(vec.len(), 10); // Truncated from 10.7§Comparison with Alternatives
| Method | Behavior | Range Check | Fractional |
|---|---|---|---|
truncate_to_usize() | Towards zero | ✓ | Discarded |
as usize (raw) | Undefined | ✗ | Undefined |
round().as usize | Nearest | ✗ | Rounded |
floor().as usize | Towards -∞ | ✗ | Discarded |
ceil().as usize | Towards +∞ | ✗ | Discarded |
§Backend-Specific Notes
- Native f64: Uses
az::CheckedAsfor safe conversion with overflow detection - Arbitrary-precision (rug): Respects current precision, may adjust for very large numbers
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
Source§impl RealScalar for f64
impl RealScalar for f64
Source§fn kernel_mul_add_mul_mut(
&mut self,
mul: &Self,
add_mul1: &Self,
add_mul2: &Self,
)
fn kernel_mul_add_mul_mut( &mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self, )
Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
a.kernel_mul_add_mul_mut(&b, &c, &d) produces a result like &a * &b + &c * &d, but stores the result in a using its precision.
Source§fn kernel_mul_sub_mul_mut(
&mut self,
mul: &Self,
sub_mul1: &Self,
sub_mul2: &Self,
)
fn kernel_mul_sub_mul_mut( &mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self, )
Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
a.kernel_mul_sub_mul_mut(&b, &c, &d) produces a result like &a * &b - &c * &d, but stores the result in a using its precision.