num_valid/kernels/
native64_validated.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! # Validated Native 64-bit Kernel Types
4//!
5//! This module provides convenient, pre-configured type aliases for the native `f64`
6//! kernel. These types wrap [`f64`] and [`num::Complex<f64>`] in the [`RealValidated`]
7//! and [`ComplexValidated`] structs, bundling them with specific *validation policies*.
8//!
9//! These type aliases are the primary entry point for users who want to work with
10//! validated numbers that provide compile-time guarantees about their properties (e.g., finiteness).
11//!
12//! ## Policies
13//!
14//! Two main policies are provided:
15//!
16//! - **[`Native64StrictFinite`]:** Enforces that all values are finite (not `NaN` or `Infinity`)
17//!   in all build modes. Operations on types using this policy will panic on validation
18//!   failure in debug builds and return a `Result` in release builds. This is the safest and
19//!   most common choice.
20//!
21//! - **[`Native64StrictFiniteInDebug`]:** Also enforces finiteness, but validation checks that
22//!   would panic are **only performed in debug builds**. In release builds, these checks are
23//!   skipped for performance, and operations assume the inputs are valid. This is for
24//!   performance-critical code where the developer can guarantee the validity of inputs.
25//!
26//! ## Example
27//!
28//! ```rust
29//! use num_valid::kernels::native64_validated::RealNative64StrictFinite;
30//! use num_valid::functions::Sqrt;
31//! use try_create::TryNew;
32//!
33//! // Creation succeeds because 4.0 is a valid, finite number.
34//! let x = RealNative64StrictFinite::try_new(4.0).unwrap();
35//!
36//! // Creation fails for non-finite numbers.
37//! assert!(RealNative64StrictFinite::try_new(f64::NAN).is_err());
38//!
39//! // Mathematical operations are available through traits.
40//! let sqrt_x = x.sqrt();
41//! assert_eq!(*sqrt_x.as_ref(), 2.0);
42//! ```
43
44use crate::kernels::{
45    ComplexValidated, NumKernelStrictFinite, NumKernelStrictFiniteInDebug, RealValidated,
46};
47
48//------------------------------------------------------------------------------------------------------------
49/// A kernel policy that enforces strict finiteness for `f64` and `Complex<f64>` values.
50///
51/// This is a type alias for [`NumKernelStrictFinite<f64, 53>`].
52///
53/// It ensures that all validated values are finite (not `NaN` or `Infinity`).
54/// In debug builds, operations that fail validation will panic. In release builds, they
55/// will return an error. This policy is used by [`RealNative64StrictFinite`] and
56/// [`ComplexNative64StrictFinite`].
57pub type Native64StrictFinite = NumKernelStrictFinite<f64, 53>;
58//------------------------------------------------------------------------------------------------------------
59
60//------------------------------------------------------------------------------------------------------------
61/// A kernel policy that enforces strict finiteness for `f64` values **only in debug builds**.
62///
63/// This is a type alias for [`NumKernelStrictFiniteInDebug<f64, 53>`].
64///
65/// This policy is designed for performance-critical applications. In debug builds, it
66/// behaves identically to [`Native64StrictFinite`], panicking on validation failures.
67/// In **release builds**, these validation checks are **disabled**, and operations proceed
68/// assuming the inputs are valid. Use this policy with caution when you can guarantee
69/// the integrity of your data in release environments.
70pub type Native64StrictFiniteInDebug = NumKernelStrictFiniteInDebug<f64, 53>;
71//------------------------------------------------------------------------------------------------------------
72
73//------------------------------------------------------------------------------------------------------------
74/// A validated real number that guarantees its inner `f64` value is finite.
75///
76/// This is a type alias for [`RealValidated<Native64StrictFinite>`].
77///
78/// It is the standard, safe-to-use validated real number type for the native `f64` kernel.
79/// It prevents the representation of `NaN` and `Infinity`.
80pub type RealNative64StrictFinite = RealValidated<Native64StrictFinite>;
81
82/// A validated complex number that guarantees its inner `f64` parts are finite.
83///
84/// This is a type alias for [`ComplexValidated<Native64StrictFinite>`].
85///
86/// It is the standard, safe-to-use validated complex number type for the native `f64` kernel.
87/// It ensures that both the real and imaginary components are finite values.
88pub type ComplexNative64StrictFinite = ComplexValidated<Native64StrictFinite>;
89//------------------------------------------------------------------------------------------------------------
90
91//------------------------------------------------------------------------------------------------------------
92/// A validated real number that checks for finiteness **only in debug builds**.
93///
94/// This is a type alias for [`RealValidated<Native64StrictFiniteInDebug>`].
95///
96/// Use this type in performance-sensitive contexts where the overhead of validation
97/// in release builds is unacceptable and inputs are known to be valid.
98pub type RealNative64StrictFiniteInDebug = RealValidated<Native64StrictFiniteInDebug>;
99
100/// A validated complex number that checks for finiteness **only in debug builds**.
101///
102/// This is a type alias for [`ComplexValidated<Native64StrictFiniteInDebug>`].
103///
104/// Use this type in performance-sensitive contexts where the overhead of validation
105/// in release builds is unacceptable and inputs are known to be valid.
106pub type ComplexNative64StrictFiniteInDebug = ComplexValidated<Native64StrictFiniteInDebug>;
107//------------------------------------------------------------------------------------------------------------
108
109// --- Hashing Implementation ---------------------------------------------------------
110// Note: The Hash trait is implemented generically in the validation module for all
111// RealValidated<K> types where K::RealPolicy implements GuaranteesFiniteValues.
112// This ensures that validated types with finite value guarantees can be used as
113// keys in HashMap and other hash-based collections.
114//
115// The implementation hashes the raw IEEE 754 bit representation of the f64 value,
116// with special handling for signed zeros to maintain the hash contract that
117// a == b implies hash(a) == hash(b).
118//-------------------------------------------------------------
119
120//------------------------------------------------------------------------------------------------
121#[cfg(test)]
122mod tests {
123    use super::*;
124    use crate::{
125        Clamp, ComplexScalarConstructors, ComplexScalarGetParts, ComplexScalarMutateParts,
126        ComplexScalarSetParts, Constants, ExpM1, FpChecks, Hypot, Ln1p, MulAddRef, NegAssign,
127        RealScalar, Rounding, Sign, TotalCmp,
128        functions::{
129            ACos, ACosH, ACosHErrors, ACosHInputErrors, ACosRealErrors, ACosRealInputErrors, ASin,
130            ASinH, ASinRealErrors, ASinRealInputErrors, ATan, ATan2, ATan2Errors,
131            ATanComplexErrors, ATanComplexInputErrors, ATanH, ATanHErrors, ATanHInputErrors, Abs,
132            Arg, Classify, Conjugate, Cos, CosH, Exp, ExpErrors, Ln, Log2, Log10,
133            LogarithmComplexErrors, LogarithmComplexInputErrors, Max, Min, Pow,
134            PowComplexBaseRealExponentErrors, PowIntExponentErrors, PowIntExponentInputErrors,
135            PowRealBaseRealExponentErrors, Reciprocal, ReciprocalErrors, Sin, SinH, Sqrt,
136            SqrtRealErrors, Tan, TanH,
137        },
138        validation::{ErrorsTryFromf64, ErrorsValidationRawComplex, ErrorsValidationRawReal},
139    };
140    use num::{Complex, One, Zero};
141    use std::{
142        cmp::Ordering,
143        f64::consts::*,
144        num::FpCategory,
145        ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
146    };
147    use try_create::{IntoInner, New, TryNew, TryNewValidated};
148
149    type RealValidated = RealNative64StrictFinite;
150    type ComplexValidated = ComplexNative64StrictFinite;
151
152    mod fp_checks {
153        use super::*;
154
155        #[test]
156        fn is_finite() {
157            let real = RealValidated::try_new(1.).unwrap();
158            assert!(real.is_finite());
159
160            let real = RealValidated::try_new(f64::INFINITY);
161            assert!(real.is_err());
162
163            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
164            assert!(complex.is_finite());
165
166            let complex = ComplexValidated::try_new(Complex::new(f64::INFINITY, 1.));
167            assert!(complex.is_err());
168        }
169
170        #[test]
171        fn is_infinite() {
172            let real = RealValidated::try_new(1.).unwrap();
173            assert!(!real.is_infinite());
174
175            let real = RealValidated::try_new(f64::INFINITY);
176            assert!(real.is_err());
177
178            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
179            assert!(!complex.is_infinite());
180
181            let complex = ComplexValidated::try_new(Complex::new(f64::INFINITY, 1.));
182            assert!(complex.is_err());
183        }
184
185        #[test]
186        fn is_nan() {
187            let real = RealValidated::try_new(1.).unwrap();
188            assert!(!real.is_nan());
189
190            let real = RealValidated::try_new(f64::NAN);
191            assert!(matches!(real, Err(ErrorsValidationRawReal::IsNaN { .. })));
192
193            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
194            assert!(!complex.is_nan());
195
196            let complex = ComplexValidated::try_new(Complex::new(f64::NAN, 1.));
197            assert!(matches!(
198                complex,
199                Err(ErrorsValidationRawComplex::InvalidRealPart {
200                    source: ErrorsValidationRawReal::IsNaN { .. }
201                })
202            ));
203        }
204
205        #[test]
206        fn is_normal() {
207            let real = RealValidated::try_new(1.).unwrap();
208            assert!(real.is_normal());
209
210            let real = RealValidated::try_new(0.).unwrap();
211            assert!(!real.is_normal());
212
213            let complex = ComplexValidated::try_new(Complex::new(1., 1.)).unwrap();
214            assert!(complex.is_normal());
215
216            let complex = ComplexValidated::try_new(Complex::new(0., 0.)).unwrap();
217            assert!(!complex.is_normal());
218        }
219    }
220
221    mod abs {
222        use super::*;
223
224        mod real {
225            use super::*;
226
227            #[test]
228            fn abs_valid() {
229                let value = RealValidated::try_new(-4.).unwrap();
230
231                let expected_result = RealValidated::try_new(4.).unwrap();
232                assert_eq!(value.clone().try_abs().unwrap(), expected_result);
233                assert_eq!(value.abs(), expected_result);
234            }
235
236            #[test]
237            fn abs_zero() {
238                let value = RealValidated::try_new(0.).unwrap();
239
240                let expected_result = RealValidated::try_new(0.).unwrap();
241                assert_eq!(value.clone().try_abs().unwrap(), expected_result);
242                assert_eq!(value.abs(), expected_result);
243            }
244
245            /*
246            #[cfg(feature = "rug")]
247            #[test]
248            fn abs_nan() {
249                let value =
250                    RealValidated::try_new(rug::Float::with_val(53, rug::float::Special::Nan))
251                        .unwrap();
252                let result = value.try_abs();
253                assert!(matches!(result, Err(AbsRealErrors::Input { .. })));
254            }
255
256            #[cfg(feature = "rug")]
257            #[test]
258            fn abs_infinite() {
259                let value = RealValidated::try_new(rug::Float::with_val(
260                    53,
261                    rug::float::Special::Infinity,
262                ))
263                .unwrap();
264                let result = value.try_abs();
265                assert!(matches!(result, Err(AbsRealErrors::Input { .. })));
266            }
267            */
268        }
269
270        mod complex {
271            use super::*;
272
273            #[test]
274            fn abs_valid() {
275                let value = ComplexValidated::try_new(Complex::new(3., 4.)).unwrap();
276
277                let expected_result = RealValidated::try_new(5.).unwrap();
278                assert_eq!(value.clone().try_abs().unwrap(), expected_result);
279                assert_eq!(value.abs(), expected_result);
280            }
281
282            #[test]
283            fn abs_zero() {
284                let value = ComplexValidated::try_new(Complex::new(0., 0.)).unwrap();
285
286                let expected_result = RealValidated::try_new(0.).unwrap();
287                assert_eq!(value.clone().try_abs().unwrap(), expected_result);
288                assert_eq!(value.abs(), expected_result);
289            }
290            /*
291            #[test]
292            fn abs_nan() {
293                let value = Complex64Validated::try_new(Complex::new(
294                    53,
295                    (
296                        rug::Float::with_val(53, rug::float::Special::Nan),
297                        0.,
298                    ),
299                ))
300                .unwrap();
301                assert!(matches!(
302                    value.try_abs(),
303                    Err(AbsComplexErrors::Input { .. })
304                ));
305            }
306
307            #[test]
308            fn abs_infinite() {
309                let value = Complex64Validated::try_new(Complex::new(
310                    53,
311                    (
312                        rug::Float::with_val(53, rug::float::Special::Infinity),
313                        0.,
314                    ),
315                ))
316                .unwrap();
317                assert!(matches!(
318                    value.try_abs(),
319                    Err(AbsComplexErrors::Input { .. })
320                ));
321            }
322            */
323        }
324    }
325
326    mod builders {
327        use super::*;
328
329        mod real {
330            use super::*;
331
332            #[test]
333            fn into_inner() {
334                let value = RealValidated::try_new(1.23).unwrap();
335                assert_eq!(value.into_inner(), 1.23);
336            }
337
338            #[test]
339            fn new() {
340                let value = RealValidated::new(1.23);
341                assert_eq!(value, 1.23);
342            }
343
344            #[test]
345            fn try_new_nan() {
346                let err = RealValidated::try_new(f64::NAN).unwrap_err();
347                assert!(matches!(err, ErrorsValidationRawReal::IsNaN { .. }));
348            }
349
350            #[test]
351            fn try_new_pos_infinity() {
352                let err = RealValidated::try_new(f64::INFINITY).unwrap_err();
353                assert!(matches!(err, ErrorsValidationRawReal::IsPosInfinity { .. }));
354            }
355
356            #[test]
357            fn try_new_neg_infinity() {
358                let err = RealValidated::try_new(f64::NEG_INFINITY).unwrap_err();
359                assert!(matches!(err, ErrorsValidationRawReal::IsNegInfinity { .. }));
360            }
361        }
362
363        mod complex {
364            use super::*;
365
366            #[test]
367            fn into_inner() {
368                let v = Complex::new(1., 2.);
369                let value = ComplexValidated::try_new(v).unwrap();
370                assert_eq!(value.into_inner(), v);
371            }
372
373            #[test]
374            fn new() {
375                let v = Complex::new(1., 2.);
376                let value = ComplexValidated::new(v);
377                assert_eq!(value.into_inner(), v);
378            }
379
380            #[test]
381            fn real_part() {
382                let c1 = ComplexValidated::try_new_validated(Complex::new(1.23, 4.56)).unwrap();
383                assert_eq!(c1.real_part(), 1.23);
384
385                let c2 = ComplexValidated::try_new_validated(Complex::new(-7.89, 0.12)).unwrap();
386                assert_eq!(c2.real_part(), -7.89);
387
388                let c3 = ComplexValidated::try_new_validated(Complex::new(0., 10.)).unwrap();
389                assert_eq!(c3.real_part(), 0.);
390
391                let c_nan_re =
392                    ComplexValidated::try_new_validated(Complex::new(f64::NAN, 5.)).unwrap_err();
393                assert!(matches!(
394                    c_nan_re,
395                    ErrorsValidationRawComplex::InvalidRealPart {
396                        source: ErrorsValidationRawReal::IsNaN { .. }
397                    }
398                ));
399
400                let c_inf_re = ComplexValidated::try_new_validated(Complex::new(f64::INFINITY, 5.))
401                    .unwrap_err();
402                assert!(matches!(
403                    c_inf_re,
404                    ErrorsValidationRawComplex::InvalidRealPart {
405                        source: ErrorsValidationRawReal::IsPosInfinity { .. }
406                    }
407                ));
408
409                let c_neg_inf_re =
410                    ComplexValidated::try_new_validated(Complex::new(f64::NEG_INFINITY, 5.))
411                        .unwrap_err();
412                assert!(matches!(
413                    c_neg_inf_re,
414                    ErrorsValidationRawComplex::InvalidRealPart {
415                        source: ErrorsValidationRawReal::IsNegInfinity { .. }
416                    }
417                ));
418            }
419
420            #[test]
421            fn imag_part() {
422                let c1 = ComplexValidated::try_new_validated(Complex::new(1.23, 4.56)).unwrap();
423                assert_eq!(c1.imag_part(), 4.56);
424
425                let c2 = ComplexValidated::try_new_validated(Complex::new(-7.89, 0.12)).unwrap();
426                assert_eq!(c2.imag_part(), 0.12);
427
428                let c3 = ComplexValidated::try_new_validated(Complex::new(10., 0.)).unwrap();
429                assert_eq!(c3.imag_part(), 0.);
430
431                let c_nan_im =
432                    ComplexValidated::try_new_validated(Complex::new(5., f64::NAN)).unwrap_err();
433                assert!(matches!(
434                    c_nan_im,
435                    ErrorsValidationRawComplex::InvalidImaginaryPart {
436                        source: ErrorsValidationRawReal::IsNaN { .. }
437                    }
438                ));
439
440                let c_inf_im = ComplexValidated::try_new_validated(Complex::new(5., f64::INFINITY))
441                    .unwrap_err();
442                assert!(matches!(
443                    c_inf_im,
444                    ErrorsValidationRawComplex::InvalidImaginaryPart {
445                        source: ErrorsValidationRawReal::IsPosInfinity { .. }
446                    }
447                ));
448
449                let c_neg_inf_im =
450                    ComplexValidated::try_new_validated(Complex::new(5., f64::NEG_INFINITY))
451                        .unwrap_err();
452                assert!(matches!(
453                    c_neg_inf_im,
454                    ErrorsValidationRawComplex::InvalidImaginaryPart {
455                        source: ErrorsValidationRawReal::IsNegInfinity { .. }
456                    }
457                ));
458            }
459
460            #[test]
461            fn try_new_complex() {
462                let r1 = RealValidated::try_new(1.23).unwrap();
463                let i1 = RealValidated::try_new(4.56).unwrap();
464                let c1 = ComplexValidated::try_new_complex(*r1.as_ref(), *i1.as_ref()).unwrap();
465                assert_eq!(c1.real_part(), r1);
466                assert_eq!(c1.imag_part(), i1);
467
468                let r2 = RealValidated::try_new(-7.89).unwrap();
469                let i2 = RealValidated::try_new(-0.12).unwrap();
470                let c2 = ComplexValidated::try_new_complex(*r2.as_ref(), *i2.as_ref()).unwrap();
471                assert_eq!(c2.real_part(), r2);
472                assert_eq!(c2.imag_part(), i2);
473
474                let r3 = RealValidated::try_new(0.).unwrap();
475                let i3 = RealValidated::try_new(0.).unwrap();
476                let c3 = ComplexValidated::try_new_complex(*r3.as_ref(), *i3.as_ref()).unwrap();
477                assert_eq!(c3.real_part(), r3);
478                assert_eq!(c3.real_part(), i3);
479                assert!(c3.is_zero());
480
481                let c_nan_re = ComplexValidated::try_new_complex(f64::NAN, 5.).unwrap_err();
482                assert!(matches!(
483                    c_nan_re,
484                    ErrorsValidationRawComplex::InvalidRealPart { .. }
485                ));
486
487                let c_inf_im = ComplexValidated::try_new_complex(10., f64::INFINITY).unwrap_err();
488                assert!(matches!(
489                    c_inf_im,
490                    ErrorsValidationRawComplex::InvalidImaginaryPart { .. }
491                ));
492
493                let c_nan_re_inf_im =
494                    ComplexValidated::try_new_complex(f64::NAN, f64::INFINITY).unwrap_err();
495                assert!(matches!(
496                    c_nan_re_inf_im,
497                    ErrorsValidationRawComplex::InvalidBothParts { .. }
498                ));
499            }
500
501            #[test]
502            fn try_new_pure_real() {
503                let r1 = RealValidated::try_new(1.23).unwrap();
504                let c1 = ComplexValidated::try_new_pure_real(*r1.as_ref()).unwrap();
505                assert_eq!(c1.real_part(), r1);
506                assert!(c1.imag_part().is_zero());
507
508                let c_nan = ComplexValidated::try_new_pure_real(f64::NAN).unwrap_err();
509                assert!(matches!(
510                    c_nan,
511                    ErrorsValidationRawComplex::InvalidRealPart {
512                        source: ErrorsValidationRawReal::IsNaN { .. }
513                    }
514                ));
515            }
516
517            #[test]
518            fn try_new_pure_imaginary() {
519                let i1 = RealValidated::try_new(1.23).unwrap();
520                let c1 = ComplexValidated::try_new_pure_imaginary(*i1.as_ref()).unwrap();
521                assert!(c1.real_part().is_zero());
522                assert_eq!(c1.imag_part(), i1);
523
524                let c_nan = ComplexValidated::try_new_pure_imaginary(f64::NAN).unwrap_err();
525                assert!(matches!(
526                    c_nan,
527                    ErrorsValidationRawComplex::InvalidImaginaryPart {
528                        source: ErrorsValidationRawReal::IsNaN { .. }
529                    }
530                ));
531            }
532
533            #[test]
534            fn add_to_real_part() {
535                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
536                c.add_to_real_part(&RealValidated::try_new(3.).unwrap());
537                assert_eq!(c.real_part(), 4.);
538                assert_eq!(c.imag_part(), 2.);
539
540                c.add_to_real_part(&RealValidated::try_new(-5.).unwrap());
541                assert_eq!(c.real_part(), -1.);
542                assert_eq!(c.imag_part(), 2.);
543            }
544
545            #[test]
546            fn add_to_imaginary_part() {
547                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
548                c.add_to_imaginary_part(&RealValidated::try_new(3.).unwrap());
549                assert_eq!(c.real_part(), 1.);
550                assert_eq!(c.imag_part(), 5.);
551
552                c.add_to_imaginary_part(&RealValidated::try_new(-4.).unwrap());
553                assert_eq!(c.real_part(), 1.);
554                assert_eq!(c.imag_part(), 1.);
555            }
556
557            #[test]
558            fn multiply_real_part() {
559                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
560                c.multiply_real_part(&RealValidated::try_new(3.).unwrap());
561                assert_eq!(c.real_part(), 3.);
562                assert_eq!(c.imag_part(), 2.);
563
564                c.multiply_real_part(&RealValidated::try_new(-2.).unwrap());
565                assert_eq!(c.real_part(), -6.);
566                assert_eq!(c.imag_part(), 2.);
567            }
568
569            #[test]
570            fn multiply_imaginary_part() {
571                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
572                c.multiply_imaginary_part(&RealValidated::try_new(3.).unwrap());
573                assert_eq!(c.real_part(), 1.);
574                assert_eq!(c.imag_part(), 6.);
575
576                c.multiply_imaginary_part(&RealValidated::try_new(-0.5).unwrap());
577                assert_eq!(c.real_part(), 1.);
578                assert_eq!(c.imag_part(), -3.);
579            }
580
581            #[test]
582            fn set_real_part() {
583                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
584                c.set_real_part(RealValidated::try_new(3.).unwrap());
585                assert_eq!(c.real_part(), 3.);
586                assert_eq!(c.imag_part(), 2.);
587
588                c.set_real_part(RealValidated::try_new(-4.).unwrap());
589                assert_eq!(c.real_part(), -4.);
590                assert_eq!(c.imag_part(), 2.);
591            }
592
593            #[test]
594            fn set_imaginary_part() {
595                let mut c = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
596                c.set_imaginary_part(RealValidated::try_new(3.).unwrap());
597                assert_eq!(c.real_part(), 1.);
598                assert_eq!(c.imag_part(), 3.);
599
600                c.set_imaginary_part(RealValidated::try_new(-4.).unwrap());
601                assert_eq!(c.real_part(), 1.);
602                assert_eq!(c.imag_part(), -4.);
603            }
604        }
605    }
606
607    mod mul {
608        use super::*;
609
610        mod real {
611            use super::*;
612
613            #[test]
614            fn multiply_ref() {
615                let r1 = RealValidated::try_new_validated(3.).unwrap();
616                let r2 = RealValidated::try_new_validated(4.).unwrap();
617                let result = r1 * &r2;
618                assert_eq!(result, RealValidated::try_new_validated(12.).unwrap());
619            }
620        }
621
622        mod complex {
623            use super::*;
624
625            #[test]
626            fn multiply_ref() {
627                let c1 = ComplexValidated::try_new_validated(Complex::new(1., 2.)).unwrap();
628                let c2 = ComplexValidated::try_new_validated(Complex::new(3., 4.)).unwrap();
629                let result = c1 * &c2;
630                assert_eq!(
631                    result,
632                    ComplexValidated::try_new_validated(Complex::new(-5., 10.)).unwrap()
633                ); // (1*3 - 2*4) + (1*4 + 2*3)i
634            }
635
636            #[test]
637            fn complex_times_real() {
638                let r = RealValidated::try_new_validated(2.).unwrap();
639                let c = ComplexValidated::try_new_validated(Complex::new(3., 4.)).unwrap();
640
641                let result_expected =
642                    ComplexValidated::try_new_validated(Complex::new(6., 8.)).unwrap(); // 2 * (3 + 4i) = 6 + 8i
643
644                let result = c.clone() * &r;
645                assert_eq!(&result, &result_expected);
646
647                let result = c.clone() * r.clone();
648                assert_eq!(&result, &result_expected);
649
650                let mut result = c.clone();
651                result *= &r;
652                assert_eq!(&result, &result_expected);
653
654                let mut result = c.clone();
655                result *= r;
656                assert_eq!(&result, &result_expected);
657            }
658
659            #[test]
660            fn real_times_complex() {
661                let r = RealValidated::try_new_validated(2.).unwrap();
662                let c = ComplexValidated::try_new_validated(Complex::new(3., 4.)).unwrap();
663
664                let result_expected =
665                    ComplexValidated::try_new_validated(Complex::new(6., 8.)).unwrap(); // 2 * (3 + 4i) = 6 + 8i
666
667                let result = &r * c.clone();
668                assert_eq!(&result, &result_expected);
669
670                let result = r * c.clone();
671                assert_eq!(&result, &result_expected);
672            }
673        }
674    }
675
676    mod arithmetic {
677        use super::*;
678
679        mod real {
680            use super::*;
681
682            #[test]
683            fn add() {
684                let r1 = RealValidated::try_new_validated(3.).unwrap();
685                let r2 = RealValidated::try_new_validated(4.).unwrap();
686
687                let expected_result = RealValidated::try_new_validated(7.).unwrap();
688
689                let result = r1.clone().add(&r2);
690                assert_eq!(result, expected_result);
691
692                let result = r1.clone().add(r2.clone());
693                assert_eq!(result, expected_result);
694
695                let result = (&r1).add(r2.clone());
696                assert_eq!(result, expected_result);
697
698                let result = (&r1).add(&r2);
699                assert_eq!(result, expected_result);
700
701                let mut result = r1.clone();
702                result.add_assign(&r2);
703                assert_eq!(result, expected_result);
704
705                let mut result = r1.clone();
706                result.add_assign(r2);
707                assert_eq!(result, expected_result);
708            }
709
710            #[test]
711            fn sub() {
712                let r1 = RealValidated::try_new_validated(3.).unwrap();
713                let r2 = RealValidated::try_new_validated(4.).unwrap();
714
715                let expected_result = RealValidated::try_new_validated(-1.).unwrap();
716
717                let result = r1.clone().sub(&r2);
718                assert_eq!(result, expected_result);
719
720                let result = r1.clone().sub(r2.clone());
721                assert_eq!(result, expected_result);
722
723                let result = (&r1).sub(r2.clone());
724                assert_eq!(result, expected_result);
725
726                let result = (&r1).sub(&r2);
727                assert_eq!(result, expected_result);
728
729                let mut result = r1.clone();
730                result.sub_assign(&r2);
731                assert_eq!(result, expected_result);
732
733                let mut result = r1.clone();
734                result.sub_assign(r2);
735                assert_eq!(result, expected_result);
736            }
737
738            #[test]
739            fn mul() {
740                let r1 = RealValidated::try_new_validated(3.).unwrap();
741                let r2 = RealValidated::try_new_validated(4.).unwrap();
742
743                let expected_result = RealValidated::try_new_validated(12.).unwrap();
744
745                let result = r1.clone().mul(&r2);
746                assert_eq!(result, expected_result);
747
748                let result = r1.clone().mul(r2.clone());
749                assert_eq!(result, expected_result);
750
751                let result = (&r1).mul(r2.clone());
752                assert_eq!(result, expected_result);
753
754                let result = (&r1).mul(&r2);
755                assert_eq!(result, expected_result);
756
757                let mut result = r1.clone();
758                result.mul_assign(&r2);
759                assert_eq!(result, expected_result);
760
761                let mut result = r1.clone();
762                result.mul_assign(r2);
763                assert_eq!(result, expected_result);
764            }
765
766            #[test]
767            fn div() {
768                let r1 = RealValidated::try_new_validated(3.).unwrap();
769                let r2 = RealValidated::try_new_validated(4.).unwrap();
770
771                let expected_result = RealValidated::try_new_validated(0.75).unwrap();
772
773                let result = r1.clone().div(&r2);
774                assert_eq!(result, expected_result);
775
776                let result = r1.clone().div(r2.clone());
777                assert_eq!(result, expected_result);
778
779                let result = (&r1).div(r2.clone());
780                assert_eq!(result, expected_result);
781
782                let result = (&r1).div(&r2);
783                assert_eq!(result, expected_result);
784
785                let mut result = r1.clone();
786                result.div_assign(&r2);
787                assert_eq!(result, expected_result);
788
789                let mut result = r1.clone();
790                result.div_assign(r2);
791                assert_eq!(result, expected_result);
792            }
793
794            #[test]
795            fn neg() {
796                let num = RealValidated::try_new_validated(1.).unwrap();
797                let expected = RealValidated::try_new_validated(-1.).unwrap();
798                assert_eq!(num.neg(), expected);
799            }
800
801            #[test]
802            fn neg_assign() {
803                let mut num = 1.;
804                num.neg_assign();
805                let expected = -1.;
806                assert_eq!(&num, &expected);
807
808                let mut num = RealValidated::one();
809                num.neg_assign();
810                let expected = RealValidated::try_new_validated(-1.).unwrap();
811                assert_eq!(&num, &expected);
812            }
813
814            #[test]
815            #[should_panic(expected = "Division failed validation")]
816            fn div_by_zero() {
817                let one = RealValidated::one();
818                let zero = RealValidated::zero();
819                let _ = &one / &zero;
820            }
821
822            #[test]
823            #[should_panic(expected = "Division failed validation")]
824            fn div_assign_by_zero() {
825                let mut num = RealValidated::one();
826                let zero_ref = &RealValidated::zero();
827                num /= zero_ref;
828            }
829
830            #[test]
831            fn mul_add() {
832                let a = RealValidated::try_new(2.0).unwrap();
833                let b = RealValidated::try_new(3.0).unwrap();
834                let c = RealValidated::try_new(4.0).unwrap();
835                // 2*3 + 4 = 10
836                assert_eq!(a.mul_add_ref(&b, &c), RealValidated::try_new(10.0).unwrap());
837            }
838        }
839
840        mod complex {
841            use super::*;
842
843            #[test]
844            fn add() {
845                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
846                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
847
848                let expected_result =
849                    ComplexValidated::try_new_validated(Complex::new(6., -1.)).unwrap();
850
851                let result = r1.clone().add(&r2);
852                assert_eq!(result, expected_result);
853
854                let result = r1.clone().add(r2.clone());
855                assert_eq!(result, expected_result);
856
857                let result = (&r1).add(r2.clone());
858                assert_eq!(result, expected_result);
859
860                let result = (&r1).add(&r2);
861                assert_eq!(result, expected_result);
862
863                let mut result = r1.clone();
864                result.add_assign(&r2);
865                assert_eq!(result, expected_result);
866
867                let mut result = r1.clone();
868                result.add_assign(r2);
869                assert_eq!(result, expected_result);
870            }
871
872            #[test]
873            fn sub() {
874                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
875                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
876
877                let expected_result =
878                    ComplexValidated::try_new_validated(Complex::new(-2., 7.)).unwrap();
879
880                let result = r1.clone().sub(&r2);
881                assert_eq!(result, expected_result);
882
883                let result = r1.clone().sub(r2.clone());
884                assert_eq!(result, expected_result);
885
886                let result = (&r1).sub(r2.clone());
887                assert_eq!(result, expected_result);
888
889                let result = (&r1).sub(&r2);
890                assert_eq!(result, expected_result);
891
892                let mut result = r1.clone();
893                result.sub_assign(&r2);
894                assert_eq!(result, expected_result);
895
896                let mut result = r1.clone();
897                result.sub_assign(r2);
898                assert_eq!(result, expected_result);
899            }
900
901            #[test]
902            fn mul() {
903                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
904                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
905
906                let expected_result =
907                    ComplexValidated::try_new_validated(Complex::new(20., 4.)).unwrap();
908
909                let result = r1.clone().mul(&r2);
910                assert_eq!(result, expected_result);
911
912                let result = r1.clone().mul(r2.clone());
913                assert_eq!(result, expected_result);
914
915                let result = (&r1).mul(r2.clone());
916                assert_eq!(result, expected_result);
917
918                let result = (&r1).mul(&r2);
919                assert_eq!(result, expected_result);
920
921                let mut result = r1.clone();
922                result.mul_assign(&r2);
923                assert_eq!(result, expected_result);
924
925                let mut result = r1.clone();
926                result.mul_assign(r2);
927                assert_eq!(result, expected_result);
928            }
929
930            #[test]
931            fn div() {
932                let r1 = ComplexValidated::try_new_validated(Complex::new(2., 3.)).unwrap();
933                let r2 = ComplexValidated::try_new_validated(Complex::new(4., -4.)).unwrap();
934
935                let expected_result =
936                    ComplexValidated::try_new_validated(Complex::new(-0.125, 0.625)).unwrap();
937
938                let result = r1.clone().div(&r2);
939                assert_eq!(result, expected_result);
940
941                let result = r1.clone().div(r2.clone());
942                assert_eq!(result, expected_result);
943
944                let result = (&r1).div(r2.clone());
945                assert_eq!(result, expected_result);
946
947                let result = (&r1).div(&r2);
948                assert_eq!(result, expected_result);
949
950                let mut result = r1.clone();
951                result.div_assign(&r2);
952                assert_eq!(result, expected_result);
953
954                let mut result = r1.clone();
955                result.div_assign(r2);
956                assert_eq!(result, expected_result);
957            }
958
959            #[test]
960            fn neg() {
961                let v = Complex::new(1., 2.);
962
963                let num = ComplexValidated::try_new_validated(v).unwrap();
964                let expected = Complex::new(-1., -2.);
965                assert_eq!(num.neg().into_inner(), expected);
966            }
967
968            #[test]
969            fn neg_assign() {
970                let v = Complex::new(1., 2.);
971
972                let mut num = ComplexValidated::try_new_validated(v).unwrap();
973                let expected = Complex::new(-1., -2.);
974                num.neg_assign();
975                assert_eq!(num.as_ref(), &expected);
976            }
977
978            #[test]
979            #[should_panic(expected = "Division failed validation")]
980            fn div_by_zero() {
981                let one = ComplexValidated::one();
982                let zero = ComplexValidated::zero();
983                let _ = &one / &zero;
984            }
985
986            #[test]
987            #[should_panic(expected = "Division failed validation")]
988            fn div_assign_by_zero() {
989                let mut num = ComplexValidated::one();
990                let zero_ref = &ComplexValidated::zero();
991                num /= zero_ref;
992            }
993
994            #[test]
995            fn mul_add() {
996                let ca = ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap();
997                let cb = ComplexValidated::try_new(Complex::new(3.0, 4.0)).unwrap();
998                let cc = ComplexValidated::try_new(Complex::new(5.0, 6.0)).unwrap();
999                // (1+2i)*(3+4i) + (5+6i) = (3+4i+6i-8) + (5+6i) = (-5+10i) + (5+6i) = 0+16i
1000                let expected = ComplexValidated::try_new(Complex::new(0.0, 16.0)).unwrap();
1001                assert_eq!(ca.mul_add_ref(&cb, &cc), expected);
1002            }
1003        }
1004    }
1005
1006    mod real_scalar_methods {
1007        use super::*;
1008
1009        #[test]
1010        fn test_constants() {
1011            assert_eq!(<RealValidated as Constants>::epsilon(), f64::EPSILON);
1012            assert_eq!(<RealValidated as Constants>::negative_one(), -1.0);
1013            assert_eq!(<RealValidated as Constants>::one_div_2(), 0.5);
1014            assert_eq!(<RealValidated as Constants>::two(), 2.0);
1015            assert_eq!(<RealValidated as Constants>::max_finite(), f64::MAX);
1016            assert_eq!(<RealValidated as Constants>::min_finite(), f64::MIN);
1017            assert_eq!(<RealValidated as Constants>::pi(), std::f64::consts::PI);
1018            assert_eq!(
1019                <RealValidated as Constants>::two_pi(),
1020                std::f64::consts::PI * 2.0
1021            );
1022            assert_eq!(
1023                <RealValidated as Constants>::pi_div_2(),
1024                std::f64::consts::FRAC_PI_2
1025            );
1026            assert_eq!(<RealValidated as Constants>::ln_2(), std::f64::consts::LN_2);
1027            assert_eq!(
1028                <RealValidated as Constants>::ln_10(),
1029                std::f64::consts::LN_10
1030            );
1031            assert_eq!(
1032                <RealValidated as Constants>::log10_2(),
1033                std::f64::consts::LOG10_2
1034            );
1035            assert_eq!(
1036                <RealValidated as Constants>::log2_10(),
1037                std::f64::consts::LOG2_10
1038            );
1039            assert_eq!(
1040                <RealValidated as Constants>::log2_e(),
1041                std::f64::consts::LOG2_E
1042            );
1043            assert_eq!(
1044                <RealValidated as Constants>::log10_e(),
1045                std::f64::consts::LOG10_E
1046            );
1047            assert_eq!(<RealValidated as Constants>::e(), std::f64::consts::E);
1048        }
1049
1050        #[test]
1051        fn round_ties_even() {
1052            let f = RealValidated::try_new(3.3).unwrap();
1053            let g = RealValidated::try_new(-3.3).unwrap();
1054            let h = RealValidated::try_new(3.5).unwrap();
1055            let i = RealValidated::try_new(4.5).unwrap();
1056            let j = RealValidated::try_new(-3.5).unwrap();
1057            let k = RealValidated::try_new(-4.5).unwrap();
1058
1059            assert_eq!(
1060                f.kernel_round_ties_even(),
1061                RealValidated::try_new(3.0).unwrap()
1062            );
1063            assert_eq!(
1064                g.kernel_round_ties_even(),
1065                RealValidated::try_new(-3.0).unwrap()
1066            );
1067            assert_eq!(
1068                h.kernel_round_ties_even(),
1069                RealValidated::try_new(4.0).unwrap()
1070            );
1071            assert_eq!(
1072                i.kernel_round_ties_even(),
1073                RealValidated::try_new(4.0).unwrap()
1074            );
1075            assert_eq!(
1076                j.kernel_round_ties_even(),
1077                RealValidated::try_new(-4.0).unwrap()
1078            );
1079            assert_eq!(
1080                k.kernel_round_ties_even(),
1081                RealValidated::try_new(-4.0).unwrap()
1082            );
1083        }
1084
1085        #[test]
1086        fn classify() {
1087            let normal = RealValidated::try_new(1.0).unwrap();
1088            assert_eq!(normal.kernel_classify(), FpCategory::Normal);
1089
1090            let zero = RealValidated::zero();
1091            assert_eq!(zero.kernel_classify(), FpCategory::Zero);
1092
1093            // Subnormals, Infinite and NaN are not constructible with StrictFinitePolicy
1094
1095            let subnormal_err = RealValidated::try_new(f64::MIN_POSITIVE / 2.).unwrap_err();
1096            assert!(matches!(
1097                subnormal_err,
1098                ErrorsValidationRawReal::IsSubnormal { .. }
1099            ));
1100
1101            let pos_inf_err = RealValidated::try_new(f64::INFINITY).unwrap_err();
1102            assert!(matches!(
1103                pos_inf_err,
1104                ErrorsValidationRawReal::IsPosInfinity { .. }
1105            ));
1106
1107            let neg_inf_err = RealValidated::try_new(f64::NEG_INFINITY).unwrap_err();
1108            assert!(matches!(
1109                neg_inf_err,
1110                ErrorsValidationRawReal::IsNegInfinity { .. }
1111            ));
1112
1113            let nan_err = RealValidated::try_new(f64::NAN).unwrap_err();
1114            assert!(matches!(nan_err, ErrorsValidationRawReal::IsNaN { .. }));
1115        }
1116
1117        #[test]
1118        fn try_from_f64_valid() {
1119            let val = RealValidated::try_from_f64(123.45).unwrap();
1120            assert_eq!(val.as_ref(), &123.45);
1121        }
1122
1123        #[test]
1124        fn try_from_f64_invalid() {
1125            let err = RealValidated::try_from_f64(f64::NAN).unwrap_err();
1126            assert!(matches!(
1127                err,
1128                ErrorsTryFromf64::Output {
1129                    source: ErrorsValidationRawReal::IsNaN { .. }
1130                }
1131            ));
1132        }
1133
1134        #[test]
1135        fn rounding_and_trunc() {
1136            let val1 = RealValidated::try_new(3.7).unwrap();
1137            let val2 = RealValidated::try_new(-3.7).unwrap();
1138
1139            assert_eq!(
1140                val1.clone().kernel_ceil(),
1141                RealValidated::try_new(4.0).unwrap()
1142            );
1143            assert_eq!(
1144                val2.clone().kernel_ceil(),
1145                RealValidated::try_new(-3.0).unwrap()
1146            );
1147
1148            assert_eq!(
1149                val1.clone().kernel_floor(),
1150                RealValidated::try_new(3.0).unwrap()
1151            );
1152            assert_eq!(
1153                val2.clone().kernel_floor(),
1154                RealValidated::try_new(-4.0).unwrap()
1155            );
1156
1157            assert_eq!(
1158                val1.clone().kernel_round(),
1159                RealValidated::try_new(4.0).unwrap()
1160            );
1161            assert_eq!(
1162                val2.clone().kernel_round(),
1163                RealValidated::try_new(-4.0).unwrap()
1164            );
1165
1166            assert_eq!(
1167                val1.clone().kernel_trunc(),
1168                RealValidated::try_new(3.0).unwrap()
1169            );
1170            assert_eq!(
1171                val2.clone().kernel_trunc(),
1172                RealValidated::try_new(-3.0).unwrap()
1173            );
1174
1175            // Using a tolerance for fract_ due to floating point representation
1176            let frac1 = val1.kernel_fract();
1177            assert!((frac1.as_ref() - 0.7).abs() < 1e-9);
1178
1179            let frac2 = val2.kernel_fract();
1180            assert!((frac2.as_ref() - (-0.7)).abs() < 1e-9);
1181        }
1182
1183        #[test]
1184        fn sign_and_constants() {
1185            let pos = RealValidated::try_new(5.0).unwrap();
1186            let neg = RealValidated::try_new(-5.0).unwrap();
1187            let zero = RealValidated::zero();
1188
1189            assert!(pos.kernel_is_sign_positive());
1190            assert!(!pos.kernel_is_sign_negative());
1191
1192            assert!(!neg.kernel_is_sign_positive());
1193            assert!(neg.kernel_is_sign_negative());
1194
1195            assert!(zero.kernel_is_sign_positive()); // +0.0 is positive
1196            assert!(!zero.kernel_is_sign_negative());
1197
1198            let neg_zero = RealValidated::try_new(-0.0).unwrap();
1199            assert!(!neg_zero.kernel_is_sign_positive());
1200            assert!(neg_zero.kernel_is_sign_negative());
1201
1202            assert_eq!(pos.clone().kernel_copysign(&neg), neg);
1203            assert_eq!(neg.clone().kernel_copysign(&pos), pos);
1204
1205            assert_eq!(
1206                RealValidated::one_div_2(),
1207                RealValidated::try_new(0.5).unwrap()
1208            );
1209            assert_eq!(RealValidated::two(), RealValidated::try_new(2.0).unwrap());
1210            assert_eq!(
1211                RealValidated::max_finite(),
1212                RealValidated::try_new(f64::MAX).unwrap()
1213            );
1214            assert_eq!(
1215                RealValidated::min_finite(),
1216                RealValidated::try_new(f64::MIN).unwrap()
1217            );
1218        }
1219
1220        #[test]
1221        fn epsilon() {
1222            let eps = RealValidated::epsilon();
1223            assert!(eps.is_finite() && eps > RealValidated::zero());
1224            let expected_eps_val = 2.0f64.pow(-52);
1225            let expected_eps = RealValidated::try_new(expected_eps_val).unwrap();
1226            assert_eq!(eps, expected_eps, "Epsilon value mismatch");
1227        }
1228
1229        #[test]
1230        fn clamp() {
1231            let val = RealValidated::try_new(5.).unwrap();
1232            let min_val = RealValidated::try_new(0.).unwrap();
1233            let max_val = RealValidated::try_new(10.).unwrap();
1234
1235            assert_eq!(val.clone().kernel_clamp(&min_val, &max_val), val);
1236            assert_eq!(
1237                RealValidated::try_new(-5.)
1238                    .unwrap()
1239                    .kernel_clamp(&min_val, &max_val),
1240                min_val
1241            );
1242            assert_eq!(
1243                RealValidated::try_new(15.)
1244                    .unwrap()
1245                    .kernel_clamp(&min_val, &max_val),
1246                max_val
1247            );
1248        }
1249
1250        #[test]
1251        fn hypot() {
1252            let a = RealValidated::try_new(3.).unwrap();
1253            let b = RealValidated::try_new(4.).unwrap();
1254            let expected = RealValidated::try_new(5.).unwrap();
1255            assert_eq!(a.kernel_hypot(&b), expected);
1256        }
1257
1258        #[test]
1259        fn signum() {
1260            assert_eq!(
1261                RealValidated::try_new(5.).unwrap().kernel_signum(),
1262                RealValidated::one()
1263            );
1264            assert_eq!(
1265                RealValidated::try_new(-5.).unwrap().kernel_signum(),
1266                RealValidated::negative_one()
1267            );
1268            // rug::Float::signum of 0. is 1.
1269            assert_eq!(RealValidated::zero().kernel_signum(), RealValidated::one());
1270        }
1271
1272        #[test]
1273        fn total_cmp() {
1274            let r1 = RealValidated::try_new(1.).unwrap();
1275            let r2 = RealValidated::try_new(2.).unwrap();
1276            assert_eq!(r1.total_cmp(&r1), Ordering::Equal);
1277            assert_eq!(r1.total_cmp(&r2), Ordering::Less);
1278            assert_eq!(r2.total_cmp(&r1), Ordering::Greater);
1279        }
1280
1281        #[test]
1282        fn mul_add_mul_mut() {
1283            let mut a = RealValidated::try_new(2.).unwrap();
1284            let b = RealValidated::try_new(3.).unwrap(); // mul
1285            let c = RealValidated::try_new(4.).unwrap(); // add_mul1
1286            let d = RealValidated::try_new(5.).unwrap(); // add_mul2
1287            // Expected: a = a*b + c*d = 2*3 + 4*5 = 6 + 20 = 26
1288            a.kernel_mul_add_mul_mut(&b, &c, &d);
1289            assert_eq!(a, RealValidated::try_new(26.).unwrap());
1290        }
1291
1292        #[test]
1293        fn mul_sub_mul_mut() {
1294            let mut a = RealValidated::try_new(10.).unwrap();
1295            let b = RealValidated::try_new(2.).unwrap(); // mul
1296            let c = RealValidated::try_new(3.).unwrap(); // sub_mul1
1297            let d = RealValidated::try_new(4.).unwrap(); // sub_mul2
1298            // Expected: a = a*b - c*d = 10*2 - 3*4 = 20 - 12 = 8
1299            a.kernel_mul_sub_mul_mut(&b, &c, &d);
1300            assert_eq!(a, RealValidated::try_new(8.).unwrap());
1301        }
1302    }
1303
1304    mod complex_scalar_methods {
1305        use super::*;
1306        use crate::functions::{ArgErrors, ArgInputErrors};
1307
1308        #[test]
1309        fn conjugate() {
1310            let c = ComplexValidated::try_new(Complex::new(1., 2.)).unwrap();
1311            let expected = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1312            assert_eq!(c.conjugate(), expected);
1313
1314            let c_real = ComplexValidated::try_new_pure_real(5.).unwrap();
1315            assert_eq!(c_real.clone().conjugate(), c_real);
1316
1317            let c_imag = ComplexValidated::try_new_pure_imaginary(3.).unwrap();
1318            let expected_imag = ComplexValidated::try_new_pure_imaginary(-3.).unwrap();
1319            assert_eq!(c_imag.conjugate(), expected_imag);
1320        }
1321
1322        #[test]
1323        fn arg_valid() {
1324            // arg(1 + 0i) = 0
1325            let c1 = ComplexValidated::one();
1326            assert_eq!(c1.arg(), RealValidated::zero());
1327
1328            // arg(0 + i) = PI/2
1329            let c2 = ComplexValidated::try_new_pure_imaginary(1.0).unwrap();
1330            let pi_div_2 = RealValidated::try_new(FRAC_PI_2).unwrap();
1331            assert_eq!(c2.arg(), pi_div_2);
1332
1333            // arg(-1 + 0i) = PI
1334            let c3 = ComplexValidated::try_new_pure_real(-1.0).unwrap();
1335            let pi = RealValidated::try_new(PI).unwrap();
1336            assert_eq!(c3.arg(), pi);
1337
1338            // arg(1 + i) = PI/4
1339            let c4 = ComplexValidated::try_new(Complex::new(1.0, 1.0)).unwrap();
1340            let pi_div_4 = RealValidated::try_new(FRAC_PI_4).unwrap();
1341            assert_eq!(c4.arg(), pi_div_4);
1342        }
1343
1344        #[test]
1345        fn arg_zero() {
1346            let zero = ComplexValidated::zero();
1347            let res = zero.try_arg();
1348            assert!(matches!(
1349                res,
1350                Err(ArgErrors::Input {
1351                    source: ArgInputErrors::Zero { .. }
1352                })
1353            ));
1354        }
1355    }
1356
1357    mod function_traits {
1358        use super::*;
1359        use crate::functions::{
1360            ATan2InputErrors, LogarithmRealErrors, LogarithmRealInputErrors,
1361            PowComplexBaseRealExponentInputErrors, PowRealBaseRealExponentInputErrors,
1362            ReciprocalInputErrors, SqrtRealInputErrors,
1363        };
1364
1365        mod min_max {
1366            use super::*;
1367
1368            #[test]
1369            fn max_valid() {
1370                let r1 = RealValidated::try_new(3.).unwrap();
1371                let r2 = RealValidated::try_new(4.).unwrap();
1372                assert_eq!(r1.max(&r2), &r2);
1373                assert_eq!(r2.max(&r1), &r2);
1374            }
1375
1376            #[test]
1377            fn min_valid() {
1378                let r1 = RealValidated::try_new(3.).unwrap();
1379                let r2 = RealValidated::try_new(4.).unwrap();
1380                assert_eq!(r1.min(&r2), &r1);
1381                assert_eq!(r2.min(&r1), &r1);
1382            }
1383        }
1384
1385        mod exp {
1386            use super::*;
1387
1388            mod real {
1389                use super::*;
1390
1391                #[test]
1392                fn exp_valid() {
1393                    let exponent = RealValidated::try_new(1.).unwrap();
1394                    let expected = std::f64::consts::E;
1395                    assert_eq!(exponent.clone().try_exp().unwrap().as_ref(), &expected);
1396                    assert_eq!(exponent.clone().exp().as_ref(), &expected);
1397                }
1398
1399                #[test]
1400                fn exp_m1_valid() {
1401                    let exponent = RealValidated::try_new(1.).unwrap();
1402                    let expected = if cfg!(target_arch = "x86_64") {
1403                        1.718281828459045
1404                    } else if cfg!(target_arch = "aarch64") {
1405                        1.7182818284590453
1406                    } else {
1407                        todo!("Not implemented for this architecture");
1408                    };
1409                    assert_eq!(exponent.clone().kernel_exp_m1().as_ref(), &expected);
1410                }
1411
1412                #[test]
1413                fn exp_overflow() {
1414                    let large_val = RealValidated::try_new(1.0e60).unwrap(); // exp(1.0e60) is very large
1415                    let res_large = large_val.try_exp();
1416                    assert!(matches!(
1417                        res_large,
1418                        Err(ExpErrors::Output {
1419                            source: ErrorsValidationRawReal::IsPosInfinity { .. }
1420                        })
1421                    ),);
1422                }
1423            } // end mod 
1424
1425            mod complex {
1426                use super::*;
1427
1428                #[test]
1429                fn exp_valid() {
1430                    let exponent = ComplexValidated::try_new(Complex::new(0., PI)).unwrap();
1431                    let expected = Complex::new(-1., 1.2246467991473532e-16);
1432                    assert_eq!(exponent.clone().try_exp().unwrap().as_ref(), &expected);
1433                    assert_eq!(exponent.clone().exp().as_ref(), &expected);
1434                }
1435            } // end mod complex
1436        } // end mod exp
1437
1438        mod logarithm {
1439            use super::*;
1440
1441            mod real {
1442                use super::*;
1443
1444                #[test]
1445                fn ln_valid() {
1446                    let e = RealValidated::one().exp();
1447                    let expected = 1.0;
1448                    assert_eq!(e.clone().try_ln().unwrap().as_ref(), &expected);
1449                    assert_eq!(e.clone().ln().as_ref(), &expected);
1450                }
1451
1452                #[test]
1453                fn log10_valid() {
1454                    let v = RealValidated::try_new(100.).unwrap();
1455                    let expected = 2.0;
1456                    assert_eq!(v.clone().try_log10().unwrap().as_ref(), &expected);
1457                    assert_eq!(v.clone().log10().as_ref(), &expected);
1458                }
1459
1460                #[test]
1461                fn log2_valid() {
1462                    let v = RealValidated::try_new(4.).unwrap();
1463                    let expected = 2.0;
1464                    assert_eq!(v.clone().try_log2().unwrap().as_ref(), &expected);
1465                    assert_eq!(v.clone().log2().as_ref(), &expected);
1466                }
1467
1468                #[test]
1469                fn ln_1p_valid() {
1470                    // v = e - 1;
1471                    let v = RealValidated::one().exp() - RealValidated::one();
1472
1473                    // ln(1 + v) = ln(1 + e - 1) = ln(e) = 1
1474                    assert_eq!(v.clone().kernel_ln_1p().as_ref(), &1.);
1475                }
1476
1477                #[test]
1478                fn ln_domain_errors() {
1479                    let neg_val = RealValidated::try_new(-1.).unwrap();
1480                    assert!(matches!(
1481                        neg_val.try_ln(),
1482                        Err(LogarithmRealErrors::Input {
1483                            source: LogarithmRealInputErrors::NegativeArgument { .. }
1484                        })
1485                    ));
1486
1487                    let zero_val = RealValidated::zero();
1488                    assert!(matches!(
1489                        zero_val.try_ln(),
1490                        Err(LogarithmRealErrors::Input {
1491                            source: LogarithmRealInputErrors::ZeroArgument { .. }
1492                        })
1493                    ));
1494                }
1495
1496                #[test]
1497                fn log10_domain_errors() {
1498                    let neg_val = RealValidated::try_new(-1.).unwrap();
1499                    assert!(matches!(
1500                        neg_val.try_log10(),
1501                        Err(LogarithmRealErrors::Input {
1502                            source: LogarithmRealInputErrors::NegativeArgument { .. }
1503                        })
1504                    ));
1505
1506                    let zero_val = RealValidated::zero();
1507                    assert!(matches!(
1508                        zero_val.try_log10(),
1509                        Err(LogarithmRealErrors::Input {
1510                            source: LogarithmRealInputErrors::ZeroArgument { .. }
1511                        })
1512                    ));
1513                }
1514
1515                #[test]
1516                fn log2_domain_errors() {
1517                    let neg_val = RealValidated::try_new(-1.).unwrap();
1518                    assert!(matches!(
1519                        neg_val.try_log2(),
1520                        Err(LogarithmRealErrors::Input {
1521                            source: LogarithmRealInputErrors::NegativeArgument { .. }
1522                        })
1523                    ));
1524
1525                    let zero_val = RealValidated::zero();
1526                    assert!(matches!(
1527                        zero_val.try_log2(),
1528                        Err(LogarithmRealErrors::Input {
1529                            source: LogarithmRealInputErrors::ZeroArgument { .. }
1530                        })
1531                    ));
1532                }
1533            } // end mod real
1534
1535            mod complex {
1536                use super::*;
1537
1538                #[test]
1539                fn ln_valid() {
1540                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1541                    let expected = Complex::new(0.8047189562170503, -1.1071487177940904);
1542                    assert_eq!(v.clone().try_ln().unwrap().as_ref(), &expected);
1543                    assert_eq!(v.clone().ln().as_ref(), &expected);
1544                }
1545
1546                #[test]
1547                fn log10_valid() {
1548                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1549                    let expected = Complex::new(0.3494850021680094, -0.480828578784234);
1550                    assert_eq!(v.clone().try_log10().unwrap().as_ref(), &expected);
1551                    assert_eq!(v.clone().log10().as_ref(), &expected);
1552                }
1553
1554                #[test]
1555                fn log2_valid() {
1556                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1557                    let expected = Complex::new(1.1609640474436813, -1.5972779646881088);
1558                    assert_eq!(v.clone().try_log2().unwrap().as_ref(), &expected);
1559                    assert_eq!(v.clone().log2().as_ref(), &expected);
1560                }
1561
1562                #[test]
1563                fn ln_zero() {
1564                    let zero_val = ComplexValidated::zero();
1565                    assert!(matches!(
1566                        zero_val.try_ln(),
1567                        Err(LogarithmComplexErrors::Input {
1568                            source: LogarithmComplexInputErrors::ZeroArgument { .. }
1569                        })
1570                    ));
1571                }
1572
1573                #[test]
1574                fn log10_zero() {
1575                    let zero_val = ComplexValidated::zero();
1576                    assert!(matches!(
1577                        zero_val.try_log10(),
1578                        Err(LogarithmComplexErrors::Input {
1579                            source: LogarithmComplexInputErrors::ZeroArgument { .. }
1580                        })
1581                    ));
1582                }
1583
1584                #[test]
1585                fn log2_zero() {
1586                    let zero_val = ComplexValidated::zero();
1587                    assert!(matches!(
1588                        zero_val.try_log2(),
1589                        Err(LogarithmComplexErrors::Input {
1590                            source: LogarithmComplexInputErrors::ZeroArgument { .. }
1591                        })
1592                    ));
1593                }
1594            } // end mod complex
1595        } // end mod logarithm
1596
1597        mod pow {
1598            use super::*;
1599
1600            mod real_base {
1601                use super::*;
1602
1603                #[test]
1604                fn negative_base_real_exponent_error() {
1605                    let base = RealValidated::try_new(-2.).unwrap();
1606                    let exponent = RealValidated::try_new(0.5).unwrap();
1607                    let res = base.try_pow(&exponent);
1608                    assert!(matches!(
1609                        res,
1610                        Err(PowRealBaseRealExponentErrors::Input {
1611                            source: PowRealBaseRealExponentInputErrors::NegativeBase { .. }
1612                        })
1613                    ));
1614                }
1615
1616                #[test]
1617                fn real_base_uint_exponent_valid() {
1618                    let base = RealValidated::try_new(2.).unwrap();
1619                    assert_eq!(
1620                        base.clone().try_pow(3u8).unwrap(),
1621                        RealValidated::try_new(8.).unwrap()
1622                    );
1623                    assert_eq!(
1624                        base.clone().try_pow(3u16).unwrap(),
1625                        RealValidated::try_new(8.).unwrap()
1626                    );
1627                    assert_eq!(
1628                        base.clone().try_pow(3u32).unwrap(),
1629                        RealValidated::try_new(8.).unwrap()
1630                    );
1631                    assert_eq!(
1632                        base.clone().try_pow(3u64).unwrap(),
1633                        RealValidated::try_new(8.).unwrap()
1634                    );
1635                    assert_eq!(
1636                        base.clone().try_pow(3u128).unwrap(),
1637                        RealValidated::try_new(8.).unwrap()
1638                    );
1639                    assert_eq!(
1640                        base.clone().try_pow(3usize).unwrap(),
1641                        RealValidated::try_new(8.).unwrap()
1642                    );
1643
1644                    assert_eq!(base.clone().pow(3u8), RealValidated::try_new(8.).unwrap());
1645                    assert_eq!(base.clone().pow(3u16), RealValidated::try_new(8.).unwrap());
1646                    assert_eq!(base.clone().pow(3u32), RealValidated::try_new(8.).unwrap());
1647                    assert_eq!(base.clone().pow(3u64), RealValidated::try_new(8.).unwrap());
1648                    assert_eq!(base.clone().pow(3u128), RealValidated::try_new(8.).unwrap());
1649                    assert_eq!(
1650                        base.clone().pow(3usize),
1651                        RealValidated::try_new(8.).unwrap()
1652                    );
1653                }
1654
1655                #[test]
1656                fn real_base_int_exponent_valid() {
1657                    let base = RealValidated::try_new(2.).unwrap();
1658                    assert_eq!(
1659                        base.clone().try_pow(3i8).unwrap(),
1660                        RealValidated::try_new(8.).unwrap()
1661                    );
1662                    assert_eq!(
1663                        base.clone().try_pow(3i16).unwrap(),
1664                        RealValidated::try_new(8.).unwrap()
1665                    );
1666                    assert_eq!(
1667                        base.clone().try_pow(3i32).unwrap(),
1668                        RealValidated::try_new(8.).unwrap()
1669                    );
1670                    assert_eq!(
1671                        base.clone().try_pow(3i64).unwrap(),
1672                        RealValidated::try_new(8.).unwrap()
1673                    );
1674                    assert_eq!(
1675                        base.clone().try_pow(3i128).unwrap(),
1676                        RealValidated::try_new(8.).unwrap()
1677                    );
1678                    assert_eq!(
1679                        base.clone().try_pow(3isize).unwrap(),
1680                        RealValidated::try_new(8.).unwrap()
1681                    );
1682
1683                    assert_eq!(base.clone().pow(3i8), RealValidated::try_new(8.).unwrap());
1684                    assert_eq!(base.clone().pow(3i16), RealValidated::try_new(8.).unwrap());
1685                    assert_eq!(base.clone().pow(3i32), RealValidated::try_new(8.).unwrap());
1686                    assert_eq!(base.clone().pow(3i64), RealValidated::try_new(8.).unwrap());
1687                    assert_eq!(base.clone().pow(3i128), RealValidated::try_new(8.).unwrap());
1688                    assert_eq!(
1689                        base.clone().pow(3isize),
1690                        RealValidated::try_new(8.).unwrap()
1691                    );
1692                }
1693
1694                #[test]
1695                fn real_base_int_exponent_zero_neg_exp_error() {
1696                    let base = RealValidated::zero();
1697                    let exponent: i32 = -2;
1698                    let res = base.try_pow(exponent);
1699                    assert!(matches!(
1700                        res,
1701                        Err(PowIntExponentErrors::Input {
1702                            source: PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
1703                        })
1704                    ));
1705                }
1706
1707                #[test]
1708                fn real_base_real_exponent_valid() {
1709                    let base = RealValidated::try_new(2.).unwrap();
1710                    let exponent = RealValidated::try_new(3.).unwrap();
1711                    let expected = 8.;
1712                    assert_eq!(base.clone().try_pow(&exponent).unwrap().as_ref(), &expected);
1713                    assert_eq!(base.clone().pow(&exponent).as_ref(), &expected);
1714                }
1715            }
1716
1717            mod complex_base {
1718                use super::*;
1719
1720                #[test]
1721                fn complex_base_uint_exponent_valid() {
1722                    let base = ComplexValidated::try_new(Complex::new(2., 3.)).unwrap();
1723                    let expected_res = ComplexValidated::try_new(Complex::new(-46., 9.)).unwrap();
1724
1725                    assert_eq!(&base.clone().try_pow(3u8).unwrap(), &expected_res);
1726                    assert_eq!(&base.clone().try_pow(3u16).unwrap(), &expected_res);
1727                    assert_eq!(&base.clone().try_pow(3u32).unwrap(), &expected_res);
1728                    assert_eq!(&base.clone().try_pow(3u64).unwrap(), &expected_res);
1729                    assert_eq!(&base.clone().try_pow(3u128).unwrap(), &expected_res);
1730                    assert_eq!(&base.clone().try_pow(3usize).unwrap(), &expected_res);
1731
1732                    assert_eq!(&base.clone().pow(3u8), &expected_res);
1733                    assert_eq!(&base.clone().pow(3u16), &expected_res);
1734                    assert_eq!(&base.clone().pow(3u32), &expected_res);
1735                    assert_eq!(&base.clone().pow(3u64), &expected_res);
1736                    assert_eq!(&base.clone().pow(3u128), &expected_res);
1737                    assert_eq!(&base.clone().pow(3usize), &expected_res);
1738                }
1739
1740                #[test]
1741                fn complex_base_int_exponent_valid() {
1742                    let base = ComplexValidated::try_new(Complex::new(2., 3.)).unwrap();
1743                    let expected_res = ComplexValidated::try_new(Complex::new(-46., 9.)).unwrap();
1744
1745                    assert_eq!(&base.clone().try_pow(3i8).unwrap(), &expected_res);
1746                    assert_eq!(&base.clone().try_pow(3i16).unwrap(), &expected_res);
1747                    assert_eq!(&base.clone().try_pow(3i32).unwrap(), &expected_res);
1748                    assert_eq!(&base.clone().try_pow(3i64).unwrap(), &expected_res);
1749                    assert_eq!(&base.clone().try_pow(3i128).unwrap(), &expected_res);
1750                    assert_eq!(&base.clone().try_pow(3isize).unwrap(), &expected_res);
1751
1752                    assert_eq!(&base.clone().pow(3i8), &expected_res);
1753                    assert_eq!(&base.clone().pow(3i16), &expected_res);
1754                    assert_eq!(&base.clone().pow(3i32), &expected_res);
1755                    assert_eq!(&base.clone().pow(3i64), &expected_res);
1756                    assert_eq!(&base.clone().pow(3i128), &expected_res);
1757                    assert_eq!(&base.clone().pow(3isize), &expected_res);
1758                }
1759
1760                #[test]
1761                fn complex_zero_base_negative_real_exponent_error() {
1762                    let base = ComplexValidated::zero();
1763                    let exponent = RealValidated::try_new(-2.).unwrap();
1764                    let res = base.try_pow(&exponent);
1765                    assert!(matches!(
1766                        res,
1767                        Err(PowComplexBaseRealExponentErrors::Input {
1768                            source:
1769                                PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent { .. }
1770                        })
1771                    ));
1772                }
1773
1774                #[test]
1775                fn complex_zero_base_zero_real_exponent() {
1776                    let base = ComplexValidated::zero();
1777                    let exponent = RealValidated::zero();
1778                    let res = base.try_pow(&exponent).unwrap();
1779                    assert_eq!(res, ComplexValidated::one());
1780                }
1781
1782                #[test]
1783                fn complex_base_int_exponent_zero_neg_exp_error() {
1784                    let base = ComplexValidated::zero();
1785                    let exponent: i32 = -2;
1786                    let res = base.try_pow(exponent);
1787                    assert!(matches!(
1788                        res,
1789                        Err(PowIntExponentErrors::Input {
1790                            source: PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
1791                        })
1792                    ));
1793                }
1794
1795                #[test]
1796                fn complex_base_real_exponent_valid() {
1797                    let base = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
1798                    let exponent = RealValidated::try_new(3.).unwrap();
1799                    let expected = Complex::new(-11.000000000000004, 1.9999999999999973);
1800                    assert_eq!(base.clone().try_pow(&exponent).unwrap().as_ref(), &expected);
1801                    assert_eq!(base.clone().pow(&exponent).as_ref(), &expected);
1802                }
1803
1804                #[test]
1805                fn complex_zero_base_real_exponent_valid() {
1806                    let base = ComplexValidated::zero();
1807                    let exponent = RealValidated::try_new(3.).unwrap();
1808                    let expected = Complex::new(0., 0.);
1809                    assert_eq!(base.clone().try_pow(&exponent).unwrap().as_ref(), &expected);
1810                    assert_eq!(base.clone().pow(&exponent).as_ref(), &expected);
1811                }
1812            }
1813        }
1814
1815        mod reciprocal {
1816            use super::*;
1817
1818            mod real {
1819                use super::*;
1820
1821                #[test]
1822                fn reciprocal_valid() {
1823                    let v = RealValidated::try_new(2.).unwrap();
1824
1825                    let res = v.clone().try_reciprocal().unwrap();
1826                    assert_eq!(res.into_inner(), 0.5);
1827
1828                    let res = v.clone().reciprocal();
1829                    assert_eq!(res.into_inner(), 0.5);
1830                }
1831
1832                #[test]
1833                fn reciprocal_real_zero() {
1834                    let zero_val = RealValidated::zero();
1835                    let res = zero_val.try_reciprocal();
1836                    assert!(matches!(
1837                        res,
1838                        Err(ReciprocalErrors::Input {
1839                            source: ReciprocalInputErrors::DivisionByZero { .. }
1840                        })
1841                    ));
1842                }
1843            }
1844
1845            mod complex {
1846                use super::*;
1847
1848                #[test]
1849                fn reciprocal_valid() {
1850                    let v = ComplexValidated::try_new(Complex::new(3., 4.)).unwrap();
1851
1852                    let expected = Complex::new(0.12, -0.16);
1853
1854                    let res = v.clone().try_reciprocal().unwrap();
1855                    assert_eq!(res.as_ref(), &expected);
1856
1857                    let res = v.clone().reciprocal();
1858                    assert_eq!(res.as_ref(), &expected);
1859                }
1860
1861                #[test]
1862                fn reciprocal_complex_zero() {
1863                    let zero_val = ComplexValidated::zero();
1864                    let res = zero_val.try_reciprocal();
1865                    assert!(matches!(
1866                        res,
1867                        Err(ReciprocalErrors::Input {
1868                            source: ReciprocalInputErrors::DivisionByZero { .. }
1869                        })
1870                    ));
1871                }
1872            }
1873        } // end mod reciprocal
1874
1875        mod sqrt {
1876            use super::*;
1877
1878            mod real {
1879                use super::*;
1880
1881                #[test]
1882                fn sqrt_valid() {
1883                    let v = RealValidated::try_new(9.).unwrap();
1884                    assert_eq!(v.clone().try_sqrt().unwrap().as_ref(), &3.);
1885                    assert_eq!(v.clone().sqrt().as_ref(), &3.);
1886                }
1887
1888                #[test]
1889                fn sqrt_negative_input() {
1890                    let neg_val = RealValidated::try_new(-4.).unwrap();
1891                    let res = neg_val.try_sqrt();
1892                    assert!(matches!(
1893                        res,
1894                        Err(SqrtRealErrors::Input {
1895                            source: SqrtRealInputErrors::NegativeValue { .. }
1896                        })
1897                    ));
1898                }
1899            } // end mod real
1900
1901            mod complex {
1902                use super::*;
1903
1904                #[test]
1905                fn sqrt_valid() {
1906                    let expected = Complex::new(1., 2.);
1907                    let v = ComplexValidated::try_new(expected * expected).unwrap();
1908
1909                    let expected = Complex::new(1.0000000000000002, 2.);
1910                    assert_eq!(v.clone().try_sqrt().unwrap().as_ref(), &expected);
1911                    assert_eq!(v.clone().sqrt().as_ref(), &expected);
1912                }
1913            }
1914        } // end mod sqrt
1915
1916        mod trigonometric {
1917            use super::*;
1918
1919            mod real {
1920                use super::*;
1921
1922                #[test]
1923                fn sin_real_valid() {
1924                    let v = RealValidated::pi_div_2();
1925
1926                    let expected = 1.;
1927                    assert_eq!(v.clone().try_sin().unwrap().as_ref(), &expected);
1928                    assert_eq!(v.clone().sin().as_ref(), &expected);
1929                }
1930
1931                #[test]
1932                fn cos_real_valid() {
1933                    let v = RealValidated::pi();
1934
1935                    let expected = -1.;
1936                    assert_eq!(v.clone().try_cos().unwrap().as_ref(), &expected);
1937                    assert_eq!(v.clone().cos().as_ref(), &expected);
1938                }
1939
1940                #[test]
1941                fn tan_real_valid() {
1942                    let v = RealValidated::one();
1943
1944                    let expected = if cfg!(target_arch = "x86_64") {
1945                        1.5574077246549023
1946                    } else if cfg!(target_arch = "aarch64") {
1947                        1.557407724654902
1948                    } else {
1949                        todo!("Implement for other architectures");
1950                    };
1951                    assert_eq!(v.clone().try_tan().unwrap().as_ref(), &expected);
1952                    assert_eq!(v.clone().tan().as_ref(), &expected);
1953                }
1954
1955                #[test]
1956                fn asin_real_valid() {
1957                    let v = RealValidated::one();
1958
1959                    let expected = std::f64::consts::FRAC_PI_2; // π/2
1960                    assert_eq!(v.clone().try_asin().unwrap().as_ref(), &expected);
1961                    assert_eq!(v.clone().asin().as_ref(), &expected);
1962                }
1963
1964                #[test]
1965                fn acos_real_valid() {
1966                    let v = RealValidated::one();
1967
1968                    let expected = 0.;
1969                    assert_eq!(v.clone().try_acos().unwrap().as_ref(), &expected);
1970                    assert_eq!(v.clone().acos().as_ref(), &expected);
1971                }
1972
1973                #[test]
1974                fn atan_real_valid() {
1975                    let v = RealValidated::one();
1976
1977                    let expected = std::f64::consts::FRAC_PI_4; // π/4
1978                    assert_eq!(v.clone().try_atan().unwrap().as_ref(), &expected);
1979                    assert_eq!(v.clone().atan().as_ref(), &expected);
1980                }
1981
1982                #[test]
1983                fn atan2_valid() {
1984                    let one = RealValidated::one();
1985                    let zero = RealValidated::zero();
1986
1987                    let expected = std::f64::consts::FRAC_PI_2; // π/2
1988                    assert_eq!(one.clone().try_atan2(&zero).unwrap().as_ref(), &expected);
1989                    assert_eq!(one.clone().atan2(&zero).as_ref(), &expected);
1990
1991                    let expected = 0.;
1992                    assert_eq!(zero.clone().try_atan2(&one).unwrap().as_ref(), &expected);
1993                    assert_eq!(zero.clone().atan2(&one).as_ref(), &expected);
1994
1995                    let expected = std::f64::consts::FRAC_PI_4; // π/4
1996                    assert_eq!(one.clone().try_atan2(&one).unwrap().as_ref(), &expected);
1997                    assert_eq!(one.clone().atan2(&one).as_ref(), &expected);
1998                }
1999
2000                #[test]
2001                fn atan2_zero_over_zero() {
2002                    let zero_val = RealValidated::zero();
2003                    let res = zero_val.try_atan2(&RealValidated::zero());
2004                    assert!(matches!(
2005                        res,
2006                        Err(ATan2Errors::Input {
2007                            source: ATan2InputErrors::ZeroOverZero { .. }
2008                        })
2009                    ));
2010                }
2011
2012                /*
2013                #[test]
2014                #[ignore = "at the moment we cannot create a pole for the Tan function"]
2015                fn tan_real_pole() {
2016                    // tan(PI/2) is a pole
2017                    let pi_half = RealValidated::pi_div_2();
2018                    let res = pi_half.try_tan();
2019                    println!("Result: {:?}", res);
2020                    assert!(matches!(
2021                        res,
2022                        Err(TanRealErrors::Input {
2023                            source: TanRealInputErrors::ArgumentIsPole { .. }
2024                        })
2025                    ));
2026                }
2027                */
2028
2029                #[test]
2030                fn asin_real_out_of_domain() {
2031                    let val_gt_1 = RealValidated::try_new(1.5).unwrap();
2032                    assert!(matches!(
2033                        val_gt_1.try_asin(),
2034                        Err(ASinRealErrors::Input {
2035                            source: ASinRealInputErrors::OutOfDomain { .. }
2036                        })
2037                    ));
2038                    let val_lt_neg1 = RealValidated::try_new(-1.5).unwrap();
2039                    assert!(matches!(
2040                        val_lt_neg1.try_asin(),
2041                        Err(ASinRealErrors::Input {
2042                            source: ASinRealInputErrors::OutOfDomain { .. }
2043                        })
2044                    ));
2045                }
2046
2047                #[test]
2048                fn acos_real_out_of_domain() {
2049                    let val_gt_1 = RealValidated::try_new(1.5).unwrap();
2050                    assert!(matches!(
2051                        val_gt_1.try_acos(),
2052                        Err(ACosRealErrors::Input {
2053                            source: ACosRealInputErrors::OutOfDomain { .. }
2054                        })
2055                    ));
2056                    let val_lt_neg1 = RealValidated::try_new(-1.5).unwrap();
2057                    assert!(matches!(
2058                        val_lt_neg1.try_acos(),
2059                        Err(ACosRealErrors::Input {
2060                            source: ACosRealInputErrors::OutOfDomain { .. }
2061                        })
2062                    ));
2063                }
2064            } // end mod real
2065
2066            mod complex {
2067                use super::*;
2068
2069                #[test]
2070                fn sin_complex_valid() {
2071                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2072
2073                    let expected = if cfg!(target_arch = "x86_64") {
2074                        Complex::new(3.165778513216168, -1.9596010414216063)
2075                    } else if cfg!(target_arch = "aarch64") {
2076                        Complex::new(3.165778513216168, -1.959601041421606)
2077                    } else {
2078                        todo!("Implement for other architectures");
2079                    };
2080                    assert_eq!(v.clone().try_sin().unwrap().as_ref(), &expected);
2081                    assert_eq!(v.clone().sin().as_ref(), &expected);
2082
2083                    let zero = ComplexValidated::zero();
2084                    let expected = Complex::new(0., 0.);
2085                    assert_eq!(zero.clone().try_sin().unwrap().as_ref(), &expected);
2086                    assert_eq!(zero.clone().sin().as_ref(), &expected);
2087                }
2088
2089                #[test]
2090                fn cos_complex_valid() {
2091                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2092
2093                    let expected = if cfg!(target_arch = "x86_64") {
2094                        Complex::new(2.0327230070196656, 3.0518977991518)
2095                    } else if cfg!(target_arch = "aarch64") {
2096                        Complex::new(2.0327230070196656, 3.0518977991517997)
2097                    } else {
2098                        todo!("Implement for other architectures");
2099                    };
2100                    assert_eq!(v.clone().try_cos().unwrap().as_ref(), &expected);
2101                    assert_eq!(v.clone().cos().as_ref(), &expected);
2102
2103                    let zero = ComplexValidated::zero();
2104                    let expected = Complex::new(1., 0.);
2105                    assert_eq!(zero.clone().try_cos().unwrap().as_ref(), &expected);
2106                    assert_eq!(zero.clone().cos().as_ref(), &expected);
2107                }
2108
2109                #[test]
2110                fn tan_complex_valid() {
2111                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2112
2113                    let expected = Complex::new(0.03381282607989669, -1.0147936161466335);
2114                    assert_eq!(v.clone().try_tan().unwrap().as_ref(), &expected);
2115                    assert_eq!(v.clone().tan().as_ref(), &expected);
2116
2117                    let zero = ComplexValidated::zero();
2118                    let expected = Complex::new(0., 0.);
2119                    assert_eq!(zero.clone().try_tan().unwrap().as_ref(), &expected);
2120                    assert_eq!(zero.clone().tan().as_ref(), &expected);
2121                }
2122
2123                #[test]
2124                fn asin_complex_valid() {
2125                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2126
2127                    let expected = Complex::new(0.42707858639247614, -1.528570919480998);
2128                    assert_eq!(v.clone().try_asin().unwrap().as_ref(), &expected);
2129                    assert_eq!(v.clone().asin().as_ref(), &expected);
2130
2131                    let zero = ComplexValidated::zero();
2132                    let expected = Complex::new(0., 0.);
2133                    assert_eq!(zero.clone().try_asin().unwrap().as_ref(), &expected);
2134                    assert_eq!(zero.clone().asin().as_ref(), &expected);
2135                }
2136
2137                #[test]
2138                fn acos_complex_valid() {
2139                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2140
2141                    let expected = Complex::new(1.14371774040242, 1.5285709194809995);
2142                    assert_eq!(v.clone().try_acos().unwrap().as_ref(), &expected);
2143                    assert_eq!(v.clone().acos().as_ref(), &expected);
2144
2145                    let one = ComplexValidated::one();
2146                    let expected = Complex::new(0., 0.);
2147                    assert_eq!(one.clone().try_acos().unwrap().as_ref(), &expected);
2148                    assert_eq!(one.clone().acos().as_ref(), &expected);
2149                }
2150
2151                #[test]
2152                fn atan_complex_valid() {
2153                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2154
2155                    let expected = Complex::new(1.3389725222944935, -0.4023594781085251);
2156                    assert_eq!(v.clone().try_atan().unwrap().as_ref(), &expected);
2157                    assert_eq!(v.clone().atan().as_ref(), &expected);
2158
2159                    let zero = ComplexValidated::zero();
2160                    let expected = Complex::new(0., 0.);
2161                    assert_eq!(zero.clone().try_atan().unwrap().as_ref(), &expected);
2162                    assert_eq!(zero.clone().atan().as_ref(), &expected);
2163                }
2164
2165                #[test]
2166                fn atan_complex_pole() {
2167                    // atan(i) and atan(-i) are poles
2168                    let i_val = ComplexValidated::try_new_pure_imaginary(1.).unwrap();
2169                    assert!(matches!(
2170                        i_val.try_atan(),
2171                        Err(ATanComplexErrors::Input {
2172                            source: ATanComplexInputErrors::ArgumentIsPole { .. }
2173                        })
2174                    ));
2175
2176                    let neg_i_val = ComplexValidated::try_new_pure_imaginary(-1.).unwrap();
2177                    assert!(matches!(
2178                        neg_i_val.try_atan(),
2179                        Err(ATanComplexErrors::Input {
2180                            source: ATanComplexInputErrors::ArgumentIsPole { .. }
2181                        })
2182                    ));
2183                }
2184            } // end mod complex
2185        } // end mod trigonometric
2186
2187        mod hyperbolic {
2188            use super::*;
2189
2190            mod real {
2191                use super::*;
2192
2193                #[test]
2194                fn atanh_real_valid() {
2195                    let v = RealValidated::zero();
2196                    let expected = 0.;
2197                    assert_eq!(v.clone().try_atanh().unwrap().as_ref(), &expected);
2198                    assert_eq!(v.clone().atanh().as_ref(), &expected);
2199                }
2200
2201                #[test]
2202                fn atanh_real_out_of_domain() {
2203                    let val_ge_1 = RealValidated::one(); // atanh(1) is Inf
2204                    assert!(matches!(
2205                        val_ge_1.try_atanh(),
2206                        Err(ATanHErrors::Input {
2207                            source: ATanHInputErrors::OutOfDomain { .. }
2208                        })
2209                    ));
2210
2211                    let val_le_neg1 = RealValidated::negative_one(); // atanh(-1) is -Inf
2212                    assert!(matches!(
2213                        val_le_neg1.try_atanh(),
2214                        Err(ATanHErrors::Input {
2215                            source: ATanHInputErrors::OutOfDomain { .. }
2216                        })
2217                    ));
2218                }
2219
2220                #[test]
2221                fn acosh_real_valid() {
2222                    let v = RealValidated::one();
2223                    let expected = 0.;
2224                    assert_eq!(v.clone().try_acosh().unwrap().as_ref(), &expected);
2225                    assert_eq!(v.clone().acosh().as_ref(), &expected);
2226                }
2227
2228                #[test]
2229                fn acosh_real_out_of_domain() {
2230                    let val_lt_1 = RealValidated::try_new(0.5).unwrap();
2231                    assert!(matches!(
2232                        val_lt_1.try_acosh(),
2233                        Err(ACosHErrors::Input {
2234                            source: ACosHInputErrors::OutOfDomain { .. }
2235                        })
2236                    ));
2237                }
2238
2239                #[test]
2240                fn asinh_real_valid() {
2241                    let v = RealValidated::one();
2242                    let expected = 0.881373587019543;
2243                    assert_eq!(v.clone().try_asinh().unwrap().as_ref(), &expected);
2244                    assert_eq!(v.clone().asinh().as_ref(), &expected);
2245                }
2246
2247                #[test]
2248                fn sinh_real_valid() {
2249                    let v = RealValidated::try_new(0.881373587019543).unwrap();
2250                    let expected = 1.;
2251                    assert_eq!(v.clone().try_sinh().unwrap().as_ref(), &expected);
2252                    assert_eq!(v.clone().sinh().as_ref(), &expected);
2253                }
2254
2255                #[test]
2256                fn cosh_real_valid() {
2257                    let v = RealValidated::one();
2258                    let expected = 1.5430806348152437;
2259                    assert_eq!(v.clone().try_cosh().unwrap().as_ref(), &expected);
2260                    assert_eq!(v.clone().cosh().as_ref(), &expected);
2261                }
2262
2263                #[test]
2264                fn tanh_real_valid() {
2265                    let v = RealValidated::one();
2266                    let expected = 0.7615941559557649;
2267                    assert_eq!(v.clone().try_tanh().unwrap().as_ref(), &expected);
2268                    assert_eq!(v.clone().tanh().as_ref(), &expected);
2269                }
2270            }
2271
2272            mod complex {
2273                use super::*;
2274
2275                #[test]
2276                fn sinh_valid() {
2277                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2278                    let expected = Complex::new(-0.4890562590412937, -1.4031192506220405);
2279                    assert_eq!(v.clone().try_sinh().unwrap().as_ref(), &expected);
2280                    assert_eq!(v.clone().sinh().as_ref(), &expected);
2281                }
2282
2283                #[test]
2284                fn cosh_valid() {
2285                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2286                    let expected = Complex::new(-0.64214812471552, -1.0686074213827783);
2287                    assert_eq!(v.clone().try_cosh().unwrap().as_ref(), &expected);
2288                    assert_eq!(v.clone().cosh().as_ref(), &expected);
2289                }
2290
2291                #[test]
2292                fn tanh_valid() {
2293                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2294                    let expected = if cfg!(target_arch = "x86_64") {
2295                        Complex::new(1.16673625724092, 0.24345820118572523)
2296                    } else if cfg!(target_arch = "aarch64") {
2297                        Complex::new(1.16673625724092, 0.24345820118572528)
2298                    } else {
2299                        todo!("Missing target architecture!");
2300                    };
2301                    assert_eq!(v.clone().try_tanh().unwrap().as_ref(), &expected);
2302                    assert_eq!(v.clone().tanh().as_ref(), &expected);
2303                }
2304
2305                #[test]
2306                fn asinh_valid() {
2307                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2308                    let expected = Complex::new(1.4693517443681852, -1.0634400235777521);
2309                    Complex::new(1.4693517443681852, -1.0634400235777521);
2310                    assert_eq!(v.clone().try_asinh().unwrap().as_ref(), &expected);
2311                    assert_eq!(v.clone().asinh().as_ref(), &expected);
2312                }
2313
2314                #[test]
2315                fn acosh_valid() {
2316                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2317                    let expected = Complex::new(1.528570919480998, -1.1437177404024206);
2318                    assert_eq!(v.clone().try_acosh().unwrap().as_ref(), &expected);
2319                    assert_eq!(v.clone().acosh().as_ref(), &expected);
2320                }
2321
2322                #[test]
2323                fn atanh_valid() {
2324                    let v = ComplexValidated::try_new(Complex::new(1., -2.)).unwrap();
2325                    let expected = Complex::new(0.1732867951399864, -1.1780972450961724);
2326                    assert_eq!(v.clone().try_atanh().unwrap().as_ref(), &expected);
2327                    assert_eq!(v.clone().atanh().as_ref(), &expected);
2328                }
2329
2330                /*
2331                #[test]
2332                #[ignore = "at the moment we cannot create a pole for the ATanH function"]
2333                fn tanh_complex_pole() {
2334                    // tanh(z) has poles where cosh(z) = 0. e.g. z = i * (PI/2 + k*PI)
2335                    let pi_half = RealValidated::pi_div_2().into_inner();
2336                    let pole_val =
2337                        Complex64Validated::try_new_pure_imaginary(pi_half).unwrap();
2338                    println!("Atanh(Pole value): {:?}", pole_val.clone().try_tanh());
2339                    assert!(matches!(
2340                        pole_val.try_tanh(),
2341                        Err(TanHComplexErrors::Input {
2342                            source: TanHComplexInputErrors::OutOfDomain { .. }
2343                        })
2344                    ));
2345                }
2346                */
2347
2348                #[test]
2349                fn acosh_out_of_domain() {
2350                    // acosh(z) domain is C \ (-inf, 1) on real axis
2351                    let val_on_branch_cut = ComplexValidated::try_new_pure_real(0.5).unwrap();
2352                    assert!(matches!(
2353                        val_on_branch_cut.try_acosh(),
2354                        Err(ACosHErrors::Input {
2355                            source: ACosHInputErrors::OutOfDomain { .. }
2356                        })
2357                    ));
2358
2359                    let val_on_branch_cut_neg = ComplexValidated::try_new_pure_real(-5.).unwrap();
2360                    assert!(matches!(
2361                        val_on_branch_cut_neg.try_acosh(),
2362                        Err(ACosHErrors::Input {
2363                            source: ACosHInputErrors::OutOfDomain { .. }
2364                        })
2365                    ));
2366                }
2367
2368                #[test]
2369                fn atanh_out_of_domain() {
2370                    let val_ge_1 = ComplexValidated::try_new_pure_real(1.).unwrap();
2371                    assert!(matches!(
2372                        val_ge_1.try_atanh(),
2373                        Err(ATanHErrors::Input {
2374                            source: ATanHInputErrors::OutOfDomain { .. }
2375                        })
2376                    ));
2377
2378                    let val_le_neg1 = ComplexValidated::try_new_pure_real(-1.).unwrap();
2379                    assert!(matches!(
2380                        val_le_neg1.try_atanh(),
2381                        Err(ATanHErrors::Input {
2382                            source: ATanHInputErrors::OutOfDomain { .. }
2383                        })
2384                    ));
2385                }
2386            }
2387
2388            /*
2389            #[test]
2390            #[ignore = "at the moment we cannot create a pole for the TanH function"]
2391            fn tanh_out_of_domain() {
2392                // tanh(z) has poles where cosh(z) = 0. e.g. z = i * (PI/2 + k*PI)
2393                let pi_half = RealValidated::pi_div_2().into_inner();
2394                let pole_val = Complex64Validated::try_new_pure_imaginary(pi_half).unwrap();
2395                println!("TanH(Pole value): {:?}", pole_val.clone().try_tanh());
2396                assert!(matches!(
2397                    pole_val.try_tanh(),
2398                    Err(TanHComplexErrors::Input {
2399                        source: TanHComplexInputErrors::OutOfDomain { .. }
2400                    })
2401                ));
2402            }
2403            */
2404        } // end mod hyperbolic
2405    }
2406
2407    mod summation {
2408        use super::*;
2409
2410        #[test]
2411        fn sum_real() {
2412            let values = vec![
2413                RealValidated::try_new(1.0).unwrap(),
2414                RealValidated::try_new(2.0).unwrap(),
2415                RealValidated::try_new(3.0).unwrap(),
2416                RealValidated::try_new(4.0).unwrap(),
2417                RealValidated::try_new(5.0).unwrap(),
2418            ];
2419            let sum: RealValidated = values.into_iter().sum();
2420            assert_eq!(sum, RealValidated::try_new(15.0).unwrap());
2421        }
2422
2423        #[test]
2424        fn sum_real_compensated() {
2425            // Test case where simple summation might lose precision
2426            let values = vec![
2427                RealValidated::try_new(1.0e100).unwrap(),
2428                RealValidated::try_new(1.0).unwrap(),
2429                RealValidated::try_new(-1.0e100).unwrap(),
2430            ];
2431            let sum: RealValidated = values.into_iter().sum();
2432            // The Neumaier sum should correctly result in 1.0
2433            assert_eq!(sum, RealValidated::try_new(1.0).unwrap());
2434        }
2435
2436        #[test]
2437        fn sum_complex() {
2438            let values = vec![
2439                ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap(),
2440                ComplexValidated::try_new(Complex::new(3.0, 4.0)).unwrap(),
2441                ComplexValidated::try_new(Complex::new(5.0, 6.0)).unwrap(),
2442            ];
2443            let sum: ComplexValidated = values.into_iter().sum();
2444            assert_eq!(
2445                sum,
2446                ComplexValidated::try_new(Complex::new(9.0, 12.0)).unwrap()
2447            );
2448        }
2449
2450        #[test]
2451        fn sum_complex_compensated() {
2452            let values = vec![
2453                ComplexValidated::try_new(Complex::new(1.0e100, -1.0e100)).unwrap(),
2454                ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap(),
2455                ComplexValidated::try_new(Complex::new(-1.0e100, 1.0e100)).unwrap(),
2456            ];
2457            let sum: ComplexValidated = values.into_iter().sum();
2458            assert_eq!(
2459                sum,
2460                ComplexValidated::try_new(Complex::new(1.0, 2.0)).unwrap()
2461            );
2462        }
2463    } // end mod summation
2464
2465    mod neumaier_sum {
2466        use crate::neumaier_compensated_sum::NeumaierSum;
2467        use try_create::TryNewValidated;
2468
2469        use super::*;
2470
2471        mod real {
2472            use super::*;
2473
2474            #[test]
2475            fn new() {
2476                let neumaier = NeumaierSum::new(RealValidated::try_new_validated(1.0).unwrap());
2477                assert_eq!(neumaier.sum_before_compensation(), &1.0);
2478                assert_eq!(neumaier.compensation(), &0.0);
2479            }
2480
2481            #[test]
2482            fn zero() {
2483                let neumaier = NeumaierSum::<RealValidated>::zero();
2484                assert_eq!(neumaier.sum_before_compensation(), &0.0);
2485                assert_eq!(neumaier.compensation(), &0.0);
2486            }
2487
2488            #[test]
2489            fn add() {
2490                let mut neumaier = NeumaierSum::zero();
2491                neumaier.add(RealValidated::try_new_validated(1.0).unwrap());
2492                neumaier.add(RealValidated::try_new_validated(1e-16).unwrap());
2493                neumaier.add(RealValidated::try_new_validated(-1.0).unwrap());
2494                assert_eq!(neumaier.sum_before_compensation(), &0.0);
2495                assert_eq!(neumaier.compensation(), &1e-16);
2496            }
2497
2498            #[test]
2499            fn sum() {
2500                let mut neumaier = NeumaierSum::zero();
2501                neumaier.add(RealValidated::try_new_validated(1.0).unwrap());
2502                neumaier.add(RealValidated::try_new_validated(1e-16).unwrap());
2503                neumaier.add(RealValidated::try_new_validated(-1.0).unwrap());
2504                assert_eq!(neumaier.sum_before_compensation(), &0.0);
2505                assert_eq!(neumaier.compensation(), &1e-16);
2506                assert_eq!(neumaier.sum().as_ref(), &1e-16);
2507                println!("compensated sum = {}", neumaier.sum());
2508            }
2509
2510            #[test]
2511            fn reset() {
2512                let mut neumaier = NeumaierSum::zero();
2513                neumaier.add(RealValidated::try_new_validated(1.0).unwrap());
2514                neumaier.add(RealValidated::try_new_validated(1e-16).unwrap());
2515                assert_eq!(neumaier.sum_before_compensation(), &1.0);
2516                assert_eq!(neumaier.compensation(), &1e-16);
2517
2518                neumaier.reset();
2519                assert_eq!(neumaier.sum_before_compensation(), &0.0);
2520                assert_eq!(neumaier.compensation(), &0.0);
2521            }
2522
2523            #[test]
2524            fn sum_big_values() {
2525                let values = [1.0, 1e100, 1.0, -1e100]
2526                    .iter()
2527                    .map(|&v| RealValidated::try_new_validated(v).unwrap())
2528                    .collect::<Vec<_>>();
2529                let sum = values.iter().cloned().sum::<RealValidated>();
2530                assert_eq!(sum, 2.0);
2531
2532                let neumaier = NeumaierSum::new_sequential(values);
2533                assert_eq!(neumaier.sum(), 2.0);
2534                println!("compensated sum = {}", neumaier.sum());
2535            }
2536
2537            #[test]
2538            fn sum_small_values() {
2539                let values = [1.0, 1e-100, -1.0]
2540                    .iter()
2541                    .map(|&v| RealValidated::try_new_validated(v).unwrap())
2542                    .collect::<Vec<_>>();
2543                let sum = values.iter().cloned().sum::<RealValidated>();
2544                assert_eq!(sum, 1e-100);
2545
2546                let neumaier = NeumaierSum::new_sequential(values);
2547                assert_eq!(neumaier.sum(), 1e-100);
2548                println!("compensated sum = {}", neumaier.sum());
2549            }
2550        }
2551
2552        mod complex {
2553            use super::*;
2554
2555            #[test]
2556            fn new() {
2557                let neumaier = NeumaierSum::new(
2558                    ComplexValidated::try_new_validated(Complex::new(1.0, 2.0)).unwrap(),
2559                );
2560                assert_eq!(
2561                    neumaier.sum_before_compensation().as_ref(),
2562                    &Complex::new(1.0, 2.0)
2563                );
2564                assert_eq!(neumaier.compensation().as_ref(), &Complex::new(0.0, 0.0));
2565            }
2566
2567            #[test]
2568            fn zero() {
2569                let neumaier = NeumaierSum::<ComplexValidated>::zero();
2570
2571                let zero = Complex::new(0.0, 0.0);
2572                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2573                assert_eq!(neumaier.compensation().as_ref(), &zero);
2574            }
2575
2576            #[test]
2577            fn add() {
2578                let zero = Complex::new(0.0, 0.0);
2579                let v = Complex::new(1e-16, 2e-16);
2580
2581                let mut neumaier = NeumaierSum::zero();
2582                neumaier.add(ComplexValidated::try_new_validated(Complex::new(1.0, 2.0)).unwrap());
2583                neumaier.add(ComplexValidated::try_new_validated(v).unwrap());
2584                neumaier
2585                    .add(ComplexValidated::try_new_validated(Complex::new(-1.0, -2.0)).unwrap());
2586
2587                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2588                assert_eq!(neumaier.compensation().as_ref(), &v);
2589            }
2590
2591            #[test]
2592            fn sum() {
2593                let zero = Complex::new(0.0, 0.0);
2594                let v = Complex::new(1e-16, 2e-16);
2595
2596                let mut neumaier = NeumaierSum::zero();
2597                neumaier.add(ComplexValidated::try_new_validated(Complex::new(1.0, 2.0)).unwrap());
2598                neumaier.add(ComplexValidated::try_new_validated(v).unwrap());
2599                neumaier
2600                    .add(ComplexValidated::try_new_validated(Complex::new(-1.0, -2.0)).unwrap());
2601                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2602                assert_eq!(neumaier.compensation().as_ref(), &v);
2603                assert_eq!(neumaier.sum().as_ref(), &v);
2604                println!("compensated sum = {}", neumaier.sum());
2605            }
2606
2607            #[test]
2608            fn reset() {
2609                let zero = Complex::new(0.0, 0.0);
2610                let a = Complex::new(1.0, 2.0);
2611                let v = Complex::new(1e-16, 2e-16);
2612
2613                let mut neumaier = NeumaierSum::zero();
2614                neumaier.add(ComplexValidated::try_new_validated(a).unwrap());
2615                neumaier.add(ComplexValidated::try_new_validated(v).unwrap());
2616                assert_eq!(neumaier.sum_before_compensation().as_ref(), &a);
2617                assert_eq!(neumaier.compensation().as_ref(), &v);
2618
2619                neumaier.reset();
2620                assert_eq!(neumaier.sum_before_compensation().as_ref(), &zero);
2621                assert_eq!(neumaier.compensation().as_ref(), &zero);
2622            }
2623
2624            #[test]
2625            fn sum_big_values() {
2626                let values = [
2627                    Complex::new(1.0, 2.0),
2628                    Complex::new(1e100, 2e100),
2629                    Complex::new(1.0, 2.0),
2630                    Complex::new(-1e100, -2e100),
2631                ]
2632                .iter()
2633                .map(|&v| ComplexValidated::try_new_validated(v).unwrap())
2634                .collect::<Vec<_>>();
2635                let sum = values.clone().into_iter().sum::<ComplexValidated>();
2636                let expected_sum = Complex::new(2., 4.);
2637                assert_eq!(sum.as_ref(), &expected_sum);
2638
2639                let neumaier = NeumaierSum::new_sequential(values);
2640                assert_eq!(neumaier.sum().as_ref(), &expected_sum);
2641                println!("compensated sum = {}", neumaier.sum());
2642            }
2643
2644            #[test]
2645            fn sum_small_values() {
2646                let v = Complex::new(1e-100, 2e-100);
2647
2648                let values = [Complex::new(1.0, 2.0), v, Complex::new(-1.0, -2.0)]
2649                    .iter()
2650                    .map(|&v| ComplexValidated::try_new_validated(v).unwrap())
2651                    .collect::<Vec<_>>();
2652                let sum = values.iter().cloned().sum::<ComplexValidated>();
2653                let sum_expected = v;
2654                assert_eq!(sum.as_ref(), &sum_expected);
2655
2656                let neumaier = NeumaierSum::new_sequential(values);
2657                assert_eq!(neumaier.sum().as_ref(), &sum_expected);
2658                println!("compensated sum = {}", neumaier.sum());
2659            }
2660        }
2661    }
2662
2663    mod random {
2664        use super::*;
2665        use crate::{
2666            RandomSampleFromF64,
2667            kernels::native64_validated::{ComplexNative64StrictFinite, RealNative64StrictFinite},
2668            new_random_vec,
2669        };
2670        use rand::{Rng, SeedableRng, distr::Uniform, rngs::StdRng};
2671
2672        /// Tests the random generation of a `RealValidated` value.
2673        /// It uses a seeded RNG to ensure deterministic results and checks
2674        /// if the generated value falls within the expected [0, 1) range.
2675        #[test]
2676        fn test_random_real_validated() {
2677            let seed = [42; 32];
2678            let mut rng = StdRng::from_seed(seed);
2679
2680            let random_real: RealNative64StrictFinite = rng.random();
2681
2682            // rng.random::<f64>() produces a value in [0, 1), so the converted value should be in the same range.
2683            assert_eq!(random_real, 0.23713468825474326);
2684
2685            // Check for determinism
2686            let mut rng2 = StdRng::from_seed(seed);
2687            let random_real2: RealNative64StrictFinite = rng2.random();
2688            assert_eq!(random_real, random_real2);
2689        }
2690
2691        /// Tests the random generation of a `ComplexValidated` value.
2692        /// It uses a seeded RNG for determinism and verifies that both the real
2693        /// and imaginary parts of the generated complex number are within the
2694        /// expected [0, 1) range.
2695        #[test]
2696        fn test_random_complex_validated() {
2697            let seed = [99; 32];
2698            let mut rng = StdRng::from_seed(seed);
2699
2700            let random_complex: ComplexNative64StrictFinite = rng.random();
2701
2702            // The real and imaginary parts are generated independently,
2703            // so both should be in the [0, 1) range.
2704            let real_part = random_complex.real_part();
2705            let imag_part = random_complex.imag_part();
2706
2707            assert_eq!(real_part, 0.9995546882627792);
2708            assert_eq!(imag_part, 0.08932180682540247);
2709
2710            // Check for determinism
2711            let mut rng2 = StdRng::from_seed(seed);
2712            let random_complex2: ComplexNative64StrictFinite = rng2.random();
2713            assert_eq!(random_complex, random_complex2);
2714        }
2715
2716        const SEED: [u8; 32] = [42; 32];
2717
2718        #[test]
2719        fn test_sample_real_validated() {
2720            let mut rng = StdRng::from_seed(SEED);
2721            let dist = Uniform::new(-10.0, 10.0).unwrap();
2722
2723            let val = RealNative64StrictFinite::sample_from(&dist, &mut rng);
2724            assert_eq!(val, -5.257306234905137);
2725
2726            // Check determinism
2727            let mut rng2 = StdRng::from_seed(SEED);
2728            let val2 = RealNative64StrictFinite::sample_from(&dist, &mut rng2);
2729            assert_eq!(val, val2);
2730        }
2731
2732        #[test]
2733        fn test_sample_complex_validated() {
2734            let mut rng = StdRng::from_seed(SEED);
2735            let dist = Uniform::new(-10.0, 10.0).unwrap();
2736
2737            let val = ComplexNative64StrictFinite::sample_from(&dist, &mut rng);
2738            assert_eq!(val.real_part(), -5.257306234905137);
2739            assert_eq!(val.imag_part(), 7.212119776268775);
2740
2741            // Check determinism
2742            let mut rng2 = StdRng::from_seed(SEED);
2743            let val2 = ComplexNative64StrictFinite::sample_from(&dist, &mut rng2);
2744            assert_eq!(val, val2);
2745        }
2746
2747        #[test]
2748        fn new_random_vec_real() {
2749            let mut rng = StdRng::from_seed(SEED);
2750            let dist = Uniform::new(-10.0, 10.0).unwrap();
2751            let vec: Vec<RealNative64StrictFinite> = new_random_vec(3, &dist, &mut rng);
2752            assert_eq!(vec.len(), 3);
2753            assert_eq!(vec[0], -5.257306234905137);
2754            assert_eq!(vec[1], 7.212119776268775);
2755            assert_eq!(vec[2], -4.666248990558111);
2756
2757            // Check determinism
2758            let mut rng2 = StdRng::from_seed(SEED);
2759            let vec2: Vec<RealNative64StrictFinite> = new_random_vec(3, &dist, &mut rng2);
2760            assert_eq!(vec, vec2);
2761        }
2762
2763        #[test]
2764        fn new_random_vec_complex() {
2765            let mut rng = StdRng::from_seed(SEED);
2766            let dist = Uniform::new(-10.0, 10.0).unwrap();
2767            let vec: Vec<ComplexNative64StrictFinite> = new_random_vec(3, &dist, &mut rng);
2768            assert_eq!(vec.len(), 3);
2769            assert_eq!(vec[0].real_part(), -5.257306234905137);
2770            assert_eq!(vec[0].imag_part(), 7.212119776268775);
2771            assert_eq!(vec[1].real_part(), -4.666248990558111);
2772            assert_eq!(vec[1].imag_part(), 9.66047141517383);
2773            assert_eq!(vec[2].real_part(), -9.04279551029691);
2774            assert_eq!(vec[2].imag_part(), -1.026624649331671);
2775
2776            // Check determinism
2777            let mut rng2 = StdRng::from_seed(SEED);
2778            let vec2: Vec<ComplexNative64StrictFinite> = new_random_vec(3, &dist, &mut rng2);
2779            assert_eq!(vec, vec2);
2780        }
2781    }
2782
2783    mod hash_map_key_usage {
2784        use crate::{
2785            functions::Sign,
2786            kernels::native64_validated::{
2787                RealNative64StrictFinite, RealNative64StrictFiniteInDebug,
2788            },
2789        };
2790        use std::collections::HashMap;
2791        use try_create::TryNew;
2792
2793        #[test]
2794        fn test_native64_as_hashmap_key() {
2795            let mut map = HashMap::new();
2796            let key1 = RealNative64StrictFinite::try_new(1.0).unwrap();
2797            let key2 = RealNative64StrictFinite::try_new(2.5).unwrap();
2798
2799            map.insert(key1.clone(), "one");
2800            map.insert(key2, "two_point_five");
2801
2802            assert_eq!(
2803                map.get(&RealNative64StrictFinite::try_new(1.0).unwrap()),
2804                Some(&"one")
2805            );
2806            assert_eq!(map.len(), 2);
2807
2808            // Overwrite an existing key
2809            let old_value = map.insert(key1.clone(), "new_one");
2810            assert_eq!(old_value, Some("one"));
2811            assert_eq!(map.get(&key1), Some(&"new_one"));
2812        }
2813
2814        #[test]
2815        fn test_native64_debug_as_hashmap_key() {
2816            let mut map = HashMap::new();
2817            let key1 = RealNative64StrictFiniteInDebug::try_new(1.0).unwrap();
2818            let key2 = RealNative64StrictFiniteInDebug::try_new(2.5).unwrap();
2819
2820            map.insert(key1.clone(), "one_debug");
2821            map.insert(key2, "two_point_five_debug");
2822
2823            assert_eq!(
2824                map.get(&RealNative64StrictFiniteInDebug::try_new(1.0).unwrap()),
2825                Some(&"one_debug")
2826            );
2827            assert_eq!(map.len(), 2);
2828
2829            // Overwrite an existing key
2830            let old_value = map.insert(key1.clone(), "new_one_debug");
2831            assert_eq!(old_value, Some("one_debug"));
2832            assert_eq!(map.get(&key1), Some(&"new_one_debug"));
2833        }
2834
2835        #[test]
2836        fn test_hashmap_basic_operations() {
2837            let mut map = HashMap::new();
2838            let key1 = RealNative64StrictFinite::try_new(1.0).unwrap();
2839            let key2 = RealNative64StrictFinite::try_new(2.5).unwrap();
2840            let key3 = RealNative64StrictFinite::try_new(1.0).unwrap(); // Same as key1
2841
2842            // Insert and verify
2843            assert_eq!(map.insert(key1, "one"), None);
2844            assert_eq!(map.insert(key2, "two_point_five"), None);
2845            assert_eq!(map.len(), 2);
2846
2847            // Test key equality (key3 should be equal to key1)
2848            assert_eq!(map.get(&key3), Some(&"one"));
2849
2850            // Overwrite existing key
2851            assert_eq!(map.insert(key3, "one_updated"), Some("one"));
2852            assert_eq!(map.len(), 2); // Size shouldn't change
2853        }
2854
2855        #[test]
2856        fn test_hashset_operations() {
2857            use std::collections::HashSet;
2858            let mut set = HashSet::new();
2859
2860            let val1 = RealNative64StrictFinite::try_new(1.0).unwrap();
2861            let val2 = RealNative64StrictFinite::try_new(2.0).unwrap();
2862            let val1_duplicate = RealNative64StrictFinite::try_new(1.0).unwrap();
2863
2864            assert!(set.insert(val1));
2865            assert!(set.insert(val2));
2866            assert!(!set.insert(val1_duplicate)); // Should return false (already exists)
2867
2868            assert_eq!(set.len(), 2);
2869            assert!(set.contains(&RealNative64StrictFinite::try_new(1.0).unwrap()));
2870        }
2871
2872        #[test]
2873        fn test_hash_consistency() {
2874            use std::collections::hash_map::DefaultHasher;
2875            use std::hash::{Hash, Hasher};
2876
2877            let val1 = RealNative64StrictFinite::try_new(1.234).unwrap();
2878            let val2 = RealNative64StrictFinite::try_new(1.234).unwrap();
2879
2880            // Equal values should have equal hashes
2881            let mut hasher1 = DefaultHasher::new();
2882            let mut hasher2 = DefaultHasher::new();
2883
2884            val1.hash(&mut hasher1);
2885            val2.hash(&mut hasher2);
2886
2887            assert_eq!(hasher1.finish(), hasher2.finish());
2888            assert_eq!(val1, val2); // Verify they're actually equal
2889        }
2890
2891        #[test]
2892        fn test_hash_signed_zero() {
2893            use std::collections::hash_map::DefaultHasher;
2894            use std::hash::{Hash, Hasher};
2895
2896            let val1 = RealNative64StrictFinite::try_new(0.0).unwrap();
2897            assert!(val1.kernel_is_sign_positive());
2898            let val2 = RealNative64StrictFinite::try_new(-0.0).unwrap();
2899            assert!(val2.kernel_is_sign_negative());
2900
2901            // Verify the underlying f64 values have different bit patterns
2902            assert_ne!(
2903                0.0f64.to_bits(),
2904                (-0.0f64).to_bits(),
2905                "Sanity check: +0.0 and -0.0 should have different bit patterns"
2906            );
2907
2908            assert_eq!(val1, val2); // Verify they're actually equal
2909
2910            // Equal values should have equal hashes
2911            let mut hasher1 = DefaultHasher::new();
2912            let mut hasher2 = DefaultHasher::new();
2913
2914            val1.hash(&mut hasher1);
2915            val2.hash(&mut hasher2);
2916
2917            assert_eq!(hasher1.finish(), hasher2.finish());
2918        }
2919    }
2920
2921    mod test_truncate_to_usize {
2922        use super::*;
2923        use crate::validation::ErrorsRawRealToInteger;
2924
2925        #[test]
2926        fn test_positive_integers() {
2927            // Whole numbers should convert exactly
2928            let value = RealNative64StrictFinite::try_new(42.0).unwrap();
2929            assert_eq!(value.truncate_to_usize().unwrap(), 42);
2930
2931            let value = RealNative64StrictFinite::try_new(1.0).unwrap();
2932            assert_eq!(value.truncate_to_usize().unwrap(), 1);
2933
2934            let value = RealNative64StrictFinite::try_new(100.0).unwrap();
2935            assert_eq!(value.truncate_to_usize().unwrap(), 100);
2936        }
2937
2938        #[test]
2939        fn test_positive_fractionals_truncate() {
2940            // Positive fractional parts should be discarded (truncated toward zero)
2941            let value = RealNative64StrictFinite::try_new(42.9).unwrap();
2942            assert_eq!(value.truncate_to_usize().unwrap(), 42);
2943
2944            let value = RealNative64StrictFinite::try_new(3.7).unwrap();
2945            assert_eq!(value.truncate_to_usize().unwrap(), 3);
2946
2947            let value = RealNative64StrictFinite::try_new(0.9).unwrap();
2948            assert_eq!(value.truncate_to_usize().unwrap(), 0);
2949
2950            let value = RealNative64StrictFinite::try_new(99.999).unwrap();
2951            assert_eq!(value.truncate_to_usize().unwrap(), 99);
2952        }
2953
2954        #[test]
2955        fn test_zero_cases() {
2956            // Zero should convert to 0
2957            let value = RealNative64StrictFinite::try_new(0.0).unwrap();
2958            assert_eq!(value.truncate_to_usize().unwrap(), 0);
2959
2960            // Positive fractional values less than 1 should truncate to 0
2961            let value = RealNative64StrictFinite::try_new(0.1).unwrap();
2962            assert_eq!(value.truncate_to_usize().unwrap(), 0);
2963
2964            let value = RealNative64StrictFinite::try_new(0.5).unwrap();
2965            assert_eq!(value.truncate_to_usize().unwrap(), 0);
2966        }
2967
2968        #[test]
2969        fn test_large_valid_values() {
2970            // Large but representable values within usize range
2971            let value = RealNative64StrictFinite::try_new(1_000_000.7).unwrap();
2972            assert_eq!(value.truncate_to_usize().unwrap(), 1_000_000);
2973
2974            let value = RealNative64StrictFinite::try_new(1_000_000_000.0).unwrap();
2975            assert_eq!(value.truncate_to_usize().unwrap(), 1_000_000_000);
2976
2977            // Test with a value close to but less than usize::MAX (on 64-bit systems)
2978            let max_safe = (usize::MAX as f64) - 2048.0; // Subtract to avoid precision issues
2979            let value = RealNative64StrictFinite::try_new(max_safe).unwrap();
2980            let result = value.truncate_to_usize().unwrap();
2981            assert!(result < usize::MAX);
2982        }
2983
2984        #[test]
2985        fn test_negative_values_error() {
2986            // Negative values should return OutOfRange error
2987            let value = RealNative64StrictFinite::try_new(-1.0).unwrap();
2988            let result = value.truncate_to_usize();
2989            assert!(matches!(
2990                result,
2991                Err(ErrorsRawRealToInteger::OutOfRange { .. })
2992            ));
2993
2994            let value = RealNative64StrictFinite::try_new(-10.5).unwrap();
2995            let result = value.truncate_to_usize();
2996            assert!(matches!(
2997                result,
2998                Err(ErrorsRawRealToInteger::OutOfRange { .. })
2999            ));
3000
3001            let value = RealNative64StrictFinite::try_new(-0.1).unwrap();
3002            let result = value.truncate_to_usize();
3003            assert!(matches!(result, Ok(0)));
3004
3005            let value = RealNative64StrictFinite::try_new(-1000.0).unwrap();
3006            let result = value.truncate_to_usize();
3007            assert!(matches!(
3008                result,
3009                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3010            ));
3011        }
3012
3013        #[test]
3014        fn test_too_large_values_error() {
3015            // Values larger than usize::MAX should return OutOfRange error
3016            let too_large = (usize::MAX as f64) * 2.0;
3017            let value = RealNative64StrictFinite::try_new(too_large).unwrap();
3018            let result = value.truncate_to_usize();
3019            assert!(matches!(
3020                result,
3021                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3022            ));
3023
3024            let value = RealNative64StrictFinite::try_new(1e20).unwrap();
3025            let result = value.truncate_to_usize();
3026            assert!(matches!(
3027                result,
3028                Err(ErrorsRawRealToInteger::OutOfRange { .. })
3029            ));
3030        }
3031
3032        #[test]
3033        fn test_edge_cases() {
3034            // Test values very close to boundaries
3035
3036            // Just above zero
3037            let value = RealNative64StrictFinite::try_new(f64::EPSILON).unwrap();
3038            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3039
3040            // Just below 1
3041            let value = RealNative64StrictFinite::try_new(1.0 - f64::EPSILON).unwrap();
3042            assert_eq!(value.truncate_to_usize().unwrap(), 0);
3043
3044            // Just above 1
3045            let value = RealNative64StrictFinite::try_new(1.0 + f64::EPSILON).unwrap();
3046            assert_eq!(value.truncate_to_usize().unwrap(), 1);
3047        }
3048
3049        #[test]
3050        fn test_truncation_behavior() {
3051            // Verify truncation (toward zero) behavior vs other rounding modes
3052            let test_cases = [
3053                (2.1, 2),
3054                (2.5, 2), // truncate, not round
3055                (2.9, 2),
3056                (3.0, 3),
3057                (3.1, 3),
3058                (99.999, 99),
3059            ];
3060
3061            for (input, expected) in test_cases {
3062                let value = RealNative64StrictFinite::try_new(input)
3063                    .unwrap()
3064                    .truncate_to_usize()
3065                    .unwrap();
3066                assert_eq!(
3067                    value, expected,
3068                    "Failed for input {}: expected {}, got {:?}",
3069                    input, expected, value
3070                );
3071            }
3072        }
3073
3074        #[test]
3075        fn test_error_details() {
3076            // Test that error variants contain expected information
3077
3078            // OutOfRange error for negative value
3079            let value = RealNative64StrictFinite::try_new(-5.0).unwrap();
3080            if let Err(ErrorsRawRealToInteger::OutOfRange {
3081                value: err_val,
3082                min,
3083                max,
3084                ..
3085            }) = value.truncate_to_usize()
3086            {
3087                assert_eq!(err_val, -5.0);
3088                assert_eq!(min, usize::MIN);
3089                assert_eq!(max, usize::MAX);
3090            } else {
3091                panic!("Expected OutOfRange error for negative value");
3092            }
3093
3094            // OutOfRange error for too large value
3095            let large_value = 1e20;
3096            let value = RealNative64StrictFinite::try_new(large_value).unwrap();
3097            if let Err(ErrorsRawRealToInteger::OutOfRange {
3098                value: err_val,
3099                min,
3100                max,
3101                ..
3102            }) = value.truncate_to_usize()
3103            {
3104                assert_eq!(err_val, large_value);
3105                assert_eq!(min, usize::MIN);
3106                assert_eq!(max, usize::MAX);
3107            } else {
3108                panic!("Expected OutOfRange error for large value");
3109            }
3110        }
3111
3112        #[test]
3113        fn test_practical_usage_scenario() {
3114            // Test a realistic usage scenario: creating a vector with calculated size
3115            fn create_vector_with_calculated_size<T: Default + Clone>(
3116                size_float: RealNative64StrictFinite,
3117            ) -> Result<Vec<T>, Box<dyn std::error::Error>> {
3118                let size = size_float.truncate_to_usize()?;
3119                Ok(vec![T::default(); size])
3120            }
3121
3122            // Valid case
3123            let calculated_size = RealNative64StrictFinite::try_new(10.7).unwrap();
3124            let vec: Vec<i32> = create_vector_with_calculated_size(calculated_size).unwrap();
3125            assert_eq!(vec.len(), 10); // Truncated from 10.7
3126
3127            // Error case - negative size
3128            let negative_size = RealNative64StrictFinite::try_new(-5.0).unwrap();
3129            let result: Result<Vec<i32>, _> = create_vector_with_calculated_size(negative_size);
3130            assert!(result.is_err());
3131
3132            // Error case - too large size
3133            let huge_size = RealNative64StrictFinite::try_new(1e20).unwrap();
3134            let result: Result<Vec<i32>, _> = create_vector_with_calculated_size(huge_size);
3135            assert!(result.is_err());
3136        }
3137
3138        #[test]
3139        fn test_consistency_with_f64_behavior() {
3140            // Verify that our implementation behaves consistently with direct f64 operations
3141            let test_values = [0.0, 1.0, 2.5, 42.9, 100.0, 0.1, 0.9];
3142
3143            for &val in &test_values {
3144                let validated = RealNative64StrictFinite::try_new(val).unwrap();
3145                let result = validated.truncate_to_usize().unwrap();
3146
3147                // Compare with direct f64 truncation
3148                let expected = val.trunc() as usize;
3149                assert_eq!(result, expected, "Mismatch for value {}", val);
3150            }
3151        }
3152    }
3153}