Skip to main content

num_valid/backends/native/
validated.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! # Validated Native Kernel Types
4//!
5//! This module provides convenient, pre-configured type aliases for the native `f32` and `f64`
6//! kernels. These types wrap native real and complex values in the [`RealValidated`](crate::core::types::RealValidated)
7//! and [`ComplexValidated`](crate::core::types::ComplexValidated) structs, bundling them with specific *validation policies*.
8//!
9//! These type aliases are the primary entry point for users who want to work with
10//! validated numbers that provide compile-time guarantees about their properties (e.g., finiteness).
11//!
12//! ## Policies
13//!
14//! Two main policies are provided:
15//!
16//! - **`Native64StrictFinite`:** Enforces that all values are finite (not `NaN` or `Infinity`)
17//!   in all build modes. Operations on types using this policy will panic on validation
18//!   failure in debug builds and return a `Result` in release builds. This is the safest and
19//!   most common choice.
20//!
21//! - **`Native64StrictFiniteInDebug`:** Also enforces finiteness, but validation checks that
22//!   would panic are **only performed in debug builds**. In release builds, these checks are
23//!   skipped for performance, and operations assume the inputs are valid. This is for
24//!   performance-critical code where the developer can guarantee the validity of inputs.
25//!
26//! ## Example
27//!
28//! ```rust
29//! use num_valid::{RealNative64StrictFinite, functions::Sqrt};
30//! use try_create::TryNew;
31//!
32//! // Creation succeeds because 4.0 is a valid, finite number.
33//! let x = RealNative64StrictFinite::try_new(4.0).unwrap();
34//!
35//! // Creation fails for non-finite numbers.
36//! assert!(RealNative64StrictFinite::try_new(f64::NAN).is_err());
37//!
38//! // Mathematical operations are available through traits.
39//! let sqrt_x = x.sqrt();
40//! assert_eq!(*sqrt_x.as_ref(), 2.0);
41//! ```
42//!
43//! ## Zero-Copy Conversions with Bytemuck
44//!
45//! The validated types in this module implement [`bytemuck::CheckedBitPattern`] and
46//! [`bytemuck::NoUninit`], enabling safe, zero-copy conversions between `f64` byte
47//! representations and validated types. This is particularly useful for:
48//!
49//! - Interoperability with binary data formats and serialization
50//! - Performance-critical code working with byte arrays
51//! - Loading validated numbers from external data sources
52//!
53//! The conversion automatically validates the bit pattern, rejecting invalid values
54//! (NaN, Infinity, subnormal numbers) while maintaining zero-cost performance for
55//! valid inputs:
56//!
57//! ```rust
58//! use num_valid::RealNative64StrictFinite;
59//! use bytemuck::checked::try_from_bytes;
60//!
61//! // Valid conversion
62//! let value = 42.0_f64;
63//! let bytes = value.to_ne_bytes();
64//! let validated: &RealNative64StrictFinite = try_from_bytes(&bytes).unwrap();
65//! assert_eq!(*validated.as_ref(), 42.0);
66//!
67//! // Invalid values are rejected
68//! let nan_bytes = f64::NAN.to_ne_bytes();
69//! assert!(try_from_bytes::<RealNative64StrictFinite>(&nan_bytes).is_err());
70//! ```
71//!
72//! For comprehensive examples of valid conversions, error handling, and slice operations,
73//! see the test module in the source code.
74
75use crate::kernels::{
76    ComplexValidated, NumKernelStrictFinite, NumKernelStrictFiniteInDebug, RealValidated,
77};
78
79//------------------------------------------------------------------------------------------------------------
80/// A kernel policy that enforces strict finiteness for `f64` and `Complex<f64>` values.
81///
82/// This is a type alias for [`NumKernelStrictFinite<f64, 53>`].
83///
84/// It ensures that all validated values are finite (not `NaN` or `Infinity`).
85/// In debug builds, operations that fail validation will panic. In release builds, they
86/// will return an error. This policy is used by [`RealNative64StrictFinite`] and
87/// [`ComplexNative64StrictFinite`].
88pub type Native64StrictFinite = NumKernelStrictFinite<f64, 53>;
89//------------------------------------------------------------------------------------------------------------
90
91//------------------------------------------------------------------------------------------------------------
92/// A kernel policy that enforces strict finiteness for `f64` values **only in debug builds**.
93///
94/// This is a type alias for [`NumKernelStrictFiniteInDebug<f64, 53>`].
95///
96/// This policy is designed for performance-critical applications. In debug builds, it
97/// behaves identically to [`Native64StrictFinite`], panicking on validation failures.
98/// In **release builds**, these validation checks are **disabled**, and operations proceed
99/// assuming the inputs are valid. Use this policy with caution when you can guarantee
100/// the integrity of your data in release environments.
101pub type Native64StrictFiniteInDebug = NumKernelStrictFiniteInDebug<f64, 53>;
102//------------------------------------------------------------------------------------------------------------
103
104//------------------------------------------------------------------------------------------------------------
105/// A validated real number that guarantees its inner `f64` value is finite.
106///
107/// This is a type alias for [`RealValidated<Native64StrictFinite>`].
108///
109/// It is the standard, safe-to-use validated real number type for the native `f64` kernel.
110/// It prevents the representation of `NaN` and `Infinity`.
111pub type RealNative64StrictFinite = RealValidated<Native64StrictFinite>;
112
113/// A validated complex number that guarantees its inner `f64` parts are finite.
114///
115/// This is a type alias for [`ComplexValidated<Native64StrictFinite>`].
116///
117/// It is the standard, safe-to-use validated complex number type for the native `f64` kernel.
118/// It ensures that both the real and imaginary components are finite values.
119pub type ComplexNative64StrictFinite = ComplexValidated<Native64StrictFinite>;
120//------------------------------------------------------------------------------------------------------------
121
122//------------------------------------------------------------------------------------------------------------
123/// A kernel policy that enforces strict finiteness for `f32` and `Complex<f32>` values.
124///
125/// This is a type alias for [`NumKernelStrictFinite<f32, 24>`].
126///
127/// It ensures that all validated values are finite (not `NaN` or `Infinity`).
128/// In debug builds, operations that fail validation will panic. In release builds, they
129/// will return an error. This policy is used by [`RealNative32StrictFinite`] and
130/// [`ComplexNative32StrictFinite`].
131pub type Native32StrictFinite = NumKernelStrictFinite<f32, 24>;
132//------------------------------------------------------------------------------------------------------------
133
134//------------------------------------------------------------------------------------------------------------
135/// A kernel policy that enforces strict finiteness for `f32` values **only in debug builds**.
136///
137/// This is a type alias for [`NumKernelStrictFiniteInDebug<f32, 24>`].
138///
139/// This policy is designed for performance-critical applications. In debug builds, it
140/// behaves identically to [`Native32StrictFinite`], panicking on validation failures.
141/// In **release builds**, these validation checks are **disabled**, and operations proceed
142/// assuming the inputs are valid. Use this policy with caution when you can guarantee
143/// the integrity of your data in release environments.
144pub type Native32StrictFiniteInDebug = NumKernelStrictFiniteInDebug<f32, 24>;
145//------------------------------------------------------------------------------------------------------------
146
147//------------------------------------------------------------------------------------------------------------
148/// A validated real number that guarantees its inner `f32` value is finite.
149///
150/// This is a type alias for [`RealValidated<Native32StrictFinite>`].
151///
152/// It is the standard, safe-to-use validated real number type for the native `f32` kernel.
153/// It prevents the representation of `NaN` and `Infinity`.
154pub type RealNative32StrictFinite = RealValidated<Native32StrictFinite>;
155
156/// A validated complex number that guarantees its inner `f32` parts are finite.
157///
158/// This is a type alias for [`ComplexValidated<Native32StrictFinite>`].
159///
160/// It is the standard, safe-to-use validated complex number type for the native `f32` kernel.
161/// It ensures that both the real and imaginary components are finite values.
162pub type ComplexNative32StrictFinite = ComplexValidated<Native32StrictFinite>;
163//------------------------------------------------------------------------------------------------------------
164
165//------------------------------------------------------------------------------------------------------------
166/// A validated real number that checks for finiteness **only in debug builds**.
167///
168/// This is a type alias for [`RealValidated<Native64StrictFiniteInDebug>`].
169///
170/// Use this type in performance-sensitive contexts where the overhead of validation
171/// in release builds is unacceptable and inputs are known to be valid.
172pub type RealNative64StrictFiniteInDebug = RealValidated<Native64StrictFiniteInDebug>;
173
174/// A validated complex number that checks for finiteness **only in debug builds**.
175///
176/// This is a type alias for [`ComplexValidated<Native64StrictFiniteInDebug>`].
177///
178/// Use this type in performance-sensitive contexts where the overhead of validation
179/// in release builds is unacceptable and inputs are known to be valid.
180pub type ComplexNative64StrictFiniteInDebug = ComplexValidated<Native64StrictFiniteInDebug>;
181//------------------------------------------------------------------------------------------------------------
182
183// --- Hashing Implementation ---------------------------------------------------------
184// Note: The Hash trait is implemented generically in the validation module for all
185// RealValidated<K> types where K::RealPolicy implements GuaranteesFiniteRealValues.
186// This ensures that validated types with finite value guarantees can be used as
187// keys in HashMap and other hash-based collections.
188//
189// The implementation hashes the raw IEEE 754 bit representation of the f64 value,
190// with special handling for signed zeros to maintain the hash contract that
191// a == b implies hash(a) == hash(b).
192//-------------------------------------------------------------
193
194//------------------------------------------------------------------------------------------------
195#[cfg(test)]
196mod tests {
197    use super::*;
198    use crate::{
199        Clamp, ComplexScalarConstructors, ComplexScalarGetParts, ComplexScalarMutateParts,
200        ComplexScalarSetParts, Constants, ExpM1, FpChecks, Hypot, Ln1p, MulAddRef, RealScalar,
201        Rounding, Sign, TotalCmp,
202        core::errors::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
203        functions::{
204            ACos, ACosH, ACosHErrors, ACosHInputErrors, ACosRealErrors, ACosRealInputErrors, ASin,
205            ASinH, ASinRealErrors, ASinRealInputErrors, ATan, ATan2, ATan2Errors,
206            ATanComplexErrors, ATanComplexInputErrors, ATanH, ATanHErrors, ATanHInputErrors, Abs,
207            Arg, Classify, Conjugate, Cos, CosH, Exp, ExpErrors, Ln, Log2, Log10,
208            LogarithmComplexErrors, LogarithmComplexInputErrors, Max, Min, NegAssign, Pow,
209            PowComplexBaseRealExponentErrors, PowIntExponentErrors, PowIntExponentInputErrors,
210            PowRealBaseRealExponentErrors, Reciprocal, ReciprocalErrors, Sin, SinH, Sqrt,
211            SqrtRealErrors, Tan, TanH,
212        },
213    };
214    use approx::assert_ulps_eq;
215    use num::{Complex, One, Zero};
216    use rand::RngExt;
217    use std::{
218        assert_matches,
219        cmp::Ordering,
220        f64::consts::*,
221        num::FpCategory,
222        ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
223    };
224    use try_create::{IntoInner, TryNew, TryNewValidated};
225
226    type RealValidated = RealNative64StrictFinite;
227    type ComplexValidated = ComplexNative64StrictFinite;
228
229    mod fp_checks {
230        use super::*;
231
232        #[test]
233        fn is_finite() {
234            let real = RealValidated::try_new(1.).unwrap();
235            assert!(real.is_finite());
236
237            let real = RealValidated::try_new(f64::INFINITY);
238            assert!(real.is_err());
239
240            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
241            assert!(complex.is_finite());
242
243            let complex = ComplexValidated::try_new(Complex::new(f64::INFINITY, 1.));
244            assert!(complex.is_err());
245        }
246
247        #[test]
248        fn is_infinite() {
249            let real = RealValidated::try_new(1.).unwrap();
250            assert!(!real.is_infinite());
251
252            let real = RealValidated::try_new(f64::INFINITY);
253            assert!(real.is_err());
254
255            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
256            assert!(!complex.is_infinite());
257
258            let complex = ComplexValidated::try_new(Complex::new(f64::INFINITY, 1.));
259            assert!(complex.is_err());
260        }
261
262        #[test]
263        fn is_nan() {
264            let real = RealValidated::try_new(1.).unwrap();
265            assert!(!real.is_nan());
266
267            let real = RealValidated::try_new(f64::NAN);
268            assert!(matches!(real, Err(ErrorsValidationRawReal::IsNaN { .. })));
269
270            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
271            assert!(!complex.is_nan());
272
273            let err = ComplexValidated::try_new(Complex::new(f64::NAN, 1.)).unwrap_err();
274            assert_matches!(
275                err,
276                ErrorsValidationRawComplex::InvalidRealPart {
277                    source,
278                } if matches!(*source, ErrorsValidationRawReal::IsNaN { .. })
279            );
280        }
281
282        #[test]
283        fn is_normal() {
284            let real = RealValidated::try_new(1.).unwrap();
285            assert!(real.is_normal());
286
287            let real = RealValidated::try_new(0.).unwrap();
288            assert!(!real.is_normal());
289
290            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
291            assert!(complex.is_normal());
292
293            let complex = ComplexValidated::try_new(Complex::new(0., 0.)).unwrap();
294            assert!(!complex.is_normal());
295        }
296    }
297
298    mod new_unchecked {
299        use super::*;
300
301        mod real {
302            use super::*;
303
304            #[test]
305            fn new_unchecked_valid_value() {
306                // SAFETY: 3.0 is a valid finite f64
307                let x = unsafe { RealValidated::new_unchecked(3.) };
308                assert_eq!(*x.as_ref(), 3.);
309            }
310
311            #[test]
312            fn new_unchecked_zero() {
313                // SAFETY: 0.0 is valid
314                let x = unsafe { RealValidated::new_unchecked(0.0) };
315                assert!(x.is_zero());
316            }
317
318            #[test]
319            fn new_unchecked_negative() {
320                // SAFETY: -42.5 is a valid finite f64
321                let x = unsafe { RealValidated::new_unchecked(-42.5) };
322                assert_eq!(*x.as_ref(), -42.5);
323            }
324
325            #[test]
326            fn new_unchecked_large_value() {
327                // SAFETY: f64::MAX is finite
328                let x = unsafe { RealValidated::new_unchecked(f64::MAX) };
329                assert_eq!(*x.as_ref(), f64::MAX);
330            }
331
332            #[test]
333            fn new_unchecked_small_value() {
334                // SAFETY: f64::MIN is finite
335                let x = unsafe { RealValidated::new_unchecked(f64::MIN) };
336                assert_eq!(*x.as_ref(), f64::MIN);
337            }
338
339            #[test]
340            fn new_unchecked_epsilon() {
341                // SAFETY: f64::EPSILON is a valid finite f64
342                let x = unsafe { RealValidated::new_unchecked(f64::EPSILON) };
343                assert_eq!(*x.as_ref(), f64::EPSILON);
344            }
345
346            #[test]
347            #[cfg(debug_assertions)]
348            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
349            fn new_unchecked_nan_panics_in_debug() {
350                // In debug mode, new_unchecked validates and panics on NaN
351                let _ = unsafe { RealValidated::new_unchecked(f64::NAN) };
352            }
353
354            #[test]
355            #[cfg(debug_assertions)]
356            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
357            fn new_unchecked_infinity_panics_in_debug() {
358                // In debug mode, new_unchecked validates and panics on infinity
359                let _ = unsafe { RealValidated::new_unchecked(f64::INFINITY) };
360            }
361
362            #[test]
363            #[cfg(debug_assertions)]
364            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
365            fn new_unchecked_neg_infinity_panics_in_debug() {
366                // In debug mode, new_unchecked validates and panics on negative infinity
367                let _ = unsafe { RealValidated::new_unchecked(f64::NEG_INFINITY) };
368            }
369        }
370
371        mod complex {
372            use super::*;
373
374            #[test]
375            fn new_unchecked_valid_value() {
376                // SAFETY: Both components are valid finite f64 values
377                let z = unsafe { ComplexValidated::new_unchecked(Complex::new(1.0, 2.0)) };
378                assert_eq!(z.real_part().into_inner(), 1.0);
379                assert_eq!(z.imag_part().into_inner(), 2.0);
380            }
381
382            #[test]
383            fn new_unchecked_zero() {
384                // SAFETY: Zero is valid
385                let z = unsafe { ComplexValidated::new_unchecked(Complex::new(0.0, 0.0)) };
386                assert!(z.is_zero());
387            }
388
389            #[test]
390            fn new_unchecked_real_only() {
391                // SAFETY: Valid real part, zero imaginary
392                let z = unsafe { ComplexValidated::new_unchecked(Complex::new(5.0, 0.0)) };
393                assert_eq!(z.real_part().into_inner(), 5.0);
394                assert_eq!(z.imag_part().into_inner(), 0.0);
395            }
396
397            #[test]
398            fn new_unchecked_imaginary_only() {
399                // SAFETY: Zero real part, valid imaginary
400                let z = unsafe { ComplexValidated::new_unchecked(Complex::new(0.0, -3.0)) };
401                assert_eq!(z.real_part().into_inner(), 0.0);
402                assert_eq!(z.imag_part().into_inner(), -3.0);
403            }
404
405            #[test]
406            fn new_unchecked_negative_components() {
407                // SAFETY: Both negative finite values are valid
408                let z = unsafe { ComplexValidated::new_unchecked(Complex::new(-1.5, -2.5)) };
409                assert_eq!(z.real_part().into_inner(), -1.5);
410                assert_eq!(z.imag_part().into_inner(), -2.5);
411            }
412
413            #[test]
414            fn new_unchecked_preserves_value_in_arithmetic() {
415                // SAFETY: All values are valid finite f64
416                let a = unsafe { ComplexValidated::new_unchecked(Complex::new(1.0, 2.0)) };
417                let b = unsafe { ComplexValidated::new_unchecked(Complex::new(3.0, 4.0)) };
418                let sum = a + b;
419                assert_eq!(sum.real_part().into_inner(), 4.0);
420                assert_eq!(sum.imag_part().into_inner(), 6.0);
421            }
422
423            #[test]
424            #[cfg(debug_assertions)]
425            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
426            fn new_unchecked_nan_real_part_panics_in_debug() {
427                // In debug mode, new_unchecked validates and panics on NaN in real part
428                let _ = unsafe { ComplexValidated::new_unchecked(Complex::new(f64::NAN, 1.0)) };
429            }
430
431            #[test]
432            #[cfg(debug_assertions)]
433            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
434            fn new_unchecked_nan_imag_part_panics_in_debug() {
435                // In debug mode, new_unchecked validates and panics on NaN in imaginary part
436                let _ = unsafe { ComplexValidated::new_unchecked(Complex::new(1.0, f64::NAN)) };
437            }
438
439            #[test]
440            #[cfg(debug_assertions)]
441            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
442            fn new_unchecked_infinity_real_part_panics_in_debug() {
443                // In debug mode, new_unchecked validates and panics on infinity in real part
444                let _ =
445                    unsafe { ComplexValidated::new_unchecked(Complex::new(f64::INFINITY, 1.0)) };
446            }
447
448            #[test]
449            #[cfg(debug_assertions)]
450            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
451            fn new_unchecked_infinity_imag_part_panics_in_debug() {
452                // In debug mode, new_unchecked validates and panics on infinity in imaginary part
453                let _ =
454                    unsafe { ComplexValidated::new_unchecked(Complex::new(1.0, f64::INFINITY)) };
455            }
456
457            #[test]
458            #[cfg(debug_assertions)]
459            #[should_panic(expected = "new_unchecked() validation failed in debug mode")]
460            fn new_unchecked_neg_infinity_panics_in_debug() {
461                // In debug mode, new_unchecked validates and panics on negative infinity
462                let _ = unsafe {
463                    ComplexValidated::new_unchecked(Complex::new(
464                        f64::NEG_INFINITY,
465                        f64::NEG_INFINITY,
466                    ))
467                };
468            }
469        }
470    }
471
472    mod abs {
473        use super::*;
474
475        mod real {
476            use super::*;
477
478            #[test]
479            fn abs_valid() {
480                let value = RealValidated::try_new(-4.).unwrap();
481
482                let expected_result = RealValidated::try_new(4.).unwrap();
483                assert_eq!(value.try_abs().unwrap().into_inner(), expected_result);
484                assert_eq!(value.abs().into_inner(), expected_result);
485            }
486
487            #[test]
488            fn abs_zero() {
489                let value = RealValidated::try_new(0.).unwrap();
490
491                let expected_result = RealValidated::try_new(0.).unwrap();
492                assert_eq!(value.try_abs().unwrap().into_inner(), expected_result);
493                assert_eq!(value.abs().into_inner(), expected_result);
494            }
495
496            /*
497            #[cfg(feature = "rug")]
498            #[test]
499            fn abs_nan() {
500                let value =
501                    RealValidated::try_new(rug::Float::with_val(53, rug::float::Special::Nan))
502                        .unwrap();
503                let result = value.try_abs();
504                assert!(matches!(result, Err(AbsRealErrors::Input(..))));
505            }
506
507            #[cfg(feature = "rug")]
508            #[test]
509            fn abs_infinite() {
510                let value = RealValidated::try_new(rug::Float::with_val(
511                    53,
512                    rug::float::Special::Infinity,
513                ))
514                .unwrap();
515                let result = value.try_abs();
516                assert!(matches!(result, Err(AbsRealErrors::Input(..))));
517            }
518            */
519        }
520
521        mod complex {
522            use super::*;
523
524            #[test]
525            fn abs_valid() {
526                let value = ComplexValidated::try_new(Complex::new(3., 4.)).unwrap();
527
528                let expected_result = RealValidated::try_new(5.).unwrap();
529                assert_eq!(value.try_abs().unwrap().into_inner(), expected_result);
530                assert_eq!(value.abs().into_inner(), expected_result);
531            }
532
533            #[test]
534            fn abs_zero() {
535                let value = ComplexValidated::try_new(Complex::new(0., 0.)).unwrap();
536
537                let expected_result = RealValidated::try_new(0.).unwrap();
538                assert_eq!(value.try_abs().unwrap().into_inner(), expected_result);
539                assert_eq!(value.abs().into_inner(), expected_result);
540            }
541            /*
542            #[test]
543            fn abs_nan() {
544                let value = Complex64Validated::try_new(Complex::new(
545                    53,
546                    (
547                        rug::Float::with_val(53, rug::float::Special::Nan),
548                        0.,
549                    ),
550                ))
551                .unwrap();
552                assert!(matches!(
553                    value.try_abs(),
554                    Err(AbsComplexErrors::Input(..))
555                ));
556            }
557
558            #[test]
559            fn abs_infinite() {
560                let value = Complex64Validated::try_new(Complex::new(
561                    53,
562                    (
563                        rug::Float::with_val(53, rug::float::Special::Infinity),
564                        0.,
565                    ),
566                ))
567                .unwrap();
568                assert!(matches!(
569                    value.try_abs(),
570                    Err(AbsComplexErrors::Input(..))
571                ));
572            }
573            */
574        }
575    }
576
577    mod builders {
578        use super::*;
579
580        mod real {
581            use super::*;
582
583            #[test]
584            fn into_inner() {
585                let value = RealValidated::try_new(1.23).unwrap();
586                assert_eq!(value.into_inner(), 1.23);
587            }
588
589            #[test]
590            fn new() {
591                let value = RealValidated::try_new(1.23).unwrap();
592                assert_eq!(*value.as_ref(), 1.23);
593            }
594
595            #[test]
596            fn try_new_nan() {
597                let err = RealValidated::try_new(f64::NAN).unwrap_err();
598                assert_matches!(err, ErrorsValidationRawReal::IsNaN { .. });
599            }
600
601            #[test]
602            fn try_new_pos_infinity() {
603                let err = RealValidated::try_new(f64::INFINITY).unwrap_err();
604                assert_matches!(err, ErrorsValidationRawReal::IsPosInfinity { .. });
605            }
606
607            #[test]
608            fn try_new_neg_infinity() {
609                let err = RealValidated::try_new(f64::NEG_INFINITY).unwrap_err();
610                assert_matches!(err, ErrorsValidationRawReal::IsNegInfinity { .. });
611            }
612        }
613
614        mod complex {
615            use super::*;
616
617            #[test]
618            fn into_inner() {
619                let v = Complex::new(1., 2.);
620                let value = ComplexValidated::try_new(v).unwrap();
621                assert_eq!(value.into_inner(), v);
622            }
623
624            #[test]
625            fn new() {
626                let v = Complex::new(1., 2.);
627                let value = ComplexValidated::try_new(v).unwrap();
628                assert_eq!(value.into_inner(), v);
629            }
630
631            #[test]
632            fn real_part() {
633                let c1 = ComplexValidated::try_new_validated(Complex::new(1.23, 4.56)).unwrap();
634                assert_eq!(c1.real_part().as_ref(), &1.23);
635
636                let c2 = ComplexValidated::try_new_validated(Complex::new(-7.89, 0.12)).unwrap();
637                assert_eq!(c2.real_part().as_ref(), &-7.89);
638
639                let c3 = ComplexValidated::try_new_validated(Complex::new(0., 10.)).unwrap();
640                assert!(c3.real_part().is_zero());
641
642                let c_nan_re =
643                    ComplexValidated::try_new_validated(Complex::new(f64::NAN, 5.)).unwrap_err();
644                assert_matches!(
645                    c_nan_re,
646                    ErrorsValidationRawComplex::InvalidRealPart {
647                        source
648                    } if matches!(*source, ErrorsValidationRawReal::IsNaN { .. })
649                );
650
651                let c_inf_re = ComplexValidated::try_new_validated(Complex::new(f64::INFINITY, 5.))
652                    .unwrap_err();
653                assert_matches!(
654                    c_inf_re,
655                    ErrorsValidationRawComplex::InvalidRealPart {
656                        source
657                    } if matches!(*source, ErrorsValidationRawReal::IsPosInfinity { .. })
658                );
659
660                let c_neg_inf_re =
661                    ComplexValidated::try_new_validated(Complex::new(f64::NEG_INFINITY, 5.))
662                        .unwrap_err();
663                assert_matches!(
664                    c_neg_inf_re,
665                    ErrorsValidationRawComplex::InvalidRealPart {
666                        source
667                    } if matches!(*source, ErrorsValidationRawReal::IsNegInfinity { .. })
668                );
669            }
670
671            #[test]
672            fn imag_part() {
673                let c1 = ComplexValidated::try_new_validated(Complex::new(1.23, 4.56)).unwrap();
674                assert_eq!(c1.imag_part().as_ref(), &4.56);
675
676                let c2 = ComplexValidated::try_new_validated(Complex::new(-7.89, 0.12)).unwrap();
677                assert_eq!(c2.imag_part().as_ref(), &0.12);
678
679                let c3 = ComplexValidated::try_new_validated(Complex::new(10., 0.)).unwrap();
680                assert!(c3.imag_part().is_zero());
681
682                let c_nan_im =
683                    ComplexValidated::try_new_validated(Complex::new(5., f64::NAN)).unwrap_err();
684                assert_matches!(
685                    c_nan_im,
686                    ErrorsValidationRawComplex::InvalidImaginaryPart {
687                        source
688                    } if matches!(*source, ErrorsValidationRawReal::IsNaN { .. })
689                );
690
691                let c_inf_im = ComplexValidated::try_new_validated(Complex::new(5., f64::INFINITY))
692                    .unwrap_err();
693                assert_matches!(
694                    c_inf_im,
695                    ErrorsValidationRawComplex::InvalidImaginaryPart {
696                        source
697                    } if matches!(*source, ErrorsValidationRawReal::IsPosInfinity { .. })
698                );
699
700                let c_neg_inf_im =
701                    ComplexValidated::try_new_validated(Complex::new(5., f64::NEG_INFINITY))
702                        .unwrap_err();
703                assert_matches!(
704                    c_neg_inf_im,
705                    ErrorsValidationRawComplex::InvalidImaginaryPart {
706                        source
707                    } if matches!(*source, ErrorsValidationRawReal::IsNegInfinity { .. })
708                );
709            }
710
711            #[test]
712            fn try_new_complex() {
713                let r1 = RealValidated::try_new(1.23).unwrap();
714                let i1 = RealValidated::try_new(4.56).unwrap();
715                let c1 = ComplexValidated::try_new_complex(*r1.as_ref(), *i1.as_ref()).unwrap();
716                assert_eq!(c1.real_part(), r1);
717                assert_eq!(c1.imag_part(), i1);
718
719                let r2 = RealValidated::try_new(-7.89).unwrap();
720                let i2 = RealValidated::try_new(-0.12).unwrap();
721                let c2 = ComplexValidated::try_new_complex(*r2.as_ref(), *i2.as_ref()).unwrap();
722                assert_eq!(c2.real_part(), r2);
723                assert_eq!(c2.imag_part(), i2);
724
725                let r3 = RealValidated::try_new(0.).unwrap();
726                let i3 = RealValidated::try_new(0.).unwrap();
727                let c3 = ComplexValidated::try_new_complex(*r3.as_ref(), *i3.as_ref()).unwrap();
728                assert_eq!(c3.real_part(), r3);
729                assert_eq!(c3.real_part(), i3);
730                assert!(c3.is_zero());
731
732                let c_nan_re = ComplexValidated::try_new_complex(f64::NAN, 5.).unwrap_err();
733                assert!(matches!(
734                    c_nan_re,
735                    ErrorsValidationRawComplex::InvalidRealPart { .. }
736                ));
737
738                let c_inf_im = ComplexValidated::try_new_complex(10., f64::INFINITY).unwrap_err();
739                assert!(matches!(
740                    c_inf_im,
741                    ErrorsValidationRawComplex::InvalidImaginaryPart { .. }
742                ));
743
744                let c_nan_re_inf_im =
745                    ComplexValidated::try_new_complex(f64::NAN, f64::INFINITY).unwrap_err();
746                assert!(matches!(
747                    c_nan_re_inf_im,
748                    ErrorsValidationRawComplex::InvalidBothParts { .. }
749                ));
750            }
751
752            #[test]
753            fn try_new_pure_real() {
754                let r1 = RealValidated::try_new(1.23).unwrap();
755                let c1 = ComplexValidated::try_new_pure_real(*r1.as_ref()).unwrap();
756                assert_eq!(c1.real_part(), r1);
757                assert!(c1.imag_part().is_zero());
758
759                let c_nan = ComplexValidated::try_new_pure_real(f64::NAN).unwrap_err();
760                assert_matches!(
761                    c_nan,
762                    ErrorsValidationRawComplex::InvalidRealPart {
763                        source
764                    } if matches!(*source, ErrorsValidationRawReal::IsNaN { .. })
765                );
766            }
767
768            #[test]
769            fn try_new_pure_imaginary() {
770                let i1 = RealValidated::try_new(1.23).unwrap();
771                let c1 = ComplexValidated::try_new_pure_imaginary(*i1.as_ref()).unwrap();
772                assert!(c1.real_part().is_zero());
773                assert_eq!(c1.imag_part(), i1);
774
775                let c_nan = ComplexValidated::try_new_pure_imaginary(f64::NAN).unwrap_err();
776                assert_matches!(
777                    c_nan,
778                    ErrorsValidationRawComplex::InvalidImaginaryPart {
779                        source
780                    } if matches!(*source, ErrorsValidationRawReal::IsNaN { .. })
781                );
782            }
783
784            #[test]
785            fn add_to_real_part() {
786                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
787                c.add_to_real_part(&RealValidated::try_new(3.).unwrap());
788                assert_eq!(c.real_part().as_ref(), &4.);
789                assert_eq!(c.imag_part().as_ref(), &2.);
790
791                c.add_to_real_part(&RealValidated::try_new(-5.).unwrap());
792                assert_eq!(c.real_part().as_ref(), &-1.);
793                assert_eq!(c.imag_part().as_ref(), &2.);
794            }
795
796            #[test]
797            fn add_to_imaginary_part() {
798                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
799                c.add_to_imaginary_part(&RealValidated::try_new(3.).unwrap());
800                assert_eq!(c.real_part().as_ref(), &1.);
801                assert_eq!(c.imag_part().as_ref(), &5.);
802
803                c.add_to_imaginary_part(&RealValidated::try_new(-4.).unwrap());
804                assert_eq!(c.real_part().as_ref(), &1.);
805                assert_eq!(c.imag_part().as_ref(), &1.);
806            }
807
808            #[test]
809            fn multiply_real_part() {
810                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
811                c.multiply_real_part(&RealValidated::try_new(3.).unwrap());
812                assert_eq!(c.real_part().as_ref(), &3.);
813                assert_eq!(c.imag_part().as_ref(), &2.);
814
815                c.multiply_real_part(&RealValidated::try_new(-2.).unwrap());
816                assert_eq!(c.real_part().as_ref(), &-6.);
817                assert_eq!(c.imag_part().as_ref(), &2.);
818            }
819
820            #[test]
821            fn multiply_imaginary_part() {
822                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
823                c.multiply_imaginary_part(&RealValidated::try_new(3.).unwrap());
824                assert_eq!(c.real_part().as_ref(), &1.);
825                assert_eq!(c.imag_part().as_ref(), &6.);
826
827                c.multiply_imaginary_part(&RealValidated::try_new(-0.5).unwrap());
828                assert_eq!(c.real_part().as_ref(), &1.);
829                assert_eq!(c.imag_part().as_ref(), &-3.);
830            }
831
832            #[test]
833            fn set_real_part() {
834                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
835                c.set_real_part(RealValidated::try_new(3.).unwrap());
836                assert_eq!(c.real_part().as_ref(), &3.);
837                assert_eq!(c.imag_part().as_ref(), &2.);
838
839                c.set_real_part(RealValidated::try_new(-4.).unwrap());
840                assert_eq!(c.real_part().as_ref(), &-4.);
841                assert_eq!(c.imag_part().as_ref(), &2.);
842            }
843
844            #[test]
845            fn set_imaginary_part() {
846                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
847                c.set_imaginary_part(RealValidated::try_new(3.).unwrap());
848                assert_eq!(c.real_part().as_ref(), &1.);
849                assert_eq!(c.imag_part().as_ref(), &3.);
850
851                c.set_imaginary_part(RealValidated::try_new(-4.).unwrap());
852                assert_eq!(c.real_part().as_ref(), &1.);
853                assert_eq!(c.imag_part().as_ref(), &-4.);
854            }
855        }
856    }
857
858    mod mul {
859        use super::*;
860
861        mod real {
862            use super::*;
863
864            #[test]
865            fn multiply_ref() {
866                let r1 = RealValidated::try_new_validated(3.).unwrap();
867                let r2 = RealValidated::try_new_validated(4.).unwrap();
868                let result = r1 * r2;
869                assert_eq!(result, RealValidated::try_new_validated(12.).unwrap());
870            }
871        }
872
873        mod complex {
874            use super::*;
875
876            #[test]
877            fn multiply_ref() {
878                let c1 = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
879                let c2 = ComplexValidated::try_new_validated(Complex::new(3., 4.)).unwrap();
880                let result = c1 * c2;
881                assert_eq!(
882                    result,
883                    ComplexValidated::try_new_validated(Complex::new(-5., 10.)).unwrap()
884                ); // (1*3 - 2*4) + (1*4 + 2*3)i
885            }
886
887            #[test]
888            fn complex_times_real() {
889                let r = RealValidated::try_new_validated(2.).unwrap();
890                let c = ComplexValidated::try_new_validated(Complex::new(3., 4.)).unwrap();
891
892                let result_expected =
893                    ComplexValidated::try_new_validated(Complex::new(6., 8.)).unwrap(); // 2 * (3 + 4i) = 6 + 8i
894
895                let result = c * r;
896                assert_eq!(&result, &result_expected);
897
898                let result = c * r;
899                assert_eq!(&result, &result_expected);
900
901                let mut result = c;
902                result *= &r;
903                assert_eq!(&result, &result_expected);
904
905                let mut result = c;
906                result *= r;
907                assert_eq!(&result, &result_expected);
908            }
909
910            #[test]
911            fn real_times_complex() {
912                let r = RealValidated::try_new_validated(2.).unwrap();
913                let c = ComplexValidated::try_new_validated(Complex::new(3., 4.)).unwrap();
914
915                let result_expected =
916                    ComplexValidated::try_new_validated(Complex::new(6., 8.)).unwrap(); // 2 * (3 + 4i) = 6 + 8i
917
918                let result = r * c;
919                assert_eq!(&result, &result_expected);
920            }
921        }
922    }
923
924    mod arithmetic {
925        use super::*;
926
927        mod real {
928            use super::*;
929
930            #[test]
931            fn add() {
932                let r1 = RealValidated::try_new_validated(3.).unwrap();
933                let r2 = RealValidated::try_new_validated(4.).unwrap();
934
935                let expected_result = RealValidated::try_new_validated(7.).unwrap();
936
937                let result = r1.add(&r2);
938                assert_eq!(result, expected_result);
939
940                let result = r1.add(r2);
941                assert_eq!(result, expected_result);
942
943                let result = (&r1).add(r2);
944                assert_eq!(result, expected_result);
945
946                let result = (&r1).add(&r2);
947                assert_eq!(result, expected_result);
948
949                let mut result = r1;
950                result.add_assign(&r2);
951                assert_eq!(result, expected_result);
952
953                let mut result = r1;
954                result.add_assign(r2);
955                assert_eq!(result, expected_result);
956            }
957
958            #[test]
959            fn sub() {
960                let r1 = RealValidated::try_new_validated(3.).unwrap();
961                let r2 = RealValidated::try_new_validated(4.).unwrap();
962
963                let expected_result = RealValidated::try_new_validated(-1.).unwrap();
964
965                let result = r1.sub(&r2);
966                assert_eq!(result, expected_result);
967
968                let result = r1.sub(r2);
969                assert_eq!(result, expected_result);
970
971                let result = (&r1).sub(r2);
972                assert_eq!(result, expected_result);
973
974                let result = (&r1).sub(&r2);
975                assert_eq!(result, expected_result);
976
977                let mut result = r1;
978                result.sub_assign(&r2);
979                assert_eq!(result, expected_result);
980
981                let mut result = r1;
982                result.sub_assign(r2);
983                assert_eq!(result, expected_result);
984            }
985
986            #[test]
987            fn mul() {
988                let r1 = RealValidated::try_new_validated(3.).unwrap();
989                let r2 = RealValidated::try_new_validated(4.).unwrap();
990
991                let expected_result = RealValidated::try_new_validated(12.).unwrap();
992
993                let result = r1.mul(&r2);
994                assert_eq!(result, expected_result);
995
996                let result = r1.mul(r2);
997                assert_eq!(result, expected_result);
998
999                let result = (&r1).mul(r2);
1000                assert_eq!(result, expected_result);
1001
1002                let result = (&r1).mul(&r2);
1003                assert_eq!(result, expected_result);
1004
1005                let mut result = r1;
1006                result.mul_assign(&r2);
1007                assert_eq!(result, expected_result);
1008
1009                let mut result = r1;
1010                result.mul_assign(r2);
1011                assert_eq!(result, expected_result);
1012            }
1013
1014            #[test]
1015            fn div() {
1016                let r1 = RealValidated::try_new_validated(3.).unwrap();
1017                let r2 = RealValidated::try_new_validated(4.).unwrap();
1018
1019                let expected_result = RealValidated::try_new_validated(0.75).unwrap();
1020
1021                let result = r1.div(&r2);
1022                assert_eq!(result, expected_result);
1023
1024                let result = r1.div(r2);
1025                assert_eq!(result, expected_result);
1026
1027                let result = (&r1).div(r2);
1028                assert_eq!(result, expected_result);
1029
1030                let result = (&r1).div(&r2);
1031                assert_eq!(result, expected_result);
1032
1033                let mut result = r1;
1034                result.div_assign(&r2);
1035                assert_eq!(result, expected_result);
1036
1037                let mut result = r1;
1038                result.div_assign(r2);
1039                assert_eq!(result, expected_result);
1040            }
1041
1042            #[test]
1043            fn neg() {
1044                let num = RealValidated::try_new_validated(1.).unwrap();
1045                let expected = RealValidated::try_new_validated(-1.).unwrap();
1046                assert_eq!(num.neg(), expected);
1047            }
1048
1049            #[test]
1050            fn neg_assign() {
1051                let mut num = 1.;
1052                num.neg_assign();
1053                let expected = -1.;
1054                assert_eq!(&num, &expected);
1055
1056                let mut num = RealValidated::one();
1057                num.neg_assign();
1058                let expected = RealValidated::try_new_validated(-1.).unwrap();
1059                assert_eq!(&num, &expected);
1060            }
1061
1062            #[test]
1063            #[should_panic(expected = "Division failed validation")]
1064            fn div_by_zero() {
1065                let one = RealValidated::one();
1066                let zero = RealValidated::zero();
1067                let _ = one / zero;
1068            }
1069
1070            #[test]
1071            #[should_panic(expected = "Division failed validation")]
1072            fn div_assign_by_zero() {
1073                let mut num = RealValidated::one();
1074                let zero_ref = &RealValidated::zero();
1075                num /= zero_ref;
1076            }
1077
1078            #[test]
1079            fn mul_add() {
1080                let a = RealValidated::try_new(2.0).unwrap();
1081                let b = RealValidated::try_new(3.0).unwrap();
1082                let c = RealValidated::try_new(4.0).unwrap();
1083                // 2*3 + 4 = 10
1084                assert_eq!(a.mul_add_ref(&b, &c), RealValidated::try_new(10.0).unwrap());
1085            }
1086        }
1087
1088        mod complex {
1089            use super::*;
1090
1091            #[test]
1092            fn add() {
1093                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
1094                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
1095
1096                let expected_result =
1097                    ComplexValidated::try_new_validated(Complex::new(6., -1.)).unwrap();
1098
1099                let result = r1.add(&r2);
1100                assert_eq!(result, expected_result);
1101
1102                let result = r1.add(r2);
1103                assert_eq!(result, expected_result);
1104
1105                let result = (&r1).add(r2);
1106                assert_eq!(result, expected_result);
1107
1108                let result = (&r1).add(&r2);
1109                assert_eq!(result, expected_result);
1110
1111                let mut result = r1;
1112                result.add_assign(&r2);
1113                assert_eq!(result, expected_result);
1114
1115                let mut result = r1;
1116                result.add_assign(r2);
1117                assert_eq!(result, expected_result);
1118            }
1119
1120            #[test]
1121            fn sub() {
1122                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
1123                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
1124
1125                let expected_result =
1126                    ComplexValidated::try_new_validated(Complex::new(-2., 7.)).unwrap();
1127
1128                let result = r1.sub(&r2);
1129                assert_eq!(result, expected_result);
1130
1131                let result = r1.sub(r2);
1132                assert_eq!(result, expected_result);
1133
1134                let result = (&r1).sub(r2);
1135                assert_eq!(result, expected_result);
1136
1137                let result = (&r1).sub(&r2);
1138                assert_eq!(result, expected_result);
1139
1140                let mut result = r1;
1141                result.sub_assign(&r2);
1142                assert_eq!(result, expected_result);
1143
1144                let mut result = r1;
1145                result.sub_assign(r2);
1146                assert_eq!(result, expected_result);
1147            }
1148
1149            #[test]
1150            fn mul() {
1151                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
1152                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
1153
1154                let expected_result =
1155                    ComplexValidated::try_new_validated(Complex::new(20., 4.)).unwrap();
1156
1157                let result = r1.mul(&r2);
1158                assert_eq!(result, expected_result);
1159
1160                let result = r1.mul(r2);
1161                assert_eq!(result, expected_result);
1162
1163                let result = (&r1).mul(r2);
1164                assert_eq!(result, expected_result);
1165
1166                let result = (&r1).mul(&r2);
1167                assert_eq!(result, expected_result);
1168
1169                let mut result = r1;
1170                result.mul_assign(&r2);
1171                assert_eq!(result, expected_result);
1172
1173                let mut result = r1;
1174                result.mul_assign(r2);
1175                assert_eq!(result, expected_result);
1176            }
1177
1178            #[test]
1179            fn div() {
1180                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
1181                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
1182
1183                let expected_result =
1184                    ComplexValidated::try_new_validated(Complex::new(-0.125, 0.625)).unwrap();
1185
1186                let result = r1.div(&r2);
1187                assert_eq!(result, expected_result);
1188
1189                let result = r1.div(r2);
1190                assert_eq!(result, expected_result);
1191
1192                let result = (&r1).div(r2);
1193                assert_eq!(result, expected_result);
1194
1195                let result = (&r1).div(&r2);
1196                assert_eq!(result, expected_result);
1197
1198                let mut result = r1;
1199                result.div_assign(&r2);
1200                assert_eq!(result, expected_result);
1201
1202                let mut result = r1;
1203                result.div_assign(r2);
1204                assert_eq!(result, expected_result);
1205            }
1206
1207            #[test]
1208            fn neg() {
1209                let v = Complex::new(1., 2.);
1210
1211                let num = ComplexValidated::try_new_validated(v).unwrap();
1212                let expected = Complex::new(-1., -2.);
1213                assert_eq!(num.neg().into_inner(), expected);
1214            }
1215
1216            #[test]
1217            fn neg_assign() {
1218                let v = Complex::new(1., 2.);
1219
1220                let mut num = ComplexValidated::try_new_validated(v).unwrap();
1221                let expected = Complex::new(-1., -2.);
1222                num.neg_assign();
1223                assert_eq!(num.as_ref(), &expected);
1224            }
1225
1226            #[test]
1227            #[should_panic(expected = "Division failed validation")]
1228            fn div_by_zero() {
1229                let one = ComplexValidated::one();
1230                let zero = ComplexValidated::zero();
1231                let _ = one / zero;
1232            }
1233
1234            #[test]
1235            #[should_panic(expected = "Division failed validation")]
1236            fn div_assign_by_zero() {
1237                let mut num = ComplexValidated::one();
1238                let zero_ref = &ComplexValidated::zero();
1239                num /= zero_ref;
1240            }
1241
1242            #[test]
1243            fn mul_add() {
1244                let ca = ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap();
1245                let cb = ComplexValidated::try_new(Complex::new(3.0, 4.0)).unwrap();
1246                let cc = ComplexValidated::try_new(Complex::new(5.0, 6.0)).unwrap();
1247                // (1+2i)*(3+4i) + (5+6i) = (3+4i+6i-8) + (5+6i) = (-5+10i) + (5+6i) = 0+16i
1248                let expected = ComplexValidated::try_new(Complex::new(0.0, 16.0)).unwrap();
1249                assert_eq!(ca.mul_add_ref(&cb, &cc), expected);
1250            }
1251        }
1252    }
1253
1254    mod real_scalar_methods {
1255        use crate::core::errors::RawRealConversionError;
1256
1257        use super::*;
1258
1259        #[test]
1260        fn test_constants() {
1261            assert_eq!(
1262                <RealValidated as Constants>::epsilon().as_ref(),
1263                &f64::EPSILON
1264            );
1265            assert_eq!(<RealValidated as Constants>::negative_one().as_ref(), &-1.0);
1266            assert_eq!(<RealValidated as Constants>::one_div_2().as_ref(), &0.5);
1267            assert_eq!(<RealValidated as Constants>::two().as_ref(), &2.0);
1268            assert_eq!(
1269                <RealValidated as Constants>::max_finite().as_ref(),
1270                &f64::MAX
1271            );
1272            assert_eq!(
1273                <RealValidated as Constants>::min_finite().as_ref(),
1274                &f64::MIN
1275            );
1276            assert_eq!(
1277                <RealValidated as Constants>::pi().as_ref(),
1278                &std::f64::consts::PI
1279            );
1280            assert_eq!(
1281                *<RealValidated as Constants>::two_pi().as_ref(),
1282                std::f64::consts::PI * 2.0
1283            );
1284            assert_eq!(
1285                <RealValidated as Constants>::pi_div_2().as_ref(),
1286                &std::f64::consts::FRAC_PI_2
1287            );
1288            assert_eq!(
1289                <RealValidated as Constants>::ln_2().as_ref(),
1290                &std::f64::consts::LN_2
1291            );
1292            assert_eq!(
1293                <RealValidated as Constants>::ln_10().as_ref(),
1294                &std::f64::consts::LN_10
1295            );
1296            assert_eq!(
1297                <RealValidated as Constants>::log10_2().as_ref(),
1298                &std::f64::consts::LOG10_2
1299            );
1300            assert_eq!(
1301                <RealValidated as Constants>::log2_10().as_ref(),
1302                &std::f64::consts::LOG2_10
1303            );
1304            assert_eq!(
1305                <RealValidated as Constants>::log2_e().as_ref(),
1306                &std::f64::consts::LOG2_E
1307            );
1308            assert_eq!(
1309                <RealValidated as Constants>::log10_e().as_ref(),
1310                &std::f64::consts::LOG10_E
1311            );
1312            assert_eq!(
1313                <RealValidated as Constants>::e().as_ref(),
1314                &std::f64::consts::E
1315            );
1316        }
1317
1318        #[test]
1319        fn round_ties_even() {
1320            let f = RealValidated::try_new(3.3).unwrap();
1321            let g = RealValidated::try_new(-3.3).unwrap();
1322            let h = RealValidated::try_new(3.5).unwrap();
1323            let i = RealValidated::try_new(4.5).unwrap();
1324            let j = RealValidated::try_new(-3.5).unwrap();
1325            let k = RealValidated::try_new(-4.5).unwrap();
1326
1327            assert_eq!(
1328                f.kernel_round_ties_even(),
1329                RealValidated::try_new(3.0).unwrap()
1330            );
1331            assert_eq!(
1332                g.kernel_round_ties_even(),
1333                RealValidated::try_new(-3.0).unwrap()
1334            );
1335            assert_eq!(
1336                h.kernel_round_ties_even(),
1337                RealValidated::try_new(4.0).unwrap()
1338            );
1339            assert_eq!(
1340                i.kernel_round_ties_even(),
1341                RealValidated::try_new(4.0).unwrap()
1342            );
1343            assert_eq!(
1344                j.kernel_round_ties_even(),
1345                RealValidated::try_new(-4.0).unwrap()
1346            );
1347            assert_eq!(
1348                k.kernel_round_ties_even(),
1349                RealValidated::try_new(-4.0).unwrap()
1350            );
1351        }
1352
1353        #[test]
1354        fn classify() {
1355            let normal = RealValidated::try_new(1.0).unwrap();
1356            assert_eq!(normal.classify(), FpCategory::Normal);
1357
1358            let zero = RealValidated::zero();
1359            assert_eq!(zero.classify(), FpCategory::Zero);
1360
1361            // Subnormals, Infinite and NaN are not constructible with StrictFinitePolicy
1362
1363            let subnormal_err = RealValidated::try_new(f64::MIN_POSITIVE / 2.).unwrap_err();
1364            assert!(matches!(
1365                subnormal_err,
1366                ErrorsValidationRawReal::IsSubnormal { .. }
1367            ));
1368
1369            let pos_inf_err = RealValidated::try_new(f64::INFINITY).unwrap_err();
1370            assert!(matches!(
1371                pos_inf_err,
1372                ErrorsValidationRawReal::IsPosInfinity { .. }
1373            ));
1374
1375            let neg_inf_err = RealValidated::try_new(f64::NEG_INFINITY).unwrap_err();
1376            assert!(matches!(
1377                neg_inf_err,
1378                ErrorsValidationRawReal::IsNegInfinity { .. }
1379            ));
1380
1381            let nan_err = RealValidated::try_new(f64::NAN).unwrap_err();
1382            assert!(matches!(nan_err, ErrorsValidationRawReal::IsNaN { .. }));
1383        }
1384
1385        #[test]
1386        fn try_from_f64_valid() {
1387            let val = RealValidated::try_from_f64(123.45).unwrap();
1388            assert_eq!(val.as_ref(), &123.45);
1389        }
1390
1391        #[test]
1392        fn try_from_f64_invalid() {
1393            let err = RealValidated::try_from_f64(f64::NAN).unwrap_err();
1394            assert_matches!(
1395                err,
1396                RawRealConversionError::InputValidation {
1397                    source: ErrorsValidationRawReal::IsNaN { .. }
1398                }
1399            );
1400        }
1401
1402        #[test]
1403        fn rounding_and_trunc() {
1404            let val1 = RealValidated::try_new(3.7).unwrap();
1405            let val2 = RealValidated::try_new(-3.7).unwrap();
1406
1407            assert_eq!(val1.kernel_ceil(), RealValidated::try_new(4.0).unwrap());
1408            assert_eq!(val2.kernel_ceil(), RealValidated::try_new(-3.0).unwrap());
1409
1410            assert_eq!(val1.kernel_floor(), RealValidated::try_new(3.0).unwrap());
1411            assert_eq!(val2.kernel_floor(), RealValidated::try_new(-4.0).unwrap());
1412
1413            assert_eq!(val1.kernel_round(), RealValidated::try_new(4.0).unwrap());
1414            assert_eq!(val2.kernel_round(), RealValidated::try_new(-4.0).unwrap());
1415
1416            assert_eq!(val1.kernel_trunc(), RealValidated::try_new(3.0).unwrap());
1417            assert_eq!(val2.kernel_trunc(), RealValidated::try_new(-3.0).unwrap());
1418
1419            // Using a tolerance for fract_ due to floating point representation
1420            let frac1 = val1.kernel_fract();
1421            assert!((frac1.as_ref() - 0.7).abs() < 1e-9);
1422
1423            let frac2 = val2.kernel_fract();
1424            assert!((frac2.as_ref() - (-0.7)).abs() < 1e-9);
1425        }
1426
1427        #[test]
1428        fn sign_and_constants() {
1429            let pos = RealValidated::try_new(5.0).unwrap();
1430            let neg = RealValidated::try_new(-5.0).unwrap();
1431            let zero = RealValidated::zero();
1432
1433            assert!(pos.kernel_is_sign_positive());
1434            assert!(!pos.kernel_is_sign_negative());
1435
1436            assert!(!neg.kernel_is_sign_positive());
1437            assert!(neg.kernel_is_sign_negative());
1438
1439            assert!(zero.kernel_is_sign_positive()); // +0.0 is positive
1440            assert!(!zero.kernel_is_sign_negative());
1441
1442            let neg_zero = RealValidated::try_new(-0.0).unwrap();
1443            assert!(!neg_zero.kernel_is_sign_positive());
1444            assert!(neg_zero.kernel_is_sign_negative());
1445
1446            assert_eq!(pos.kernel_copysign(&neg), neg);
1447            assert_eq!(neg.kernel_copysign(&pos), pos);
1448
1449            assert_eq!(
1450                RealValidated::one_div_2(),
1451                RealValidated::try_new(0.5).unwrap()
1452            );
1453            assert_eq!(RealValidated::two(), RealValidated::try_new(2.0).unwrap());
1454            assert_eq!(
1455                RealValidated::max_finite(),
1456                RealValidated::try_new(f64::MAX).unwrap()
1457            );
1458            assert_eq!(
1459                RealValidated::min_finite(),
1460                RealValidated::try_new(f64::MIN).unwrap()
1461            );
1462        }
1463
1464        #[test]
1465        fn epsilon() {
1466            let eps = RealValidated::epsilon();
1467            assert!(eps.is_finite() && eps > RealValidated::zero());
1468            let expected_eps_val = 2.0f64.pow(-52);
1469            let expected_eps = RealValidated::try_new(expected_eps_val).unwrap();
1470            assert_eq!(eps, expected_eps, "Epsilon value mismatch");
1471        }
1472
1473        #[test]
1474        fn clamp_ref() {
1475            let val = RealValidated::try_new(5.).unwrap();
1476            let min_val = RealValidated::try_new(0.).unwrap();
1477            let max_val = RealValidated::try_new(10.).unwrap();
1478
1479            assert_eq!(val.clamp_ref(&min_val, &max_val), val);
1480            assert_eq!(
1481                RealValidated::try_new(-5.)
1482                    .unwrap()
1483                    .clamp_ref(&min_val, &max_val),
1484                min_val
1485            );
1486            assert_eq!(
1487                RealValidated::try_new(15.)
1488                    .unwrap()
1489                    .clamp_ref(&min_val, &max_val),
1490                max_val
1491            );
1492        }
1493
1494        #[test]
1495        fn hypot() {
1496            let a = RealValidated::try_new(3.).unwrap();
1497            let b = RealValidated::try_new(4.).unwrap();
1498            let expected = RealValidated::try_new(5.).unwrap();
1499            assert_eq!(a.hypot(&b), expected);
1500        }
1501
1502        #[test]
1503        fn signum() {
1504            assert_eq!(
1505                RealValidated::try_new(5.).unwrap().kernel_signum(),
1506                RealValidated::one()
1507            );
1508            assert_eq!(
1509                RealValidated::try_new(-5.).unwrap().kernel_signum(),
1510                RealValidated::negative_one()
1511            );
1512            // rug::Float::signum of 0. is 1.
1513            assert_eq!(RealValidated::zero().kernel_signum(), RealValidated::one());
1514        }
1515
1516        #[test]
1517        fn total_cmp() {
1518            let r1 = RealValidated::try_new(1.).unwrap();
1519            let r2 = RealValidated::try_new(2.).unwrap();
1520            assert_eq!(r1.total_cmp(&r1), Ordering::Equal);
1521            assert_eq!(r1.total_cmp(&r2), Ordering::Less);
1522            assert_eq!(r2.total_cmp(&r1), Ordering::Greater);
1523        }
1524
1525        #[test]
1526        fn mul_add_mul_mut() {
1527            let mut a = RealValidated::try_new(2.).unwrap();
1528            let b = RealValidated::try_new(3.).unwrap(); // mul
1529            let c = RealValidated::try_new(4.).unwrap(); // add_mul1
1530            let d = RealValidated::try_new(5.).unwrap(); // add_mul2
1531            // Expected: a = a*b + c*d = 2*3 + 4*5 = 6 + 20 = 26
1532            a.kernel_mul_add_mul_mut(&b, &c, &d);
1533            assert_eq!(a, RealValidated::try_new(26.).unwrap());
1534        }
1535
1536        #[test]
1537        fn mul_sub_mul_mut() {
1538            let mut a = RealValidated::try_new(10.).unwrap();
1539            let b = RealValidated::try_new(2.).unwrap(); // mul
1540            let c = RealValidated::try_new(3.).unwrap(); // sub_mul1
1541            let d = RealValidated::try_new(4.).unwrap(); // sub_mul2
1542            // Expected: a = a*b - c*d = 10*2 - 3*4 = 20 - 12 = 8
1543            a.kernel_mul_sub_mul_mut(&b, &c, &d);
1544            assert_eq!(a, RealValidated::try_new(8.).unwrap());
1545        }
1546    }
1547
1548    mod complex_scalar_methods {
1549        use super::*;
1550        use crate::functions::{ArgErrors, ArgInputErrors};
1551
1552        #[test]
1553        fn conjugate() {
1554            let c = ComplexValidated::try_new(Complex::new(1., 2.)).unwrap();
1555            let expected = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1556            assert_eq!(c.conjugate(), expected);
1557
1558            let c_real = ComplexValidated::try_new_pure_real(5.).unwrap();
1559            assert_eq!(c_real.conjugate(), c_real);
1560
1561            let c_imag = ComplexValidated::try_new_pure_imaginary(3.).unwrap();
1562            let expected_imag = ComplexValidated::try_new_pure_imaginary(-3.).unwrap();
1563            assert_eq!(c_imag.conjugate(), expected_imag);
1564        }
1565
1566        #[test]
1567        fn arg_valid() {
1568            // arg(1 + 0i) = 0
1569            let c1 = ComplexValidated::one();
1570            assert_eq!(c1.arg(), RealValidated::zero());
1571
1572            // arg(0 + i) = PI/2
1573            let c2 = ComplexValidated::try_new_pure_imaginary(1.0).unwrap();
1574            let pi_div_2 = RealValidated::try_new(FRAC_PI_2).unwrap();
1575            assert_eq!(c2.arg(), pi_div_2);
1576
1577            // arg(-1 + 0i) = PI
1578            let c3 = ComplexValidated::try_new_pure_real(-1.0).unwrap();
1579            let pi = RealValidated::try_new(PI).unwrap();
1580            assert_eq!(c3.arg(), pi);
1581
1582            // arg(1 + i) = PI/4
1583            let c4 = ComplexValidated::try_new(Complex::new(1.0, 1.0)).unwrap();
1584            let pi_div_4 = RealValidated::try_new(FRAC_PI_4).unwrap();
1585            assert_eq!(c4.arg(), pi_div_4);
1586        }
1587
1588        #[test]
1589        fn arg_zero() {
1590            let zero = ComplexValidated::zero();
1591            let res = zero.try_arg();
1592            assert!(matches!(
1593                res,
1594                Err(ArgErrors::Input(ArgInputErrors::Zero { .. }))
1595            ));
1596        }
1597    }
1598
1599    mod function_traits {
1600        use super::*;
1601        use crate::functions::{
1602            ATan2InputErrors, LogarithmRealErrors, LogarithmRealInputErrors,
1603            PowComplexBaseRealExponentInputErrors, PowRealBaseRealExponentInputErrors,
1604            ReciprocalInputErrors, SqrtRealInputErrors,
1605        };
1606
1607        mod min_max {
1608            use super::*;
1609
1610            #[test]
1611            fn max_valid() {
1612                let r1 = RealValidated::try_new(3.).unwrap();
1613                let r2 = RealValidated::try_new(4.).unwrap();
1614                assert_eq!(r1.max_by_ref(&r2), &r2);
1615                assert_eq!(r2.max_by_ref(&r1), &r2);
1616            }
1617
1618            #[test]
1619            fn min_valid() {
1620                let r1 = RealValidated::try_new(3.).unwrap();
1621                let r2 = RealValidated::try_new(4.).unwrap();
1622                assert_eq!(r1.min_by_ref(&r2), &r1);
1623                assert_eq!(r2.min_by_ref(&r1), &r1);
1624            }
1625        }
1626
1627        mod exp {
1628            use super::*;
1629
1630            mod real {
1631                use super::*;
1632
1633                #[test]
1634                fn exp_valid() {
1635                    let exponent = RealValidated::try_new(1.).unwrap();
1636                    let expected = std::f64::consts::E;
1637                    assert_eq!(exponent.try_exp().unwrap().as_ref(), &expected);
1638                    assert_eq!(exponent.exp().as_ref(), &expected);
1639                }
1640
1641                #[test]
1642                fn exp_m1_valid() {
1643                    let exponent = RealValidated::try_new(1.).unwrap();
1644                    let expected = 1.718281828459045;
1645                    assert_ulps_eq!(exponent.exp_m1().as_ref(), &expected);
1646                }
1647
1648                #[test]
1649                fn exp_overflow() {
1650                    let large_val = RealValidated::try_new(1.0e60).unwrap(); // exp(1.0e60) is very large
1651                    let res_large = large_val.try_exp();
1652                    assert!(matches!(
1653                        res_large,
1654                        Err(ExpErrors::Output {
1655                            source: ErrorsValidationRawReal::IsPosInfinity { .. }
1656                        })
1657                    ),);
1658                }
1659            } // end mod 
1660
1661            mod complex {
1662                use super::*;
1663
1664                #[test]
1665                fn exp_valid() {
1666                    let exponent = ComplexValidated::try_new(Complex::new(0., PI)).unwrap();
1667                    let expected = Complex::new(-1., 1.2246467991473532e-16);
1668                    assert_eq!(exponent.try_exp().unwrap().as_ref(), &expected);
1669                    assert_eq!(exponent.exp().as_ref(), &expected);
1670                }
1671            } // end mod complex
1672        } // end mod exp
1673
1674        mod logarithm {
1675            use super::*;
1676
1677            mod real {
1678                use super::*;
1679
1680                #[test]
1681                fn ln_valid() {
1682                    let e = RealValidated::one().exp();
1683                    let expected = 1.0;
1684                    assert_eq!(e.try_ln().unwrap().as_ref(), &expected);
1685                    assert_eq!(e.ln().as_ref(), &expected);
1686                }
1687
1688                #[test]
1689                fn log10_valid() {
1690                    let v = RealValidated::try_new(100.).unwrap();
1691                    let expected = 2.0;
1692                    assert_eq!(v.try_log10().unwrap().as_ref(), &expected);
1693                    assert_eq!(v.log10().as_ref(), &expected);
1694                }
1695
1696                #[test]
1697                fn log2_valid() {
1698                    let v = RealValidated::try_new(4.).unwrap();
1699                    let expected = 2.0;
1700                    assert_eq!(v.try_log2().unwrap().as_ref(), &expected);
1701                    assert_eq!(v.log2().as_ref(), &expected);
1702                }
1703
1704                #[test]
1705                fn ln_1p_valid() {
1706                    // v = e - 1;
1707                    let v = RealValidated::one().exp() - RealValidated::one();
1708
1709                    // ln(1 + v) = ln(1 + e - 1) = ln(e) = 1
1710                    assert_eq!(v.ln_1p().as_ref(), &1.);
1711                }
1712
1713                #[test]
1714                fn ln_domain_errors() {
1715                    let neg_val = RealValidated::try_new(-1.).unwrap();
1716                    assert!(matches!(
1717                        neg_val.try_ln(),
1718                        Err(LogarithmRealErrors::Input(
1719                            LogarithmRealInputErrors::NegativeArgument { .. }
1720                        ))
1721                    ));
1722
1723                    let zero_val = RealValidated::zero();
1724                    assert!(matches!(
1725                        zero_val.try_ln(),
1726                        Err(LogarithmRealErrors::Input(
1727                            LogarithmRealInputErrors::ZeroArgument { .. }
1728                        ))
1729                    ));
1730                }
1731
1732                #[test]
1733                fn log10_domain_errors() {
1734                    let neg_val = RealValidated::try_new(-1.).unwrap();
1735                    assert!(matches!(
1736                        neg_val.try_log10(),
1737                        Err(LogarithmRealErrors::Input(
1738                            LogarithmRealInputErrors::NegativeArgument { .. }
1739                        ))
1740                    ));
1741
1742                    let zero_val = RealValidated::zero();
1743                    assert!(matches!(
1744                        zero_val.try_log10(),
1745                        Err(LogarithmRealErrors::Input(
1746                            LogarithmRealInputErrors::ZeroArgument { .. }
1747                        ))
1748                    ));
1749                }
1750
1751                #[test]
1752                fn log2_domain_errors() {
1753                    let neg_val = RealValidated::try_new(-1.).unwrap();
1754                    assert!(matches!(
1755                        neg_val.try_log2(),
1756                        Err(LogarithmRealErrors::Input(
1757                            LogarithmRealInputErrors::NegativeArgument { .. }
1758                        ))
1759                    ));
1760
1761                    let zero_val = RealValidated::zero();
1762                    assert!(matches!(
1763                        zero_val.try_log2(),
1764                        Err(LogarithmRealErrors::Input(
1765                            LogarithmRealInputErrors::ZeroArgument { .. }
1766                        ))
1767                    ));
1768                }
1769            } // end mod real
1770
1771            mod complex {
1772                use super::*;
1773
1774                #[test]
1775                fn ln_valid() {
1776                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1777                    let expected = Complex::new(0.8047189562170503, -1.1071487177940904);
1778                    assert_eq!(v.try_ln().unwrap().as_ref(), &expected);
1779                    assert_eq!(v.ln().as_ref(), &expected);
1780                }
1781
1782                #[test]
1783                fn log10_valid() {
1784                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1785                    let expected = Complex::new(0.3494850021680094, -0.480828578784234);
1786                    assert_eq!(v.try_log10().unwrap().as_ref(), &expected);
1787                    assert_eq!(v.log10().as_ref(), &expected);
1788                }
1789
1790                #[test]
1791                fn log2_valid() {
1792                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1793                    let expected = Complex::new(1.1609640474436813, -1.5972779646881088);
1794                    assert_eq!(v.try_log2().unwrap().as_ref(), &expected);
1795                    assert_eq!(v.log2().as_ref(), &expected);
1796                }
1797
1798                #[test]
1799                fn ln_zero() {
1800                    let zero_val = ComplexValidated::zero();
1801                    assert!(matches!(
1802                        zero_val.try_ln(),
1803                        Err(LogarithmComplexErrors::Input(
1804                            LogarithmComplexInputErrors::ZeroArgument { .. }
1805                        ))
1806                    ));
1807                }
1808
1809                #[test]
1810                fn log10_zero() {
1811                    let zero_val = ComplexValidated::zero();
1812                    assert!(matches!(
1813                        zero_val.try_log10(),
1814                        Err(LogarithmComplexErrors::Input(
1815                            LogarithmComplexInputErrors::ZeroArgument { .. }
1816                        ))
1817                    ));
1818                }
1819
1820                #[test]
1821                fn log2_zero() {
1822                    let zero_val = ComplexValidated::zero();
1823                    assert!(matches!(
1824                        zero_val.try_log2(),
1825                        Err(LogarithmComplexErrors::Input(
1826                            LogarithmComplexInputErrors::ZeroArgument { .. }
1827                        ))
1828                    ));
1829                }
1830            } // end mod complex
1831        } // end mod logarithm
1832
1833        mod pow {
1834            use super::*;
1835
1836            mod real_base {
1837                use super::*;
1838
1839                #[test]
1840                fn negative_base_real_exponent_error() {
1841                    let base = RealValidated::try_new(-2.).unwrap();
1842                    let exponent = RealValidated::try_new(0.5).unwrap();
1843                    let res = base.try_pow(&exponent);
1844                    assert!(matches!(
1845                        res,
1846                        Err(PowRealBaseRealExponentErrors::Input(
1847                            PowRealBaseRealExponentInputErrors::NegativeBase { .. }
1848                        ))
1849                    ));
1850                }
1851
1852                #[test]
1853                fn real_base_uint_exponent_valid() {
1854                    let base = RealValidated::try_new(2.).unwrap();
1855                    assert_eq!(
1856                        base.try_pow(3u8).unwrap(),
1857                        RealValidated::try_new(8.).unwrap()
1858                    );
1859                    assert_eq!(
1860                        base.try_pow(3u16).unwrap(),
1861                        RealValidated::try_new(8.).unwrap()
1862                    );
1863                    assert_eq!(
1864                        base.try_pow(3u32).unwrap(),
1865                        RealValidated::try_new(8.).unwrap()
1866                    );
1867                    assert_eq!(
1868                        base.try_pow(3u64).unwrap(),
1869                        RealValidated::try_new(8.).unwrap()
1870                    );
1871                    assert_eq!(
1872                        base.try_pow(3u128).unwrap(),
1873                        RealValidated::try_new(8.).unwrap()
1874                    );
1875                    assert_eq!(
1876                        base.try_pow(3usize).unwrap(),
1877                        RealValidated::try_new(8.).unwrap()
1878                    );
1879
1880                    assert_eq!(base.pow(3u8), RealValidated::try_new(8.).unwrap());
1881                    assert_eq!(base.pow(3u16), RealValidated::try_new(8.).unwrap());
1882                    assert_eq!(base.pow(3u32), RealValidated::try_new(8.).unwrap());
1883                    assert_eq!(base.pow(3u64), RealValidated::try_new(8.).unwrap());
1884                    assert_eq!(base.pow(3u128), RealValidated::try_new(8.).unwrap());
1885                    assert_eq!(base.pow(3usize), RealValidated::try_new(8.).unwrap());
1886                }
1887
1888                #[test]
1889                fn real_base_int_exponent_valid() {
1890                    let base = RealValidated::try_new(2.).unwrap();
1891                    assert_eq!(
1892                        base.try_pow(3i8).unwrap(),
1893                        RealValidated::try_new(8.).unwrap()
1894                    );
1895                    assert_eq!(
1896                        base.try_pow(3i16).unwrap(),
1897                        RealValidated::try_new(8.).unwrap()
1898                    );
1899                    assert_eq!(
1900                        base.try_pow(3i32).unwrap(),
1901                        RealValidated::try_new(8.).unwrap()
1902                    );
1903                    assert_eq!(
1904                        base.try_pow(3i64).unwrap(),
1905                        RealValidated::try_new(8.).unwrap()
1906                    );
1907                    assert_eq!(
1908                        base.try_pow(3i128).unwrap(),
1909                        RealValidated::try_new(8.).unwrap()
1910                    );
1911                    assert_eq!(
1912                        base.try_pow(3isize).unwrap(),
1913                        RealValidated::try_new(8.).unwrap()
1914                    );
1915
1916                    assert_eq!(base.pow(3i8), RealValidated::try_new(8.).unwrap());
1917                    assert_eq!(base.pow(3i16), RealValidated::try_new(8.).unwrap());
1918                    assert_eq!(base.pow(3i32), RealValidated::try_new(8.).unwrap());
1919                    assert_eq!(base.pow(3i64), RealValidated::try_new(8.).unwrap());
1920                    assert_eq!(base.pow(3i128), RealValidated::try_new(8.).unwrap());
1921                    assert_eq!(base.pow(3isize), RealValidated::try_new(8.).unwrap());
1922                }
1923
1924                #[test]
1925                fn real_base_int_exponent_zero_neg_exp_error() {
1926                    let base = RealValidated::zero();
1927                    let exponent: i32 = -2;
1928                    let res = base.try_pow(exponent);
1929                    assert!(matches!(
1930                        res,
1931                        Err(PowIntExponentErrors::Input(
1932                            PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
1933                        ))
1934                    ));
1935                }
1936
1937                #[test]
1938                fn real_base_real_exponent_valid() {
1939                    let base = RealValidated::try_new(2.).unwrap();
1940                    let exponent = RealValidated::try_new(3.).unwrap();
1941                    let expected = 8.;
1942                    assert_eq!(base.try_pow(&exponent).unwrap().as_ref(), &expected);
1943                    assert_eq!(base.pow(&exponent).as_ref(), &expected);
1944                }
1945            }
1946
1947            mod complex_base {
1948                use super::*;
1949
1950                #[test]
1951                fn complex_base_uint_exponent_valid() {
1952                    let base = ComplexValidated::try_new(Complex::new(2., 3.)).unwrap();
1953                    let expected_res = ComplexValidated::try_new(Complex::new(-46., 9.)).unwrap();
1954
1955                    assert_eq!(&base.try_pow(3u8).unwrap(), &expected_res);
1956                    assert_eq!(&base.try_pow(3u16).unwrap(), &expected_res);
1957                    assert_eq!(&base.try_pow(3u32).unwrap(), &expected_res);
1958                    assert_eq!(&base.try_pow(3u64).unwrap(), &expected_res);
1959                    assert_eq!(&base.try_pow(3u128).unwrap(), &expected_res);
1960                    assert_eq!(&base.try_pow(3usize).unwrap(), &expected_res);
1961
1962                    assert_eq!(&base.pow(3u8), &expected_res);
1963                    assert_eq!(&base.pow(3u16), &expected_res);
1964                    assert_eq!(&base.pow(3u32), &expected_res);
1965                    assert_eq!(&base.pow(3u64), &expected_res);
1966                    assert_eq!(&base.pow(3u128), &expected_res);
1967                    assert_eq!(&base.pow(3usize), &expected_res);
1968                }
1969
1970                #[test]
1971                fn complex_base_int_exponent_valid() {
1972                    let base = ComplexValidated::try_new(Complex::new(2., 3.)).unwrap();
1973                    let expected_res = ComplexValidated::try_new(Complex::new(-46., 9.)).unwrap();
1974
1975                    assert_eq!(&base.try_pow(3i8).unwrap(), &expected_res);
1976                    assert_eq!(&base.try_pow(3i16).unwrap(), &expected_res);
1977                    assert_eq!(&base.try_pow(3i32).unwrap(), &expected_res);
1978                    assert_eq!(&base.try_pow(3i64).unwrap(), &expected_res);
1979                    assert_eq!(&base.try_pow(3i128).unwrap(), &expected_res);
1980                    assert_eq!(&base.try_pow(3isize).unwrap(), &expected_res);
1981
1982                    assert_eq!(&base.pow(3i8), &expected_res);
1983                    assert_eq!(&base.pow(3i16), &expected_res);
1984                    assert_eq!(&base.pow(3i32), &expected_res);
1985                    assert_eq!(&base.pow(3i64), &expected_res);
1986                    assert_eq!(&base.pow(3i128), &expected_res);
1987                    assert_eq!(&base.pow(3isize), &expected_res);
1988                }
1989
1990                #[test]
1991                fn complex_zero_base_negative_real_exponent_error() {
1992                    let base = ComplexValidated::zero();
1993                    let exponent = RealValidated::try_new(-2.).unwrap();
1994                    let res = base.try_pow(&exponent);
1995                    assert!(matches!(
1996                        res,
1997                        Err(PowComplexBaseRealExponentErrors::Input(
1998                            PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent { .. }
1999                        ))
2000                    ));
2001                }
2002
2003                #[test]
2004                fn complex_zero_base_zero_real_exponent() {
2005                    let base = ComplexValidated::zero();
2006                    let exponent = RealValidated::zero();
2007                    let res = base.try_pow(&exponent).unwrap();
2008                    assert_eq!(res, ComplexValidated::one());
2009                }
2010
2011                #[test]
2012                fn complex_base_int_exponent_zero_neg_exp_error() {
2013                    let base = ComplexValidated::zero();
2014                    let exponent: i32 = -2;
2015                    let res = base.try_pow(exponent);
2016                    assert!(matches!(
2017                        res,
2018                        Err(PowIntExponentErrors::Input(
2019                            PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
2020                        ))
2021                    ));
2022                }
2023
2024                #[test]
2025                fn complex_base_real_exponent_valid() {
2026                    let base = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2027                    let exponent = RealValidated::try_new(3.).unwrap();
2028                    let expected = Complex::new(-11.000000000000004, 1.9999999999999973);
2029                    assert_eq!(base.try_pow(&exponent).unwrap().as_ref(), &expected);
2030                    assert_eq!(base.pow(&exponent).as_ref(), &expected);
2031                }
2032
2033                #[test]
2034                fn complex_zero_base_real_exponent_valid() {
2035                    let base = ComplexValidated::zero();
2036                    let exponent = RealValidated::try_new(3.).unwrap();
2037                    let expected = Complex::new(0., 0.);
2038                    assert_eq!(base.try_pow(&exponent).unwrap().as_ref(), &expected);
2039                    assert_eq!(base.pow(&exponent).as_ref(), &expected);
2040                }
2041            }
2042        }
2043
2044        mod reciprocal {
2045            use super::*;
2046
2047            mod real {
2048                use super::*;
2049
2050                #[test]
2051                fn reciprocal_valid() {
2052                    let v = RealValidated::try_new(2.).unwrap();
2053
2054                    let res = v.try_reciprocal().unwrap();
2055                    assert_eq!(res.into_inner(), 0.5);
2056
2057                    let res = v.reciprocal();
2058                    assert_eq!(res.into_inner(), 0.5);
2059                }
2060
2061                #[test]
2062                fn reciprocal_real_zero() {
2063                    let zero_val = RealValidated::zero();
2064                    let res = zero_val.try_reciprocal();
2065                    assert!(matches!(
2066                        res,
2067                        Err(ReciprocalErrors::Input(
2068                            ReciprocalInputErrors::DivisionByZero { .. }
2069                        ))
2070                    ));
2071                }
2072            }
2073
2074            mod complex {
2075                use super::*;
2076
2077                #[test]
2078                fn reciprocal_valid() {
2079                    let v = ComplexValidated::try_new(Complex::new(3., 4.)).unwrap();
2080
2081                    let expected = Complex::new(0.12, -0.16);
2082
2083                    let res = v.try_reciprocal().unwrap();
2084                    assert_eq!(res.as_ref(), &expected);
2085
2086                    let res = v.reciprocal();
2087                    assert_eq!(res.as_ref(), &expected);
2088                }
2089
2090                #[test]
2091                fn reciprocal_complex_zero() {
2092                    let zero_val = ComplexValidated::zero();
2093                    let res = zero_val.try_reciprocal();
2094                    assert!(matches!(
2095                        res,
2096                        Err(ReciprocalErrors::Input(
2097                            ReciprocalInputErrors::DivisionByZero { .. }
2098                        ))
2099                    ));
2100                }
2101            }
2102        } // end mod reciprocal
2103
2104        mod sqrt {
2105            use super::*;
2106
2107            mod real {
2108                use super::*;
2109
2110                #[test]
2111                fn sqrt_valid() {
2112                    let v = RealValidated::try_new(9.).unwrap();
2113                    assert_eq!(v.try_sqrt().unwrap().as_ref(), &3.);
2114                    assert_eq!(v.sqrt().as_ref(), &3.);
2115                }
2116
2117                #[test]
2118                fn sqrt_negative_input() {
2119                    let neg_val = RealValidated::try_new(-4.).unwrap();
2120                    let res = neg_val.try_sqrt();
2121                    assert!(matches!(
2122                        res,
2123                        Err(SqrtRealErrors::Input(
2124                            SqrtRealInputErrors::NegativeValue { .. }
2125                        ))
2126                    ));
2127                }
2128            } // end mod real
2129
2130            mod complex {
2131                use super::*;
2132
2133                #[test]
2134                fn sqrt_valid() {
2135                    let expected = Complex::new(1., 2.);
2136                    let v = ComplexValidated::try_new(expected * expected).unwrap();
2137
2138                    let expected = Complex::new(1.0000000000000002, 2.);
2139                    assert_eq!(v.try_sqrt().unwrap().as_ref(), &expected);
2140                    assert_eq!(v.sqrt().as_ref(), &expected);
2141                }
2142            }
2143        } // end mod sqrt
2144
2145        mod trigonometric {
2146            use super::*;
2147
2148            mod real {
2149                use super::*;
2150
2151                #[test]
2152                fn sin_real_valid() {
2153                    let v = RealValidated::pi_div_2();
2154
2155                    let expected = 1.;
2156                    assert_eq!(v.try_sin().unwrap().as_ref(), &expected);
2157                    assert_eq!(v.sin().as_ref(), &expected);
2158                }
2159
2160                #[test]
2161                fn cos_real_valid() {
2162                    let v = RealValidated::pi();
2163
2164                    let expected = -1.;
2165                    assert_eq!(v.try_cos().unwrap().as_ref(), &expected);
2166                    assert_eq!(v.cos().as_ref(), &expected);
2167                }
2168
2169                #[test]
2170                fn tan_real_valid() {
2171                    let v = RealValidated::one();
2172                    let expected = 1.5574077246549023;
2173                    assert_ulps_eq!(v.try_tan().unwrap().as_ref(), &expected);
2174                    assert_ulps_eq!(v.tan().as_ref(), &expected);
2175                }
2176
2177                #[test]
2178                fn asin_real_valid() {
2179                    let v = RealValidated::one();
2180
2181                    let expected = std::f64::consts::FRAC_PI_2; // π/2
2182                    assert_eq!(v.try_asin().unwrap().as_ref(), &expected);
2183                    assert_eq!(v.asin().as_ref(), &expected);
2184                }
2185
2186                #[test]
2187                fn acos_real_valid() {
2188                    let v = RealValidated::one();
2189
2190                    let expected = 0.;
2191                    assert_eq!(v.try_acos().unwrap().as_ref(), &expected);
2192                    assert_eq!(v.acos().as_ref(), &expected);
2193                }
2194
2195                #[test]
2196                fn atan_real_valid() {
2197                    let v = RealValidated::one();
2198
2199                    let expected = std::f64::consts::FRAC_PI_4; // π/4
2200                    assert_eq!(v.try_atan().unwrap().as_ref(), &expected);
2201                    assert_eq!(v.atan().as_ref(), &expected);
2202                }
2203
2204                #[test]
2205                fn atan2_valid() {
2206                    let one = RealValidated::one();
2207                    let zero = RealValidated::zero();
2208
2209                    let expected = std::f64::consts::FRAC_PI_2; // π/2
2210                    assert_eq!(one.try_atan2(&zero).unwrap().as_ref(), &expected);
2211                    assert_eq!(one.atan2(&zero).as_ref(), &expected);
2212
2213                    let expected = 0.;
2214                    assert_eq!(zero.try_atan2(&one).unwrap().as_ref(), &expected);
2215                    assert_eq!(zero.atan2(&one).as_ref(), &expected);
2216
2217                    let expected = std::f64::consts::FRAC_PI_4; // π/4
2218                    assert_eq!(one.try_atan2(&one).unwrap().as_ref(), &expected);
2219                    assert_eq!(one.atan2(&one).as_ref(), &expected);
2220                }
2221
2222                #[test]
2223                fn atan2_zero_over_zero() {
2224                    let zero_val = RealValidated::zero();
2225                    let res = zero_val.try_atan2(&RealValidated::zero());
2226                    assert!(matches!(
2227                        res,
2228                        Err(ATan2Errors::Input(ATan2InputErrors::ZeroOverZero { .. }))
2229                    ));
2230                }
2231
2232                /*
2233                #[test]
2234                #[ignore = "at the moment we cannot create a pole for the Tan function"]
2235                fn tan_real_pole() {
2236                    // tan(PI/2) is a pole
2237                    let pi_half = RealValidated::pi_div_2();
2238                    let res = pi_half.try_tan();
2239                    println!("Result: {:?}", res);
2240                    assert!(matches!(
2241                        res,
2242                        Err(TanRealErrors::Input(TanRealInputErrors::ArgumentIsPole { .. }))
2243                    ));
2244                }
2245                */
2246
2247                #[test]
2248                fn asin_real_out_of_domain() {
2249                    let val_gt_1 = RealValidated::try_new(1.5).unwrap();
2250                    assert!(matches!(
2251                        val_gt_1.try_asin(),
2252                        Err(ASinRealErrors::Input(
2253                            ASinRealInputErrors::OutOfDomain { .. }
2254                        ))
2255                    ));
2256                    let val_lt_neg1 = RealValidated::try_new(-1.5).unwrap();
2257                    assert!(matches!(
2258                        val_lt_neg1.try_asin(),
2259                        Err(ASinRealErrors::Input(
2260                            ASinRealInputErrors::OutOfDomain { .. }
2261                        ))
2262                    ));
2263                }
2264
2265                #[test]
2266                fn acos_real_out_of_domain() {
2267                    let val_gt_1 = RealValidated::try_new(1.5).unwrap();
2268                    assert!(matches!(
2269                        val_gt_1.try_acos(),
2270                        Err(ACosRealErrors::Input(
2271                            ACosRealInputErrors::OutOfDomain { .. }
2272                        ))
2273                    ));
2274                    let val_lt_neg1 = RealValidated::try_new(-1.5).unwrap();
2275                    assert!(matches!(
2276                        val_lt_neg1.try_acos(),
2277                        Err(ACosRealErrors::Input(
2278                            ACosRealInputErrors::OutOfDomain { .. }
2279                        ))
2280                    ));
2281                }
2282            } // end mod real
2283
2284            mod complex {
2285                use super::*;
2286
2287                #[test]
2288                fn sin_complex_valid() {
2289                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2290
2291                    let expected = if cfg!(target_arch = "x86_64") {
2292                        Complex::new(3.165778513216168, -1.9596010414216063)
2293                    } else if cfg!(target_arch = "aarch64") {
2294                        Complex::new(3.165778513216168, -1.959601041421606)
2295                    } else {
2296                        todo!("Architecture not-tested");
2297                    };
2298                    assert_eq!(v.try_sin().unwrap().as_ref(), &expected);
2299                    assert_eq!(v.sin().as_ref(), &expected);
2300
2301                    let zero = ComplexValidated::zero();
2302                    let expected = Complex::new(0., 0.);
2303                    assert_eq!(zero.try_sin().unwrap().as_ref(), &expected);
2304                    assert_eq!(zero.sin().as_ref(), &expected);
2305                }
2306
2307                #[test]
2308                fn cos_complex_valid() {
2309                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2310
2311                    let expected = if cfg!(target_arch = "x86_64") {
2312                        Complex::new(2.0327230070196656, 3.0518977991518)
2313                    } else if cfg!(target_arch = "aarch64") {
2314                        Complex::new(2.0327230070196656, 3.0518977991517997)
2315                    } else {
2316                        todo!("Architecture not-tested");
2317                    };
2318                    assert_eq!(v.try_cos().unwrap().as_ref(), &expected);
2319                    assert_eq!(v.cos().as_ref(), &expected);
2320
2321                    let zero = ComplexValidated::zero();
2322                    let expected = Complex::new(1., 0.);
2323                    assert_eq!(zero.try_cos().unwrap().as_ref(), &expected);
2324                    assert_eq!(zero.cos().as_ref(), &expected);
2325                }
2326
2327                #[test]
2328                fn tan_complex_valid() {
2329                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2330
2331                    let expected = Complex::new(0.03381282607989669, -1.0147936161466335);
2332                    assert_eq!(v.try_tan().unwrap().as_ref(), &expected);
2333                    assert_eq!(v.tan().as_ref(), &expected);
2334
2335                    let zero = ComplexValidated::zero();
2336                    let expected = Complex::new(0., 0.);
2337                    assert_eq!(zero.try_tan().unwrap().as_ref(), &expected);
2338                    assert_eq!(zero.tan().as_ref(), &expected);
2339                }
2340
2341                #[test]
2342                fn asin_complex_valid() {
2343                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2344
2345                    let expected = Complex::new(0.42707858639247614, -1.528570919480998);
2346                    assert_eq!(v.try_asin().unwrap().as_ref(), &expected);
2347                    assert_eq!(v.asin().as_ref(), &expected);
2348
2349                    let zero = ComplexValidated::zero();
2350                    let expected = Complex::new(0., 0.);
2351                    assert_eq!(zero.try_asin().unwrap().as_ref(), &expected);
2352                    assert_eq!(zero.asin().as_ref(), &expected);
2353                }
2354
2355                #[test]
2356                fn acos_complex_valid() {
2357                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2358
2359                    let expected = Complex::new(1.14371774040242, 1.5285709194809995);
2360                    assert_eq!(v.try_acos().unwrap().as_ref(), &expected);
2361                    assert_eq!(v.acos().as_ref(), &expected);
2362
2363                    let one = ComplexValidated::one();
2364                    let expected = Complex::new(0., 0.);
2365                    assert_eq!(one.try_acos().unwrap().as_ref(), &expected);
2366                    assert_eq!(one.acos().as_ref(), &expected);
2367                }
2368
2369                #[test]
2370                fn atan_complex_valid() {
2371                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2372
2373                    let expected = Complex::new(1.3389725222944935, -0.4023594781085251);
2374                    assert_eq!(v.try_atan().unwrap().as_ref(), &expected);
2375                    assert_eq!(v.atan().as_ref(), &expected);
2376
2377                    let zero = ComplexValidated::zero();
2378                    let expected = Complex::new(0., 0.);
2379                    assert_eq!(zero.try_atan().unwrap().as_ref(), &expected);
2380                    assert_eq!(zero.atan().as_ref(), &expected);
2381                }
2382
2383                #[test]
2384                fn atan_complex_pole() {
2385                    // atan(i) and atan(-i) are poles
2386                    let i_val = ComplexValidated::try_new_pure_imaginary(1.).unwrap();
2387                    assert!(matches!(
2388                        i_val.try_atan(),
2389                        Err(ATanComplexErrors::Input(
2390                            ATanComplexInputErrors::ArgumentIsPole { .. }
2391                        ))
2392                    ));
2393
2394                    let neg_i_val = ComplexValidated::try_new_pure_imaginary(-1.).unwrap();
2395                    assert!(matches!(
2396                        neg_i_val.try_atan(),
2397                        Err(ATanComplexErrors::Input(
2398                            ATanComplexInputErrors::ArgumentIsPole { .. }
2399                        ))
2400                    ));
2401                }
2402            } // end mod complex
2403        } // end mod trigonometric
2404
2405        mod hyperbolic {
2406            use super::*;
2407
2408            mod real {
2409                use super::*;
2410
2411                #[test]
2412                fn atanh_real_valid() {
2413                    let v = RealValidated::zero();
2414                    let expected = 0.;
2415                    assert_eq!(v.try_atanh().unwrap().as_ref(), &expected);
2416                    assert_eq!(v.atanh().as_ref(), &expected);
2417                }
2418
2419                #[test]
2420                fn atanh_real_out_of_domain() {
2421                    let val_ge_1 = RealValidated::one(); // atanh(1) is Inf
2422                    assert!(matches!(
2423                        val_ge_1.try_atanh(),
2424                        Err(ATanHErrors::Input(ATanHInputErrors::OutOfDomain { .. }))
2425                    ));
2426
2427                    let val_le_neg1 = RealValidated::negative_one(); // atanh(-1) is -Inf
2428                    assert!(matches!(
2429                        val_le_neg1.try_atanh(),
2430                        Err(ATanHErrors::Input(ATanHInputErrors::OutOfDomain { .. }))
2431                    ));
2432                }
2433
2434                #[test]
2435                fn acosh_real_valid() {
2436                    let v = RealValidated::one();
2437                    let expected = 0.;
2438                    assert_eq!(v.try_acosh().unwrap().as_ref(), &expected);
2439                    assert_eq!(v.acosh().as_ref(), &expected);
2440                }
2441
2442                #[test]
2443                fn acosh_real_out_of_domain() {
2444                    let val_lt_1 = RealValidated::try_new(0.5).unwrap();
2445                    assert!(matches!(
2446                        val_lt_1.try_acosh(),
2447                        Err(ACosHErrors::Input(ACosHInputErrors::OutOfDomain { .. }))
2448                    ));
2449                }
2450
2451                #[test]
2452                fn asinh_real_valid() {
2453                    let v = RealValidated::one();
2454                    let expected = 0.881373587019543;
2455                    assert_eq!(v.try_asinh().unwrap().as_ref(), &expected);
2456                    assert_eq!(v.asinh().as_ref(), &expected);
2457                }
2458
2459                #[test]
2460                fn sinh_real_valid() {
2461                    let v = RealValidated::try_new(0.881373587019543).unwrap();
2462                    let expected = 1.;
2463                    assert_eq!(v.try_sinh().unwrap().as_ref(), &expected);
2464                    assert_eq!(v.sinh().as_ref(), &expected);
2465                }
2466
2467                #[test]
2468                fn cosh_real_valid() {
2469                    let v = RealValidated::one();
2470                    let expected = 1.5430806348152437;
2471                    assert_eq!(v.try_cosh().unwrap().as_ref(), &expected);
2472                    assert_eq!(v.cosh().as_ref(), &expected);
2473                }
2474
2475                #[test]
2476                fn tanh_real_valid() {
2477                    let v = RealValidated::one();
2478                    let expected = 0.7615941559557649;
2479                    assert_eq!(v.try_tanh().unwrap().as_ref(), &expected);
2480                    assert_eq!(v.tanh().as_ref(), &expected);
2481                }
2482            }
2483
2484            mod complex {
2485                use super::*;
2486
2487                #[test]
2488                fn sinh_valid() {
2489                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2490                    let expected = Complex::new(-0.4890562590412937, -1.4031192506220405);
2491                    assert_eq!(v.try_sinh().unwrap().as_ref(), &expected);
2492                    assert_eq!(v.sinh().as_ref(), &expected);
2493                }
2494
2495                #[test]
2496                fn cosh_valid() {
2497                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2498                    let expected = Complex::new(-0.64214812471552, -1.0686074213827783);
2499                    assert_eq!(v.try_cosh().unwrap().as_ref(), &expected);
2500                    assert_eq!(v.cosh().as_ref(), &expected);
2501                }
2502
2503                #[test]
2504                fn tanh_valid() {
2505                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2506                    let expected = if cfg!(target_arch = "x86_64") {
2507                        Complex::new(1.16673625724092, 0.24345820118572523)
2508                    } else if cfg!(target_arch = "aarch64") {
2509                        Complex::new(1.16673625724092, 0.24345820118572528)
2510                    } else {
2511                        todo!("Architecture not-tested");
2512                    };
2513                    assert_eq!(v.try_tanh().unwrap().as_ref(), &expected);
2514                    assert_eq!(v.tanh().as_ref(), &expected);
2515                }
2516
2517                #[test]
2518                fn asinh_valid() {
2519                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2520                    let expected = Complex::new(1.4693517443681852, -1.0634400235777521);
2521                    Complex::new(1.4693517443681852, -1.0634400235777521);
2522                    assert_eq!(v.try_asinh().unwrap().as_ref(), &expected);
2523                    assert_eq!(v.asinh().as_ref(), &expected);
2524                }
2525
2526                #[test]
2527                fn acosh_valid() {
2528                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2529                    let expected = Complex::new(1.528570919480998, -1.1437177404024206);
2530                    assert_eq!(v.try_acosh().unwrap().as_ref(), &expected);
2531                    assert_eq!(v.acosh().as_ref(), &expected);
2532                }
2533
2534                #[test]
2535                fn atanh_valid() {
2536                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2537                    let expected = Complex::new(0.1732867951399864, -1.1780972450961724);
2538                    assert_eq!(v.try_atanh().unwrap().as_ref(), &expected);
2539                    assert_eq!(v.atanh().as_ref(), &expected);
2540                }
2541
2542                /*
2543                #[test]
2544                #[ignore = "at the moment we cannot create a pole for the ATanH function"]
2545                fn tanh_complex_pole() {
2546                    // tanh(z) has poles where cosh(z) = 0. e.g. z = i * (PI/2 + k*PI)
2547                    let pi_half = RealValidated::pi_div_2().into_inner();
2548                    let pole_val =
2549                        Complex64Validated::try_new_pure_imaginary(pi_half).unwrap();
2550                    println!("Atanh(Pole value): {:?}", pole_val.clone().try_tanh());
2551                    assert!(matches!(
2552                        pole_val.try_tanh(),
2553                        Err(TanHComplexErrors::Input(TanHComplexInputErrors::OutOfDomain { .. }))
2554                    ));
2555                }
2556                */
2557
2558                #[test]
2559                fn acosh_out_of_domain() {
2560                    // acosh(z) domain is C \ (-inf, 1) on real axis
2561                    let val_on_branch_cut = ComplexValidated::try_new_pure_real(0.5).unwrap();
2562                    assert!(matches!(
2563                        val_on_branch_cut.try_acosh(),
2564                        Err(ACosHErrors::Input(ACosHInputErrors::OutOfDomain { .. }))
2565                    ));
2566
2567                    let val_on_branch_cut_neg = ComplexValidated::try_new_pure_real(-5.).unwrap();
2568                    assert!(matches!(
2569                        val_on_branch_cut_neg.try_acosh(),
2570                        Err(ACosHErrors::Input(ACosHInputErrors::OutOfDomain { .. }))
2571                    ));
2572                }
2573
2574                #[test]
2575                fn atanh_out_of_domain() {
2576                    let val_ge_1 = ComplexValidated::try_new_pure_real(1.).unwrap();
2577                    assert!(matches!(
2578                        val_ge_1.try_atanh(),
2579                        Err(ATanHErrors::Input(ATanHInputErrors::OutOfDomain { .. }))
2580                    ));
2581
2582                    let val_le_neg1 = ComplexValidated::try_new_pure_real(-1.).unwrap();
2583                    assert!(matches!(
2584                        val_le_neg1.try_atanh(),
2585                        Err(ATanHErrors::Input(ATanHInputErrors::OutOfDomain { .. }))
2586                    ));
2587                }
2588            }
2589
2590            /*
2591            #[test]
2592            #[ignore = "at the moment we cannot create a pole for the TanH function"]
2593            fn tanh_out_of_domain() {
2594                // tanh(z) has poles where cosh(z) = 0. e.g. z = i * (PI/2 + k*PI)
2595                let pi_half = RealValidated::pi_div_2().into_inner();
2596                let pole_val = Complex64Validated::try_new_pure_imaginary(pi_half).unwrap();
2597                println!("TanH(Pole value): {:?}", pole_val.clone().try_tanh());
2598                assert!(matches!(
2599                    pole_val.try_tanh(),
2600                    Err(TanHComplexErrors::Input(TanHComplexInputErrors::OutOfDomain { .. }))
2601                ));
2602            }
2603            */
2604        } // end mod hyperbolic
2605    }
2606
2607    mod summation {
2608        use super::*;
2609
2610        #[test]
2611        fn sum_real() {
2612            let values = vec![
2613                RealValidated::try_new(1.0).unwrap(),
2614                RealValidated::try_new(2.0).unwrap(),
2615                RealValidated::try_new(3.0).unwrap(),
2616                RealValidated::try_new(4.0).unwrap(),
2617                RealValidated::try_new(5.0).unwrap(),
2618            ];
2619            let sum: RealValidated = values.into_iter().sum();
2620            assert_eq!(sum, RealValidated::try_new(15.0).unwrap());
2621        }
2622
2623        #[test]
2624        fn sum_real_compensated() {
2625            // Test case where simple summation might lose precision
2626            let values = vec![
2627                RealValidated::try_new(1.0e100).unwrap(),
2628                RealValidated::try_new(1.0).unwrap(),
2629                RealValidated::try_new(-1.0e100).unwrap(),
2630            ];
2631            let sum: RealValidated = values.into_iter().sum();
2632            // The Neumaier sum should correctly result in 1.0
2633            assert_eq!(sum, RealValidated::try_new(1.0).unwrap());
2634        }
2635
2636        #[test]
2637        fn sum_complex() {
2638            let values = vec![
2639                ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap(),
2640                ComplexValidated::try_new(Complex::new(3.0, 4.0)).unwrap(),
2641                ComplexValidated::try_new(Complex::new(5.0, 6.0)).unwrap(),
2642            ];
2643            let sum: ComplexValidated = values.into_iter().sum();
2644            assert_eq!(
2645                sum,
2646                ComplexValidated::try_new(Complex::new(9.0, 12.0)).unwrap()
2647            );
2648        }
2649
2650        #[test]
2651        fn sum_complex_compensated() {
2652            let values = vec![
2653                ComplexValidated::try_new(Complex::new(1.0e100, -1.0e100)).unwrap(),
2654                ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap(),
2655                ComplexValidated::try_new(Complex::new(-1.0e100, 1.0e100)).unwrap(),
2656            ];
2657            let sum: ComplexValidated = values.into_iter().sum();
2658            assert_eq!(
2659                sum,
2660                ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap()
2661            );
2662        }
2663    } // end mod summation
2664
2665    mod neumaier_sum {
2666        use crate::algorithms::accumulators::{Accumulator, NeumaierSum};
2667        use try_create::TryNewValidated;
2668
2669        use super::*;
2670
2671        mod real {
2672            use super::*;
2673
2674            #[test]
2675            fn new() {
2676                let neumaier = NeumaierSum::<RealValidated>::new();
2677                assert_eq!(neumaier.sum_before_compensation().as_ref(), &0.0);
2678                assert_eq!(neumaier.compensation().as_ref(), &0.0);
2679            }
2680
2681            #[test]
2682            fn add() {
2683                let mut neumaier = NeumaierSum::new();
2684                neumaier.push(RealValidated::try_new_validated(1.0).unwrap());
2685                neumaier.push(RealValidated::try_new_validated(1e-16).unwrap());
2686                neumaier.push(RealValidated::try_new_validated(-1.0).unwrap());
2687                assert_eq!(neumaier.sum_before_compensation().as_ref(), &0.0);
2688                assert_eq!(neumaier.compensation().as_ref(), &1e-16);
2689            }
2690
2691            #[test]
2692            fn sum() {
2693                let mut neumaier = NeumaierSum::new();
2694                neumaier.push(RealValidated::try_new_validated(1.0).unwrap());
2695                neumaier.push(RealValidated::try_new_validated(1e-16).unwrap());
2696                neumaier.push(RealValidated::try_new_validated(-1.0).unwrap());
2697                assert_eq!(neumaier.sum_before_compensation().as_ref(), &0.0);
2698                assert_eq!(neumaier.compensation().as_ref(), &1e-16);
2699                let sum = neumaier.result();
2700                assert_eq!(sum.as_ref(), &1e-16);
2701                println!("compensated sum = {}", sum);
2702            }
2703
2704            #[test]
2705            fn sum_big_values() {
2706                let values = [1.0, 1e100, 1.0, -1e100]
2707                    .iter()
2708                    .map(|&v| RealValidated::try_new_validated(v).unwrap())
2709                    .collect::<Vec<_>>();
2710                let sum = values.iter().cloned().sum::<RealValidated>();
2711                assert_eq!(sum.as_ref(), &2.0);
2712
2713                let neumaier = NeumaierSum::new_sequential(values);
2714                let sum = neumaier.result();
2715                assert_eq!(sum.as_ref(), &2.0);
2716                println!("compensated sum = {}", sum);
2717            }
2718
2719            #[test]
2720            fn sum_small_values() {
2721                let values = [1.0, 1e-100, -1.0]
2722                    .iter()
2723                    .map(|&v| RealValidated::try_new_validated(v).unwrap())
2724                    .collect::<Vec<_>>();
2725                let sum = values.iter().cloned().sum::<RealValidated>();
2726                assert_eq!(sum.as_ref(), &1e-100);
2727
2728                let neumaier = NeumaierSum::new_sequential(values);
2729                let sum = neumaier.result();
2730                assert_eq!(sum.as_ref(), &1e-100);
2731                println!("compensated sum = {}", sum);
2732            }
2733        }
2734
2735        mod complex {
2736            use super::*;
2737
2738            #[test]
2739            fn new() {
2740                let neumaier = NeumaierSum::<ComplexValidated>::new();
2741
2742                let zero = Complex::new(0.0, 0.0);
2743                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2744                assert_eq!(neumaier.compensation().as_ref(), &zero);
2745            }
2746
2747            #[test]
2748            fn add() {
2749                let zero = Complex::new(0.0, 0.0);
2750                let v = Complex::new(1e-16, 2e-16);
2751
2752                let mut neumaier = NeumaierSum::new();
2753                neumaier.push(ComplexValidated::try_new_validated(Complex::new(1.0, 2.0)).unwrap());
2754                neumaier.push(ComplexValidated::try_new_validated(v).unwrap());
2755                neumaier
2756                    .push(ComplexValidated::try_new_validated(Complex::new(-1.0, -2.0)).unwrap());
2757
2758                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2759                assert_eq!(neumaier.compensation().as_ref(), &v);
2760            }
2761
2762            #[test]
2763            fn sum() {
2764                let zero = Complex::new(0.0, 0.0);
2765                let v = Complex::new(1e-16, 2e-16);
2766
2767                let mut neumaier = NeumaierSum::new();
2768                neumaier.push(ComplexValidated::try_new_validated(Complex::new(1.0, 2.0)).unwrap());
2769                neumaier.push(ComplexValidated::try_new_validated(v).unwrap());
2770                neumaier
2771                    .push(ComplexValidated::try_new_validated(Complex::new(-1.0, -2.0)).unwrap());
2772                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2773                assert_eq!(neumaier.compensation().as_ref(), &v);
2774                let sum = neumaier.result();
2775                assert_eq!(sum.as_ref(), &v);
2776                println!("compensated sum = {}", sum);
2777            }
2778
2779            #[test]
2780            fn sum_big_values() {
2781                let values = [
2782                    Complex::new(1.0, 2.0),
2783                    Complex::new(1e100, 2e100),
2784                    Complex::new(1.0, 2.0),
2785                    Complex::new(-1e100, -2e100),
2786                ]
2787                .iter()
2788                .map(|&v| ComplexValidated::try_new_validated(v).unwrap())
2789                .collect::<Vec<_>>();
2790                let sum = values.clone().into_iter().sum::<ComplexValidated>();
2791                let expected_sum = Complex::new(2., 4.);
2792                assert_eq!(sum.as_ref(), &expected_sum);
2793
2794                let neumaier = NeumaierSum::new_sequential(values);
2795                let sum = neumaier.result();
2796                assert_eq!(sum.as_ref(), &expected_sum);
2797                println!("compensated sum = {}", sum);
2798            }
2799
2800            #[test]
2801            fn sum_small_values() {
2802                let v = Complex::new(1e-100, 2e-100);
2803
2804                let values = [Complex::new(1.0, 2.0), v, Complex::new(-1.0, -2.0)]
2805                    .iter()
2806                    .map(|&v| ComplexValidated::try_new_validated(v).unwrap())
2807                    .collect::<Vec<_>>();
2808                let sum = values.iter().cloned().sum::<ComplexValidated>();
2809                let sum_expected = v;
2810                assert_eq!(sum.as_ref(), &sum_expected);
2811
2812                let neumaier = NeumaierSum::new_sequential(values);
2813                let sum = neumaier.result();
2814                assert_eq!(sum.as_ref(), &sum_expected);
2815                println!("compensated sum = {}", sum);
2816            }
2817        }
2818    }
2819
2820    mod random {
2821        use super::*;
2822        use super::{ComplexNative64StrictFinite, RealNative64StrictFinite};
2823        use crate::{RandomSampleFromF64, new_random_vec};
2824        use rand::{SeedableRng, distr::Uniform, rngs::StdRng};
2825
2826        /// Tests the random generation of a `RealValidated` value.
2827        /// It uses a seeded RNG to ensure deterministic results and checks
2828        /// if the generated value falls within the expected [0, 1) range.
2829        #[test]
2830        fn test_random_real_validated() {
2831            let seed = [42; 32];
2832            let mut rng = StdRng::from_seed(seed);
2833
2834            let random_real: RealNative64StrictFinite = rng.random();
2835
2836            // rng.random::<f64>() produces a value in [0, 1), so the converted value should be in the same range.
2837            assert_eq!(random_real.as_ref(), &0.23713468825474326);
2838
2839            // Check for determinism
2840            let mut rng2 = StdRng::from_seed(seed);
2841            let random_real2: RealNative64StrictFinite = rng2.random();
2842            assert_eq!(random_real, random_real2);
2843        }
2844
2845        /// Tests the random generation of a `ComplexValidated` value.
2846        /// It uses a seeded RNG for determinism and verifies that both the real
2847        /// and imaginary parts of the generated complex number are within the
2848        /// expected [0, 1) range.
2849        #[test]
2850        fn test_random_complex_validated() {
2851            let seed = [99; 32];
2852            let mut rng = StdRng::from_seed(seed);
2853
2854            let random_complex: ComplexNative64StrictFinite = rng.random();
2855
2856            // The real and imaginary parts are generated independently,
2857            // so both should be in the [0, 1) range.
2858            let real_part = random_complex.real_part();
2859            let imag_part = random_complex.imag_part();
2860
2861            assert_eq!(real_part.as_ref(), &0.9995546882627792);
2862            assert_eq!(imag_part.as_ref(), &0.08932180682540247);
2863
2864            // Check for determinism
2865            let mut rng2 = StdRng::from_seed(seed);
2866            let random_complex2: ComplexNative64StrictFinite = rng2.random();
2867            assert_eq!(random_complex, random_complex2);
2868        }
2869
2870        const SEED: [u8; 32] = [42; 32];
2871
2872        #[test]
2873        fn test_sample_real_validated() {
2874            let mut rng = StdRng::from_seed(SEED);
2875            let dist = Uniform::new(-10.0, 10.0).unwrap();
2876
2877            let val = RealNative64StrictFinite::sample_from(&dist, &mut rng);
2878            assert_eq!(val.as_ref(), &-5.257306234905137);
2879
2880            // Check determinism
2881            let mut rng2 = StdRng::from_seed(SEED);
2882            let val2 = RealNative64StrictFinite::sample_from(&dist, &mut rng2);
2883            assert_eq!(val, val2);
2884        }
2885
2886        #[test]
2887        fn test_sample_complex_validated() {
2888            let mut rng = StdRng::from_seed(SEED);
2889            let dist = Uniform::new(-10.0, 10.0).unwrap();
2890
2891            let val = ComplexNative64StrictFinite::sample_from(&dist, &mut rng);
2892            assert_eq!(val.real_part().as_ref(), &-5.257306234905137);
2893            assert_eq!(val.imag_part().as_ref(), &7.212119776268775);
2894
2895            // Check determinism
2896            let mut rng2 = StdRng::from_seed(SEED);
2897            let val2 = ComplexNative64StrictFinite::sample_from(&dist, &mut rng2);
2898            assert_eq!(val, val2);
2899        }
2900
2901        #[test]
2902        fn new_random_vec_real() {
2903            let mut rng = StdRng::from_seed(SEED);
2904            let dist = Uniform::new(-10.0, 10.0).unwrap();
2905            let vec: Vec<RealNative64StrictFinite> = new_random_vec(3, &dist, &mut rng);
2906            assert_eq!(vec.len(), 3);
2907            assert_eq!(vec[0].as_ref(), &-5.257306234905137);
2908            assert_eq!(vec[1].as_ref(), &7.212119776268775);
2909            assert_eq!(vec[2].as_ref(), &-4.666248990558111);
2910
2911            // Check determinism
2912            let mut rng2 = StdRng::from_seed(SEED);
2913            let vec2: Vec<RealNative64StrictFinite> = new_random_vec(3, &dist, &mut rng2);
2914            assert_eq!(vec, vec2);
2915        }
2916
2917        #[test]
2918        fn new_random_vec_complex() {
2919            let mut rng = StdRng::from_seed(SEED);
2920            let dist = Uniform::new(-10.0, 10.0).unwrap();
2921            let vec: Vec<ComplexNative64StrictFinite> = new_random_vec(3, &dist, &mut rng);
2922            assert_eq!(vec.len(), 3);
2923            assert_eq!(vec[0].real_part().as_ref(), &-5.257306234905137);
2924            assert_eq!(vec[0].imag_part().as_ref(), &7.212119776268775);
2925            assert_eq!(vec[1].real_part().as_ref(), &-4.666248990558111);
2926            assert_eq!(vec[1].imag_part().as_ref(), &9.66047141517383);
2927            assert_eq!(vec[2].real_part().as_ref(), &-9.04279551029691);
2928            assert_eq!(vec[2].imag_part().as_ref(), &-1.026624649331671);
2929
2930            // Check determinism
2931            let mut rng2 = StdRng::from_seed(SEED);
2932            let vec2: Vec<ComplexNative64StrictFinite> = new_random_vec(3, &dist, &mut rng2);
2933            assert_eq!(vec, vec2);
2934        }
2935    }
2936
2937    mod hash_map_key_usage {
2938        use crate::{
2939            backends::native::validated::{
2940                ComplexNative64StrictFinite, RealNative64StrictFinite,
2941                RealNative64StrictFiniteInDebug,
2942            },
2943            functions::Sign,
2944        };
2945        use num::Complex;
2946        use std::collections::HashMap;
2947        use try_create::TryNew;
2948
2949        #[test]
2950        fn test_native64_as_hashmap_key() {
2951            let mut map = HashMap::new();
2952            let key1 = RealNative64StrictFinite::try_new(1.0).unwrap();
2953            let key2 = RealNative64StrictFinite::try_new(2.5).unwrap();
2954
2955            map.insert(key1, "one");
2956            map.insert(key2, "two_point_five");
2957
2958            assert_eq!(
2959                map.get(&RealNative64StrictFinite::try_new(1.0).unwrap()),
2960                Some(&"one")
2961            );
2962            assert_eq!(map.len(), 2);
2963
2964            // Overwrite an existing key
2965            let old_value = map.insert(key1, "new_one");
2966            assert_eq!(old_value, Some("one"));
2967            assert_eq!(map.get(&key1), Some(&"new_one"));
2968        }
2969
2970        #[test]
2971        fn test_native64_debug_as_hashmap_key() {
2972            let mut map = HashMap::new();
2973            let key1 = RealNative64StrictFiniteInDebug::try_new(1.0).unwrap();
2974            let key2 = RealNative64StrictFiniteInDebug::try_new(2.5).unwrap();
2975
2976            map.insert(key1, "one_debug");
2977            map.insert(key2, "two_point_five_debug");
2978
2979            assert_eq!(
2980                map.get(&RealNative64StrictFiniteInDebug::try_new(1.0).unwrap()),
2981                Some(&"one_debug")
2982            );
2983            assert_eq!(map.len(), 2);
2984
2985            // Overwrite an existing key
2986            let old_value = map.insert(key1, "new_one_debug");
2987            assert_eq!(old_value, Some("one_debug"));
2988            assert_eq!(map.get(&key1), Some(&"new_one_debug"));
2989        }
2990
2991        #[test]
2992        fn test_hashmap_basic_operations() {
2993            let mut map = HashMap::new();
2994            let key1 = RealNative64StrictFinite::try_new(1.0).unwrap();
2995            let key2 = RealNative64StrictFinite::try_new(2.5).unwrap();
2996            let key3 = RealNative64StrictFinite::try_new(1.0).unwrap(); // Same as key1
2997
2998            // Insert and verify
2999            assert_eq!(map.insert(key1, "one"), None);
3000            assert_eq!(map.insert(key2, "two_point_five"), None);
3001            assert_eq!(map.len(), 2);
3002
3003            // Test key equality (key3 should be equal to key1)
3004            assert_eq!(map.get(&key3), Some(&"one"));
3005
3006            // Overwrite existing key
3007            assert_eq!(map.insert(key3, "one_updated"), Some("one"));
3008            assert_eq!(map.len(), 2); // Size shouldn't change
3009        }
3010
3011        #[test]
3012        fn test_hashset_operations() {
3013            use std::collections::HashSet;
3014            let mut set = HashSet::new();
3015
3016            let val1 = RealNative64StrictFinite::try_new(1.0).unwrap();
3017            let val2 = RealNative64StrictFinite::try_new(2.0).unwrap();
3018            let val1_duplicate = RealNative64StrictFinite::try_new(1.0).unwrap();
3019
3020            assert!(set.insert(val1));
3021            assert!(set.insert(val2));
3022            assert!(!set.insert(val1_duplicate)); // Should return false (already exists)
3023
3024            assert_eq!(set.len(), 2);
3025            assert!(set.contains(&RealNative64StrictFinite::try_new(1.0).unwrap()));
3026        }
3027
3028        #[test]
3029        fn test_hash_consistency() {
3030            use std::collections::hash_map::DefaultHasher;
3031            use std::hash::{Hash, Hasher};
3032
3033            let val1 = RealNative64StrictFinite::try_new(1.234).unwrap();
3034            let val2 = RealNative64StrictFinite::try_new(1.234).unwrap();
3035
3036            // Equal values should have equal hashes
3037            let mut hasher1 = DefaultHasher::new();
3038            let mut hasher2 = DefaultHasher::new();
3039
3040            val1.hash(&mut hasher1);
3041            val2.hash(&mut hasher2);
3042
3043            assert_eq!(hasher1.finish(), hasher2.finish());
3044            assert_eq!(val1, val2); // Verify they're actually equal
3045        }
3046
3047        #[test]
3048        fn test_hash_signed_zero() {
3049            use std::collections::hash_map::DefaultHasher;
3050            use std::hash::{Hash, Hasher};
3051
3052            let val1 = RealNative64StrictFinite::try_new(0.0).unwrap();
3053            assert!(val1.kernel_is_sign_positive());
3054            let val2 = RealNative64StrictFinite::try_new(-0.0).unwrap();
3055            assert!(val2.kernel_is_sign_negative());
3056
3057            // Verify the underlying f64 values have different bit patterns
3058            assert_ne!(
3059                0.0f64.to_bits(),
3060                (-0.0f64).to_bits(),
3061                "Sanity check: +0.0 and -0.0 should have different bit patterns"
3062            );
3063
3064            assert_eq!(val1, val2); // Verify they're actually equal
3065
3066            // Equal values should have equal hashes
3067            let mut hasher1 = DefaultHasher::new();
3068            let mut hasher2 = DefaultHasher::new();
3069
3070            val1.hash(&mut hasher1);
3071            val2.hash(&mut hasher2);
3072
3073            assert_eq!(hasher1.finish(), hasher2.finish());
3074        }
3075
3076        #[test]
3077        fn test_complex_as_hashmap_key() {
3078            let mut map = HashMap::new();
3079            let key1 = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
3080            let key2 = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
3081
3082            map.insert(key1, "one_plus_two_i");
3083            map.insert(key2, "three_plus_four_i");
3084
3085            assert_eq!(
3086                map.get(&ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap()),
3087                Some(&"one_plus_two_i")
3088            );
3089            assert_eq!(map.len(), 2);
3090
3091            // Overwrite an existing key
3092            let old_value = map.insert(key1, "updated_complex");
3093            assert_eq!(old_value, Some("one_plus_two_i"));
3094            assert_eq!(map.get(&key1), Some(&"updated_complex"));
3095        }
3096
3097        #[test]
3098        fn test_complex_hash_consistency() {
3099            use std::collections::hash_map::DefaultHasher;
3100            use std::hash::{Hash, Hasher};
3101
3102            let val1 = ComplexNative64StrictFinite::try_new(Complex::new(1.234, 5.678)).unwrap();
3103            let val2 = ComplexNative64StrictFinite::try_new(Complex::new(1.234, 5.678)).unwrap();
3104
3105            // Equal values should have equal hashes
3106            let mut hasher1 = DefaultHasher::new();
3107            let mut hasher2 = DefaultHasher::new();
3108
3109            val1.hash(&mut hasher1);
3110            val2.hash(&mut hasher2);
3111
3112            assert_eq!(hasher1.finish(), hasher2.finish());
3113            assert_eq!(val1, val2); // Verify they're actually equal
3114        }
3115
3116        #[test]
3117        fn test_complex_hash_signed_zero() {
3118            use std::collections::hash_map::DefaultHasher;
3119            use std::hash::{Hash, Hasher};
3120
3121            // Test all combinations of signed zeros
3122            let val1 = ComplexNative64StrictFinite::try_new(Complex::new(0.0, 0.0)).unwrap();
3123            let val2 = ComplexNative64StrictFinite::try_new(Complex::new(-0.0, 0.0)).unwrap();
3124            let val3 = ComplexNative64StrictFinite::try_new(Complex::new(0.0, -0.0)).unwrap();
3125            let val4 = ComplexNative64StrictFinite::try_new(Complex::new(-0.0, -0.0)).unwrap();
3126
3127            // All should be equal
3128            assert_eq!(val1, val2);
3129            assert_eq!(val1, val3);
3130            assert_eq!(val1, val4);
3131
3132            // All should have the same hash
3133            let mut hasher1 = DefaultHasher::new();
3134            let mut hasher2 = DefaultHasher::new();
3135            let mut hasher3 = DefaultHasher::new();
3136            let mut hasher4 = DefaultHasher::new();
3137
3138            val1.hash(&mut hasher1);
3139            val2.hash(&mut hasher2);
3140            val3.hash(&mut hasher3);
3141            val4.hash(&mut hasher4);
3142
3143            let hash1 = hasher1.finish();
3144            let hash2 = hasher2.finish();
3145            let hash3 = hasher3.finish();
3146            let hash4 = hasher4.finish();
3147
3148            assert_eq!(hash1, hash2);
3149            assert_eq!(hash1, hash3);
3150            assert_eq!(hash1, hash4);
3151        }
3152
3153        #[test]
3154        fn test_complex_different_values_different_hashes() {
3155            use std::collections::hash_map::DefaultHasher;
3156            use std::hash::{Hash, Hasher};
3157
3158            let val1 = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
3159            let val2 = ComplexNative64StrictFinite::try_new(Complex::new(2.0, 1.0)).unwrap();
3160            let val3 = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.001)).unwrap();
3161
3162            // Different values should (very likely) have different hashes
3163            let mut hasher1 = DefaultHasher::new();
3164            let mut hasher2 = DefaultHasher::new();
3165            let mut hasher3 = DefaultHasher::new();
3166
3167            val1.hash(&mut hasher1);
3168            val2.hash(&mut hasher2);
3169            val3.hash(&mut hasher3);
3170
3171            let hash1 = hasher1.finish();
3172            let hash2 = hasher2.finish();
3173            let hash3 = hasher3.finish();
3174
3175            // These are not guaranteed but extremely likely
3176            assert_ne!(val1, val2);
3177            assert_ne!(val1, val3);
3178            assert_ne!(hash1, hash2);
3179            assert_ne!(hash1, hash3);
3180        }
3181
3182        #[test]
3183        fn test_complex_hashset_operations() {
3184            use std::collections::HashSet;
3185
3186            let mut set = HashSet::new();
3187
3188            let val1 = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
3189            let val2 = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
3190            let val1_duplicate =
3191                ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
3192
3193            assert!(set.insert(val1));
3194            assert!(set.insert(val2));
3195            assert!(!set.insert(val1_duplicate)); // Should return false (already exists)
3196
3197            assert_eq!(set.len(), 2);
3198            assert!(
3199                set.contains(
3200                    &ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap()
3201                )
3202            );
3203        }
3204    }
3205
3206    mod test_truncate_to_usize {
3207        use super::*;
3208        use crate::core::errors::ErrorsRawRealToInteger;
3209
3210        #[test]
3211        fn test_positive_integers() {
3212            // Whole numbers should convert exactly
3213            let value = RealNative64StrictFinite::try_new(42.0).unwrap();
3214            assert_eq!(value.truncate_to_usize().unwrap(), 42);
3215
3216            let value = RealNative64StrictFinite::try_new(1.0).unwrap();
3217            assert_eq!(value.truncate_to_usize().unwrap(), 1);
3218
3219            let value = RealNative64StrictFinite::try_new(100.0).unwrap();
3220            assert_eq!(value.truncate_to_usize().unwrap(), 100);
3221        }
3222
3223        #[test]
3224        fn test_positive_fractionals_truncate() {
3225            // Positive fractional parts should be discarded (truncated toward zero)
3226            let value = RealNative64StrictFinite::try_new(42.9).unwrap();
3227            assert_eq!(value.truncate_to_usize().unwrap(), 42);
3228
3229            let value = RealNative64StrictFinite::try_new(3.7).unwrap();
3230            assert_eq!(value.truncate_to_usize().unwrap(), 3);
3231
3232            let value = RealNative64StrictFinite::try_new(0.9).unwrap();
3233            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3234
3235            let value = RealNative64StrictFinite::try_new(99.999).unwrap();
3236            assert_eq!(value.truncate_to_usize().unwrap(), 99);
3237        }
3238
3239        #[test]
3240        fn test_zero_cases() {
3241            // Zero should convert to 0
3242            let value = RealNative64StrictFinite::try_new(0.0).unwrap();
3243            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3244
3245            // Positive fractional values less than 1 should truncate to 0
3246            let value = RealNative64StrictFinite::try_new(0.1).unwrap();
3247            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3248
3249            let value = RealNative64StrictFinite::try_new(0.5).unwrap();
3250            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3251        }
3252
3253        #[test]
3254        fn test_large_valid_values() {
3255            // Large but representable values within usize range
3256            let value = RealNative64StrictFinite::try_new(1_000_000.7).unwrap();
3257            assert_eq!(value.truncate_to_usize().unwrap(), 1_000_000);
3258
3259            let value = RealNative64StrictFinite::try_new(1_000_000_000.0).unwrap();
3260            assert_eq!(value.truncate_to_usize().unwrap(), 1_000_000_000);
3261
3262            // Test with a value close to but less than usize::MAX (on 64-bit systems)
3263            let max_safe = (usize::MAX as f64) - 2048.0; // Subtract to avoid precision issues
3264            let value = RealNative64StrictFinite::try_new(max_safe).unwrap();
3265            let result = value.truncate_to_usize().unwrap();
3266            assert!(result < usize::MAX);
3267        }
3268
3269        #[test]
3270        fn test_negative_values_error() {
3271            // Negative values should return OutOfRange error
3272            let value = RealNative64StrictFinite::try_new(-1.0).unwrap();
3273            let result = value.truncate_to_usize();
3274            assert!(matches!(
3275                result,
3276                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3277            ));
3278
3279            let value = RealNative64StrictFinite::try_new(-10.5).unwrap();
3280            let result = value.truncate_to_usize();
3281            assert!(matches!(
3282                result,
3283                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3284            ));
3285
3286            let value = RealNative64StrictFinite::try_new(-0.1).unwrap();
3287            let result = value.truncate_to_usize();
3288            assert!(matches!(result, Ok(0)));
3289
3290            let value = RealNative64StrictFinite::try_new(-1000.0).unwrap();
3291            let result = value.truncate_to_usize();
3292            assert!(matches!(
3293                result,
3294                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3295            ));
3296        }
3297
3298        #[test]
3299        fn test_too_large_values_error() {
3300            // Values larger than usize::MAX should return OutOfRange error
3301            let too_large = (usize::MAX as f64) * 2.0;
3302            let value = RealNative64StrictFinite::try_new(too_large).unwrap();
3303            let result = value.truncate_to_usize();
3304            assert!(matches!(
3305                result,
3306                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3307            ));
3308
3309            let value = RealNative64StrictFinite::try_new(1e20).unwrap();
3310            let result = value.truncate_to_usize();
3311            assert!(matches!(
3312                result,
3313                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3314            ));
3315        }
3316
3317        #[test]
3318        fn test_edge_cases() {
3319            // Test values very close to boundaries
3320
3321            // Just above zero
3322            let value = RealNative64StrictFinite::try_new(f64::EPSILON).unwrap();
3323            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3324
3325            // Just below 1
3326            let value = RealNative64StrictFinite::try_new(1.0 - f64::EPSILON).unwrap();
3327            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3328
3329            // Just above 1
3330            let value = RealNative64StrictFinite::try_new(1.0 + f64::EPSILON).unwrap();
3331            assert_eq!(value.truncate_to_usize().unwrap(), 1);
3332        }
3333
3334        #[test]
3335        fn test_truncation_behavior() {
3336            // Verify truncation (toward zero) behavior vs other rounding modes
3337            let test_cases = [
3338                (2.1, 2),
3339                (2.5, 2), // truncate, not round
3340                (2.9, 2),
3341                (3.0, 3),
3342                (3.1, 3),
3343                (99.999, 99),
3344            ];
3345
3346            for (input, expected) in test_cases {
3347                let value = RealNative64StrictFinite::try_new(input)
3348                    .unwrap()
3349                    .truncate_to_usize()
3350                    .unwrap();
3351                assert_eq!(
3352                    value, expected,
3353                    "Failed for input {}: expected {}, got {:?}",
3354                    input, expected, value
3355                );
3356            }
3357        }
3358
3359        #[test]
3360        fn test_error_details() {
3361            // Test that error variants contain expected information
3362
3363            // OutOfRange error for negative value
3364            let value = RealNative64StrictFinite::try_new(-5.0).unwrap();
3365            if let Err(ErrorsRawRealToInteger::OutOfRange {
3366                value: err_val,
3367                min,
3368                max,
3369                ..
3370            }) = value.truncate_to_usize()
3371            {
3372                assert_eq!(err_val, -5.0);
3373                assert_eq!(min, usize::MIN);
3374                assert_eq!(max, usize::MAX);
3375            } else {
3376                panic!("Expected OutOfRange error for negative value");
3377            }
3378
3379            // OutOfRange error for too large value
3380            let large_value = 1e20;
3381            let value = RealNative64StrictFinite::try_new(large_value).unwrap();
3382            if let Err(ErrorsRawRealToInteger::OutOfRange {
3383                value: err_val,
3384                min,
3385                max,
3386                ..
3387            }) = value.truncate_to_usize()
3388            {
3389                assert_eq!(err_val, large_value);
3390                assert_eq!(min, usize::MIN);
3391                assert_eq!(max, usize::MAX);
3392            } else {
3393                panic!("Expected OutOfRange error for large value");
3394            }
3395        }
3396
3397        #[test]
3398        fn test_practical_usage_scenario() {
3399            // Test a realistic usage scenario: creating a vector with calculated size
3400            fn create_vector_with_calculated_size<T: Default + Clone>(
3401                size_float: RealNative64StrictFinite,
3402            ) -> Result<Vec<T>, Box<dyn std::error::Error>> {
3403                let size = size_float.truncate_to_usize()?;
3404                Ok(vec![T::default(); size])
3405            }
3406
3407            // Valid case
3408            let calculated_size = RealNative64StrictFinite::try_new(10.7).unwrap();
3409            let vec: Vec<i32> = create_vector_with_calculated_size(calculated_size).unwrap();
3410            assert_eq!(vec.len(), 10); // Truncated from 10.7
3411
3412            // Error case - negative size
3413            let negative_size = RealNative64StrictFinite::try_new(-5.0).unwrap();
3414            let result: Result<Vec<i32>, _> = create_vector_with_calculated_size(negative_size);
3415            assert!(result.is_err());
3416
3417            // Error case - too large size
3418            let huge_size = RealNative64StrictFinite::try_new(1e20).unwrap();
3419            let result: Result<Vec<i32>, _> = create_vector_with_calculated_size(huge_size);
3420            assert!(result.is_err());
3421        }
3422
3423        #[test]
3424        fn test_consistency_with_f64_behavior() {
3425            // Verify that our implementation behaves consistently with direct f64 operations
3426            let test_values = [0.0, 1.0, 2.5, 42.9, 100.0, 0.1, 0.9];
3427
3428            for &val in &test_values {
3429                let validated = RealNative64StrictFinite::try_new(val).unwrap();
3430                let result = validated.truncate_to_usize().unwrap();
3431
3432                // Compare with direct f64 truncation
3433                let expected = val.trunc() as usize;
3434                assert_eq!(result, expected, "Mismatch for value {}", val);
3435            }
3436        }
3437    }
3438
3439    mod bytemuck_conversions {
3440        use super::*;
3441        use bytemuck::checked::{CheckedCastError, try_from_bytes};
3442
3443        mod real_strict_finite {
3444            use super::*;
3445
3446            #[test]
3447            fn valid_value_from_bytes() {
3448                let value = 42.0_f64;
3449                let bytes = value.to_ne_bytes();
3450
3451                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3452                    try_from_bytes(&bytes);
3453                assert!(result.is_ok());
3454                assert_eq!(*result.unwrap().as_ref(), 42.0);
3455            }
3456
3457            #[test]
3458            fn valid_value_try_cast() {
3459                let value = 42.0_f64;
3460                let bytes = value.to_ne_bytes();
3461                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3462                    try_from_bytes(&bytes);
3463                assert!(result.is_ok());
3464                assert_eq!(*result.unwrap().as_ref(), 42.0);
3465            }
3466
3467            #[test]
3468            fn zero_from_bytes() {
3469                let value = 0.0_f64;
3470                let bytes = value.to_ne_bytes();
3471
3472                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3473                    try_from_bytes(&bytes);
3474                assert!(result.is_ok());
3475                assert_eq!(*result.unwrap().as_ref(), 0.0);
3476            }
3477
3478            #[test]
3479            fn negative_zero_from_bytes() {
3480                let value = -0.0_f64;
3481                let bytes = value.to_ne_bytes();
3482
3483                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3484                    try_from_bytes(&bytes);
3485                assert!(result.is_ok());
3486                assert_eq!(*result.unwrap().as_ref(), -0.0);
3487            }
3488
3489            #[test]
3490            fn max_value_from_bytes() {
3491                let value = f64::MAX;
3492                let bytes = value.to_ne_bytes();
3493
3494                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3495                    try_from_bytes(&bytes);
3496                assert!(result.is_ok());
3497                assert_eq!(*result.unwrap().as_ref(), f64::MAX);
3498            }
3499
3500            #[test]
3501            fn min_value_from_bytes() {
3502                let value = f64::MIN;
3503                let bytes = value.to_ne_bytes();
3504
3505                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3506                    try_from_bytes(&bytes);
3507                assert!(result.is_ok());
3508                assert_eq!(*result.unwrap().as_ref(), f64::MIN);
3509            }
3510
3511            #[test]
3512            fn nan_from_bytes_fails() {
3513                let value = f64::NAN;
3514                let bytes = value.to_ne_bytes();
3515
3516                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3517                    try_from_bytes(&bytes);
3518                assert!(result.is_err());
3519                assert!(matches!(result, Err(CheckedCastError::InvalidBitPattern)));
3520            }
3521
3522            #[test]
3523            fn nan_try_cast_fails() {
3524                let value = f64::NAN;
3525                let bytes = value.to_ne_bytes();
3526                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3527                    try_from_bytes(&bytes);
3528                assert!(result.is_err());
3529                assert!(matches!(result, Err(CheckedCastError::InvalidBitPattern)));
3530            }
3531
3532            #[test]
3533            fn infinity_from_bytes_fails() {
3534                let value = f64::INFINITY;
3535                let bytes = value.to_ne_bytes();
3536
3537                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3538                    try_from_bytes(&bytes);
3539                assert!(result.is_err());
3540                assert!(matches!(result, Err(CheckedCastError::InvalidBitPattern)));
3541            }
3542
3543            #[test]
3544            fn neg_infinity_from_bytes_fails() {
3545                let value = f64::NEG_INFINITY;
3546                let bytes = value.to_ne_bytes();
3547
3548                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3549                    try_from_bytes(&bytes);
3550                assert!(result.is_err());
3551                assert!(matches!(result, Err(CheckedCastError::InvalidBitPattern)));
3552            }
3553
3554            #[test]
3555            fn subnormal_from_bytes_fails() {
3556                let value = f64::MIN_POSITIVE / 2.0; // subnormal
3557                let bytes = value.to_ne_bytes();
3558
3559                let result: Result<&RealNative64StrictFinite, CheckedCastError> =
3560                    try_from_bytes(&bytes);
3561                assert!(result.is_err());
3562                assert!(matches!(result, Err(CheckedCastError::InvalidBitPattern)));
3563            }
3564
3565            #[test]
3566            fn round_trip_conversion() {
3567                let original = RealNative64StrictFinite::try_new(123.456).unwrap();
3568                let as_f64 = *original.as_ref();
3569                let bytes = as_f64.to_ne_bytes();
3570
3571                let from_bytes: &RealNative64StrictFinite = try_from_bytes(&bytes).unwrap();
3572                assert_eq!(original, *from_bytes);
3573            }
3574
3575            #[test]
3576            fn vec_conversion() {
3577                let values = vec![
3578                    RealNative64StrictFinite::try_new(1.0).unwrap(),
3579                    RealNative64StrictFinite::try_new(2.0).unwrap(),
3580                    RealNative64StrictFinite::try_new(3.0).unwrap(),
3581                    RealNative64StrictFinite::try_new(4.0).unwrap(),
3582                ];
3583
3584                // Cast to bytes
3585                let bytes = bytemuck::cast_slice::<RealNative64StrictFinite, u8>(&values);
3586
3587                // Try to cast back - should succeed
3588                let result: Result<&[RealNative64StrictFinite], CheckedCastError> =
3589                    bytemuck::checked::try_cast_slice(bytes);
3590                assert!(result.is_ok());
3591
3592                let validated_slice = result.unwrap();
3593                assert_eq!(validated_slice.len(), 4);
3594                assert_eq!(*validated_slice[0].as_ref(), 1.0);
3595                assert_eq!(*validated_slice[3].as_ref(), 4.0);
3596            }
3597
3598            #[test]
3599            fn direct_f64_slice_with_invalid_values() {
3600                // Create bytes representing f64 values, some invalid
3601                let mut bytes = Vec::new();
3602                bytes.extend_from_slice(&1.0_f64.to_ne_bytes());
3603                bytes.extend_from_slice(&f64::NAN.to_ne_bytes());
3604                bytes.extend_from_slice(&3.0_f64.to_ne_bytes());
3605
3606                // Should fail because of NaN
3607                let result: Result<&[RealNative64StrictFinite], CheckedCastError> =
3608                    bytemuck::checked::try_cast_slice(&bytes);
3609                assert!(result.is_err());
3610            }
3611        }
3612
3613        mod vec_conversions {
3614            use super::*;
3615            use try_create::TryNew;
3616
3617            #[test]
3618            fn vec_f64_to_validated_all_valid() {
3619                // Create a Vec<f64> with all valid values
3620                let f64_vec = [1.0, 2.5, -3.7, 0.0, 42.0];
3621
3622                // Convert to Vec<RealNative64StrictFinite>
3623                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3624                    .iter()
3625                    .map(|&x| RealNative64StrictFinite::try_new(x))
3626                    .collect();
3627
3628                assert!(validated_vec.is_ok());
3629                let validated_vec = validated_vec.unwrap();
3630
3631                // Verify length
3632                assert_eq!(validated_vec.len(), 5);
3633
3634                // Verify values
3635                assert_eq!(*validated_vec[0].as_ref(), 1.0);
3636                assert_eq!(*validated_vec[1].as_ref(), 2.5);
3637                assert_eq!(*validated_vec[2].as_ref(), -3.7);
3638                assert_eq!(*validated_vec[3].as_ref(), 0.0);
3639                assert_eq!(*validated_vec[4].as_ref(), 42.0);
3640            }
3641
3642            #[test]
3643            fn vec_f64_to_validated_with_nan() {
3644                // Create a Vec<f64> with a NaN value
3645                let f64_vec = [1.0, 2.5, f64::NAN, 0.0, 42.0];
3646
3647                // Conversion should fail on the NaN
3648                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3649                    .iter()
3650                    .map(|&x| RealNative64StrictFinite::try_new(x))
3651                    .collect();
3652
3653                assert!(validated_vec.is_err());
3654            }
3655
3656            #[test]
3657            fn vec_f64_to_validated_with_infinity() {
3658                // Create a Vec<f64> with an infinity value
3659                let f64_vec = [1.0, f64::INFINITY, 3.0];
3660
3661                // Conversion should fail on the infinity
3662                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3663                    .iter()
3664                    .map(|&x| RealNative64StrictFinite::try_new(x))
3665                    .collect();
3666
3667                assert!(validated_vec.is_err());
3668            }
3669
3670            #[test]
3671            fn vec_f64_to_validated_with_subnormal() {
3672                // Create a Vec<f64> with a subnormal value
3673                let subnormal = f64::MIN_POSITIVE / 2.0;
3674                let f64_vec = [1.0, subnormal, 3.0];
3675
3676                // Conversion should fail on the subnormal
3677                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3678                    .iter()
3679                    .map(|&x| RealNative64StrictFinite::try_new(x))
3680                    .collect();
3681
3682                assert!(validated_vec.is_err());
3683            }
3684
3685            #[test]
3686            fn vec_validated_to_f64() {
3687                // Create a Vec<RealNative64StrictFinite>
3688                let validated_vec = [
3689                    RealNative64StrictFinite::try_new(1.0).unwrap(),
3690                    RealNative64StrictFinite::try_new(2.5).unwrap(),
3691                    RealNative64StrictFinite::try_new(-3.7).unwrap(),
3692                    RealNative64StrictFinite::try_new(0.0).unwrap(),
3693                    RealNative64StrictFinite::try_new(42.0).unwrap(),
3694                ];
3695
3696                // Convert to Vec<f64>
3697                let f64_vec: Vec<f64> = validated_vec.iter().map(|x| *x.as_ref()).collect();
3698
3699                // Verify length
3700                assert_eq!(f64_vec.len(), 5);
3701
3702                // Verify values
3703                assert_eq!(f64_vec[0], 1.0);
3704                assert_eq!(f64_vec[1], 2.5);
3705                assert_eq!(f64_vec[2], -3.7);
3706                assert_eq!(f64_vec[3], 0.0);
3707                assert_eq!(f64_vec[4], 42.0);
3708            }
3709
3710            #[test]
3711            fn vec_round_trip_conversion() {
3712                // Start with Vec<f64>
3713                let original_f64 = vec![1.0, 2.5, -3.7, 0.0, 42.0, -999.123];
3714
3715                // Convert to Vec<RealNative64StrictFinite>
3716                let validated_vec: Vec<RealNative64StrictFinite> = original_f64
3717                    .iter()
3718                    .map(|&x| RealNative64StrictFinite::try_new(x).unwrap())
3719                    .collect();
3720
3721                // Convert back to Vec<f64>
3722                let final_f64: Vec<f64> = validated_vec.iter().map(|x| *x.as_ref()).collect();
3723
3724                let slice_f64 =
3725                    bytemuck::cast_slice::<RealNative64StrictFinite, f64>(&validated_vec);
3726                assert_eq!(slice_f64, &original_f64);
3727
3728                // Should be identical
3729                assert_eq!(original_f64, final_f64);
3730            }
3731
3732            #[test]
3733            fn vec_empty() {
3734                // Empty Vec<f64>
3735                let f64_vec: Vec<f64> = vec![];
3736
3737                // Convert to Vec<RealNative64StrictFinite>
3738                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3739                    .iter()
3740                    .map(|&x| RealNative64StrictFinite::try_new(x))
3741                    .collect();
3742
3743                assert!(validated_vec.is_ok());
3744                assert_eq!(validated_vec.unwrap().len(), 0);
3745            }
3746
3747            #[test]
3748            fn vec_large_values() {
3749                // Test with extreme but valid values
3750                let f64_vec = vec![f64::MAX, f64::MIN, f64::MIN_POSITIVE, -f64::MIN_POSITIVE];
3751
3752                // All should be valid
3753                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3754                    .iter()
3755                    .map(|&x| RealNative64StrictFinite::try_new(x))
3756                    .collect();
3757
3758                assert!(validated_vec.is_ok());
3759                let validated_vec = validated_vec.unwrap();
3760
3761                // Verify round-trip
3762                let f64_back: Vec<f64> = validated_vec.iter().map(|x| *x.as_ref()).collect();
3763
3764                assert_eq!(f64_vec, f64_back);
3765            }
3766
3767            #[test]
3768            fn vec_with_zeros() {
3769                // Test with positive and negative zeros
3770                let f64_vec = [0.0, -0.0, 1.0, -1.0];
3771
3772                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3773                    .iter()
3774                    .map(|&x| RealNative64StrictFinite::try_new(x))
3775                    .collect();
3776
3777                assert!(validated_vec.is_ok());
3778                let validated_vec = validated_vec.unwrap();
3779
3780                assert_eq!(*validated_vec[0].as_ref(), 0.0);
3781                assert_eq!(*validated_vec[1].as_ref(), -0.0);
3782            }
3783
3784            #[test]
3785            fn vec_using_from_iter() {
3786                // Test using from_iter for a more idiomatic approach
3787                let f64_vec = [1.0, 2.0, 3.0, 4.0, 5.0];
3788
3789                // Using from_iter with filter_map to handle errors
3790                let validated_vec: Vec<RealNative64StrictFinite> = f64_vec
3791                    .iter()
3792                    .filter_map(|&x| RealNative64StrictFinite::try_new(x).ok())
3793                    .collect();
3794
3795                assert_eq!(validated_vec.len(), 5);
3796            }
3797
3798            #[test]
3799            fn vec_conversion_preserves_order() {
3800                // Test that order is preserved through conversion
3801                let f64_vec: Vec<f64> = (0..100).map(|i| i as f64 * 0.1).collect();
3802
3803                let validated_vec: Vec<RealNative64StrictFinite> = f64_vec
3804                    .iter()
3805                    .map(|&x| RealNative64StrictFinite::try_new(x).unwrap())
3806                    .collect();
3807
3808                // Convert back and verify order
3809                for (i, val) in validated_vec.iter().enumerate() {
3810                    assert_eq!(*val.as_ref(), i as f64 * 0.1);
3811                }
3812            }
3813
3814            #[test]
3815            fn vec_partial_conversion_with_find() {
3816                // Test finding the first invalid value
3817                let f64_vec = [1.0, 2.0, f64::NAN, 4.0, 5.0];
3818
3819                // Find which index has the invalid value
3820                let (invalid_idx, _) = f64_vec
3821                    .iter()
3822                    .enumerate()
3823                    .find(|(_, x)| RealNative64StrictFinite::try_new(**x).is_err())
3824                    .expect("Should find invalid value");
3825
3826                assert_eq!(invalid_idx, 2);
3827            }
3828
3829            #[test]
3830            fn vec_consume_and_convert() {
3831                // Test consuming the original vector
3832                let f64_vec = vec![1.0, 2.0, 3.0];
3833
3834                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3835                    .into_iter()
3836                    .map(RealNative64StrictFinite::try_new)
3837                    .collect();
3838
3839                assert!(validated_vec.is_ok());
3840                assert_eq!(validated_vec.unwrap().len(), 3);
3841
3842                // f64_vec is moved and cannot be used here
3843            }
3844
3845            #[test]
3846            fn vec_validated_to_f64_with_try_cast_vec() {
3847                use bytemuck::allocation::try_cast_vec;
3848
3849                // Create a Vec<RealNative64StrictFinite>
3850                let validated_vec: Vec<RealNative64StrictFinite> = vec![
3851                    RealNative64StrictFinite::try_new(1.0).unwrap(),
3852                    RealNative64StrictFinite::try_new(2.5).unwrap(),
3853                    RealNative64StrictFinite::try_new(-3.7).unwrap(),
3854                    RealNative64StrictFinite::try_new(0.0).unwrap(),
3855                    RealNative64StrictFinite::try_new(42.0).unwrap(),
3856                ];
3857
3858                // Try to cast Vec<RealNative64StrictFinite> -> Vec<f64> using bytemuck
3859                let f64_vec_result: Result<Vec<f64>, _> = try_cast_vec(validated_vec);
3860
3861                // This should work because:
3862                // - RealNative64StrictFinite implements NoUninit āœ“
3863                // - f64 implements AnyBitPattern āœ“
3864                // - Both have same size and alignment (repr(transparent)) āœ“
3865                assert!(
3866                    f64_vec_result.is_ok(),
3867                    "try_cast_vec should work for Vec<RealNative64StrictFinite> -> Vec<f64>"
3868                );
3869
3870                let f64_vec = f64_vec_result.unwrap();
3871                assert_eq!(f64_vec.len(), 5);
3872                assert_eq!(f64_vec[0], 1.0);
3873                assert_eq!(f64_vec[1], 2.5);
3874                assert_eq!(f64_vec[2], -3.7);
3875                assert_eq!(f64_vec[3], 0.0);
3876                assert_eq!(f64_vec[4], 42.0);
3877            }
3878
3879            #[test]
3880            fn vec_f64_to_validated_try_cast_vec_fails() {
3881                // Create a Vec<f64>
3882                let f64_vec = [1.0, 2.5, -3.7, 0.0, 42.0];
3883
3884                // Try to cast Vec<f64> -> Vec<RealNative64StrictFinite> using bytemuck
3885                // This SHOULD NOT compile because RealNative64StrictFinite does not implement AnyBitPattern
3886                // (it only implements CheckedBitPattern, which requires validation)
3887
3888                // Uncomment the following line to verify it doesn't compile:
3889                // let validated_result: Result<Vec<RealNative64StrictFinite>, _> = try_cast_vec(f64_vec);
3890
3891                // Instead, we must use the iterator approach with validation:
3892                let validated_vec: Result<Vec<RealNative64StrictFinite>, _> = f64_vec
3893                    .iter()
3894                    .map(|&x| RealNative64StrictFinite::try_new(x))
3895                    .collect();
3896
3897                assert!(validated_vec.is_ok());
3898                assert_eq!(validated_vec.unwrap().len(), 5);
3899            }
3900        }
3901
3902        mod real_strict_finite_in_debug {
3903            use super::*;
3904
3905            #[test]
3906            fn valid_value_from_bytes() {
3907                let value = 42.0_f64;
3908                let bytes = value.to_ne_bytes();
3909
3910                let result: Result<&RealNative64StrictFiniteInDebug, CheckedCastError> =
3911                    try_from_bytes(&bytes);
3912                assert!(result.is_ok());
3913                assert_eq!(*result.unwrap().as_ref(), 42.0);
3914            }
3915
3916            #[test]
3917            fn nan_from_bytes() {
3918                let value = f64::NAN;
3919                let bytes = value.to_ne_bytes();
3920
3921                let result: Result<&RealNative64StrictFiniteInDebug, CheckedCastError> =
3922                    try_from_bytes(&bytes);
3923
3924                #[cfg(debug_assertions)]
3925                {
3926                    // In debug mode, should fail
3927                    assert!(result.is_err());
3928                    assert!(matches!(result, Err(CheckedCastError::InvalidBitPattern)));
3929                }
3930
3931                #[cfg(not(debug_assertions))]
3932                {
3933                    // In release mode, validation is skipped
3934                    // This test documents the behavior but is NOT safe
3935                    // Don't use this in production without guarantees!
3936                    assert!(result.is_ok());
3937                }
3938            }
3939
3940            #[test]
3941            fn infinity_from_bytes() {
3942                let value = f64::INFINITY;
3943                let bytes = value.to_ne_bytes();
3944
3945                let result: Result<&RealNative64StrictFiniteInDebug, CheckedCastError> =
3946                    try_from_bytes(&bytes);
3947
3948                #[cfg(debug_assertions)]
3949                {
3950                    assert!(result.is_err());
3951                }
3952
3953                #[cfg(not(debug_assertions))]
3954                {
3955                    assert!(result.is_ok());
3956                }
3957            }
3958
3959            #[test]
3960            fn round_trip_with_valid_value() {
3961                let original = RealNative64StrictFiniteInDebug::try_new(123.456).unwrap();
3962                let as_f64 = *original.as_ref();
3963                let bytes = as_f64.to_ne_bytes();
3964
3965                let from_bytes: &RealNative64StrictFiniteInDebug = try_from_bytes(&bytes).unwrap();
3966                assert_eq!(original, *from_bytes);
3967            }
3968        }
3969
3970        #[test]
3971        fn alignment_check() {
3972            use std::mem;
3973
3974            // Verify that RealNative64StrictFinite has the same alignment as f64
3975            assert_eq!(
3976                mem::align_of::<RealNative64StrictFinite>(),
3977                mem::align_of::<f64>()
3978            );
3979
3980            // Verify size
3981            assert_eq!(
3982                mem::size_of::<RealNative64StrictFinite>(),
3983                mem::size_of::<f64>()
3984            );
3985        }
3986    }
3987
3988    /// Tests for the conditional `Copy` implementation.
3989    ///
3990    /// These tests verify that `RealValidated` and `ComplexValidated` implement `Copy`
3991    /// when their underlying raw types implement `Copy` (e.g., `f64`, `Complex<f64>`).
3992    mod copy_trait_tests {
3993        use super::*;
3994
3995        mod real_copy {
3996            use super::*;
3997
3998            #[test]
3999            fn real_is_copy() {
4000                // Verify RealNative64StrictFinite is Copy
4001                fn assert_copy<T: Copy>() {}
4002                assert_copy::<RealNative64StrictFinite>();
4003                assert_copy::<RealNative64StrictFiniteInDebug>();
4004            }
4005
4006            #[test]
4007            fn real_copy_semantics() {
4008                let x = RealNative64StrictFinite::try_new(3.).unwrap();
4009                let y = x; // Copy, not move
4010                let z = x; // x is still valid because it was copied
4011                assert_eq!(x, y);
4012                assert_eq!(x, z);
4013            }
4014
4015            #[test]
4016            fn real_copy_in_function_call() {
4017                fn takes_by_value(val: RealNative64StrictFinite) -> f64 {
4018                    *val.as_ref()
4019                }
4020
4021                let x = RealNative64StrictFinite::try_new(42.0).unwrap();
4022                let result1 = takes_by_value(x);
4023                let result2 = takes_by_value(x); // x is still valid after first call
4024                assert_eq!(result1, 42.0);
4025                assert_eq!(result2, 42.0);
4026            }
4027
4028            #[test]
4029            fn real_copy_in_loop() {
4030                let x = RealNative64StrictFinite::try_new(1.0).unwrap();
4031                let mut sum = RealNative64StrictFinite::zero();
4032
4033                for _ in 0..5 {
4034                    sum += x; // x is copied each iteration
4035                }
4036
4037                assert_eq!(*sum.as_ref(), 5.0);
4038                assert_eq!(*x.as_ref(), 1.0); // x unchanged
4039            }
4040
4041            #[test]
4042            fn real_copy_with_arithmetic() {
4043                let a = RealNative64StrictFinite::try_new(2.0).unwrap();
4044                let b = RealNative64StrictFinite::try_new(3.0).unwrap();
4045
4046                // All of these use copies of a and b
4047                let sum = a + b;
4048                let diff = a - b;
4049                let prod = a * b;
4050                let quot = a / b;
4051
4052                // a and b still valid
4053                assert_eq!(*a.as_ref(), 2.0);
4054                assert_eq!(*b.as_ref(), 3.0);
4055                assert_eq!(*sum.as_ref(), 5.0);
4056                assert_eq!(*diff.as_ref(), -1.0);
4057                assert_eq!(*prod.as_ref(), 6.0);
4058                assert!((quot.as_ref() - 2.0 / 3.0).abs() < 1e-10);
4059            }
4060        }
4061
4062        mod complex_copy {
4063            use super::*;
4064
4065            #[test]
4066            fn complex_is_copy() {
4067                // Verify ComplexNative64StrictFinite is Copy
4068                fn assert_copy<T: Copy>() {}
4069                assert_copy::<ComplexNative64StrictFinite>();
4070                assert_copy::<ComplexNative64StrictFiniteInDebug>();
4071            }
4072
4073            #[test]
4074            fn complex_copy_semantics() {
4075                let z = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
4076                let w = z; // Copy, not move
4077                let v = z; // z is still valid because it was copied
4078                assert_eq!(z, w);
4079                assert_eq!(z, v);
4080            }
4081
4082            #[test]
4083            fn complex_copy_in_function_call() {
4084                fn takes_by_value(val: ComplexNative64StrictFinite) -> Complex<f64> {
4085                    val.into_inner()
4086                }
4087
4088                let z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
4089                let result1 = takes_by_value(z);
4090                let result2 = takes_by_value(z); // z is still valid after first call
4091                assert_eq!(result1, Complex::new(3.0, 4.0));
4092                assert_eq!(result2, Complex::new(3.0, 4.0));
4093            }
4094
4095            #[test]
4096            fn complex_copy_with_arithmetic() {
4097                let a = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
4098                let b = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
4099
4100                // All of these use copies of a and b
4101                let sum = a + b;
4102                let diff = a - b;
4103                let prod = a * b;
4104
4105                // a and b still valid
4106                assert_eq!(a.into_inner(), Complex::new(1.0, 2.0));
4107                assert_eq!(b.into_inner(), Complex::new(3.0, 4.0));
4108                assert_eq!(sum.into_inner(), Complex::new(4.0, 6.0));
4109                assert_eq!(diff.into_inner(), Complex::new(-2.0, -2.0));
4110                // (1+2i)(3+4i) = 3 + 4i + 6i + 8i² = 3 + 10i - 8 = -5 + 10i
4111                assert_eq!(prod.into_inner(), Complex::new(-5.0, 10.0));
4112            }
4113
4114            #[test]
4115            fn complex_copy_in_loop() {
4116                let z = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 1.0)).unwrap();
4117                let mut sum = ComplexNative64StrictFinite::zero();
4118
4119                for _ in 0..3 {
4120                    sum += z; // z is copied each iteration
4121                }
4122
4123                assert_eq!(sum.into_inner(), Complex::new(3.0, 3.0));
4124                assert_eq!(z.into_inner(), Complex::new(1.0, 1.0)); // z unchanged
4125            }
4126        }
4127
4128        mod mixed_copy {
4129            use super::*;
4130
4131            #[test]
4132            fn real_and_complex_copy_in_expression() {
4133                let r = RealNative64StrictFinite::try_new(2.0).unwrap();
4134                let z = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 1.0)).unwrap();
4135
4136                // Complex * Real uses copies
4137                let result1 = z * r;
4138                let result2 = z * r;
4139
4140                // Both still valid
4141                assert_eq!(*r.as_ref(), 2.0);
4142                assert_eq!(z.into_inner(), Complex::new(1.0, 1.0));
4143                assert_eq!(result1.into_inner(), Complex::new(2.0, 2.0));
4144                assert_eq!(result2.into_inner(), Complex::new(2.0, 2.0));
4145            }
4146        }
4147    }
4148}