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 method
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
, anyRealScalar
type 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
,RealNative64StrictFinite
andRealNative64StrictFiniteInDebug
,RawReal
isf64
. - For
RealRugStrictFinite<P>
,RawReal
isrug::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.
§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 inHashMap
andHashSet
- No Total Ordering: The library intentionally avoids
Ord
in favor of more efficient reference-basedfunctions::Max
/functions::Min
operations
§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
:kernel_clamp()
.
- From
-
Specialized Functions:
- From
ATan2
:atan2()
. - From
ExpM1
/Ln1p
:kernel_exp_m1()
andkernel_ln_1p()
. - From
Hypot
:kernel_hypot()
for computing sqrt(a² + b²). - From
Classify
:kernel_classify()
.
- From
-
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 nativef64
constants.
§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
.
Provided Methods§
Sourcefn truncate_to_usize(
self,
) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>>
fn truncate_to_usize( self, ) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>>
Safely truncates the real number and converts it to a usize
.
This method first truncates the floating-point number towards zero (discarding any
fractional part) and then attempts to convert the result to a usize
. The conversion
is fallible and returns a detailed error if the value cannot be represented as a usize
.
§Behavior
-
Truncation: The fractional part is discarded, moving the value towards zero:
3.7
becomes3
-2.9
becomes-2
0.9
becomes0
-
Conversion: The truncated integer is then converted to
usize
:- Must be non-negative (≥ 0)
- Must not exceed
usize::MAX
- Must be finite (not NaN or infinity)
§Return Value
Ok(usize)
: If the truncated value is within the valid range ofusize
(i.e.,0 ≤ truncated_value ≤ usize::MAX
).Err(ErrorsRawRealToInteger)
: If the conversion fails, with specific error variants:NotFinite
: The original value isNaN
or±∞
OutOfRange
: The truncated value is negative or exceedsusize::MAX
§Use Cases
This method is particularly useful for:
- Converting floating-point indices to array indices
- Converting floating-point sizes to collection capacities
- Interfacing with APIs that require
usize
parameters - Safe downcasting from floating-point calculations to integer contexts
§Examples
§Successful Conversions
use num_valid::{RealNative64StrictFinite, RealScalar};
use try_create::TryNew;
// Positive values with fractional parts
let value = RealNative64StrictFinite::try_new(42.9).unwrap();
assert_eq!(value.truncate_to_usize().unwrap(), 42);
// Zero
let zero = RealNative64StrictFinite::try_new(0.0).unwrap();
assert_eq!(zero.truncate_to_usize().unwrap(), 0);
// Large but valid values
let large = RealNative64StrictFinite::try_new(1_000_000.7).unwrap();
assert_eq!(large.truncate_to_usize().unwrap(), 1_000_000);
// Positive fractional values less than 1
let small = RealNative64StrictFinite::try_new(0.9).unwrap();
assert_eq!(small.truncate_to_usize().unwrap(), 0);
§Error Cases
use num_valid::{RealNative64StrictFinite, RealScalar, validation::ErrorsRawRealToInteger};
use try_create::TryNew;
// Negative values are not valid for usize
let negative = RealNative64StrictFinite::try_new(-10.5).unwrap();
let result = negative.truncate_to_usize();
assert!(matches!(result, Err(ErrorsRawRealToInteger::OutOfRange { .. })));
// Values that are too large for usize
let too_large = RealNative64StrictFinite::try_new(1e20).unwrap();
let result = too_large.truncate_to_usize();
assert!(matches!(result, Err(ErrorsRawRealToInteger::OutOfRange { .. })));
§Practical Usage Example
use num_valid::{RealNative64StrictFinite, RealScalar};
use try_create::TryNew;
fn create_vector_with_calculated_size<T: Default + Clone>(
size_float: RealNative64StrictFinite
) -> Result<Vec<T>, Box<dyn std::error::Error>> {
// Safely convert the floating-point size to usize
let size = size_float.truncate_to_usize()?;
// Create vector with the calculated size
Ok(vec![T::default(); size])
}
// Usage
let calculated_size = RealNative64StrictFinite::try_new(10.7).unwrap();
let vec: Vec<i32> = create_vector_with_calculated_size(calculated_size).unwrap();
assert_eq!(vec.len(), 10); // Truncated from 10.7
§Comparison with Other Conversion Methods
Method | Behavior | Range Check | Fractional Handling |
---|---|---|---|
truncate_to_usize() | Towards zero | ✓ | Discarded |
as usize (raw cast) | Undefined for out-of-range | ✗ | Undefined |
round().as usize | Nearest integer | ✗ | Rounded |
floor().as usize | Towards -∞ | ✗ | Discarded |
ceil().as usize | Towards +∞ | ✗ | Discarded |
§Performance Notes
- This method is optimized for safety over performance
- The finite check is performed first, avoiding unnecessary conversions for invalid inputs
- For performance-critical code where inputs are guaranteed to be valid, consider using unchecked casting methods (but only after careful validation)
§Backend-Specific Behavior
§Native f64
Backend
- Uses
az::CheckedAs
for safe conversion with overflow detection - Leverages hardware floating-point classification
- Direct delegation to standard library truncation
§Arbitrary-Precision (rug
) Backend
- Conversion respects the current precision setting
- May involve internal precision adjustments for very large numbers
- Exact integer detection when possible
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.