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