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, ErrorsTryFromf64, ErrorsValidationRawComplex,
55        ErrorsValidationRawReal, StrictFinitePolicy, ValidationPolicyComplex, ValidationPolicyReal,
56    },
57};
58use duplicate::duplicate_item;
59use num::{Complex, Zero};
60use num_traits::{MulAdd, MulAddAssign};
61use serde::Serialize;
62use std::{
63    cmp::Ordering,
64    fmt::{Debug, Display},
65    marker::PhantomData,
66    num::FpCategory,
67    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
68};
69
70/// A baseline trait for raw scalar types, defining core operations and properties.
71///
72/// This trait must be implemented by the underlying number types used in a kernel,
73/// such as like [`f64`] or [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
74/// It provides a standard interface for arithmetic
75/// and a suite of `unchecked_*` methods for mathematical functions.
76///
77/// # Safety and Contracts
78///
79/// The `unchecked_*` methods are designed for performance and assume that the caller
80/// has already validated the inputs. Calling them with invalid data (e.g., `unchecked_sqrt`
81/// on a negative real number) may lead to panics, incorrect results, or undefined behavior,
82/// depending on the underlying type's implementation.
83pub trait RawScalarTrait:
84    Serialize
85    + Debug
86    + Display
87    + Clone
88    + Sync
89    + Send
90    + Add<Output = Self>
91    + Sub<Output = Self>
92    + Mul<Output = Self>
93    + Div<Output = Self>
94    + for<'a> Add<&'a Self, Output = Self>
95    + for<'a> Sub<&'a Self, Output = Self>
96    + for<'a> Mul<&'a Self, Output = Self>
97    + for<'a> Div<&'a Self, Output = Self>
98    + AddAssign
99    + SubAssign
100    + MulAssign
101    + DivAssign
102    + for<'a> AddAssign<&'a Self>
103    + for<'a> SubAssign<&'a Self>
104    + for<'a> MulAssign<&'a Self>
105    + for<'a> DivAssign<&'a Self>
106    + Neg<Output = Self>
107    + NegAssign
108    + NeumaierAddable
109    + PartialEq
110//    + MulAddRef
111    + FpChecks
112    + 'static
113{
114    /// The associated error type for validation failures of this raw type.
115    type ValidationErrors: std::error::Error;
116
117    fn is_zero(&self) -> bool;
118
119    fn raw_zero(precision: u32) -> Self;
120
121    fn raw_one(precision: u32) -> Self;
122
123    fn raw_negative_one(precision: u32) -> Self {
124        Self::raw_one(precision).neg()
125    }
126
127    /// Computes the reciprocal (1/x) without validation.
128    /// 
129    /// **Contract:** The caller must ensure `self` is not zero.
130    fn unchecked_reciprocal(self) -> Self;
131
132    /// Computes the exponential (e^x) without validation.
133    /// 
134    /// **Contract:** The caller must ensure the input is valid.
135    fn unchecked_exp(self) -> Self;
136
137    /// Computes the square root without validation.
138    /// 
139    /// **Contract:** For real numbers, the caller must ensure `self >= 0`.
140    fn unchecked_sqrt(self) -> Self;
141
142    fn unchecked_sin(self) -> Self;
143
144    fn unchecked_asin(self) -> Self;
145
146    fn unchecked_cos(self) -> Self;
147
148    fn unchecked_acos(self) -> Self;
149
150    fn unchecked_tan(self) -> Self;
151
152    fn unchecked_atan(self) -> Self;
153
154    fn unchecked_sinh(self) -> Self;
155
156    fn unchecked_asinh(self) -> Self;
157
158    fn unchecked_cosh(self) -> Self;
159
160    fn unchecked_acosh(self) -> Self;
161
162    fn unchecked_tanh(self) -> Self;
163
164    fn unchecked_atanh(self) -> Self;
165
166    fn unchecked_ln(self) -> Self;
167    fn unchecked_log2(self) -> Self;
168    fn unchecked_log10(self) -> Self;
169
170    /// Raises `self` to the power of an `i8` exponent without validation.
171    /// 
172    /// **Contract:** The caller must ensure the inputs are valid.
173    fn unchecked_pow_exponent_i8(self, exponent: &i8) -> Self;
174
175    /// Raises `self` to the power of an `i16` exponent without validation.
176    /// 
177    /// **Contract:** The caller must ensure the inputs are valid.
178    fn unchecked_pow_exponent_i16(self, exponent: &i16) -> Self;
179
180    /// Raises `self` to the power of an `i32` exponent without validation.
181    /// 
182    /// **Contract:** The caller must ensure the inputs are valid.
183    fn unchecked_pow_exponent_i32(self, exponent: &i32) -> Self;
184
185    /// Raises `self` to the power of an `i64` exponent without validation.
186    /// 
187    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
188    /// includes ensuring the `exponent` is within the representable range of the underlying
189    /// power function (e.g., `i32` for `f64::powi`).
190    fn unchecked_pow_exponent_i64(self, exponent: &i64) -> Self;
191
192    /// Raises `self` to the power of an `i128` exponent without validation.
193    /// 
194    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
195    /// includes ensuring the `exponent` is within the representable range of the underlying
196    /// power function (e.g., `i32` for `f64::powi`).
197    fn unchecked_pow_exponent_i128(self, exponent: &i128) -> Self;
198
199    /// Raises `self` to the power of an `isize` exponent without validation.
200    /// 
201    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
202    /// includes ensuring the `exponent` is within the representable range of the underlying
203    /// power function (e.g., `i32` for `f64::powi`).
204    fn unchecked_pow_exponent_isize(self, exponent: &isize) -> Self;
205
206    /// Raises `self` to the power of an `u8` exponent without validation.
207    /// 
208    /// **Contract:** The caller must ensure the inputs are valid.
209    fn unchecked_pow_exponent_u8(self, exponent: &u8) -> Self;
210
211    /// Raises `self` to the power of an `u16` exponent without validation.
212    /// 
213    /// **Contract:** The caller must ensure the inputs are valid.
214    fn unchecked_pow_exponent_u16(self, exponent: &u16) -> Self;
215
216    /// Raises `self` to the power of an `u32` exponent without validation.
217    /// 
218    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
219    /// includes ensuring the `exponent` is within the representable range of the underlying
220    /// power function (e.g., `i32` for `f64::powi`).
221    fn unchecked_pow_exponent_u32(self, exponent: &u32) -> Self;
222
223    /// Raises `self` to the power of an `u64` exponent without validation.
224    /// 
225    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
226    /// includes ensuring the `exponent` is within the representable range of the underlying
227    /// power function (e.g., `i32` for `f64::powi`).
228    fn unchecked_pow_exponent_u64(self, exponent: &u64) -> Self;
229
230    /// Raises `self` to the power of an `u128` exponent without validation.
231    /// 
232    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
233    /// includes ensuring the `exponent` is within the representable range of the underlying
234    /// power function (e.g., `i32` for `f64::powi`).
235    fn unchecked_pow_exponent_u128(self, exponent: &u128) -> Self;
236
237    /// Raises `self` to the power of an `usize` exponent without validation.
238    /// 
239    /// **Contract:** The caller must ensure the inputs are valid. For integer powers, this
240    /// includes ensuring the `exponent` is within the representable range of the underlying
241    /// power function (e.g., `i32` for `f64::powi`).
242    fn unchecked_pow_exponent_usize(self, exponent: &usize) -> Self;
243
244    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
245    ///
246    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
247    ///
248    /// **Contract:** The caller must ensure all inputs are valid.
249    fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self;
250}
251
252/// A trait for raw real scalar types, extending [`RawScalarTrait`] with real-specific operations.
253///
254/// This trait is implemented by the underlying real number types within a kernel, such as [`f64`]
255/// or [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
256/// It builds upon [`RawScalarTrait`] by adding operations that are unique
257/// to real numbers, like `atan2`, and by enforcing an ordering relationship.
258///
259/// # Trait Bounds
260///
261/// - `RawScalarTrait<ValidationErrors = ErrorsValidationRawReal<Self>>`: Ensures that the type
262///   is a raw scalar and that its validation error type is the standard one for real numbers.
263/// - [`PartialOrd`]: Requires that the type can be partially ordered, which is fundamental for
264///   real numbers.
265/// - [`PartialOrd<f64>`]: These crucial bounds allow instances of the raw
266///   real type to be directly compared with `f64` constants. This is essential for implementing
267///   domain checks (e.g., `value < 0.0` or `value >= 0.0`) that work across
268///   both [`f64`] and [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) without extra conversions.
269///
270/// # Associated Types
271///
272/// - `type RawComplex: RawComplexTrait<RawReal = Self>`: This links the raw real type to its
273///   corresponding complex number representation. For example, for [`f64`], this would be
274///   [`num::Complex<f64>`]. This association is vital for operations that can transition
275///   from the real to the complex domain.
276pub trait RawRealTrait:
277    RawScalarTrait<ValidationErrors = ErrorsValidationRawReal<Self>>
278    + PartialOrd
279    + PartialOrd<f64>
280    + Sign
281    + Rounding
282{
283    /// The associated complex type that uses this type as its real part.
284    type RawComplex: RawComplexTrait<RawReal = Self>;
285
286    /// Computes the absolute value of `self` without validation.
287    ///
288    /// **Contract:** The caller must ensure that the input value has already been validated
289    /// and is suitable for the operation.
290    fn unchecked_abs(self) -> Self;
291
292    /// Computes the four-quadrant arctangent of `self` (`y`) and `denominator` (`x`) without validation.
293    ///
294    /// **Contract:** The caller must ensure that `self` and `denominator` are not both zero.
295    fn unchecked_atan2(self, denominator: &Self) -> Self;
296
297    /// Raises `self` to the power of a real `exponent` without validation.
298    ///
299    /// **Contract:** The caller must ensure the inputs are valid for the power function. For
300    /// example, if `self` is negative, the `exponent` should be an integer, but this function
301    /// does not enforce this.
302    fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self;
303
304    fn unchecked_hypot(self, other: &Self) -> Self;
305
306    fn unchecked_ln_1p(self) -> Self;
307
308    fn unchecked_exp_m1(self) -> Self;
309
310    /// Multiplies two pairs and adds them, rounding to the nearest.
311    /// `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.
312    ///
313    /// **Contract:** The caller must ensure all inputs are valid.
314    fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
315
316    /// Multiplies two pairs and subtracts them, rounding to the nearest.
317    /// `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.
318    ///
319    /// **Contract:** The caller must ensure all inputs are valid.
320    fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
321
322    fn raw_total_cmp(&self, other: &Self) -> Ordering;
323
324    /// Clamps the value within the specified bounds.
325    fn raw_clamp(self, min: &Self, max: &Self) -> Self;
326
327    fn raw_classify(&self) -> FpCategory;
328
329    fn raw_two(precision: u32) -> Self;
330
331    fn raw_one_div_2(precision: u32) -> Self;
332
333    fn raw_pi(precision: u32) -> Self;
334
335    fn raw_two_pi(precision: u32) -> Self;
336
337    fn raw_pi_div_2(precision: u32) -> Self;
338
339    fn raw_max_finite(precision: u32) -> Self;
340
341    fn raw_min_finite(precision: u32) -> Self;
342
343    fn raw_epsilon(precision: u32) -> Self;
344
345    fn raw_ln_2(_precision: u32) -> Self;
346
347    fn raw_ln_10(_precision: u32) -> Self;
348
349    fn raw_log10_2(_precision: u32) -> Self;
350
351    fn raw_log2_10(_precision: u32) -> Self;
352
353    fn raw_log2_e(_precision: u32) -> Self;
354
355    fn raw_log10_e(_precision: u32) -> Self;
356
357    fn raw_e(_precision: u32) -> Self;
358
359    fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
360        value: f64,
361    ) -> Result<Self, ErrorsTryFromf64<Self>>;
362
363    /// Returns the precision (in bits) of the raw real type.
364    fn precision(&self) -> u32;
365}
366
367/// A trait for raw complex scalar types, extending [`RawScalarTrait`].
368///
369/// This trait is implemented by the underlying complex number types within a kernel,
370/// such as [`num::Complex<f64>`]. It builds upon [`RawScalarTrait`] by adding operations
371/// that are unique to complex numbers.
372///
373/// # Trait Bounds
374///
375/// - `RawScalarTrait<...>`: Ensures the type is a raw scalar and fixes its validation
376///   error type to [`ErrorsValidationRawComplex`], which in turn wraps the validation
377///   error of the associated real type. This establishes a consistent error structure.
378/// - [`Conjugate`]: Requires that the complex number can be conjugated.
379///
380/// # Associated Types
381///
382/// - `type RawReal: RawRealTrait<RawComplex = Self>`: This is a critical part of the
383///   design. It links the complex type to its underlying real component type (e.g., [`f64`]
384///   for [`num::Complex<f64>`]). This associated real type must itself implement [`RawRealTrait`],
385///   creating a two-way link between the real and complex raw types.
386///
387/// # Methods
388///
389/// This trait provides methods for accessing components and performing complex-specific
390/// mathematical operations without validation checks.
391pub trait RawComplexTrait:
392    RawScalarTrait<
393        ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<Self::RawReal>>,
394    > + Conjugate
395    + for<'a> Mul<&'a Self::RawReal, Output = Self>
396    + for<'a> MulAssign<&'a Self::RawReal>
397{
398    /// The associated real type that makes up the components of this complex type.
399    type RawReal: RawRealTrait<RawComplex = Self>;
400
401    fn new_unchecked_raw_complex(real: Self::RawReal, imag: Self::RawReal) -> Self;
402
403    /// Computes the absolute value (modulus or norm) of `self` without validation.
404    ///
405    /// **Contract:** The caller must ensure the input is valid for this operation.
406    fn unchecked_abs(self) -> Self::RawReal;
407
408    /// Returns a reference to the real part of the complex number.
409    fn raw_real_part(&self) -> &Self::RawReal;
410
411    /// Returns a reference to the imaginary part of the complex number.
412    fn raw_imag_part(&self) -> &Self::RawReal;
413
414    /// Returns a mutable reference to the real part of the complex number.
415    fn mut_raw_real_part(&mut self) -> &mut Self::RawReal;
416
417    /// Returns a mutable reference to the imaginary part of the complex number.
418    fn mut_raw_imag_part(&mut self) -> &mut Self::RawReal;
419
420    /// Computes the argument (or phase) of `self` in radians, without validation.
421    ///
422    /// **Contract:** The caller must ensure that `self` is not zero.
423    fn unchecked_arg(self) -> Self::RawReal;
424
425    /// Raises `self` to the power of a real `exponent` without validation.
426    ///
427    /// **Contract:** The caller must ensure the inputs are valid for the power function.
428    fn unchecked_pow_exponent_real(self, exponent: &Self::RawReal) -> Self;
429}
430
431impl RawScalarTrait for f64 {
432    type ValidationErrors = ErrorsValidationRawReal<f64>;
433
434    #[inline(always)]
435    fn raw_zero(_precision: u32) -> f64 {
436        0.
437    }
438
439    #[inline(always)]
440    fn is_zero(&self) -> bool {
441        <Self as Zero>::is_zero(self)
442    }
443    #[inline(always)]
444    fn raw_one(_precision: u32) -> f64 {
445        1.
446    }
447
448    #[duplicate_item(
449        unchecked_method       method;
450        [unchecked_reciprocal] [recip];
451        [unchecked_exp]        [exp];
452        [unchecked_sqrt]       [sqrt];
453        [unchecked_sin]        [sin];
454        [unchecked_asin]       [asin];
455        [unchecked_cos]        [cos];
456        [unchecked_acos]       [acos];
457        [unchecked_tan]        [tan];
458        [unchecked_atan]       [atan];
459        [unchecked_sinh]       [sinh];
460        [unchecked_asinh]      [asinh];
461        [unchecked_cosh]       [cosh];
462        [unchecked_acosh]      [acosh];
463        [unchecked_tanh]       [tanh];
464        [unchecked_atanh]      [atanh];
465        [unchecked_ln]         [ln];
466        [unchecked_log2]       [log2];
467        [unchecked_log10]      [log10];
468    )]
469    #[inline(always)]
470    fn unchecked_method(self) -> f64 {
471        f64::method(self)
472    }
473
474    #[duplicate_item(
475        unchecked_method             exponent_type;
476        [unchecked_pow_exponent_i8]  [i8];
477        [unchecked_pow_exponent_i16] [i16];
478        [unchecked_pow_exponent_u8]  [u8];
479        [unchecked_pow_exponent_u16] [u16];
480    )]
481    #[inline(always)]
482    fn unchecked_method(self, exponent: &exponent_type) -> f64 {
483        f64::powi(self, (*exponent).into())
484    }
485
486    #[inline(always)]
487    fn unchecked_pow_exponent_i32(self, exponent: &i32) -> Self {
488        f64::powi(self, *exponent)
489    }
490
491    #[duplicate_item(
492        unchecked_method               exponent_type;
493        [unchecked_pow_exponent_i64]   [i64];
494        [unchecked_pow_exponent_i128]  [i128];
495        [unchecked_pow_exponent_isize] [isize];
496        [unchecked_pow_exponent_u32]   [u32];
497        [unchecked_pow_exponent_u64]   [u64];
498        [unchecked_pow_exponent_u128]  [u128];
499        [unchecked_pow_exponent_usize] [usize];
500    )]
501    #[inline(always)]
502    fn unchecked_method(self, exponent: &exponent_type) -> f64 {
503        f64::powi(
504            self,
505            (*exponent)
506                .try_into()
507                .expect("The exponent {exponent} cannot be converted to an integer of type i32"),
508        )
509    }
510
511    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
512    ///
513    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
514    #[inline(always)]
515    fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
516        f64::mul_add(self, *b, *c)
517    }
518}
519
520impl RawRealTrait for f64 {
521    type RawComplex = Complex<f64>;
522
523    #[inline(always)]
524    fn unchecked_abs(self) -> f64 {
525        f64::abs(self)
526    }
527
528    #[inline(always)]
529    fn unchecked_atan2(self, denominator: &Self) -> Self {
530        f64::atan2(self, *denominator)
531    }
532
533    #[inline(always)]
534    fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self {
535        f64::powf(self, *exponent)
536    }
537
538    #[inline(always)]
539    fn unchecked_hypot(self, other: &Self) -> Self {
540        f64::hypot(self, *other)
541    }
542
543    fn unchecked_ln_1p(self) -> Self {
544        f64::ln_1p(self)
545    }
546
547    fn unchecked_exp_m1(self) -> Self {
548        f64::exp_m1(self)
549    }
550
551    /// Multiplies two pairs and adds them in one fused operation, rounding to the nearest with only one rounding error.
552    /// `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.
553    #[inline(always)]
554    fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
555        self.mul_add_assign(*mul, add_mul1 * add_mul2);
556    }
557
558    /// Multiplies two pairs and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
559    /// `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.
560    #[inline(always)]
561    fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
562        self.mul_add_assign(*mul, -sub_mul1 * sub_mul2);
563    }
564
565    fn raw_total_cmp(&self, other: &Self) -> Ordering {
566        f64::total_cmp(self, other)
567    }
568
569    /// Clamps the value within the specified bounds.
570    fn raw_clamp(self, min: &Self, max: &Self) -> Self {
571        f64::clamp(self, *min, *max)
572    }
573
574    fn raw_classify(&self) -> FpCategory {
575        f64::classify(*self)
576    }
577
578    fn raw_two(_precision: u32) -> Self {
579        2.
580    }
581
582    fn raw_one_div_2(_precision: u32) -> Self {
583        0.5
584    }
585
586    fn raw_pi(_precision: u32) -> Self {
587        std::f64::consts::PI
588    }
589
590    fn raw_two_pi(_precision: u32) -> Self {
591        2. * std::f64::consts::PI
592    }
593
594    fn raw_pi_div_2(_precision: u32) -> Self {
595        std::f64::consts::FRAC_PI_2
596    }
597
598    fn raw_max_finite(_precision: u32) -> Self {
599        f64::MAX
600    }
601
602    fn raw_min_finite(_precision: u32) -> Self {
603        f64::MIN
604    }
605
606    fn raw_epsilon(_precision: u32) -> Self {
607        f64::EPSILON
608    }
609
610    fn raw_ln_2(_precision: u32) -> Self {
611        std::f64::consts::LN_2
612    }
613
614    fn raw_ln_10(_precision: u32) -> Self {
615        std::f64::consts::LN_10
616    }
617
618    fn raw_log10_2(_precision: u32) -> Self {
619        std::f64::consts::LOG10_2
620    }
621
622    fn raw_log2_10(_precision: u32) -> Self {
623        std::f64::consts::LOG2_10
624    }
625
626    fn raw_log2_e(_precision: u32) -> Self {
627        std::f64::consts::LOG2_E
628    }
629
630    fn raw_log10_e(_precision: u32) -> Self {
631        std::f64::consts::LOG10_E
632    }
633
634    fn raw_e(_precision: u32) -> Self {
635        std::f64::consts::E
636    }
637
638    #[inline(always)]
639    fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
640        value: f64,
641    ) -> Result<Self, ErrorsTryFromf64<f64>> {
642        RealPolicy::validate(value).map_err(|e| ErrorsTryFromf64::Output { source: e })
643    }
644
645    fn precision(&self) -> u32 {
646        53 // f64 has 53 bits of precision
647    }
648}
649
650impl RawScalarTrait for Complex<f64> {
651    type ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<f64>>;
652
653    #[inline(always)]
654    fn raw_zero(_precision: u32) -> Self {
655        Complex::new(0., 0.)
656    }
657
658    #[inline(always)]
659    fn is_zero(&self) -> bool {
660        <Self as Zero>::is_zero(self)
661    }
662
663    #[inline(always)]
664    fn raw_one(_precision: u32) -> Self {
665        Complex::new(1., 0.)
666    }
667
668    #[duplicate_item(
669        unchecked_method       method;
670        [unchecked_exp]        [exp];
671        [unchecked_sqrt]       [sqrt];
672        [unchecked_sin]        [sin];
673        [unchecked_asin]       [asin];
674        [unchecked_cos]        [cos];
675        [unchecked_acos]       [acos];
676        [unchecked_tan]        [tan];
677        [unchecked_atan]       [atan];
678        [unchecked_sinh]       [sinh];
679        [unchecked_asinh]      [asinh];
680        [unchecked_cosh]       [cosh];
681        [unchecked_acosh]      [acosh];
682        [unchecked_tanh]       [tanh];
683        [unchecked_atanh]      [atanh];
684        [unchecked_ln]         [ln];
685        [unchecked_log10]      [log10];
686    )]
687    #[inline(always)]
688    fn unchecked_method(self) -> Self {
689        Complex::<f64>::method(self)
690    }
691
692    #[inline(always)]
693    fn unchecked_reciprocal(self) -> Self {
694        Complex::<f64>::inv(&self)
695    }
696
697    #[inline(always)]
698    fn unchecked_log2(self) -> Self {
699        Complex::<f64>::ln(self) / std::f64::consts::LN_2
700    }
701
702    #[duplicate_item(
703        unchecked_method             exponent_type;
704        [unchecked_pow_exponent_i8]  [i8];
705        [unchecked_pow_exponent_i16] [i16];
706    )]
707    #[inline(always)]
708    fn unchecked_method(self, exponent: &exponent_type) -> Self {
709        Complex::<f64>::powi(&self, (*exponent).into())
710    }
711
712    #[inline(always)]
713    fn unchecked_pow_exponent_i32(self, exponent: &i32) -> Self {
714        Complex::<f64>::powi(&self, *exponent)
715    }
716
717    #[duplicate_item(
718        unchecked_method               exponent_type;
719        [unchecked_pow_exponent_i64]   [i64];
720        [unchecked_pow_exponent_i128]  [i128];
721        [unchecked_pow_exponent_isize] [isize];
722    )]
723    #[inline(always)]
724    fn unchecked_method(self, exponent: &exponent_type) -> Self {
725        Complex::<f64>::powi(
726            &self,
727            (*exponent)
728                .try_into()
729                .expect("The exponent {exponent} cannot be converted to an integer of type i32"),
730        )
731    }
732
733    #[duplicate_item(
734        unchecked_method             exponent_type;
735        [unchecked_pow_exponent_u8]  [u8];
736        [unchecked_pow_exponent_u16] [u16];
737    )]
738    #[inline(always)]
739    fn unchecked_method(self, exponent: &exponent_type) -> Self {
740        Complex::<f64>::powu(&self, (*exponent).into())
741    }
742
743    #[inline(always)]
744    fn unchecked_pow_exponent_u32(self, exponent: &u32) -> Self {
745        Complex::<f64>::powu(&self, *exponent)
746    }
747
748    #[duplicate_item(
749        unchecked_method               exponent_type;
750        [unchecked_pow_exponent_u64]   [u64];
751        [unchecked_pow_exponent_u128]  [u128];
752        [unchecked_pow_exponent_usize] [usize];
753    )]
754    #[inline(always)]
755    fn unchecked_method(self, exponent: &exponent_type) -> Self {
756        Complex::<f64>::powu(
757            &self,
758            (*exponent)
759                .try_into()
760                .expect("The exponent {exponent} cannot be converted to an integer of type u32"),
761        )
762    }
763
764    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
765    ///
766    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
767    #[inline(always)]
768    fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
769        Complex::<f64>::mul_add(self, *b, *c)
770    }
771}
772
773impl RawComplexTrait for Complex<f64> {
774    type RawReal = f64;
775
776    fn new_unchecked_raw_complex(real: f64, imag: f64) -> Self {
777        Complex::<f64>::new(real, imag)
778    }
779
780    /// Returns a mutable reference to the real part of the complex number.
781    fn mut_raw_real_part(&mut self) -> &mut f64 {
782        &mut self.re
783    }
784
785    /// Returns a mutable reference to the imaginary part of the complex number.
786    fn mut_raw_imag_part(&mut self) -> &mut f64 {
787        &mut self.im
788    }
789
790    #[inline(always)]
791    fn unchecked_abs(self) -> f64 {
792        Complex::<f64>::norm(self)
793    }
794
795    #[inline(always)]
796    fn raw_real_part(&self) -> &f64 {
797        &self.re
798    }
799
800    #[inline(always)]
801    fn raw_imag_part(&self) -> &f64 {
802        &self.im
803    }
804
805    #[inline(always)]
806    fn unchecked_arg(self) -> f64 {
807        Complex::<f64>::arg(self)
808    }
809
810    #[inline(always)]
811    fn unchecked_pow_exponent_real(self, exponent: &f64) -> Self {
812        Complex::<f64>::powf(self, *exponent)
813    }
814}
815//------------------------------------------------------------------------------------------------------------
816
817//------------------------------------------------------------------------------------------------------------
818/// Defines the identity of a raw numerical kernel by associating its fundamental types.
819///
820/// This trait acts as a low-level building block that groups the core "raw"
821/// types of a numerical backend. It specifies which concrete types implement
822/// [`RawRealTrait`] and [`RawComplexTrait`] for a given kernel.
823///
824/// It is primarily used as a supertrait for [`NumKernel`], which extends
825/// this type-level association with concrete validation logic and precision information.
826pub trait RawKernel: Send + Sync + 'static {
827    /// The raw real type associated with this kernel (e.g., [`f64`]).
828    type RawReal: RawRealTrait;
829
830    /// The raw complex type associated with this kernel (e.g., [`Complex<f64>`]).
831    type RawComplex: RawComplexTrait<RawReal = Self::RawReal>;
832}
833//------------------------------------------------------------------------------------------------------------
834
835//------------------------------------------------------------------------------------------------------------
836/// Defines a complete numerical kernel, acting as the central configuration point.
837///
838/// This trait is the primary bound for generic functions that need to operate
839/// across different numerical backends. It bundles together:
840/// 1.  The raw underlying types (e.g., `f64`) via the [`RawKernel`] supertrait.
841/// 2.  The specific validation logic for those types.
842/// 3.  The precision of the kernel in bits.
843/// 4.  The final, high-level `Real` and `Complex` validated types.
844pub trait NumKernel: RawKernel + Sized {
845    /// The precision of the kernel in bits (e.g., `53` for `f64`).
846    const PRECISION: u32;
847
848    /// The validation policy for real numbers.
849    ///
850    /// # Note
851    /// The bound on `ValidationPolicyReal::Error` is a critical architectural choice. It enforces that the
852    /// error type defined by a policy (`RealPolicy::Error`) MUST be the same as the
853    /// canonical validation error type associated with its value (`RealPolicy::Value::ValidationErrors`).
854    /// This prevents mismatches and simplifies error handling throughout the library.
855    type RealPolicy: ValidationPolicyReal<
856            Value = Self::RawReal,
857            Error = <Self::RawReal as RawScalarTrait>::ValidationErrors,
858        >;
859
860    /// The validation policy for complex numbers.
861    ///
862    /// # Note
863    /// The bound on `ValidationPolicyComplex::Error` is a critical architectural choice. It enforces that the
864    /// error type defined by a policy (`ComplexPolicy::Error`) MUST be the same as the
865    /// canonical validation error type associated with its value (`ComplexPolicy::Value::ValidationErrors`).
866    /// This prevents mismatches and simplifies error handling throughout the library.
867    type ComplexPolicy: ValidationPolicyComplex<
868            Value = Self::RawComplex,
869            Error = <Self::RawComplex as RawScalarTrait>::ValidationErrors,
870        >;
871
872    /// The final, high-level, validated real scalar type for this kernel.
873    /// This is typically an alias for `RealValidated<Self>`.
874    type Real: RealScalar<RawReal = Self::RawReal>;
875
876    /// The final, high-level, validated complex scalar type for this kernel.
877    /// This is typically an alias for `ComplexValidated<Self>`.
878    /// The `RealType = Self::Real` bound ensures the complex type is composed of the
879    /// corresponding validated real type from the same kernel.
880    type Complex: ComplexScalar<RealType = Self::Real>;
881}
882//------------------------------------------------------------------------------------------------------------
883
884//-----------------------------------------------------------------------------------------------
885/// A strict finite kernel validation policy for raw real numbers.
886/// This policy ensures that the real numbers are finite and not NaN.
887pub struct NumKernelStrictFinite<RawReal: RawRealTrait, const PRECISION: u32> {
888    _phantom: PhantomData<RawReal>,
889}
890
891impl<RawReal: RawRealTrait, const PRECISION: u32> RawKernel
892    for NumKernelStrictFinite<RawReal, PRECISION>
893{
894    type RawReal = RawReal;
895    type RawComplex = RawReal::RawComplex;
896}
897
898impl<RawReal: RawRealTrait, const PRECISION: u32> NumKernel
899    for NumKernelStrictFinite<RawReal, PRECISION>
900where
901    StrictFinitePolicy<RawReal, PRECISION>: ValidationPolicyReal<Value = RawReal>,
902    StrictFinitePolicy<RawReal::RawComplex, PRECISION>:
903        ValidationPolicyComplex<Value = RawReal::RawComplex>,
904{
905    const PRECISION: u32 = PRECISION;
906
907    type RealPolicy = StrictFinitePolicy<RawReal, PRECISION>;
908
909    type ComplexPolicy = StrictFinitePolicy<RawReal::RawComplex, PRECISION>;
910
911    type Real = RealValidated<Self>;
912    type Complex = ComplexValidated<Self>;
913}
914//-----------------------------------------------------------------------------------------------
915
916//-----------------------------------------------------------------------------------------------
917pub struct NumKernelStrictFiniteInDebug<RawReal: RawRealTrait, const PRECISION: u32> {
918    _phantom: PhantomData<RawReal>,
919}
920
921impl<RawReal: RawRealTrait, const PRECISION: u32> RawKernel
922    for NumKernelStrictFiniteInDebug<RawReal, PRECISION>
923{
924    type RawReal = RawReal;
925    type RawComplex = RawReal::RawComplex;
926}
927
928impl<RawReal: RawRealTrait, const PRECISION: u32> NumKernel
929    for NumKernelStrictFiniteInDebug<RawReal, PRECISION>
930where
931    StrictFinitePolicy<RawReal, PRECISION>: ValidationPolicyReal<Value = RawReal>,
932    StrictFinitePolicy<RawReal::RawComplex, PRECISION>:
933        ValidationPolicyComplex<Value = RawReal::RawComplex>,
934{
935    const PRECISION: u32 = PRECISION;
936
937    type RealPolicy = DebugValidationPolicy<StrictFinitePolicy<RawReal, PRECISION>>;
938
939    type ComplexPolicy = DebugValidationPolicy<StrictFinitePolicy<RawReal::RawComplex, PRECISION>>;
940
941    type Real = RealValidated<Self>;
942    type Complex = ComplexValidated<Self>;
943}
944
945//-----------------------------------------------------------------------------------------------