Skip to main content

num_valid/core/
policies.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! Validation policies for scalar types.
4//!
5//! This module provides the validation policies that determine how scalar values
6//! are checked for validity. The primary policy is `StrictFinitePolicy`, which
7//! ensures values are finite and not subnormal.
8
9use crate::core::{
10    errors::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
11    traits::{
12        raw::{RawComplexTrait, RawRealTrait, RawScalarValidate},
13        validation::{
14            GuaranteesFiniteComplexValues, GuaranteesFiniteRealValues, ValidationPolicyComplex,
15            ValidationPolicyReal,
16        },
17    },
18};
19use duplicate::duplicate_item;
20use num::Complex;
21use std::marker::PhantomData;
22use try_create::ValidationPolicy;
23
24/// A validation policy that checks for strict finiteness.
25///
26/// For floating-point types (`ScalarType = `[`f32`], `ScalarType = `[`f64`], `ScalarType = `[`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html)), this policy ensures that the value is:
27/// - Not NaN (Not a Number).
28/// - Not positive or negative Infinity.
29/// - Not subnormal (for `f32`/`f64`).
30///   While [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) maintains its specified precision rather than having distinct subnormal
31///   representation in the IEEE 754 sense, this policy will also reject [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) values that are classified as
32///   [`FpCategory::Subnormal`](std::num::FpCategory::Subnormal) (e.g., results of underflow that are tiny but not exactly zero).
33///
34/// For complex types (`ScalarType = `[`Complex<f32>`], `ScalarType = `[`Complex<f64>`], `ScalarType = `[`rug::Complex`](https://docs.rs/rug/latest/rug/struct.Complex.html)), this policy applies
35/// the strict finiteness check to both the real and imaginary parts.
36///
37/// This struct is a Zero-Sized Type (ZST) and uses [`PhantomData`] to associate
38/// with the `ScalarType` it validates.
39pub struct StrictFinitePolicy<ScalarType: Sized, const PRECISION: u32>(PhantomData<ScalarType>);
40
41/// A type alias for a validation policy that enforces strict finiteness for the raw [`f64`] type.
42///
43/// This is a convenient alias for [`StrictFinitePolicy<f64, 53>`], configured specifically
44/// for Rust's native 64-bit floating-point number. It is used to validate that a given [`f64`]
45/// value is suitable for use within the library's validated types.
46///
47/// This policy ensures that a `f64` value is:
48/// - Not `NaN` (Not a Number).
49/// - Not positive or negative `Infinity`.
50/// - Not a subnormal number.
51///
52/// It is a fundamental building block for the native `f64` kernel, providing the validation
53/// logic for [`RealNative64StrictFinite`](crate::backends::native::validated::RealNative64StrictFinite).
54///
55/// # Example
56///
57/// ```rust
58/// use num_valid::{
59///     core::{
60///         errors::ErrorsValidationRawReal,
61///         policies::Native64RawRealStrictFinitePolicy,
62///     },
63/// };
64/// use try_create::ValidationPolicy;
65///
66/// // A valid finite number passes validation.
67/// assert!(Native64RawRealStrictFinitePolicy::validate(1.0).is_ok());
68///
69/// // NaN fails validation.
70/// let result_nan = Native64RawRealStrictFinitePolicy::validate(f64::NAN);
71/// assert!(matches!(result_nan, Err(ErrorsValidationRawReal::IsNaN { .. })));
72///
73/// // Infinity fails validation.
74/// let result_inf = Native64RawRealStrictFinitePolicy::validate(f64::INFINITY);
75/// assert!(matches!(result_inf, Err(ErrorsValidationRawReal::IsPosInfinity { .. })));
76/// ```
77pub type Native64RawRealStrictFinitePolicy = StrictFinitePolicy<f64, { f64::MANTISSA_DIGITS }>;
78
79/// A type alias for a validation policy that enforces strict finiteness for the raw [`num::Complex<f64>`] type.
80///
81/// This is a convenient alias for [`StrictFinitePolicy<Complex<f64>, 53>`], configured for
82/// Rust's native 64-bit complex numbers. It is used to validate that a given [`num::Complex<f64>`]
83/// value is suitable for use within the library's validated types.
84///
85/// This policy applies the strict finiteness check (as defined by [`Native64RawRealStrictFinitePolicy`])
86/// to both the real and imaginary parts of the complex number. A [`num::Complex<f64>`] value is considered
87/// valid if and only if both of its components are finite (not `NaN`, `Infinity`, or subnormal).
88///
89/// It is a fundamental building block for the native `f64` kernel, providing the validation
90/// logic for [`ComplexNative64StrictFinite`](crate::backends::native::validated::ComplexNative64StrictFinite).
91///
92/// # Example
93///
94/// ```rust
95/// use num_valid::{
96///     core::{
97///         errors::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
98///         policies::Native64RawComplexStrictFinitePolicy,
99///     },
100/// };
101/// use try_create::ValidationPolicy;
102/// use num::Complex;
103///
104/// // A complex number with valid finite parts passes validation.
105/// let valid_complex = Complex::new(1.0, -2.0);
106/// assert!(Native64RawComplexStrictFinitePolicy::validate(valid_complex).is_ok());
107///
108/// // A complex number with NaN in the real part fails validation.
109/// let nan_complex = Complex::new(f64::NAN, 2.0);
110/// let result_nan = Native64RawComplexStrictFinitePolicy::validate(nan_complex);
111/// assert!(matches!(result_nan, Err(ErrorsValidationRawComplex::InvalidRealPart { .. })));
112///
113/// // A complex number with Infinity in the imaginary part fails validation.
114/// let inf_complex = Complex::new(1.0, f64::INFINITY);
115/// let result_inf = Native64RawComplexStrictFinitePolicy::validate(inf_complex);
116/// assert!(matches!(result_inf, Err(ErrorsValidationRawComplex::InvalidImaginaryPart { .. })));
117///
118/// // A complex number with invalid parts in both also fails.
119/// let both_invalid = Complex::new(f64::NAN, f64::INFINITY);
120/// let result_both = Native64RawComplexStrictFinitePolicy::validate(both_invalid);
121/// assert!(matches!(result_both, Err(ErrorsValidationRawComplex::InvalidBothParts { .. })));
122/// ```
123pub type Native64RawComplexStrictFinitePolicy =
124    StrictFinitePolicy<Complex<f64>, { f64::MANTISSA_DIGITS }>;
125
126/// A type alias for a validation policy that enforces strict finiteness for the raw [`f32`] type.
127///
128/// This is a convenient alias for [`StrictFinitePolicy<f32, 24>`], configured specifically
129/// for Rust's native 32-bit floating-point number. It is used to validate that a given [`f32`]
130/// value is suitable for use within the library's validated types.
131///
132/// This policy ensures that a `f32` value is:
133/// - Not `NaN` (Not a Number).
134/// - Not positive or negative `Infinity`.
135/// - Not a subnormal number.
136///
137/// It is a fundamental building block for the native `f32` kernel, providing the validation
138/// logic for [`RealNative32StrictFinite`](crate::backends::native::validated::RealNative32StrictFinite).
139///
140/// # Example
141///
142/// ```rust
143/// use num_valid::{
144///     core::{
145///         errors::ErrorsValidationRawReal,
146///         policies::Native32RawRealStrictFinitePolicy,
147///     },
148/// };
149/// use try_create::ValidationPolicy;
150///
151/// // A valid finite number passes validation.
152/// assert!(Native32RawRealStrictFinitePolicy::validate(1.0).is_ok());
153///
154/// // NaN fails validation.
155/// let result_nan = Native32RawRealStrictFinitePolicy::validate(f32::NAN);
156/// assert!(matches!(result_nan, Err(ErrorsValidationRawReal::IsNaN { .. })));
157///
158/// // Infinity fails validation.
159/// let result_inf = Native32RawRealStrictFinitePolicy::validate(f32::INFINITY);
160/// assert!(matches!(result_inf, Err(ErrorsValidationRawReal::IsPosInfinity { .. })));
161/// ```
162pub type Native32RawRealStrictFinitePolicy = StrictFinitePolicy<f32, { f32::MANTISSA_DIGITS }>;
163
164/// A type alias for a validation policy that enforces strict finiteness for the raw [`num::Complex<f32>`] type.
165///
166/// This is a convenient alias for [`StrictFinitePolicy<Complex<f32>, 24>`], configured for
167/// Rust's native 32-bit complex numbers. It is used to validate that a given [`num::Complex<f32>`]
168/// value is suitable for use within the library's validated types.
169///
170/// This policy applies the strict finiteness check (as defined by [`Native32RawRealStrictFinitePolicy`])
171/// to both the real and imaginary parts of the complex number. A [`num::Complex<f32>`] value is considered
172/// valid if and only if both of its components are finite (not `NaN`, `Infinity`, or subnormal).
173///
174/// It is a fundamental building block for the native `f32` kernel, providing the validation
175/// logic for [`ComplexNative32StrictFinite`](crate::backends::native::validated::ComplexNative32StrictFinite).
176///
177/// # Example
178///
179/// ```rust
180/// use num_valid::{
181///     core::{
182///         errors::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
183///         policies::Native32RawComplexStrictFinitePolicy,
184///     },
185/// };
186/// use try_create::ValidationPolicy;
187/// use num::Complex;
188///
189/// // A complex number with valid finite parts passes validation.
190/// let valid_complex = Complex::new(1.0, -2.0);
191/// assert!(Native32RawComplexStrictFinitePolicy::validate(valid_complex).is_ok());
192///
193/// // A complex number with NaN in the real part fails validation.
194/// let nan_complex = Complex::new(f32::NAN, 2.0);
195/// let result_nan = Native32RawComplexStrictFinitePolicy::validate(nan_complex);
196/// assert!(matches!(result_nan, Err(ErrorsValidationRawComplex::InvalidRealPart { .. })));
197///
198/// // A complex number with Infinity in the imaginary part fails validation.
199/// let inf_complex = Complex::new(1.0, f32::INFINITY);
200/// let result_inf = Native32RawComplexStrictFinitePolicy::validate(inf_complex);
201/// assert!(matches!(result_inf, Err(ErrorsValidationRawComplex::InvalidImaginaryPart { .. })));
202///
203/// // A complex number with invalid parts in both also fails.
204/// let both_invalid = Complex::new(f32::NAN, f32::INFINITY);
205/// let result_both = Native32RawComplexStrictFinitePolicy::validate(both_invalid);
206/// assert!(matches!(result_both, Err(ErrorsValidationRawComplex::InvalidBothParts { .. })));
207/// ```
208pub type Native32RawComplexStrictFinitePolicy =
209    StrictFinitePolicy<Complex<f32>, { f32::MANTISSA_DIGITS }>;
210
211/// Ensures the `f32`/`f64` value is strictly finite.
212///
213/// This policy checks if the `f32`/`f64` value is:
214/// - Not NaN (Not a Number).
215/// - Not positive or negative Infinity.
216/// - Not subnormal.
217///
218/// # Errors
219///
220/// Returns [`ErrorsValidationRawReal`] if the value
221/// fails any of these checks.
222#[duplicate_item(
223    T mantissa_digits;
224    [f32] [24];
225    [f64] [53];
226)]
227impl ValidationPolicy for StrictFinitePolicy<T, mantissa_digits> {
228    type Value = T;
229    type Error = ErrorsValidationRawReal<T>;
230
231    #[inline(always)]
232    fn validate_ref(value: &T) -> Result<(), Self::Error> {
233        value.validate_raw_scalar_ref()
234    }
235}
236
237//------------------------------------------------------------------------------------------------
238/// A validation policy that is active only in debug builds.
239///
240/// This struct acts as a wrapper around another [`ValidationPolicy`].
241///
242/// - In **debug builds** (`#[cfg(debug_assertions)]`), it delegates validation
243///   directly to the inner policy `P`.
244/// - In **release builds** (`#[cfg(not(debug_assertions))]`), it becomes a "no-op"
245///   (no operation), meaning its `validate` and `validate_ref` methods do nothing
246///   and always return `Ok`.
247///
248/// This is useful for enforcing strict, potentially expensive validations during
249/// development and testing, while eliminating their performance overhead in production code.
250///
251/// # Generic Parameters
252///
253/// - `P`: The inner [`ValidationPolicy`] to use during debug builds.
254///
255/// # Example
256///
257/// ```rust,ignore
258/// use num_valid::{validation::{DebugValidationPolicy, StrictFinitePolicy, Native64RawRealStrictFinitePolicy}};
259/// use try_create::ValidationPolicy;
260///
261/// // Define a policy that uses Native64RawRealStrictFinitePolicy
262/// // (i.e. StrictFinitePolicy<f64, 53>) only in debug builds.
263/// type MyPolicy = DebugValidationPolicy<Native64RawRealStrictFinitePolicy>;
264///
265/// let nan_value = f64::NAN;
266/// let result = MyPolicy::validate(nan_value);
267///
268/// #[cfg(debug_assertions)]
269/// {
270///     // In debug mode, the validation fails because StrictFinitePolicy catches NaN.
271///     assert!(result.is_err());
272/// }
273///
274/// #[cfg(not(debug_assertions))]
275/// {
276///     // In release mode, the validation is skipped and always succeeds.
277///     assert!(result.is_ok());
278/// }
279/// ```
280pub struct DebugValidationPolicy<P: ValidationPolicy>(PhantomData<P>);
281
282impl<P: ValidationPolicy> ValidationPolicy for DebugValidationPolicy<P> {
283    type Value = P::Value;
284    type Error = P::Error;
285
286    #[inline(always)]
287    fn validate_ref(value: &Self::Value) -> Result<(), Self::Error> {
288        // In debug builds, this implementation delegates to the inner policy `P`.
289        #[cfg(debug_assertions)]
290        {
291            // Delegate to the inner policy's validation logic.
292            P::validate_ref(value)
293        }
294        #[cfg(not(debug_assertions))]
295        {
296            let _ = value; // Avoid unused variable warning in release mode.
297            // In release mode, this is a no-op.
298            // The validation is skipped, and we always return Ok.
299            // This allows the compiler to optimize away the validation logic entirely.
300            // This is useful for performance-critical code where validation is not needed in production.
301            // Note: The `value` is not used here, but we keep it to match the signature of `validate_ref`.
302            // This way, we can still call this method without needing to change the function signature.
303            // This is particularly useful when this policy is used in generic contexts
304            // where the `validate_ref` method is expected to take a reference to the value.
305            // The `PhantomData` ensures that the type system knows about `P` even
306            // though we don't use it directly in the release build.
307            // This is a common pattern in Rust to create zero-sized types that carry type information.
308            Ok(())
309        }
310    }
311}
312
313impl<P> ValidationPolicyReal for DebugValidationPolicy<P>
314where
315    P: ValidationPolicyReal,
316{
317    const PRECISION: u32 = P::PRECISION;
318}
319
320impl<P> ValidationPolicyComplex for DebugValidationPolicy<P>
321where
322    P: ValidationPolicyComplex,
323{
324    const PRECISION: u32 = P::PRECISION;
325}
326//------------------------------------------------------------------------------------------------
327
328//------------------------------------------------------------------------------------------------
329/// Validates a complex number by checking both its real and imaginary parts.
330///
331/// This function uses the provided real validation function `validation_func_raw_real` to
332/// validate both parts.
333/// If both parts are valid, it returns `Ok(())`. If either part is invalid,
334/// it returns an appropriate error variant from the `ErrorsValidationRawComplex` enum.
335///
336/// # Errors
337/// Returns [`ErrorsValidationRawComplex<P::Error>`](ErrorsValidationRawComplex)
338/// if either the real part, the imaginary part, or both parts fail validation
339/// using the real validation function `validation_func_raw_real`.
340pub(crate) fn validate_complex_from_parts<T: RawRealTrait>(
341    real_part: &T,
342    imag_part: &T,
343    validation_func_raw_real: fn(&T) -> Result<(), ErrorsValidationRawReal<T>>,
344) -> Result<(), ErrorsValidationRawComplex<ErrorsValidationRawReal<T>>> {
345    let real_validation = validation_func_raw_real(real_part);
346    let imag_validation = validation_func_raw_real(imag_part);
347    match (real_validation, imag_validation) {
348        (Ok(()), Ok(())) => Ok(()),
349        (Ok(()), Err(imag_err)) => Err(ErrorsValidationRawComplex::InvalidImaginaryPart {
350            source: Box::new(imag_err),
351        }),
352        (Err(real_err), Ok(())) => Err(ErrorsValidationRawComplex::InvalidRealPart {
353            source: Box::new(real_err),
354        }),
355        (Err(real_err), Err(imag_err)) => Err(ErrorsValidationRawComplex::InvalidBothParts {
356            real_error: Box::new(real_err),
357            imag_error: Box::new(imag_err),
358        }),
359    }
360}
361//------------------------------------------------------------------------------------------------
362
363//-------------------------------------------------------------
364/// Validates a value using the given policy, but only in debug builds.
365/// In release builds, this function is a no-op and should be optimized away.
366///
367/// # Panics
368///
369/// In debug builds, this function will panic if `P::validate_ref(value)` returns an `Err`.
370#[inline(always)]
371pub fn validate_in_debug<P: ValidationPolicy>(value: &P::Value, msg: &str) {
372    #[cfg(debug_assertions)]
373    {
374        if let Err(e) = P::validate_ref(value) {
375            panic!("Debug validation of {msg} value failed: {e}");
376        }
377    }
378    #[cfg(not(debug_assertions))]
379    {
380        // These are no-op in release builds
381        let _ = value;
382        let _ = msg;
383    }
384}
385//--------------------------------------------------------------------------------------------------
386
387//--------------------------------------------------------------------------------------------------
388/// Ensures both the real and imaginary parts of a `Complex<f64>` value are strictly finite.
389///
390/// This policy applies the [`StrictFinitePolicy<f64>`](StrictFinitePolicy) to both
391/// the real and imaginary components of the complex number.
392///
393/// # Errors
394///
395/// Returns [`ErrorsValidationRawComplex<ErrorsValidationRawReal<f64>>`](ErrorsValidationRawComplex)
396/// if either the real part, the imaginary part, or both parts fail the
397/// `StrictFinitePolicy<f64>` checks.
398#[duplicate_item(
399    T mantissa_digits;
400    [f32] [24];
401    [f64] [53];
402)]
403impl ValidationPolicy for StrictFinitePolicy<Complex<T>, mantissa_digits> {
404    type Value = Complex<T>;
405    type Error = ErrorsValidationRawComplex<ErrorsValidationRawReal<T>>;
406
407    fn validate_ref(value: &Complex<T>) -> Result<(), Self::Error> {
408        validate_complex_from_parts(
409            &value.re,
410            &value.im,
411            StrictFinitePolicy::<T, mantissa_digits>::validate_ref,
412        )
413    }
414}
415
416impl<RawReal: RawRealTrait, const PRECISION: u32> ValidationPolicyReal
417    for StrictFinitePolicy<RawReal, PRECISION>
418where
419    StrictFinitePolicy<RawReal, PRECISION>:
420        ValidationPolicy<Value = RawReal, Error = <RawReal as RawScalarValidate>::ValidationError>,
421{
422    const PRECISION: u32 = PRECISION;
423}
424
425impl<RawComplex: RawComplexTrait, const PRECISION: u32> ValidationPolicyComplex
426    for StrictFinitePolicy<RawComplex, PRECISION>
427where
428    StrictFinitePolicy<RawComplex, PRECISION>: ValidationPolicy<
429            Value = RawComplex,
430            Error = <RawComplex as RawScalarValidate>::ValidationError,
431        >,
432{
433    const PRECISION: u32 = PRECISION;
434}
435
436//--------------------------------------------------------------------------------------------------
437// Rug Implementations (conditional compilation)
438//--------------------------------------------------------------------------------------------------
439
440#[cfg(feature = "rug")]
441pub(crate) mod rug_impls {
442    use super::*; // Imports items from the parent module (validation)
443    use crate::core::errors::capture_backtrace;
444    use std::num::FpCategory;
445
446    /// Ensures the [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) value is strictly finite.
447    ///
448    /// This policy checks if the underlying [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) value:
449    /// - Is not NaN (Not a Number).
450    /// - Is not positive nor negative Infinity.
451    /// - Has the specified precision (equal to `PRECISION`).
452    ///
453    /// Note: [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html) does not have a direct concept of "subnormal" in the same
454    /// way IEEE 754 floats do; it maintains its specified precision.
455    ///
456    /// # Errors
457    ///
458    /// Returns [`ErrorsValidationRawReal<rug::Float>`](ErrorsValidationRawReal)
459    /// if the value fails any of these checks.
460    impl<const PRECISION: u32> ValidationPolicy for StrictFinitePolicy<rug::Float, PRECISION> {
461        type Value = rug::Float;
462        type Error = ErrorsValidationRawReal<rug::Float>;
463
464        fn validate_ref(value: &rug::Float) -> Result<(), Self::Error> {
465            let actual_precision = value.prec();
466            if actual_precision == PRECISION {
467                // rug::Float uses std::num::FpCategory via its own classify method
468                match value.classify() {
469                    FpCategory::Infinite => {
470                        if value.is_sign_positive() {
471                            Err(ErrorsValidationRawReal::IsPosInfinity {
472                                backtrace: capture_backtrace(),
473                            })
474                        } else {
475                            Err(ErrorsValidationRawReal::IsNegInfinity {
476                                backtrace: capture_backtrace(),
477                            })
478                        }
479                    }
480                    FpCategory::Nan => Err(ErrorsValidationRawReal::IsNaN {
481                        value: value.clone(),
482                        backtrace: capture_backtrace(),
483                    }),
484                    FpCategory::Subnormal => Err(ErrorsValidationRawReal::IsSubnormal {
485                        value: value.clone(),
486                        backtrace: capture_backtrace(),
487                    }),
488                    FpCategory::Zero | FpCategory::Normal => Ok(()),
489                }
490            } else {
491                Err(ErrorsValidationRawReal::PrecisionMismatch {
492                    input_value: value.clone(),
493                    actual_precision,
494                    requested_precision: PRECISION,
495                    backtrace: capture_backtrace(),
496                })
497            }
498        }
499    }
500
501    /// Ensures both the real and imaginary parts of a [`rug::Complex`](https://docs.rs/rug/latest/rug/struct.Complex.html) value are strictly finite.
502    ///
503    /// This policy applies the [`StrictFinitePolicy<rug::Float>`]
504    /// (which checks the underlying [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html)) to both the real and imaginary
505    /// components of the [`rug::Complex`](https://docs.rs/rug/latest/rug/struct.Complex.html).
506    ///
507    /// # Errors
508    ///
509    /// Returns [`ErrorsValidationRawComplex<ErrorsValidationRawReal<rug::Float>>`](ErrorsValidationRawComplex)
510    /// if either the real part, the imaginary part, or both parts fail the
511    /// `StrictFinitePolicy<RealRugStrictFinite<Precision>>` checks.
512    impl<const PRECISION: u32> ValidationPolicy for StrictFinitePolicy<rug::Complex, PRECISION> {
513        type Value = rug::Complex;
514        type Error = ErrorsValidationRawComplex<ErrorsValidationRawReal<rug::Float>>;
515
516        fn validate_ref(value: &rug::Complex) -> Result<(), Self::Error> {
517            validate_complex_from_parts(
518                value.real(),
519                value.imag(),
520                StrictFinitePolicy::<rug::Float, PRECISION>::validate_ref,
521            )
522        }
523    }
524}
525//-------------------------------------------------------------
526
527// Implement the marker for `StrictFinitePolicy` for any real scalar type.
528impl<RawReal: RawRealTrait, const PRECISION: u32> GuaranteesFiniteRealValues
529    for StrictFinitePolicy<RawReal, PRECISION>
530where
531    // This bound is necessary to satisfy the supertrait requirements of GuaranteesFiniteRealValues
532    StrictFinitePolicy<RawReal, PRECISION>: ValidationPolicyReal,
533{
534}
535
536// Implement the marker for `DebugValidationPolicy<StrictFinitePolicy>` for any real scalar type.
537impl<RawReal: RawRealTrait, const PRECISION: u32> GuaranteesFiniteRealValues
538    for DebugValidationPolicy<StrictFinitePolicy<RawReal, PRECISION>>
539where
540    // This bound is necessary to satisfy the supertrait requirements of GuaranteesFiniteRealValues
541    StrictFinitePolicy<RawReal, PRECISION>: ValidationPolicyReal,
542{
543}
544
545// Implement the marker for `StrictFinitePolicy` for any complex scalar type.
546impl<RawComplex: RawComplexTrait, const PRECISION: u32> GuaranteesFiniteComplexValues
547    for StrictFinitePolicy<RawComplex, PRECISION>
548where
549    // This bound is necessary to satisfy the supertrait requirements of GuaranteesFiniteComplexValues
550    StrictFinitePolicy<RawComplex, PRECISION>: ValidationPolicyComplex,
551{
552}
553
554// Implement the marker for `DebugValidationPolicy<StrictFinitePolicy>` for any complex scalar type.
555impl<RawComplex: RawComplexTrait, const PRECISION: u32> GuaranteesFiniteComplexValues
556    for DebugValidationPolicy<StrictFinitePolicy<RawComplex, PRECISION>>
557where
558    // This bound is necessary to satisfy the supertrait requirements of GuaranteesFiniteComplexValues
559    StrictFinitePolicy<RawComplex, PRECISION>: ValidationPolicyComplex,
560{
561}
562//-------------------------------------------------------------