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