num_valid/
kernels.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! # Numerical Kernels and Validated Types
4//!
5//! This module is the core of the numerical backend for the [`num-valid`](crate) crate.
6//! It defines the fundamental traits, types, and operations for floating-point arithmetic.
7//!
8//! ## Core Architecture
9//!
10//! The architecture is built on three key concepts:
11//!
12//! 1.  **Raw Traits ([`RawScalarTrait`], [`RawRealTrait`], [`RawComplexTrait`]):**
13//!     These traits define the baseline contract for a "raw" number type (like [`f64`] or
14//!     [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html)).
15//!     They provide a comprehensive set of `unchecked_*` methods for arithmetic and mathematical
16//!     functions. The "unchecked" prefix signifies that these methods do **not** perform
17//!     any validation (e.g., for domain, finiteness, or division by zero) and are intended
18//!     for internal use where validity has already been confirmed.
19//!
20//! 2.  **Validated Structs ([`RealValidated`], [`ComplexValidated`]):**
21//!     These are wrapper types (newtypes) that enforce correctness. An instance of `RealValidated<P>`
22//!     is guaranteed to hold a raw value that has been successfully validated against the policy `P`.
23//!     All operations on these types (addition, `sqrt`, etc.) are designed to preserve this validity,
24//!     either by returning a `Result` or by panicking on failure in debug builds.
25//!
26//! 3.  **Validation Policies ([`NumKernel`]):**
27//!     This trait allows the validation strategy to be generic. A kernel can be configured with
28//!     different policies, such as [`NumKernelStrictFinite`], which ensures all numbers are
29//!     finite (not NaN or Infinity).
30//!
31//! ## Available Kernels
32//!
33//! The library provides concrete kernels that bundle these concepts:
34//!
35//! - **`native64`:** Uses Rust's standard [`f64`] and `num::Complex<f64>` as the raw types.
36//!   This is the default, high-performance kernel.
37//!
38//! - **`rug` (feature-gated):** Uses arbitrary-precision types from the [`rug`](https://crates.io/crates/rug) crate,
39//!   ideal for high-precision scientific computing.
40
41pub mod native64;
42pub mod native64_validated;
43mod validated;
44
45#[cfg(feature = "rug")]
46pub mod rug;
47
48pub use validated::{ComplexValidated, RealValidated};
49
50use crate::{
51    ComplexScalar, Conjugate, FpChecks, NegAssign, NeumaierAddable, RealScalar,
52    functions::{Rounding, Sign},
53    validation::{
54        DebugValidationPolicy, ErrorsRawRealToInteger, ErrorsTryFromf64,
55        ErrorsValidationRawComplex, ErrorsValidationRawReal, StrictFinitePolicy,
56        ValidationPolicyComplex, ValidationPolicyReal,
57    },
58};
59use az::CheckedAs;
60use duplicate::duplicate_item;
61use num::{Complex, Zero};
62use num_traits::{MulAdd, MulAddAssign};
63use serde::{Deserialize, Serialize};
64use std::{
65    backtrace::Backtrace,
66    cmp::Ordering,
67    fmt::{Debug, Display},
68    hash::{Hash, Hasher},
69    marker::PhantomData,
70    num::FpCategory,
71    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
72};
73
74/// A baseline trait for raw scalar types, defining core operations and properties.
75///
76/// This trait must be implemented by the underlying number types used in a kernel,
77/// such as like [`f64`] or [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
78/// It provides a standard interface for arithmetic
79/// and a suite of `unchecked_*` methods for mathematical functions.
80///
81/// # Safety and Contracts
82///
83/// The `unchecked_*` methods are designed for performance and assume that the caller
84/// has already validated the inputs. Calling them with invalid data (e.g., `unchecked_sqrt`
85/// on a negative real number) may lead to panics, incorrect results, or undefined behavior,
86/// depending on the underlying type's implementation.
87pub trait RawScalarTrait:
88    Serialize + for<'a> Deserialize<'a>
89    + Debug
90    + Display
91    + Clone
92    + Sync
93    + Send
94    + Add<Output = Self>
95    + Sub<Output = Self>
96    + Mul<Output = Self>
97    + Div<Output = Self>
98    + for<'a> Add<&'a Self, Output = Self>
99    + for<'a> Sub<&'a Self, Output = Self>
100    + for<'a> Mul<&'a Self, Output = Self>
101    + for<'a> Div<&'a Self, Output = Self>
102    + AddAssign
103    + SubAssign
104    + MulAssign
105    + DivAssign
106    + for<'a> AddAssign<&'a Self>
107    + for<'a> SubAssign<&'a Self>
108    + for<'a> MulAssign<&'a Self>
109    + for<'a> DivAssign<&'a Self>
110    + Neg<Output = Self>
111    + NegAssign
112    + NeumaierAddable
113    + PartialEq
114//    + MulAddRef
115    + FpChecks
116    + 'static
117{
118    /// The associated error type for validation failures of this raw type.
119    type ValidationErrors: std::error::Error;
120
121    fn is_zero(&self) -> bool;
122
123    fn raw_zero(precision: u32) -> Self;
124
125    fn raw_one(precision: u32) -> Self;
126
127    fn raw_negative_one(precision: u32) -> Self {
128        Self::raw_one(precision).neg()
129    }
130
131    /// Computes the reciprocal (1/x) without validation.
132    /// 
133    /// **Contract:** The caller must ensure `self` is not zero.
134    fn unchecked_reciprocal(self) -> Self;
135
136    /// Computes the exponential (e^x) without validation.
137    /// 
138    /// **Contract:** The caller must ensure the input is valid.
139    fn unchecked_exp(self) -> Self;
140
141    /// Computes the square root without validation.
142    /// 
143    /// **Contract:** For real numbers, the caller must ensure `self >= 0`.
144    fn unchecked_sqrt(self) -> Self;
145
146    fn unchecked_sin(self) -> Self;
147
148    fn unchecked_asin(self) -> Self;
149
150    fn unchecked_cos(self) -> Self;
151
152    fn unchecked_acos(self) -> Self;
153
154    fn unchecked_tan(self) -> Self;
155
156    fn unchecked_atan(self) -> Self;
157
158    fn unchecked_sinh(self) -> Self;
159
160    fn unchecked_asinh(self) -> Self;
161
162    fn unchecked_cosh(self) -> Self;
163
164    fn unchecked_acosh(self) -> Self;
165
166    fn unchecked_tanh(self) -> Self;
167
168    fn unchecked_atanh(self) -> Self;
169
170    fn unchecked_ln(self) -> Self;
171    fn unchecked_log2(self) -> Self;
172    fn unchecked_log10(self) -> Self;
173
174    /// Raises `self` to the power of an `i8` exponent without validation.
175    /// 
176    /// **Contract:** The caller must ensure the inputs are valid.
177    fn unchecked_pow_exponent_i8(self, exponent: &i8) -> Self;
178
179    /// Raises `self` to the power of an `i16` exponent without validation.
180    /// 
181    /// **Contract:** The caller must ensure the inputs are valid.
182    fn unchecked_pow_exponent_i16(self, exponent: &i16) -> Self;
183
184    /// Raises `self` to the power of an `i32` exponent without validation.
185    /// 
186    /// **Contract:** The caller must ensure the inputs are valid.
187    fn unchecked_pow_exponent_i32(self, exponent: &i32) -> Self;
188
189    /// Raises `self` to the power of an `i64` exponent without validation.
190    /// 
191    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
192    /// includes ensuring the `exponent` is within the representable range of the underlying
193    /// power function (e.g., `i32` for `f64::powi`).
194    fn unchecked_pow_exponent_i64(self, exponent: &i64) -> Self;
195
196    /// Raises `self` to the power of an `i128` exponent without validation.
197    /// 
198    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
199    /// includes ensuring the `exponent` is within the representable range of the underlying
200    /// power function (e.g., `i32` for `f64::powi`).
201    fn unchecked_pow_exponent_i128(self, exponent: &i128) -> Self;
202
203    /// Raises `self` to the power of an `isize` exponent without validation.
204    /// 
205    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
206    /// includes ensuring the `exponent` is within the representable range of the underlying
207    /// power function (e.g., `i32` for `f64::powi`).
208    fn unchecked_pow_exponent_isize(self, exponent: &isize) -> Self;
209
210    /// Raises `self` to the power of an `u8` exponent without validation.
211    /// 
212    /// **Contract:** The caller must ensure the inputs are valid.
213    fn unchecked_pow_exponent_u8(self, exponent: &u8) -> Self;
214
215    /// Raises `self` to the power of an `u16` exponent without validation.
216    /// 
217    /// **Contract:** The caller must ensure the inputs are valid.
218    fn unchecked_pow_exponent_u16(self, exponent: &u16) -> Self;
219
220    /// Raises `self` to the power of an `u32` exponent without validation.
221    /// 
222    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
223    /// includes ensuring the `exponent` is within the representable range of the underlying
224    /// power function (e.g., `i32` for `f64::powi`).
225    fn unchecked_pow_exponent_u32(self, exponent: &u32) -> Self;
226
227    /// Raises `self` to the power of an `u64` exponent without validation.
228    /// 
229    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
230    /// includes ensuring the `exponent` is within the representable range of the underlying
231    /// power function (e.g., `i32` for `f64::powi`).
232    fn unchecked_pow_exponent_u64(self, exponent: &u64) -> Self;
233
234    /// Raises `self` to the power of an `u128` exponent without validation.
235    /// 
236    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
237    /// includes ensuring the `exponent` is within the representable range of the underlying
238    /// power function (e.g., `i32` for `f64::powi`).
239    fn unchecked_pow_exponent_u128(self, exponent: &u128) -> Self;
240
241    /// Raises `self` to the power of an `usize` exponent without validation.
242    /// 
243    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
244    /// includes ensuring the `exponent` is within the representable range of the underlying
245    /// power function (e.g., `i32` for `f64::powi`).
246    fn unchecked_pow_exponent_usize(self, exponent: &usize) -> Self;
247
248    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
249    ///
250    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
251    ///
252    /// **Contract:** The caller must ensure all inputs are valid.
253    fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self;
254}
255
256/// A trait for raw real scalar types, extending [`RawScalarTrait`] with real-specific operations.
257///
258/// This trait defines the fundamental operations for real number types without
259/// validation or safety checks. Implementations should assume inputs are valid
260/// and focus on computational efficiency.
261///
262/// This trait is implemented by the underlying real number types within a kernel, such as [`f64`]
263/// or [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
264/// It builds upon [`RawScalarTrait`] by adding operations that are unique
265/// to real numbers, like `atan2`, and by enforcing an ordering relationship.
266///
267/// ## Hashing Support
268///
269/// Types implementing this trait must provide a `compute_hash` method that:
270/// - Produces consistent hash values for mathematically equal numbers
271/// - Handles floating-point edge cases (like signed zeros) correctly  
272/// - Maintains the contract that `a == b` implies `hash(a) == hash(b)`
273///
274/// This enables validated wrapper types to implement [`Hash`] when appropriate
275/// validation policies guarantee finite values.
276///
277/// # Trait Bounds
278///
279/// - `RawScalarTrait<ValidationErrors = ErrorsValidationRawReal<Self>>`: Ensures that the type
280///   is a raw scalar and that its validation error type is the standard one for real numbers.
281/// - [`PartialOrd`]: Requires that the type can be partially ordered, which is fundamental for
282///   real numbers.
283/// - [`PartialOrd<f64>`]: These crucial bounds allow instances of the raw
284///   real type to be directly compared with `f64` constants. This is essential for implementing
285///   domain checks (e.g., `value < 0.0` or `value >= 0.0`) that work across
286///   both [`f64`] and [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) without extra conversions.
287///
288/// # Associated Types
289///
290/// - `type RawComplex: RawComplexTrait<RawReal = Self>`: This links the raw real type to its
291///   corresponding complex number representation. For example, for [`f64`], this would be
292///   [`num::Complex<f64>`]. This association is vital for operations that can transition
293///   from the real to the complex domain.
294pub trait RawRealTrait:
295    RawScalarTrait<ValidationErrors = ErrorsValidationRawReal<Self>>
296    + PartialOrd
297    + PartialOrd<f64>
298    + Sign
299    + Rounding
300{
301    /// The associated complex type that uses this type as its real part.
302    type RawComplex: RawComplexTrait<RawReal = Self>;
303
304    /// Computes the absolute value of `self` without validation.
305    ///
306    /// **Contract:** The caller must ensure that the input value has already been validated
307    /// and is suitable for the operation.
308    fn unchecked_abs(self) -> Self;
309
310    /// Computes the four-quadrant arctangent of `self` (`y`) and `denominator` (`x`) without validation.
311    ///
312    /// **Contract:** The caller must ensure that `self` and `denominator` are not both zero.
313    fn unchecked_atan2(self, denominator: &Self) -> Self;
314
315    /// Raises `self` to the power of a real `exponent` without validation.
316    ///
317    /// **Contract:** The caller must ensure the inputs are valid for the power function. For
318    /// example, if `self` is negative, the `exponent` should be an integer, but this function
319    /// does not enforce this.
320    fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self;
321
322    fn unchecked_hypot(self, other: &Self) -> Self;
323
324    fn unchecked_ln_1p(self) -> Self;
325
326    fn unchecked_exp_m1(self) -> Self;
327
328    /// Multiplies two pairs and adds them, rounding to the nearest.
329    /// `a.unchecked_mul_add_mul_mut(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
330    ///
331    /// **Contract:** The caller must ensure all inputs are valid.
332    fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
333
334    /// Multiplies two pairs and subtracts them, rounding to the nearest.
335    /// `a.unchecked_mul_sub_mul_mut(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
336    ///
337    /// **Contract:** The caller must ensure all inputs are valid.
338    fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
339
340    fn raw_total_cmp(&self, other: &Self) -> Ordering;
341
342    /// Clamps the value within the specified bounds.
343    fn raw_clamp(self, min: &Self, max: &Self) -> Self;
344
345    fn raw_classify(&self) -> FpCategory;
346
347    fn raw_two(precision: u32) -> Self;
348
349    fn raw_one_div_2(precision: u32) -> Self;
350
351    fn raw_pi(precision: u32) -> Self;
352
353    fn raw_two_pi(precision: u32) -> Self;
354
355    fn raw_pi_div_2(precision: u32) -> Self;
356
357    fn raw_max_finite(precision: u32) -> Self;
358
359    fn raw_min_finite(precision: u32) -> Self;
360
361    fn raw_epsilon(precision: u32) -> Self;
362
363    fn raw_ln_2(_precision: u32) -> Self;
364
365    fn raw_ln_10(_precision: u32) -> Self;
366
367    fn raw_log10_2(_precision: u32) -> Self;
368
369    fn raw_log2_10(_precision: u32) -> Self;
370
371    fn raw_log2_e(_precision: u32) -> Self;
372
373    fn raw_log10_e(_precision: u32) -> Self;
374
375    fn raw_e(_precision: u32) -> Self;
376
377    fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
378        value: f64,
379    ) -> Result<Self, ErrorsTryFromf64<Self>>;
380
381    /// Returns the precision (in bits) of the raw real type.
382    fn precision(&self) -> u32;
383
384    /// Computes a hash value for this real number.
385    ///
386    /// This method must ensure that mathematically equal values produce
387    /// the same hash, even across different representations (e.g., +0.0 and -0.0).
388    fn compute_hash<H: Hasher>(&self, state: &mut H);
389
390    /// Safely truncates the real number and converts it to a `usize`.
391    ///
392    /// This function first truncates the number towards zero (discarding any
393    /// fractional part) and then attempts to convert the result to a `usize`.
394    /// The conversion is fallible and returns a detailed error if the value
395    /// cannot be represented as a `usize`.
396    ///
397    /// # Returns
398    ///
399    /// - `Ok(usize)`: If the truncated value is within the valid range of `usize`
400    ///   (i.e., `0 <= value <= usize::MAX`).
401    /// - `Err(ErrorsRawRealToInteger)`: If the conversion fails, with a variant
402    ///   indicating the reason:
403    ///     - `NotFinite`: If the original value is `NaN` or `Infinity`.
404    ///     - `OutOfRange`: If the truncated value is negative or exceeds `usize::MAX`.
405    ///
406    /// # Note
407    ///
408    /// The `NotAnInteger` error variant is not returned by this function because
409    /// the truncation step explicitly handles the fractional part.
410    ///
411    /// # Examples
412    ///
413    /// ## Success
414    /// ```
415    /// # use num_valid::kernels::{RawRealTrait};
416    /// let value = 42.9_f64;
417    /// assert_eq!(value.truncate_to_usize().unwrap(), 42);
418    ///
419    /// let zero = 0.0_f64;
420    /// assert_eq!(zero.truncate_to_usize().unwrap(), 0);
421    /// ```
422    ///
423    /// ## Failure
424    /// ```
425    /// # use num_valid::kernels::{RawRealTrait};
426    /// # use num_valid::validation::ErrorsRawRealToInteger;
427    /// // Value is negative
428    /// let negative_value = -10.5_f64;
429    /// assert!(matches!(negative_value.truncate_to_usize(), Err(ErrorsRawRealToInteger::OutOfRange { .. })));
430    ///
431    /// // Value is too large for usize
432    /// let large_value = (usize::MAX as f64) + 100.0;
433    /// assert!(matches!(large_value.truncate_to_usize(), Err(ErrorsRawRealToInteger::OutOfRange { .. })));
434    ///
435    /// // Value is not finite
436    /// let nan_value = f64::NAN;
437    /// assert!(matches!(nan_value.truncate_to_usize(), Err(ErrorsRawRealToInteger::NotFinite { .. })));
438    /// ```
439    fn truncate_to_usize(self) -> Result<usize, ErrorsRawRealToInteger<Self, usize>>;
440}
441
442/// A trait for raw complex scalar types, extending [`RawScalarTrait`].
443///
444/// This trait is implemented by the underlying complex number types within a kernel,
445/// such as [`num::Complex<f64>`]. It builds upon [`RawScalarTrait`] by adding operations
446/// that are unique to complex numbers.
447///
448/// # Trait Bounds
449///
450/// - `RawScalarTrait<...>`: Ensures the type is a raw scalar and fixes its validation
451///   error type to [`ErrorsValidationRawComplex`], which in turn wraps the validation
452///   error of the associated real type. This establishes a consistent error structure.
453/// - [`Conjugate`]: Requires that the complex number can be conjugated.
454///
455/// # Associated Types
456///
457/// - `type RawReal: RawRealTrait<RawComplex = Self>`: This is a critical part of the
458///   design. It links the complex type to its underlying real component type (e.g., [`f64`]
459///   for [`num::Complex<f64>`]). This associated real type must itself implement [`RawRealTrait`],
460///   creating a two-way link between the real and complex raw types.
461///
462/// # Methods
463///
464/// This trait provides methods for accessing components and performing complex-specific
465/// mathematical operations without validation checks.
466pub trait RawComplexTrait:
467    RawScalarTrait<
468        ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<Self::RawReal>>,
469    > + Conjugate
470    + for<'a> Mul<&'a Self::RawReal, Output = Self>
471    + for<'a> MulAssign<&'a Self::RawReal>
472{
473    /// The associated real type that makes up the components of this complex type.
474    type RawReal: RawRealTrait<RawComplex = Self>;
475
476    fn new_unchecked_raw_complex(real: Self::RawReal, imag: Self::RawReal) -> Self;
477
478    /// Computes the absolute value (modulus or norm) of `self` without validation.
479    ///
480    /// **Contract:** The caller must ensure the input is valid for this operation.
481    fn unchecked_abs(self) -> Self::RawReal;
482
483    /// Returns a reference to the real part of the complex number.
484    fn raw_real_part(&self) -> &Self::RawReal;
485
486    /// Returns a reference to the imaginary part of the complex number.
487    fn raw_imag_part(&self) -> &Self::RawReal;
488
489    /// Returns a mutable reference to the real part of the complex number.
490    fn mut_raw_real_part(&mut self) -> &mut Self::RawReal;
491
492    /// Returns a mutable reference to the imaginary part of the complex number.
493    fn mut_raw_imag_part(&mut self) -> &mut Self::RawReal;
494
495    /// Computes the argument (or phase) of `self` in radians, without validation.
496    ///
497    /// **Contract:** The caller must ensure that `self` is not zero.
498    fn unchecked_arg(self) -> Self::RawReal;
499
500    /// Raises `self` to the power of a real `exponent` without validation.
501    ///
502    /// **Contract:** The caller must ensure the inputs are valid for the power function.
503    fn unchecked_pow_exponent_real(self, exponent: &Self::RawReal) -> Self;
504}
505
506impl RawScalarTrait for f64 {
507    type ValidationErrors = ErrorsValidationRawReal<f64>;
508
509    #[inline(always)]
510    fn raw_zero(_precision: u32) -> f64 {
511        0.
512    }
513
514    #[inline(always)]
515    fn is_zero(&self) -> bool {
516        <Self as Zero>::is_zero(self)
517    }
518    #[inline(always)]
519    fn raw_one(_precision: u32) -> f64 {
520        1.
521    }
522
523    #[duplicate_item(
524        unchecked_method       method;
525        [unchecked_reciprocal] [recip];
526        [unchecked_exp]        [exp];
527        [unchecked_sqrt]       [sqrt];
528        [unchecked_sin]        [sin];
529        [unchecked_asin]       [asin];
530        [unchecked_cos]        [cos];
531        [unchecked_acos]       [acos];
532        [unchecked_tan]        [tan];
533        [unchecked_atan]       [atan];
534        [unchecked_sinh]       [sinh];
535        [unchecked_asinh]      [asinh];
536        [unchecked_cosh]       [cosh];
537        [unchecked_acosh]      [acosh];
538        [unchecked_tanh]       [tanh];
539        [unchecked_atanh]      [atanh];
540        [unchecked_ln]         [ln];
541        [unchecked_log2]       [log2];
542        [unchecked_log10]      [log10];
543    )]
544    #[inline(always)]
545    fn unchecked_method(self) -> f64 {
546        f64::method(self)
547    }
548
549    #[duplicate_item(
550        unchecked_method             exponent_type;
551        [unchecked_pow_exponent_i8]  [i8];
552        [unchecked_pow_exponent_i16] [i16];
553        [unchecked_pow_exponent_u8]  [u8];
554        [unchecked_pow_exponent_u16] [u16];
555    )]
556    #[inline(always)]
557    fn unchecked_method(self, exponent: &exponent_type) -> f64 {
558        f64::powi(self, (*exponent).into())
559    }
560
561    #[inline(always)]
562    fn unchecked_pow_exponent_i32(self, exponent: &i32) -> Self {
563        f64::powi(self, *exponent)
564    }
565
566    #[duplicate_item(
567        unchecked_method               exponent_type;
568        [unchecked_pow_exponent_i64]   [i64];
569        [unchecked_pow_exponent_i128]  [i128];
570        [unchecked_pow_exponent_isize] [isize];
571        [unchecked_pow_exponent_u32]   [u32];
572        [unchecked_pow_exponent_u64]   [u64];
573        [unchecked_pow_exponent_u128]  [u128];
574        [unchecked_pow_exponent_usize] [usize];
575    )]
576    #[inline(always)]
577    fn unchecked_method(self, exponent: &exponent_type) -> f64 {
578        f64::powi(
579            self,
580            (*exponent)
581                .try_into()
582                .expect("The exponent {exponent} cannot be converted to an integer of type i32"),
583        )
584    }
585
586    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
587    ///
588    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
589    #[inline(always)]
590    fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
591        f64::mul_add(self, *b, *c)
592    }
593}
594
595impl RawRealTrait for f64 {
596    type RawComplex = Complex<f64>;
597
598    #[inline(always)]
599    fn unchecked_abs(self) -> f64 {
600        f64::abs(self)
601    }
602
603    #[inline(always)]
604    fn unchecked_atan2(self, denominator: &Self) -> Self {
605        f64::atan2(self, *denominator)
606    }
607
608    #[inline(always)]
609    fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self {
610        f64::powf(self, *exponent)
611    }
612
613    #[inline(always)]
614    fn unchecked_hypot(self, other: &Self) -> Self {
615        f64::hypot(self, *other)
616    }
617
618    #[inline(always)]
619    fn unchecked_ln_1p(self) -> Self {
620        f64::ln_1p(self)
621    }
622
623    #[inline(always)]
624    fn unchecked_exp_m1(self) -> Self {
625        f64::exp_m1(self)
626    }
627
628    /// Multiplies two pairs and adds them in one fused operation, rounding to the nearest with only one rounding error.
629    /// `a.unchecked_mul_add_mul_mut(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
630    #[inline(always)]
631    fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
632        self.mul_add_assign(*mul, add_mul1 * add_mul2);
633    }
634
635    /// Multiplies two pairs and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
636    /// `a.unchecked_mul_sub_mul_mut(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
637    #[inline(always)]
638    fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
639        self.mul_add_assign(*mul, -sub_mul1 * sub_mul2);
640    }
641
642    #[inline(always)]
643    fn raw_total_cmp(&self, other: &Self) -> Ordering {
644        f64::total_cmp(self, other)
645    }
646
647    /// Clamps the value within the specified bounds.
648    #[inline(always)]
649    fn raw_clamp(self, min: &Self, max: &Self) -> Self {
650        f64::clamp(self, *min, *max)
651    }
652
653    #[inline(always)]
654    fn raw_classify(&self) -> FpCategory {
655        f64::classify(*self)
656    }
657
658    #[inline(always)]
659    fn raw_two(_precision: u32) -> Self {
660        2.
661    }
662
663    #[inline(always)]
664    fn raw_one_div_2(_precision: u32) -> Self {
665        0.5
666    }
667
668    #[inline(always)]
669    fn raw_pi(_precision: u32) -> Self {
670        std::f64::consts::PI
671    }
672
673    #[inline(always)]
674    fn raw_two_pi(_precision: u32) -> Self {
675        2. * std::f64::consts::PI
676    }
677
678    #[inline(always)]
679    fn raw_pi_div_2(_precision: u32) -> Self {
680        std::f64::consts::FRAC_PI_2
681    }
682
683    #[inline(always)]
684    fn raw_max_finite(_precision: u32) -> Self {
685        f64::MAX
686    }
687
688    #[inline(always)]
689    fn raw_min_finite(_precision: u32) -> Self {
690        f64::MIN
691    }
692
693    #[inline(always)]
694    fn raw_epsilon(_precision: u32) -> Self {
695        f64::EPSILON
696    }
697
698    #[inline(always)]
699    fn raw_ln_2(_precision: u32) -> Self {
700        std::f64::consts::LN_2
701    }
702
703    #[inline(always)]
704    fn raw_ln_10(_precision: u32) -> Self {
705        std::f64::consts::LN_10
706    }
707
708    #[inline(always)]
709    fn raw_log10_2(_precision: u32) -> Self {
710        std::f64::consts::LOG10_2
711    }
712
713    #[inline(always)]
714    fn raw_log2_10(_precision: u32) -> Self {
715        std::f64::consts::LOG2_10
716    }
717
718    #[inline(always)]
719    fn raw_log2_e(_precision: u32) -> Self {
720        std::f64::consts::LOG2_E
721    }
722
723    #[inline(always)]
724    fn raw_log10_e(_precision: u32) -> Self {
725        std::f64::consts::LOG10_E
726    }
727
728    #[inline(always)]
729    fn raw_e(_precision: u32) -> Self {
730        std::f64::consts::E
731    }
732
733    #[inline(always)]
734    fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
735        value: f64,
736    ) -> Result<Self, ErrorsTryFromf64<f64>> {
737        RealPolicy::validate(value).map_err(|e| ErrorsTryFromf64::Output { source: e })
738    }
739
740    #[inline(always)]
741    fn precision(&self) -> u32 {
742        53 // f64 has 53 bits of precision
743    }
744
745    #[inline(always)]
746    fn compute_hash<H: Hasher>(&self, state: &mut H) {
747        debug_assert!(
748            self.is_finite(),
749            "Hashing a non-finite f64 value (i.e., NaN or Infinity) may lead to inconsistent results."
750        );
751        if self == &0.0 {
752            // Hash all zeros (positive and negative) to the same value
753            0.0f64.to_bits().hash(state);
754        } else {
755            self.to_bits().hash(state);
756        }
757    }
758
759    #[inline(always)]
760    fn truncate_to_usize(self) -> Result<usize, ErrorsRawRealToInteger<f64, usize>> {
761        if !self.is_finite() {
762            return Err(ErrorsRawRealToInteger::NotFinite {
763                value: self,
764                backtrace: Backtrace::force_capture(),
765            });
766        }
767
768        match self.checked_as::<usize>() {
769            Some(value) => Ok(value),
770            None => Err(ErrorsRawRealToInteger::OutOfRange {
771                value: self,
772                min: usize::MIN,
773                max: usize::MAX,
774                backtrace: Backtrace::force_capture(),
775            }),
776        }
777    }
778}
779
780impl RawScalarTrait for Complex<f64> {
781    type ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<f64>>;
782
783    #[inline(always)]
784    fn raw_zero(_precision: u32) -> Self {
785        Complex::new(0., 0.)
786    }
787
788    #[inline(always)]
789    fn is_zero(&self) -> bool {
790        <Self as Zero>::is_zero(self)
791    }
792
793    #[inline(always)]
794    fn raw_one(_precision: u32) -> Self {
795        Complex::new(1., 0.)
796    }
797
798    #[duplicate_item(
799        unchecked_method       method;
800        [unchecked_exp]        [exp];
801        [unchecked_sqrt]       [sqrt];
802        [unchecked_sin]        [sin];
803        [unchecked_asin]       [asin];
804        [unchecked_cos]        [cos];
805        [unchecked_acos]       [acos];
806        [unchecked_tan]        [tan];
807        [unchecked_atan]       [atan];
808        [unchecked_sinh]       [sinh];
809        [unchecked_asinh]      [asinh];
810        [unchecked_cosh]       [cosh];
811        [unchecked_acosh]      [acosh];
812        [unchecked_tanh]       [tanh];
813        [unchecked_atanh]      [atanh];
814        [unchecked_ln]         [ln];
815        [unchecked_log10]      [log10];
816    )]
817    #[inline(always)]
818    fn unchecked_method(self) -> Self {
819        Complex::<f64>::method(self)
820    }
821
822    #[inline(always)]
823    fn unchecked_reciprocal(self) -> Self {
824        Complex::<f64>::inv(&self)
825    }
826
827    #[inline(always)]
828    fn unchecked_log2(self) -> Self {
829        Complex::<f64>::ln(self) / std::f64::consts::LN_2
830    }
831
832    #[duplicate_item(
833        unchecked_method             exponent_type;
834        [unchecked_pow_exponent_i8]  [i8];
835        [unchecked_pow_exponent_i16] [i16];
836    )]
837    #[inline(always)]
838    fn unchecked_method(self, exponent: &exponent_type) -> Self {
839        Complex::<f64>::powi(&self, (*exponent).into())
840    }
841
842    #[inline(always)]
843    fn unchecked_pow_exponent_i32(self, exponent: &i32) -> Self {
844        Complex::<f64>::powi(&self, *exponent)
845    }
846
847    #[duplicate_item(
848        unchecked_method               exponent_type;
849        [unchecked_pow_exponent_i64]   [i64];
850        [unchecked_pow_exponent_i128]  [i128];
851        [unchecked_pow_exponent_isize] [isize];
852    )]
853    #[inline(always)]
854    fn unchecked_method(self, exponent: &exponent_type) -> Self {
855        Complex::<f64>::powi(
856            &self,
857            (*exponent)
858                .try_into()
859                .expect("The exponent {exponent} cannot be converted to an integer of type i32"),
860        )
861    }
862
863    #[duplicate_item(
864        unchecked_method             exponent_type;
865        [unchecked_pow_exponent_u8]  [u8];
866        [unchecked_pow_exponent_u16] [u16];
867    )]
868    #[inline(always)]
869    fn unchecked_method(self, exponent: &exponent_type) -> Self {
870        Complex::<f64>::powu(&self, (*exponent).into())
871    }
872
873    #[inline(always)]
874    fn unchecked_pow_exponent_u32(self, exponent: &u32) -> Self {
875        Complex::<f64>::powu(&self, *exponent)
876    }
877
878    #[duplicate_item(
879        unchecked_method               exponent_type;
880        [unchecked_pow_exponent_u64]   [u64];
881        [unchecked_pow_exponent_u128]  [u128];
882        [unchecked_pow_exponent_usize] [usize];
883    )]
884    #[inline(always)]
885    fn unchecked_method(self, exponent: &exponent_type) -> Self {
886        Complex::<f64>::powu(
887            &self,
888            (*exponent)
889                .try_into()
890                .expect("The exponent {exponent} cannot be converted to an integer of type u32"),
891        )
892    }
893
894    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
895    ///
896    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
897    #[inline(always)]
898    fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
899        Complex::<f64>::mul_add(self, *b, *c)
900    }
901}
902
903impl RawComplexTrait for Complex<f64> {
904    type RawReal = f64;
905
906    fn new_unchecked_raw_complex(real: f64, imag: f64) -> Self {
907        Complex::<f64>::new(real, imag)
908    }
909
910    /// Returns a mutable reference to the real part of the complex number.
911    fn mut_raw_real_part(&mut self) -> &mut f64 {
912        &mut self.re
913    }
914
915    /// Returns a mutable reference to the imaginary part of the complex number.
916    fn mut_raw_imag_part(&mut self) -> &mut f64 {
917        &mut self.im
918    }
919
920    #[inline(always)]
921    fn unchecked_abs(self) -> f64 {
922        Complex::<f64>::norm(self)
923    }
924
925    #[inline(always)]
926    fn raw_real_part(&self) -> &f64 {
927        &self.re
928    }
929
930    #[inline(always)]
931    fn raw_imag_part(&self) -> &f64 {
932        &self.im
933    }
934
935    #[inline(always)]
936    fn unchecked_arg(self) -> f64 {
937        Complex::<f64>::arg(self)
938    }
939
940    #[inline(always)]
941    fn unchecked_pow_exponent_real(self, exponent: &f64) -> Self {
942        Complex::<f64>::powf(self, *exponent)
943    }
944}
945//------------------------------------------------------------------------------------------------------------
946
947//------------------------------------------------------------------------------------------------------------
948/// Defines the identity of a raw numerical kernel by associating its fundamental types.
949///
950/// This trait acts as a low-level building block that groups the core "raw"
951/// types of a numerical backend. It specifies which concrete types implement
952/// [`RawRealTrait`] and [`RawComplexTrait`] for a given kernel.
953///
954/// It is primarily used as a supertrait for [`NumKernel`], which extends
955/// this type-level association with concrete validation logic and precision information.
956pub trait RawKernel: Send + Sync + 'static {
957    /// The raw real type associated with this kernel (e.g., [`f64`]).
958    type RawReal: RawRealTrait;
959
960    /// The raw complex type associated with this kernel (e.g., [`Complex<f64>`]).
961    type RawComplex: RawComplexTrait<RawReal = Self::RawReal>;
962}
963//------------------------------------------------------------------------------------------------------------
964
965//------------------------------------------------------------------------------------------------------------
966/// Defines a complete numerical kernel, acting as the central configuration point.
967///
968/// This trait is the primary bound for generic functions that need to operate
969/// across different numerical backends. It bundles together:
970/// 1.  The raw underlying types (e.g., `f64`) via the [`RawKernel`] supertrait.
971/// 2.  The specific validation logic for those types.
972/// 3.  The precision of the kernel in bits.
973/// 4.  The final, high-level `Real` and `Complex` validated types.
974pub trait NumKernel: RawKernel + Sized {
975    /// The precision of the kernel in bits (e.g., `53` for `f64`).
976    const PRECISION: u32;
977
978    /// The validation policy for real numbers.
979    ///
980    /// # Note
981    /// The bound on `ValidationPolicyReal::Error` is a critical architectural choice. It enforces that the
982    /// error type defined by a policy (`RealPolicy::Error`) MUST be the same as the
983    /// canonical validation error type associated with its value (`RealPolicy::Value::ValidationErrors`).
984    /// This prevents mismatches and simplifies error handling throughout the library.
985    type RealPolicy: ValidationPolicyReal<
986            Value = Self::RawReal,
987            Error = <Self::RawReal as RawScalarTrait>::ValidationErrors,
988        >;
989
990    /// The validation policy for complex numbers.
991    ///
992    /// # Note
993    /// The bound on `ValidationPolicyComplex::Error` is a critical architectural choice. It enforces that the
994    /// error type defined by a policy (`ComplexPolicy::Error`) MUST be the same as the
995    /// canonical validation error type associated with its value (`ComplexPolicy::Value::ValidationErrors`).
996    /// This prevents mismatches and simplifies error handling throughout the library.
997    type ComplexPolicy: ValidationPolicyComplex<
998            Value = Self::RawComplex,
999            Error = <Self::RawComplex as RawScalarTrait>::ValidationErrors,
1000        >;
1001
1002    /// The final, high-level, validated real scalar type for this kernel.
1003    /// This is typically an alias for `RealValidated<Self>`.
1004    type Real: RealScalar<RawReal = Self::RawReal>;
1005
1006    /// The final, high-level, validated complex scalar type for this kernel.
1007    /// This is typically an alias for `ComplexValidated<Self>`.
1008    /// The `RealType = Self::Real` bound ensures the complex type is composed of the
1009    /// corresponding validated real type from the same kernel.
1010    type Complex: ComplexScalar<RealType = Self::Real>;
1011}
1012//------------------------------------------------------------------------------------------------------------
1013
1014//-----------------------------------------------------------------------------------------------
1015/// A strict finite kernel validation policy for raw real numbers.
1016/// This policy ensures that the real numbers are finite and not NaN.
1017pub struct NumKernelStrictFinite<RawReal: RawRealTrait, const PRECISION: u32> {
1018    _phantom: PhantomData<RawReal>,
1019}
1020
1021impl<RawReal: RawRealTrait, const PRECISION: u32> RawKernel
1022    for NumKernelStrictFinite<RawReal, PRECISION>
1023{
1024    type RawReal = RawReal;
1025    type RawComplex = RawReal::RawComplex;
1026}
1027
1028impl<RawReal: RawRealTrait, const PRECISION: u32> NumKernel
1029    for NumKernelStrictFinite<RawReal, PRECISION>
1030where
1031    StrictFinitePolicy<RawReal, PRECISION>: ValidationPolicyReal<Value = RawReal>,
1032    StrictFinitePolicy<RawReal::RawComplex, PRECISION>:
1033        ValidationPolicyComplex<Value = RawReal::RawComplex>,
1034{
1035    const PRECISION: u32 = PRECISION;
1036
1037    type RealPolicy = StrictFinitePolicy<RawReal, PRECISION>;
1038
1039    type ComplexPolicy = StrictFinitePolicy<RawReal::RawComplex, PRECISION>;
1040
1041    type Real = RealValidated<Self>;
1042    type Complex = ComplexValidated<Self>;
1043}
1044//-----------------------------------------------------------------------------------------------
1045
1046//-----------------------------------------------------------------------------------------------
1047pub struct NumKernelStrictFiniteInDebug<RawReal: RawRealTrait, const PRECISION: u32> {
1048    _phantom: PhantomData<RawReal>,
1049}
1050
1051impl<RawReal: RawRealTrait, const PRECISION: u32> RawKernel
1052    for NumKernelStrictFiniteInDebug<RawReal, PRECISION>
1053{
1054    type RawReal = RawReal;
1055    type RawComplex = RawReal::RawComplex;
1056}
1057
1058impl<RawReal: RawRealTrait, const PRECISION: u32> NumKernel
1059    for NumKernelStrictFiniteInDebug<RawReal, PRECISION>
1060where
1061    StrictFinitePolicy<RawReal, PRECISION>: ValidationPolicyReal<Value = RawReal>,
1062    StrictFinitePolicy<RawReal::RawComplex, PRECISION>:
1063        ValidationPolicyComplex<Value = RawReal::RawComplex>,
1064{
1065    const PRECISION: u32 = PRECISION;
1066
1067    type RealPolicy = DebugValidationPolicy<StrictFinitePolicy<RawReal, PRECISION>>;
1068
1069    type ComplexPolicy = DebugValidationPolicy<StrictFinitePolicy<RawReal::RawComplex, PRECISION>>;
1070
1071    type Real = RealValidated<Self>;
1072    type Complex = ComplexValidated<Self>;
1073}
1074
1075//-----------------------------------------------------------------------------------------------