1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
4 RealScalar,
5 functions::{Conjugate, NegAssign, Rounding, Sign},
6 kernels::{
7 ComplexValidated, NumKernelStrictFinite, RawComplexTrait, RawRealTrait, RawScalarTrait,
8 RealValidated,
9 },
10 validation::{
11 ErrorsTryFromf64, ErrorsValidationRawComplex, ErrorsValidationRawReal, FpChecks,
12 ValidationPolicyReal,
13 },
14};
15use derive_more::with_trait::Neg;
16use duplicate::duplicate_item;
17use num::Complex;
18use rug::ops::{CompleteRound, Pow as RugPow};
19use std::{backtrace::Backtrace, cmp::Ordering, marker::PhantomData, num::FpCategory};
20use try_create::IntoInner;
21
22impl RawScalarTrait for rug::Float {
23 type ValidationErrors = ErrorsValidationRawReal<rug::Float>;
24
25 fn raw_zero(precision: u32) -> Self {
26 rug::Float::with_val(precision, 0.)
27 }
28
29 fn is_zero(&self) -> bool {
30 rug::Float::is_zero(self)
31 }
32
33 fn raw_one(precision: u32) -> Self {
34 rug::Float::with_val(precision, 1.)
35 }
36
37 #[duplicate_item(
38 unchecked_method method;
39 [unchecked_reciprocal] [recip];
40 [unchecked_exp] [exp];
41 [unchecked_sqrt] [sqrt];
42 [unchecked_sin] [sin];
43 [unchecked_asin] [asin];
44 [unchecked_cos] [cos];
45 [unchecked_acos] [acos];
46 [unchecked_tan] [tan];
47 [unchecked_atan] [atan];
48 [unchecked_sinh] [sinh];
49 [unchecked_asinh] [asinh];
50 [unchecked_cosh] [cosh];
51 [unchecked_acosh] [acosh];
52 [unchecked_tanh] [tanh];
53 [unchecked_atanh] [atanh];
54 [unchecked_ln] [ln];
55 [unchecked_log2] [log2];
56 [unchecked_log10] [log10];
57 )]
58 #[inline(always)]
59 fn unchecked_method(self) -> Self {
60 rug::Float::method(self)
61 }
62
63 #[duplicate_item(
64 unchecked_method exponent_type;
65 [unchecked_pow_exponent_i8] [i8];
66 [unchecked_pow_exponent_i16] [i16];
67 [unchecked_pow_exponent_i32] [i32];
68 [unchecked_pow_exponent_i64] [i64];
69 [unchecked_pow_exponent_i128] [i128];
70 [unchecked_pow_exponent_isize] [isize];
71 [unchecked_pow_exponent_u8] [u8];
72 [unchecked_pow_exponent_u16] [u16];
73 [unchecked_pow_exponent_u32] [u32];
74 [unchecked_pow_exponent_u64] [u64];
75 [unchecked_pow_exponent_u128] [u128];
76 [unchecked_pow_exponent_usize] [usize];
77 )]
78 #[inline(always)]
79 fn unchecked_method(self, exponent: &exponent_type) -> Self {
80 rug::Float::pow(self, exponent)
81 }
82
83 #[inline(always)]
87 fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
88 rug::Float::mul_add(self, b, c)
89 }
90}
91
92impl RawRealTrait for rug::Float {
93 type RawComplex = rug::Complex;
94
95 #[inline(always)]
96 fn unchecked_abs(self) -> rug::Float {
97 rug::Float::abs(self)
98 }
99
100 #[inline(always)]
101 fn unchecked_atan2(self, denominator: &Self) -> Self {
102 rug::Float::atan2(self, denominator)
103 }
104
105 #[inline(always)]
106 fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self {
107 rug::Float::pow(self, exponent)
108 }
109
110 fn unchecked_hypot(self, other: &Self) -> Self {
111 rug::Float::hypot(self, other)
112 }
113
114 fn unchecked_ln_1p(self) -> Self {
115 rug::Float::ln_1p(self)
116 }
117
118 fn unchecked_exp_m1(self) -> Self {
119 rug::Float::exp_m1(self)
120 }
121
122 #[inline(always)]
125 fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
126 self.mul_add_mul_mut(mul, add_mul1, add_mul2);
127 }
128
129 #[inline(always)]
132 fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
133 self.mul_sub_mul_mut(mul, sub_mul1, sub_mul2);
134 }
135
136 fn raw_total_cmp(&self, other: &Self) -> Ordering {
137 rug::Float::total_cmp(self, other)
138 }
139
140 fn raw_clamp(self, min: &Self, max: &Self) -> Self {
142 rug::Float::clamp(self, min, max)
143 }
144
145 fn raw_classify(&self) -> FpCategory {
146 rug::Float::classify(self)
147 }
148
149 #[inline(always)]
150 fn raw_two(precision: u32) -> Self {
151 rug::Float::with_val(precision, 2.)
152 }
153
154 #[inline(always)]
155 fn raw_one_div_2(precision: u32) -> Self {
156 rug::Float::with_val(precision, 0.5)
157 }
158
159 fn raw_pi(precision: u32) -> Self {
160 rug::Float::with_val(precision, -1.).acos()
161 }
162
163 fn raw_two_pi(precision: u32) -> Self {
164 Self::raw_pi(precision) * rug::Float::with_val(precision, 2.)
165 }
166
167 fn raw_pi_div_2(precision: u32) -> Self {
168 rug::Float::with_val(precision, 1.).asin()
169 }
170
171 fn raw_max_finite(precision: u32) -> Self {
172 let one = rug::Float::with_val(precision, 1);
178 let eps = rug::Float::with_val(precision, rug::Float::u_pow_u(2, precision)).recip();
179 let significand = one - &eps;
180
181 let max_exp = rug::float::exp_max() - 1;
183 significand * rug::Float::with_val(precision, rug::Float::u_pow_u(2, max_exp as u32))
185 }
186
187 fn raw_min_finite(precision: u32) -> Self {
188 Self::raw_max_finite(precision).neg()
189 }
190
191 fn raw_epsilon(precision: u32) -> Self {
192 rug::Float::u_pow_u(2, precision - 1)
193 .complete(precision)
194 .recip()
195 }
196
197 fn raw_ln_2(precision: u32) -> Self {
198 rug::Float::with_val(precision, 2.).ln()
199 }
200
201 fn raw_ln_10(precision: u32) -> Self {
202 rug::Float::with_val(precision, 10.).ln()
203 }
204
205 fn raw_log10_2(precision: u32) -> Self {
206 rug::Float::with_val(precision, 2.).log10()
207 }
208
209 fn raw_log2_10(precision: u32) -> Self {
210 rug::Float::with_val(precision, 10.).log2()
211 }
212
213 fn raw_log2_e(precision: u32) -> Self {
214 Self::raw_e(precision).log2()
215 }
216
217 fn raw_log10_e(precision: u32) -> Self {
218 Self::raw_e(precision).log10()
219 }
220
221 fn raw_e(precision: u32) -> Self {
222 rug::Float::with_val(precision, 1.).exp()
223 }
224
225 #[inline(always)]
226 fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
227 value: f64,
228 ) -> Result<Self, ErrorsTryFromf64<Self>> {
229 let precision = RealPolicy::PRECISION;
230 let value_rug = RealPolicy::validate(rug::Float::with_val(precision, value))
231 .map_err(|e| ErrorsTryFromf64::Output { source: e })?;
232 if value_rug == value {
233 Ok(value_rug)
234 } else {
235 Err(ErrorsTryFromf64::NonRepresentableExactly {
236 value_in: value,
237 value_converted_from_f64: value_rug,
238 precision,
239 backtrace: Backtrace::force_capture(),
240 })
241 }
242 }
243
244 fn precision(&self) -> u32 {
245 rug::Float::prec(self)
246 }
247}
248
249impl RawScalarTrait for rug::Complex {
250 type ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<rug::Float>>;
251
252 fn raw_zero(precision: u32) -> Self {
253 rug::Complex::with_val(precision, (0., 0.))
254 }
255
256 fn is_zero(&self) -> bool {
257 rug::Complex::is_zero(self)
258 }
259
260 fn raw_one(precision: u32) -> Self {
261 rug::Complex::with_val(precision, (1., 0.))
262 }
263
264 #[duplicate_item(
265 unchecked_method method;
266 [unchecked_reciprocal] [recip];
267 [unchecked_exp] [exp];
268 [unchecked_sqrt] [sqrt];
269 [unchecked_sin] [sin];
270 [unchecked_asin] [asin];
271 [unchecked_cos] [cos];
272 [unchecked_acos] [acos];
273 [unchecked_tan] [tan];
274 [unchecked_atan] [atan];
275 [unchecked_sinh] [sinh];
276 [unchecked_asinh] [asinh];
277 [unchecked_cosh] [cosh];
278 [unchecked_acosh] [acosh];
279 [unchecked_tanh] [tanh];
280 [unchecked_atanh] [atanh];
281 [unchecked_ln] [ln];
282 [unchecked_log10] [log10];
283 )]
284 #[inline(always)]
285 fn unchecked_method(self) -> Self {
286 rug::Complex::method(self)
287 }
288
289 #[inline(always)]
290 fn unchecked_log2(self) -> Self {
291 let ln_2 = rug::Float::with_val(self.real().prec(), 2.).ln();
292 rug::Complex::ln(self) / ln_2
293 }
294
295 #[duplicate_item(
296 unchecked_method exponent_type;
297 [unchecked_pow_exponent_i8] [i8];
298 [unchecked_pow_exponent_i16] [i16];
299 [unchecked_pow_exponent_i32] [i32];
300 [unchecked_pow_exponent_i64] [i64];
301 [unchecked_pow_exponent_i128] [i128];
302 [unchecked_pow_exponent_isize] [isize];
303 [unchecked_pow_exponent_u8] [u8];
304 [unchecked_pow_exponent_u16] [u16];
305 [unchecked_pow_exponent_u32] [u32];
306 [unchecked_pow_exponent_u64] [u64];
307 [unchecked_pow_exponent_u128] [u128];
308 [unchecked_pow_exponent_usize] [usize];
309 )]
310 #[inline(always)]
311 fn unchecked_method(self, exponent: &exponent_type) -> Self {
312 rug::Complex::pow(self, exponent)
313 }
314
315 #[inline(always)]
319 fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
320 rug::Complex::mul_add(self, b, c)
321 }
322}
323
324impl Conjugate for rug::Complex {
325 #[inline(always)]
326 fn conjugate(self) -> Self {
327 rug::Complex::conj(self)
328 }
329}
330
331impl RawComplexTrait for rug::Complex {
332 type RawReal = rug::Float;
333
334 fn new_unchecked_raw_complex(real: rug::Float, imag: rug::Float) -> Self {
335 debug_assert_eq!(
336 real.prec(),
337 imag.prec(),
338 "Different precision between real and imaginary part!"
339 );
340 rug::Complex::with_val(real.prec(), (real, imag))
341 }
342
343 fn mut_raw_real_part(&mut self) -> &mut rug::Float {
345 self.mut_real()
346 }
347
348 fn mut_raw_imag_part(&mut self) -> &mut rug::Float {
350 self.mut_imag()
351 }
352
353 #[inline(always)]
354 fn unchecked_abs(self) -> rug::Float {
355 rug::Complex::abs(self).into_real_imag().0
356 }
357
358 #[inline(always)]
359 fn raw_real_part(&self) -> &rug::Float {
360 self.real()
361 }
362
363 #[inline(always)]
364 fn raw_imag_part(&self) -> &rug::Float {
365 self.imag()
366 }
367
368 #[inline(always)]
369 fn unchecked_arg(self) -> rug::Float {
370 rug::Complex::arg(self).into_real_imag().0
371 }
372
373 #[inline(always)]
374 fn unchecked_pow_exponent_real(self, exponent: &rug::Float) -> Self {
375 rug::Complex::pow(self, exponent)
376 }
377}
378
379impl FpChecks for rug::Float {
380 fn is_finite(&self) -> bool {
381 rug::Float::is_finite(self)
382 }
383
384 fn is_infinite(&self) -> bool {
385 rug::Float::is_infinite(self)
386 }
387
388 fn is_nan(&self) -> bool {
389 rug::Float::is_nan(self)
390 }
391 fn is_normal(&self) -> bool {
392 rug::Float::is_normal(self)
393 }
394}
395
396impl FpChecks for rug::Complex {
397 #[inline(always)]
399 fn is_finite(&self) -> bool {
400 self.real().is_finite() && self.imag().is_finite()
401 }
402
403 #[inline(always)]
405 fn is_infinite(&self) -> bool {
406 !self.is_nan() && (self.real().is_infinite() || self.imag().is_infinite())
407 }
408
409 #[inline(always)]
411 fn is_nan(&self) -> bool {
412 self.real().is_nan() || self.imag().is_nan()
413 }
414
415 #[inline(always)]
417 fn is_normal(&self) -> bool {
418 self.real().is_normal() && self.imag().is_normal()
419 }
420}
421
422pub type RugStrictFinite<const PRECISION: u32> = NumKernelStrictFinite<rug::Float, PRECISION>;
476pub type RealRugStrictFinite<const PRECISION: u32> = RealValidated<RugStrictFinite<PRECISION>>;
481
482pub type ComplexRugStrictFinite<const PRECISION: u32> =
484 ComplexValidated<RugStrictFinite<PRECISION>>;
485
486impl Sign for rug::Float {
487 #[inline(always)]
489 fn kernel_copysign(self, sign: &Self) -> Self {
490 self.copysign(sign)
491 }
492
493 #[inline(always)]
495 fn kernel_is_sign_negative(&self) -> bool {
496 self.is_sign_negative()
497 }
498
499 #[inline(always)]
501 fn kernel_is_sign_positive(&self) -> bool {
502 self.is_sign_positive()
503 }
504
505 #[inline(always)]
513 fn kernel_signum(self) -> Self {
514 self.signum()
515 }
516}
517
518impl Rounding for rug::Float {
519 #[inline(always)]
521 fn kernel_ceil(self) -> Self {
522 self.ceil()
523 }
524
525 #[inline(always)]
527 fn kernel_floor(self) -> Self {
528 self.floor()
529 }
530
531 #[inline(always)]
533 fn kernel_fract(self) -> Self {
534 self.fract()
535 }
536
537 #[inline(always)]
539 fn kernel_round(self) -> Self {
540 self.round()
541 }
542
543 #[inline(always)]
564 fn kernel_round_ties_even(self) -> Self {
565 self.round_even()
566 }
567
568 #[inline(always)]
585 fn kernel_trunc(self) -> Self {
586 self.trunc()
587 }
588}
589
590impl<const PRECISION: u32> TryFrom<Complex<f64>> for ComplexRugStrictFinite<PRECISION> {
594 type Error = ErrorsValidationRawComplex<ErrorsTryFromf64<rug::Float>>;
595
596 fn try_from(value: Complex<f64>) -> Result<Self, Self::Error> {
597 let real_part = RealRugStrictFinite::<PRECISION>::try_from_f64(value.re);
598 let imag_part = RealRugStrictFinite::<PRECISION>::try_from_f64(value.im);
599
600 match (real_part, imag_part) {
601 (Ok(real_part), Ok(imag_part)) => Ok(Self {
602 value: rug::Complex::with_val(
603 PRECISION,
604 (real_part.into_inner(), imag_part.into_inner()),
605 ),
606 _phantom: PhantomData,
607 }),
608 (Err(error_real_part), Ok(_)) => Err(ErrorsValidationRawComplex::InvalidRealPart {
609 source: error_real_part,
610 }),
611 (Ok(_), Err(error_imaginary_part)) => {
612 Err(ErrorsValidationRawComplex::InvalidImaginaryPart {
613 source: error_imaginary_part,
614 })
615 }
616 (Err(error_real_part), Err(error_imaginary_part)) => {
617 Err(ErrorsValidationRawComplex::InvalidBothParts {
618 real_error: error_real_part,
619 imag_error: error_imaginary_part,
620 })
621 }
622 }
623 }
624}
625#[duplicate::duplicate_item(
630 T;
631 [rug::Float];
632 [rug::Complex];
633)]
634impl NegAssign for T {
636 fn neg_assign(&mut self) {
638 <T as rug::ops::NegAssign>::neg_assign(self);
639 }
640}
641#[cfg(test)]
646mod tests {
647 use super::*;
648 use crate::{
649 ACosH, ComplexRugStrictFinite, ComplexScalarConstructors, ComplexScalarGetParts,
650 ComplexScalarMutateParts, ComplexScalarSetParts, Constants, Max, Min,
651 functions::{
652 ACos, ACosHErrors, ACosHInputErrors, ACosRealErrors, ACosRealInputErrors, ASin,
653 ASinRealErrors, ASinRealInputErrors, ATan, ATan2, ATan2Errors, ATanComplexErrors,
654 ATanComplexInputErrors, ATanH, ATanHErrors, ATanHInputErrors, Abs, Clamp, Exp,
655 ExpErrors, Hypot, Ln, Log2, LogarithmComplexErrors, LogarithmComplexInputErrors,
656 NegAssign, Pow, PowComplexBaseRealExponentErrors, PowIntExponentErrors,
657 PowIntExponentInputErrors, PowRealBaseRealExponentErrors, Reciprocal, ReciprocalErrors,
658 Sqrt, SqrtRealErrors, TotalCmp,
659 },
660 validation::ErrorsValidationRawReal,
661 };
662 use num::{One, Zero};
663 use rug::Float;
664 use try_create::{TryNew, TryNewValidated};
665
666 const PRECISION: u32 = 53;
667
668 mod fp_checks {
669 use super::*;
670 use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
671 use rug::Float;
672
673 #[test]
674 fn is_finite() {
675 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
676 assert!(real.is_finite());
677
678 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, f64::INFINITY));
679 assert!(real.is_err());
680
681 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
682 53,
683 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
684 ))
685 .unwrap();
686 assert!(complex.is_finite());
687
688 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
689 53,
690 (Float::with_val(53, f64::INFINITY), Float::with_val(53, 1.0)),
691 ));
692 assert!(complex.is_err());
693 }
694
695 #[test]
696 fn is_infinite() {
697 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
698 assert!(!real.is_infinite());
699
700 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, f64::INFINITY));
701 assert!(real.is_err());
702
703 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
704 53,
705 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
706 ))
707 .unwrap();
708 assert!(!complex.is_infinite());
709
710 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
711 53,
712 (Float::with_val(53, f64::INFINITY), Float::with_val(53, 1.0)),
713 ));
714 assert!(complex.is_err());
715 }
716
717 #[test]
718 fn is_nan() {
719 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
720 assert!(!real.is_nan());
721
722 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, f64::NAN));
723 assert!(matches!(real, Err(ErrorsValidationRawReal::IsNaN { .. })));
724
725 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
726 53,
727 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
728 ))
729 .unwrap();
730 assert!(!complex.is_nan());
731
732 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
733 53,
734 (Float::with_val(53, f64::NAN), Float::with_val(53, 1.0)),
735 ));
736 assert!(matches!(
737 complex,
738 Err(ErrorsValidationRawComplex::InvalidRealPart {
739 source: ErrorsValidationRawReal::IsNaN { .. }
740 })
741 ));
742 }
743
744 #[test]
745 fn is_normal() {
746 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
747 assert!(real.is_normal());
748
749 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
750 assert!(!real.is_normal());
751
752 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
753 53,
754 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
755 ))
756 .unwrap();
757 assert!(complex.is_normal());
758
759 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
760 53,
761 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
762 ))
763 .unwrap();
764 assert!(!complex.is_normal());
765 }
766 }
767
768 mod abs {
769 use super::*;
770
771 mod real {
772 use super::*;
773
774 #[test]
775 fn abs_valid() {
776 let value =
777 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, -4.0)).unwrap();
778
779 let expected_result =
780 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 4.0)).unwrap();
781 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
782 assert_eq!(value.abs(), expected_result);
783 }
784
785 #[test]
786 fn abs_zero() {
787 let value =
788 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
789
790 let expected_result =
791 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
792 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
793 assert_eq!(value.abs(), expected_result);
794 }
795
796 }
820
821 mod complex {
822 use super::*;
823
824 #[test]
825 fn abs_valid() {
826 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
827 53,
828 (rug::Float::with_val(53, 3.0), rug::Float::with_val(53, 4.0)),
829 ))
830 .unwrap();
831
832 let expected_result =
833 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 5.0)).unwrap();
834 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
835 assert_eq!(value.abs(), expected_result);
836 }
837
838 #[test]
839 fn abs_zero() {
840 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
841 53,
842 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
843 ))
844 .unwrap();
845
846 let expected_result =
847 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
848 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
849 assert_eq!(value.abs(), expected_result);
850 }
851 }
885 }
886
887 mod max_min {
888 use super::*;
889
890 #[test]
891 fn test_realrug_max() {
892 let value =
893 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0)).unwrap();
894 let other =
895 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0)).unwrap();
896 let expected =
897 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0)).unwrap();
898 assert_eq!(Max::max(&value, &other), &expected);
899
900 let neg_value =
901 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.0))
902 .unwrap();
903 let neg_other =
904 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -5.0))
905 .unwrap();
906 let neg_expected =
907 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.0))
908 .unwrap();
909 assert_eq!(Max::max(&neg_value, &neg_other), &neg_expected);
910 }
911
912 #[test]
913 fn test_realrug_min() {
914 let value =
915 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0)).unwrap();
916 let other =
917 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0)).unwrap();
918 let expected =
919 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0)).unwrap();
920 assert_eq!(Min::min(&value, &other), &expected);
921
922 let neg_value =
923 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.0))
924 .unwrap();
925 let neg_other =
926 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -5.0))
927 .unwrap();
928 let neg_expected =
929 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -5.0))
930 .unwrap();
931 assert_eq!(Min::min(&neg_value, &neg_other), &neg_expected);
932 }
933 }
934
935 mod builders {
936 use super::*;
937
938 mod real {
939 use super::*;
940
941 #[test]
942 fn try_new_nan() {
943 let nan = rug::Float::with_val(PRECISION, f64::NAN);
944 let err = RealRugStrictFinite::<PRECISION>::try_new(nan).unwrap_err();
945 assert!(matches!(err, ErrorsValidationRawReal::IsNaN { .. }));
946 }
947
948 #[test]
949 fn try_new_pos_infinity() {
950 let pos_infinity = rug::Float::with_val(PRECISION, f64::INFINITY);
951 let err = RealRugStrictFinite::<PRECISION>::try_new(pos_infinity).unwrap_err();
952 assert!(matches!(err, ErrorsValidationRawReal::IsPosInfinity { .. }));
953 }
954
955 #[test]
956 fn try_new_neg_infinity() {
957 let neg_infinity = rug::Float::with_val(PRECISION, f64::NEG_INFINITY);
958 let err = RealRugStrictFinite::<PRECISION>::try_new(neg_infinity).unwrap_err();
959 assert!(matches!(err, ErrorsValidationRawReal::IsNegInfinity { .. }));
960 }
961 }
962
963 mod complex {
964 use super::*;
965
966 #[test]
967 fn real_part() {
968 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
969 rug::Complex::with_val(PRECISION, (1.23, 4.56)),
970 )
971 .unwrap();
972 assert_eq!(c1.real_part(), 1.23);
973
974 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
975 rug::Complex::with_val(PRECISION, (-7.89, 0.12)),
976 )
977 .unwrap();
978 assert_eq!(c2.real_part(), -7.89);
979
980 let c3 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
981 rug::Complex::with_val(PRECISION, (0.0, 10.0)),
982 )
983 .unwrap();
984 assert_eq!(c3.real_part(), 0.0);
985
986 let c_nan_re = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
987 rug::Complex::with_val(PRECISION, (f64::NAN, 5.0)),
988 )
989 .unwrap_err();
990 assert!(matches!(
991 c_nan_re,
992 ErrorsValidationRawComplex::InvalidRealPart {
993 source: ErrorsValidationRawReal::IsNaN { .. }
994 }
995 ));
996
997 let c_inf_re = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
998 rug::Complex::with_val(PRECISION, (f64::INFINITY, 5.0)),
999 )
1000 .unwrap_err();
1001 assert!(matches!(
1002 c_inf_re,
1003 ErrorsValidationRawComplex::InvalidRealPart {
1004 source: ErrorsValidationRawReal::IsPosInfinity { .. }
1005 }
1006 ));
1007
1008 let c_neg_inf_re = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1009 rug::Complex::with_val(PRECISION, (f64::NEG_INFINITY, 5.0)),
1010 )
1011 .unwrap_err();
1012 assert!(matches!(
1013 c_neg_inf_re,
1014 ErrorsValidationRawComplex::InvalidRealPart {
1015 source: ErrorsValidationRawReal::IsNegInfinity { .. }
1016 }
1017 ));
1018 }
1019
1020 #[test]
1021 fn imag_part() {
1022 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1023 rug::Complex::with_val(PRECISION, (1.23, 4.56)),
1024 )
1025 .unwrap();
1026 assert_eq!(c1.imag_part(), 4.56);
1027
1028 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1029 rug::Complex::with_val(PRECISION, (-7.89, 0.12)),
1030 )
1031 .unwrap();
1032 assert_eq!(c2.imag_part(), 0.12);
1033
1034 let c3 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1035 rug::Complex::with_val(PRECISION, (10.0, 0.0)),
1036 )
1037 .unwrap();
1038 assert_eq!(c3.imag_part(), 0.0);
1039
1040 let c_nan_im = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1041 rug::Complex::with_val(PRECISION, (5.0, f64::NAN)),
1042 )
1043 .unwrap_err();
1044 assert!(matches!(
1045 c_nan_im,
1046 ErrorsValidationRawComplex::InvalidImaginaryPart {
1047 source: ErrorsValidationRawReal::IsNaN { .. }
1048 }
1049 ));
1050
1051 let c_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1052 rug::Complex::with_val(PRECISION, (5.0, f64::INFINITY)),
1053 )
1054 .unwrap_err();
1055 assert!(matches!(
1056 c_inf_im,
1057 ErrorsValidationRawComplex::InvalidImaginaryPart {
1058 source: ErrorsValidationRawReal::IsPosInfinity { .. }
1059 }
1060 ));
1061
1062 let c_neg_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1063 rug::Complex::with_val(PRECISION, (5.0, f64::NEG_INFINITY)),
1064 )
1065 .unwrap_err();
1066 assert!(matches!(
1067 c_neg_inf_im,
1068 ErrorsValidationRawComplex::InvalidImaginaryPart {
1069 source: ErrorsValidationRawReal::IsNegInfinity { .. }
1070 }
1071 ));
1072 }
1073
1074 #[test]
1075 fn try_new_complex() {
1076 let r1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.23).unwrap();
1077 let i1 = RealRugStrictFinite::<PRECISION>::try_from_f64(4.56).unwrap();
1078 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1079 r1.as_ref().clone(),
1080 i1.as_ref().clone(),
1081 )
1082 .unwrap();
1083 assert_eq!(c1.real_part(), r1);
1084 assert_eq!(c1.imag_part(), i1);
1085
1086 let r2 = RealRugStrictFinite::<PRECISION>::try_from_f64(-7.89).unwrap();
1087 let i2 = RealRugStrictFinite::<PRECISION>::try_from_f64(-0.12).unwrap();
1088 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1089 r2.as_ref().clone(),
1090 i2.as_ref().clone(),
1091 )
1092 .unwrap();
1093 assert_eq!(c2.real_part(), r2);
1094 assert_eq!(c2.imag_part(), i2);
1095
1096 let r3 = RealRugStrictFinite::<PRECISION>::try_from_f64(0.0).unwrap();
1097 let i3 = RealRugStrictFinite::<PRECISION>::try_from_f64(0.0).unwrap();
1098 let c3 = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1099 r3.as_ref().clone(),
1100 i3.as_ref().clone(),
1101 )
1102 .unwrap();
1103 assert_eq!(c3.real_part(), r3);
1104 assert_eq!(c3.real_part(), i3);
1105 assert!(c3.is_zero());
1106
1107 let c_nan_re = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1108 Float::with_val(PRECISION, f64::NAN),
1109 Float::with_val(PRECISION, 5.0),
1110 )
1111 .unwrap_err();
1112 assert!(matches!(
1113 c_nan_re,
1114 ErrorsValidationRawComplex::InvalidRealPart { .. }
1115 ));
1116
1117 let c_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1118 Float::with_val(PRECISION, 10.0),
1119 Float::with_val(PRECISION, f64::INFINITY),
1120 )
1121 .unwrap_err();
1122 assert!(matches!(
1123 c_inf_im,
1124 ErrorsValidationRawComplex::InvalidImaginaryPart { .. }
1125 ));
1126
1127 let c_nan_re_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1128 Float::with_val(PRECISION, f64::NAN),
1129 Float::with_val(PRECISION, f64::INFINITY),
1130 )
1131 .unwrap_err();
1132 assert!(matches!(
1133 c_nan_re_inf_im,
1134 ErrorsValidationRawComplex::InvalidBothParts { .. }
1135 ));
1136 }
1137
1138 #[test]
1139 fn try_from_complexf64() {
1140 let c1_in = num::Complex::new(1.23, 4.56);
1141 let c1 = ComplexRugStrictFinite::<PRECISION>::try_from(c1_in).unwrap();
1142 assert_eq!(c1.real_part(), c1_in.re);
1143 assert_eq!(c1.imag_part(), c1_in.im);
1144
1145 let c2_in = num::Complex::new(-7.89, -0.12);
1146 let c2 = ComplexRugStrictFinite::<PRECISION>::try_from(c2_in).unwrap();
1147 assert_eq!(c2.real_part(), c2_in.re);
1148 assert_eq!(c2.imag_part(), c2_in.im);
1149
1150 let c3_in = num::Complex::new(0., 0.);
1151 let c3 = ComplexRugStrictFinite::<PRECISION>::try_from(c3_in).unwrap();
1152 assert_eq!(c3.real_part(), c3_in.re);
1153 assert_eq!(c3.imag_part(), c3_in.im);
1154
1155 let c_nan_re =
1156 ComplexRugStrictFinite::<PRECISION>::try_from(num::Complex::new(f64::NAN, 5.0))
1157 .unwrap_err();
1158 assert!(matches!(
1159 c_nan_re,
1160 ErrorsValidationRawComplex::InvalidRealPart { .. }
1161 ));
1162
1163 let c_inf_im = ComplexRugStrictFinite::<PRECISION>::try_from(num::Complex::new(
1164 10.0,
1165 f64::INFINITY,
1166 ))
1167 .unwrap_err();
1168 assert!(matches!(
1169 c_inf_im,
1170 ErrorsValidationRawComplex::InvalidImaginaryPart { .. }
1171 ));
1172
1173 let c_nan_re_inf_im = ComplexRugStrictFinite::<PRECISION>::try_from(
1174 num::Complex::new(f64::NAN, f64::INFINITY),
1175 )
1176 .unwrap_err();
1177 assert!(matches!(
1178 c_nan_re_inf_im,
1179 ErrorsValidationRawComplex::InvalidBothParts { .. }
1180 ));
1181 }
1182
1183 #[test]
1184 fn try_new_pure_real() {
1185 let r1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.23).unwrap();
1186 let c1 =
1187 ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(r1.as_ref().clone())
1188 .unwrap();
1189 assert_eq!(c1.real_part(), r1);
1190 assert!(c1.imag_part().is_zero());
1191
1192 let c_nan = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
1193 Float::with_val(PRECISION, f64::NAN),
1194 )
1195 .unwrap_err();
1196 assert!(matches!(
1197 c_nan,
1198 ErrorsValidationRawComplex::InvalidRealPart {
1199 source: ErrorsValidationRawReal::IsNaN { .. }
1200 }
1201 ));
1202 }
1203
1204 #[test]
1205 fn try_new_pure_imaginary() {
1206 let i1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.23).unwrap();
1207 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
1208 i1.as_ref().clone(),
1209 )
1210 .unwrap();
1211 assert!(c1.real_part().is_zero());
1212 assert_eq!(c1.imag_part(), i1);
1213
1214 let c_nan = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
1215 Float::with_val(PRECISION, f64::NAN),
1216 )
1217 .unwrap_err();
1218 assert!(matches!(
1219 c_nan,
1220 ErrorsValidationRawComplex::InvalidImaginaryPart {
1221 source: ErrorsValidationRawReal::IsNaN { .. }
1222 }
1223 ));
1224 }
1225
1226 #[test]
1227 fn add_to_real_part() {
1228 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1229 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1230 )
1231 .unwrap();
1232 c.add_to_real_part(&RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1233 assert_eq!(c.real_part(), 4.0);
1234 assert_eq!(c.imag_part(), 2.0);
1235
1236 c.add_to_real_part(&RealRugStrictFinite::<PRECISION>::try_from_f64(-5.0).unwrap());
1237 assert_eq!(c.real_part(), -1.0);
1238 assert_eq!(c.imag_part(), 2.0);
1239 }
1240
1241 #[test]
1242 fn add_to_imaginary_part() {
1243 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1244 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1245 )
1246 .unwrap();
1247 c.add_to_imaginary_part(
1248 &RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap(),
1249 );
1250 assert_eq!(c.real_part(), 1.0);
1251 assert_eq!(c.imag_part(), 5.0);
1252
1253 c.add_to_imaginary_part(
1254 &RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap(),
1255 );
1256 assert_eq!(c.real_part(), 1.0);
1257 assert_eq!(c.imag_part(), 1.0);
1258 }
1259
1260 #[test]
1261 fn multiply_real_part() {
1262 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1263 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1264 )
1265 .unwrap();
1266 c.multiply_real_part(&RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1267 assert_eq!(c.real_part(), 3.0);
1268 assert_eq!(c.imag_part(), 2.0);
1269
1270 c.multiply_real_part(
1271 &RealRugStrictFinite::<PRECISION>::try_from_f64(-2.0).unwrap(),
1272 );
1273 assert_eq!(c.real_part(), -6.0);
1274 assert_eq!(c.imag_part(), 2.0);
1275 }
1276
1277 #[test]
1278 fn multiply_imaginary_part() {
1279 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1280 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1281 )
1282 .unwrap();
1283 c.multiply_imaginary_part(
1284 &RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap(),
1285 );
1286 assert_eq!(c.real_part(), 1.0);
1287 assert_eq!(c.imag_part(), 6.0);
1288
1289 c.multiply_imaginary_part(
1290 &RealRugStrictFinite::<PRECISION>::try_from_f64(-0.5).unwrap(),
1291 );
1292 assert_eq!(c.real_part(), 1.0);
1293 assert_eq!(c.imag_part(), -3.0);
1294 }
1295
1296 #[test]
1297 fn set_real_part() {
1298 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1299 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1300 )
1301 .unwrap();
1302 c.set_real_part(RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1303 assert_eq!(c.real_part(), 3.0);
1304 assert_eq!(c.imag_part(), 2.0);
1305
1306 c.set_real_part(RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap());
1307 assert_eq!(c.real_part(), -4.0);
1308 assert_eq!(c.imag_part(), 2.0);
1309 }
1310
1311 #[test]
1312 fn set_imaginary_part() {
1313 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1314 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1315 )
1316 .unwrap();
1317 c.set_imaginary_part(RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1318 assert_eq!(c.real_part(), 1.0);
1319 assert_eq!(c.imag_part(), 3.0);
1320
1321 c.set_imaginary_part(RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap());
1322 assert_eq!(c.real_part(), 1.0);
1323 assert_eq!(c.imag_part(), -4.0);
1324 }
1325 }
1326 }
1327
1328 mod mul {
1329 use super::*;
1330
1331 mod real {
1332 use super::*;
1333
1334 #[test]
1335 fn multiply_ref() {
1336 let r1 = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1337 PRECISION, 3.0,
1338 ))
1339 .unwrap();
1340 let r2 = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1341 PRECISION, 4.0,
1342 ))
1343 .unwrap();
1344 let result = r1 * &r2;
1345 assert_eq!(
1346 result,
1347 RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1348 PRECISION, 12.0
1349 ))
1350 .unwrap()
1351 );
1352 }
1353 }
1354
1355 mod complex {
1356 use super::*;
1357
1358 #[test]
1359 fn multiply_ref() {
1360 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1361 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1362 )
1363 .unwrap();
1364 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1365 rug::Complex::with_val(PRECISION, (3.0, 4.0)),
1366 )
1367 .unwrap();
1368 let result = c1 * &c2;
1369 assert_eq!(
1370 result,
1371 ComplexRugStrictFinite::<PRECISION>::try_new_validated(rug::Complex::with_val(
1372 PRECISION,
1373 (-5.0, 10.0),
1374 ))
1375 .unwrap()
1376 ); }
1378
1379 #[test]
1380 fn complex_times_real() {
1381 let r = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1382 PRECISION, 2.0,
1383 ))
1384 .unwrap();
1385 let c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1386 rug::Complex::with_val(PRECISION, (3.0, 4.0)),
1387 )
1388 .unwrap();
1389
1390 let result_expected = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1391 rug::Complex::with_val(PRECISION, (6.0, 8.0)),
1392 )
1393 .unwrap(); let result = c.clone() * &r;
1396 assert_eq!(&result, &result_expected);
1397
1398 let result = c.clone() * r.clone();
1399 assert_eq!(&result, &result_expected);
1400
1401 let mut result = c.clone();
1402 result *= &r;
1403 assert_eq!(&result, &result_expected);
1404
1405 let mut result = c.clone();
1406 result *= r;
1407 assert_eq!(&result, &result_expected);
1408 }
1409
1410 #[test]
1411 fn real_times_complex() {
1412 let r = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1413 PRECISION, 2.0,
1414 ))
1415 .unwrap();
1416 let c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1417 rug::Complex::with_val(PRECISION, (3.0, 4.0)),
1418 )
1419 .unwrap();
1420
1421 let result_expected = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1422 rug::Complex::with_val(PRECISION, (6.0, 8.0)),
1423 )
1424 .unwrap(); let result = &r * c.clone();
1427 assert_eq!(&result, &result_expected);
1428
1429 let result = r * c.clone();
1430 assert_eq!(&result, &result_expected);
1431 }
1432 }
1433 }
1434
1435 mod arithmetic {
1436 use super::*;
1437
1438 mod real {
1439 use super::*;
1440
1441 #[test]
1442 fn neg_assign() {
1443 let mut a = rug::Float::with_val(PRECISION, 1.);
1444 a.neg_assign();
1445 let a_expected = rug::Float::with_val(PRECISION, -1.);
1446 assert_eq!(a, a_expected);
1447
1448 let mut b = RealRugStrictFinite::<PRECISION>::one();
1449 b.neg_assign();
1450 let b_expected = RealRugStrictFinite::<PRECISION>::try_new_validated(
1451 rug::Float::with_val(PRECISION, -1.),
1452 )
1453 .unwrap();
1454 assert_eq!(&b, &b_expected);
1455 }
1456
1457 #[test]
1458 #[should_panic(expected = "Division failed validation")]
1459 fn div_by_zero() {
1460 let one = RealRugStrictFinite::<PRECISION>::one();
1461 let zero = RealRugStrictFinite::<PRECISION>::zero();
1462 let _ = &one / &zero;
1463 }
1464
1465 #[test]
1466 #[should_panic(expected = "Division failed validation")]
1467 fn div_assign_by_zero() {
1468 let mut num = RealRugStrictFinite::<PRECISION>::one();
1469 let zero_ref = &RealRugStrictFinite::<PRECISION>::zero();
1470 num /= zero_ref;
1471 }
1472 }
1473
1474 mod complex {
1475 use super::*;
1476
1477 #[test]
1478 fn neg_assign() {
1479 let re = rug::Float::with_val(PRECISION, 1.);
1480 let im = rug::Float::with_val(PRECISION, 2.);
1481 let mut num = rug::Complex::with_val(PRECISION, (re, im));
1482 num.neg_assign();
1483 let expected = rug::Complex::with_val(
1484 PRECISION,
1485 (
1486 rug::Float::with_val(PRECISION, -1.),
1487 rug::Float::with_val(PRECISION, -2.),
1488 ),
1489 );
1490 assert_eq!(&num, &expected);
1491
1492 let mut num = ComplexRugStrictFinite::<PRECISION>::try_new_validated(num).unwrap();
1493 let expected = num.clone().neg();
1494 num.neg_assign();
1495 assert_eq!(&num, &expected);
1496 }
1497
1498 #[test]
1499 #[should_panic(expected = "Division failed validation")]
1500 fn div_by_zero() {
1501 let one = ComplexRugStrictFinite::<PRECISION>::one();
1502 let zero = ComplexRugStrictFinite::<PRECISION>::zero();
1503 let _ = &one / &zero;
1504 }
1505
1506 #[test]
1507 #[should_panic(expected = "Division failed validation")]
1508 fn div_assign_by_zero() {
1509 let mut num = ComplexRugStrictFinite::<PRECISION>::one();
1510 let zero_ref = &ComplexRugStrictFinite::<PRECISION>::zero();
1511 num /= zero_ref;
1512 }
1513 }
1514 }
1515
1516 mod real_scalar_methods {
1517 use super::*;
1518
1519 #[test]
1520 fn epsilon() {
1521 let eps = RealRugStrictFinite::<PRECISION>::epsilon();
1522 assert!(eps.is_finite() && eps > RealRugStrictFinite::<PRECISION>::zero());
1523 let expected_eps_val =
1524 rug::Float::with_val(PRECISION, 2.0).pow(1i32 - PRECISION as i32);
1525 let expected_eps = RealRugStrictFinite::<PRECISION>::try_new(expected_eps_val).unwrap();
1526 assert_eq!(eps, expected_eps, "Epsilon value mismatch");
1527 }
1528
1529 #[test]
1530 fn clamp() {
1531 let val = RealRugStrictFinite::<PRECISION>::try_from_f64(5.0).unwrap();
1532 let min_val = RealRugStrictFinite::<PRECISION>::try_from_f64(0.0).unwrap();
1533 let max_val = RealRugStrictFinite::<PRECISION>::try_from_f64(10.0).unwrap();
1534
1535 assert_eq!(val.clone().kernel_clamp(&min_val, &max_val), val);
1536 assert_eq!(
1537 RealRugStrictFinite::<PRECISION>::try_from_f64(-5.0)
1538 .unwrap()
1539 .kernel_clamp(&min_val, &max_val),
1540 min_val
1541 );
1542 assert_eq!(
1543 RealRugStrictFinite::<PRECISION>::try_from_f64(15.0)
1544 .unwrap()
1545 .kernel_clamp(&min_val, &max_val),
1546 max_val
1547 );
1548 }
1549
1550 #[test]
1551 fn hypot() {
1552 let a = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
1553 let b = RealRugStrictFinite::<PRECISION>::try_from_f64(4.0).unwrap();
1554 let expected = RealRugStrictFinite::<PRECISION>::try_from_f64(5.0).unwrap();
1555 assert_eq!(a.kernel_hypot(&b), expected);
1556 }
1557
1558 #[test]
1559 fn signum() {
1560 assert_eq!(
1561 RealRugStrictFinite::<PRECISION>::try_from_f64(5.0)
1562 .unwrap()
1563 .kernel_signum(),
1564 RealRugStrictFinite::<PRECISION>::one()
1565 );
1566 assert_eq!(
1567 RealRugStrictFinite::<PRECISION>::try_from_f64(-5.0)
1568 .unwrap()
1569 .kernel_signum(),
1570 RealRugStrictFinite::<PRECISION>::negative_one()
1571 );
1572 assert_eq!(
1574 RealRugStrictFinite::<PRECISION>::zero().kernel_signum(),
1575 RealRugStrictFinite::<PRECISION>::one()
1576 );
1577 }
1578
1579 #[test]
1580 fn total_cmp() {
1581 let r1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
1582 let r2 = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1583 assert_eq!(r1.total_cmp(&r1), Ordering::Equal);
1584 assert_eq!(r1.total_cmp(&r2), Ordering::Less);
1585 assert_eq!(r2.total_cmp(&r1), Ordering::Greater);
1586 }
1587
1588 #[test]
1589 fn mul_add_mul_mut() {
1590 let mut a = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1591 let b = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap(); let c = RealRugStrictFinite::<PRECISION>::try_from_f64(4.0).unwrap(); let d = RealRugStrictFinite::<PRECISION>::try_from_f64(5.0).unwrap(); a.kernel_mul_add_mul_mut(&b, &c, &d);
1596 assert_eq!(
1597 a,
1598 RealRugStrictFinite::<PRECISION>::try_from_f64(26.0).unwrap()
1599 );
1600 }
1601
1602 #[test]
1603 fn mul_sub_mul_mut() {
1604 let mut a = RealRugStrictFinite::<PRECISION>::try_from_f64(10.0).unwrap();
1605 let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap(); let c = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap(); let d = RealRugStrictFinite::<PRECISION>::try_from_f64(4.0).unwrap(); a.kernel_mul_sub_mul_mut(&b, &c, &d);
1610 assert_eq!(
1611 a,
1612 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1613 );
1614 }
1615
1616 #[test]
1617 fn test_real_rug_constants() {
1618 let raw_float = |f: f64| Float::with_val(PRECISION, f);
1620
1621 let pi = RealRugStrictFinite::<PRECISION>::pi();
1623 let expected_pi = raw_float(-1.0).acos();
1624 assert_eq!(pi.as_ref(), &expected_pi);
1625
1626 let two_pi = RealRugStrictFinite::<PRECISION>::two_pi();
1628 let expected_two_pi = &expected_pi * raw_float(2.0);
1629 assert_eq!(two_pi.as_ref(), &expected_two_pi);
1630
1631 let pi_div_2 = RealRugStrictFinite::<PRECISION>::pi_div_2();
1633 let expected_pi_div_2 = raw_float(1.0).asin();
1634 assert_eq!(pi_div_2.as_ref(), &expected_pi_div_2);
1635
1636 let e = RealRugStrictFinite::<PRECISION>::e();
1638 let expected_e = raw_float(1.0).exp();
1639 assert_eq!(e.as_ref(), &expected_e);
1640
1641 let log2_e = RealRugStrictFinite::<PRECISION>::log2_e();
1643 let expected_log2_e = expected_e.clone().log2();
1644 assert_eq!(log2_e.as_ref(), &expected_log2_e);
1645
1646 let log10_e = RealRugStrictFinite::<PRECISION>::log10_e();
1648 let expected_log10_e = expected_e.log10();
1649 assert_eq!(log10_e.as_ref(), &expected_log10_e);
1650
1651 let ln_2 = RealRugStrictFinite::<PRECISION>::ln_2();
1653 let expected_ln_2 = raw_float(2.0).ln();
1654 assert_eq!(ln_2.as_ref(), &expected_ln_2);
1655
1656 let ln_10 = RealRugStrictFinite::<PRECISION>::ln_10();
1658 let expected_ln_10 = raw_float(10.0).ln();
1659 assert_eq!(ln_10.as_ref(), &expected_ln_10);
1660
1661 let log2_10 = RealRugStrictFinite::<PRECISION>::log2_10();
1663 let expected_log2_10 = raw_float(10.0).log2();
1664 assert_eq!(log2_10.as_ref(), &expected_log2_10);
1665
1666 let log10_2 = RealRugStrictFinite::<PRECISION>::log10_2();
1668 let expected_log10_2 = raw_float(2.0).log10();
1669 assert_eq!(log10_2.as_ref(), &expected_log10_2);
1670
1671 let max_finite = RealRugStrictFinite::<PRECISION>::max_finite();
1673 let expected_max_finite = <rug::Float as RawRealTrait>::raw_max_finite(PRECISION);
1674 assert_eq!(max_finite.as_ref(), &expected_max_finite);
1675
1676 let min_finite = RealRugStrictFinite::<PRECISION>::min_finite();
1678 let expected_min_finite = <rug::Float as RawRealTrait>::raw_min_finite(PRECISION);
1679 assert_eq!(min_finite.as_ref(), &expected_min_finite);
1680
1681 let epsilon = RealRugStrictFinite::<PRECISION>::epsilon();
1683 let expected_epsilon = <rug::Float as RawRealTrait>::raw_epsilon(PRECISION);
1684 assert_eq!(epsilon.as_ref(), &expected_epsilon);
1685
1686 assert_eq!(
1688 RealRugStrictFinite::<PRECISION>::negative_one().as_ref(),
1689 &raw_float(-1.0)
1690 );
1691
1692 assert_eq!(
1694 RealRugStrictFinite::<PRECISION>::two().as_ref(),
1695 &raw_float(2.0)
1696 );
1697
1698 assert_eq!(
1700 RealRugStrictFinite::<PRECISION>::one_div_2().as_ref(),
1701 &raw_float(0.5)
1702 );
1703 }
1704 }
1705
1706 mod function_traits {
1707 use super::*;
1708 use crate::{
1709 functions::{
1710 ATan2InputErrors, LogarithmRealErrors, LogarithmRealInputErrors,
1711 PowComplexBaseRealExponentInputErrors, PowRealBaseRealExponentInputErrors,
1712 ReciprocalInputErrors, SqrtRealInputErrors,
1713 },
1714 validation::ErrorsValidationRawReal,
1715 };
1716
1717 mod real {
1718 use super::*;
1719
1720 #[test]
1721 fn exp_overflow() {
1722 let large_val = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0e60).unwrap(); let res_large = large_val.try_exp();
1724 assert!(matches!(
1725 res_large,
1726 Err(ExpErrors::Output {
1727 source: ErrorsValidationRawReal::IsPosInfinity { .. }
1728 })
1729 ),);
1730 }
1731
1732 #[test]
1733 fn ln_domain_errors() {
1734 let neg_val = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.0).unwrap();
1735 assert!(matches!(
1736 neg_val.try_ln(),
1737 Err(LogarithmRealErrors::Input {
1738 source: LogarithmRealInputErrors::NegativeArgument { .. }
1739 })
1740 ));
1741
1742 let zero_val = RealRugStrictFinite::<PRECISION>::zero();
1743 assert!(matches!(
1744 zero_val.try_ln(),
1745 Err(LogarithmRealErrors::Input {
1746 source: LogarithmRealInputErrors::ZeroArgument { .. }
1747 })
1748 ));
1749 }
1750 } mod complex {
1753 use super::*;
1754
1755 #[test]
1756 fn log2_zero() {
1757 let zero_val = ComplexRugStrictFinite::<PRECISION>::zero();
1758 assert!(matches!(
1759 zero_val.try_log2(),
1760 Err(LogarithmComplexErrors::Input {
1761 source: LogarithmComplexInputErrors::ZeroArgument { .. }
1762 })
1763 ));
1764 }
1765 } mod pow {
1768 use super::*;
1769
1770 mod real_base {
1771 use super::*;
1772
1773 #[test]
1774 fn negative_base_real_exponent_error() {
1775 let base = RealRugStrictFinite::<PRECISION>::try_from_f64(-2.0).unwrap();
1776 let exponent = RealRugStrictFinite::<PRECISION>::try_from_f64(0.5).unwrap();
1777 let res = base.try_pow(&exponent);
1778 assert!(matches!(
1779 res,
1780 Err(PowRealBaseRealExponentErrors::Input {
1781 source: PowRealBaseRealExponentInputErrors::NegativeBase { .. }
1782 })
1783 ));
1784 }
1785
1786 #[test]
1787 fn real_base_uint_exponent() {
1788 let base = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1789 assert_eq!(
1790 base.clone().try_pow(3u8).unwrap(),
1791 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1792 );
1793 assert_eq!(
1794 base.clone().try_pow(3u16).unwrap(),
1795 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1796 );
1797 assert_eq!(
1798 base.clone().try_pow(3u32).unwrap(),
1799 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1800 );
1801 assert_eq!(
1802 base.clone().try_pow(3u64).unwrap(),
1803 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1804 );
1805 assert_eq!(
1806 base.clone().try_pow(3u128).unwrap(),
1807 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1808 );
1809 assert_eq!(
1810 base.clone().try_pow(3usize).unwrap(),
1811 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1812 );
1813
1814 assert_eq!(
1815 base.clone().pow(3u8),
1816 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1817 );
1818 assert_eq!(
1819 base.clone().pow(3u16),
1820 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1821 );
1822 assert_eq!(
1823 base.clone().pow(3u32),
1824 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1825 );
1826 assert_eq!(
1827 base.clone().pow(3u64),
1828 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1829 );
1830 assert_eq!(
1831 base.clone().pow(3u128),
1832 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1833 );
1834 assert_eq!(
1835 base.clone().pow(3usize),
1836 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1837 );
1838 }
1839
1840 #[test]
1841 fn real_base_int_exponent() {
1842 let base = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1843 assert_eq!(
1844 base.clone().try_pow(3i8).unwrap(),
1845 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1846 );
1847 assert_eq!(
1848 base.clone().try_pow(3i16).unwrap(),
1849 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1850 );
1851 assert_eq!(
1852 base.clone().try_pow(3i32).unwrap(),
1853 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1854 );
1855 assert_eq!(
1856 base.clone().try_pow(3i64).unwrap(),
1857 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1858 );
1859 assert_eq!(
1860 base.clone().try_pow(3i128).unwrap(),
1861 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1862 );
1863 assert_eq!(
1864 base.clone().try_pow(3isize).unwrap(),
1865 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1866 );
1867
1868 assert_eq!(
1869 base.clone().pow(3i8),
1870 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1871 );
1872 assert_eq!(
1873 base.clone().pow(3i16),
1874 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1875 );
1876 assert_eq!(
1877 base.clone().pow(3i32),
1878 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1879 );
1880 assert_eq!(
1881 base.clone().pow(3i64),
1882 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1883 );
1884 assert_eq!(
1885 base.clone().pow(3i128),
1886 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1887 );
1888 assert_eq!(
1889 base.clone().pow(3isize),
1890 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1891 );
1892 }
1893
1894 #[test]
1895 fn real_base_int_exponent_zero_neg_exp_error() {
1896 let base = RealRugStrictFinite::<PRECISION>::zero();
1897 let exponent: i32 = -2;
1898 let res = base.try_pow(exponent);
1899 assert!(matches!(
1900 res,
1901 Err(PowIntExponentErrors::Input {
1902 source: PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
1903 })
1904 ));
1905 }
1906 }
1907
1908 mod complex_base {
1909 use super::*;
1910
1911 #[test]
1912 fn complex_base_uint_exponent() {
1913 let base = ComplexRugStrictFinite::<PRECISION>::try_new(
1914 rug::Complex::with_val(PRECISION, (2.0, 3.0)),
1915 )
1916 .unwrap();
1917 let expected_res = ComplexRugStrictFinite::<PRECISION>::try_new(
1918 rug::Complex::with_val(PRECISION, (-46.0, 9.0)),
1919 )
1920 .unwrap();
1921
1922 assert_eq!(&base.clone().try_pow(3u8).unwrap(), &expected_res);
1923 assert_eq!(&base.clone().try_pow(3u16).unwrap(), &expected_res);
1924 assert_eq!(&base.clone().try_pow(3u32).unwrap(), &expected_res);
1925 assert_eq!(&base.clone().try_pow(3u64).unwrap(), &expected_res);
1926 assert_eq!(&base.clone().try_pow(3u128).unwrap(), &expected_res);
1927 assert_eq!(&base.clone().try_pow(3usize).unwrap(), &expected_res);
1928
1929 assert_eq!(&base.clone().pow(3u8), &expected_res);
1930 assert_eq!(&base.clone().pow(3u16), &expected_res);
1931 assert_eq!(&base.clone().pow(3u32), &expected_res);
1932 assert_eq!(&base.clone().pow(3u64), &expected_res);
1933 assert_eq!(&base.clone().pow(3u128), &expected_res);
1934 assert_eq!(&base.clone().pow(3usize), &expected_res);
1935 }
1936
1937 #[test]
1938 fn complex_base_int_exponent() {
1939 let base = ComplexRugStrictFinite::<PRECISION>::try_new(
1940 rug::Complex::with_val(PRECISION, (2.0, 3.0)),
1941 )
1942 .unwrap();
1943 let expected_res = ComplexRugStrictFinite::<PRECISION>::try_new(
1944 rug::Complex::with_val(PRECISION, (-46.0, 9.0)),
1945 )
1946 .unwrap();
1947
1948 assert_eq!(&base.clone().try_pow(3i8).unwrap(), &expected_res);
1949 assert_eq!(&base.clone().try_pow(3i16).unwrap(), &expected_res);
1950 assert_eq!(&base.clone().try_pow(3i32).unwrap(), &expected_res);
1951 assert_eq!(&base.clone().try_pow(3i64).unwrap(), &expected_res);
1952 assert_eq!(&base.clone().try_pow(3i128).unwrap(), &expected_res);
1953 assert_eq!(&base.clone().try_pow(3isize).unwrap(), &expected_res);
1954
1955 assert_eq!(&base.clone().pow(3i8), &expected_res);
1956 assert_eq!(&base.clone().pow(3i16), &expected_res);
1957 assert_eq!(&base.clone().pow(3i32), &expected_res);
1958 assert_eq!(&base.clone().pow(3i64), &expected_res);
1959 assert_eq!(&base.clone().pow(3i128), &expected_res);
1960 assert_eq!(&base.clone().pow(3isize), &expected_res);
1961 }
1962
1963 #[test]
1964 fn complex_zero_base_negative_real_exponent_error() {
1965 let base = ComplexRugStrictFinite::<PRECISION>::zero();
1966 let exponent = RealRugStrictFinite::<PRECISION>::try_from_f64(-2.0).unwrap();
1967 let res = base.try_pow(&exponent);
1968 assert!(matches!(
1969 res,
1970 Err(PowComplexBaseRealExponentErrors::Input {
1971 source:
1972 PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent { .. }
1973 })
1974 ));
1975 }
1976
1977 #[test]
1978 fn complex_zero_base_zero_real_exponent() {
1979 let base = ComplexRugStrictFinite::<PRECISION>::zero();
1980 let exponent = RealRugStrictFinite::<PRECISION>::zero();
1981 let res = base.try_pow(&exponent).unwrap();
1982 assert_eq!(res, ComplexRugStrictFinite::<PRECISION>::one());
1983 }
1984
1985 #[test]
1986 fn complex_base_int_exponent_zero_neg_exp_error() {
1987 let base = ComplexRugStrictFinite::<PRECISION>::zero();
1988 let exponent: i32 = -2;
1989 let res = base.try_pow(exponent);
1990 assert!(matches!(
1991 res,
1992 Err(PowIntExponentErrors::Input {
1993 source: PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
1994 })
1995 ));
1996 }
1997 }
1998 }
1999
2000 #[test]
2001 fn reciprocal_real_rug_zero() {
2002 let zero_val = RealRugStrictFinite::<PRECISION>::zero();
2003 let res = zero_val.try_reciprocal();
2004 assert!(matches!(
2005 res,
2006 Err(ReciprocalErrors::Input {
2007 source: ReciprocalInputErrors::DivisionByZero { .. }
2008 })
2009 ));
2010 }
2011
2012 #[test]
2013 fn reciprocal_complex_rug_zero() {
2014 let zero_val = ComplexRugStrictFinite::<PRECISION>::zero();
2015 let res = zero_val.try_reciprocal();
2016 assert!(matches!(
2017 res,
2018 Err(ReciprocalErrors::Input {
2019 source: ReciprocalInputErrors::DivisionByZero { .. }
2020 })
2021 ));
2022 }
2023
2024 #[test]
2025 fn sqrt_real_rug_negative_input() {
2026 let neg_val = RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap();
2027 let res = neg_val.try_sqrt();
2028 assert!(matches!(
2029 res,
2030 Err(SqrtRealErrors::Input {
2031 source: SqrtRealInputErrors::NegativeValue { .. }
2032 })
2033 ));
2034 }
2035
2036 mod trigonometric {
2037 use super::*;
2038
2039 #[test]
2040 fn atan2_real_rug_zero_over_zero() {
2041 let zero_val = RealRugStrictFinite::<PRECISION>::zero();
2042 let res = zero_val.try_atan2(&RealRugStrictFinite::<PRECISION>::zero());
2043 assert!(matches!(
2044 res,
2045 Err(ATan2Errors::Input {
2046 source: ATan2InputErrors::ZeroOverZero { .. }
2047 })
2048 ));
2049 }
2050
2051 #[test]
2069 fn asin_real_rug_out_of_domain() {
2070 let val_gt_1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.5).unwrap();
2071 assert!(matches!(
2072 val_gt_1.try_asin(),
2073 Err(ASinRealErrors::Input {
2074 source: ASinRealInputErrors::OutOfDomain { .. }
2075 })
2076 ));
2077 let val_lt_neg1 = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.5).unwrap();
2078 assert!(matches!(
2079 val_lt_neg1.try_asin(),
2080 Err(ASinRealErrors::Input {
2081 source: ASinRealInputErrors::OutOfDomain { .. }
2082 })
2083 ));
2084 }
2085
2086 #[test]
2087 fn acos_real_rug_out_of_domain() {
2088 let val_gt_1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.5).unwrap();
2089 assert!(matches!(
2090 val_gt_1.try_acos(),
2091 Err(ACosRealErrors::Input {
2092 source: ACosRealInputErrors::OutOfDomain { .. }
2093 })
2094 ));
2095 let val_lt_neg1 = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.5).unwrap();
2096 assert!(matches!(
2097 val_lt_neg1.try_acos(),
2098 Err(ACosRealErrors::Input {
2099 source: ACosRealInputErrors::OutOfDomain { .. }
2100 })
2101 ));
2102 }
2103
2104 #[test]
2105 fn atan_complex_rug_pole() {
2106 let i_val = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
2108 Float::with_val(PRECISION, 1.0),
2109 )
2110 .unwrap();
2111 assert!(matches!(
2112 i_val.try_atan(),
2113 Err(ATanComplexErrors::Input {
2114 source: ATanComplexInputErrors::ArgumentIsPole { .. }
2115 })
2116 ));
2117
2118 let neg_i_val = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
2119 Float::with_val(PRECISION, -1.0),
2120 )
2121 .unwrap();
2122 assert!(matches!(
2123 neg_i_val.try_atan(),
2124 Err(ATanComplexErrors::Input {
2125 source: ATanComplexInputErrors::ArgumentIsPole { .. }
2126 })
2127 ));
2128 }
2129 } mod hyperbolic {
2132 use super::*;
2133
2134 mod real {
2135 use super::*;
2136
2137 #[test]
2138 fn atanh_real_rug_out_of_domain() {
2139 let val_ge_1 = RealRugStrictFinite::<PRECISION>::one(); assert!(matches!(
2141 val_ge_1.try_atanh(),
2142 Err(ATanHErrors::Input {
2143 source: ATanHInputErrors::OutOfDomain { .. }
2144 })
2145 ));
2146
2147 let val_le_neg1 = RealRugStrictFinite::<PRECISION>::negative_one(); assert!(matches!(
2149 val_le_neg1.try_atanh(),
2150 Err(ATanHErrors::Input {
2151 source: ATanHInputErrors::OutOfDomain { .. }
2152 })
2153 ));
2154 }
2155
2156 #[test]
2157 fn acosh_real_rug_out_of_domain() {
2158 let val_lt_1 = RealRugStrictFinite::<PRECISION>::try_from_f64(0.5).unwrap();
2159 assert!(matches!(
2160 val_lt_1.try_acosh(),
2161 Err(ACosHErrors::Input {
2162 source: ACosHInputErrors::OutOfDomain { .. }
2163 })
2164 ));
2165 }
2166 }
2167
2168 mod complex {
2169 use super::*;
2170
2171 #[test]
2190 fn acosh_out_of_domain() {
2191 let val_on_branch_cut = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
2193 Float::with_val(PRECISION, 0.5),
2194 )
2195 .unwrap();
2196 assert!(matches!(
2197 val_on_branch_cut.try_acosh(),
2198 Err(ACosHErrors::Input {
2199 source: ACosHInputErrors::OutOfDomain { .. }
2200 })
2201 ));
2202
2203 let val_on_branch_cut_neg =
2204 ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(Float::with_val(
2205 PRECISION, -5.0,
2206 ))
2207 .unwrap();
2208 assert!(matches!(
2209 val_on_branch_cut_neg.try_acosh(),
2210 Err(ACosHErrors::Input {
2211 source: ACosHInputErrors::OutOfDomain { .. }
2212 })
2213 ));
2214 }
2215
2216 #[test]
2217 fn atanh_out_of_domain() {
2218 let val_ge_1 = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
2219 Float::with_val(PRECISION, 1.0),
2220 )
2221 .unwrap();
2222 assert!(matches!(
2223 val_ge_1.try_atanh(),
2224 Err(ATanHErrors::Input {
2225 source: ATanHInputErrors::OutOfDomain { .. }
2226 })
2227 ));
2228
2229 let val_le_neg1 = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
2230 Float::with_val(PRECISION, -1.0),
2231 )
2232 .unwrap();
2233 assert!(matches!(
2234 val_le_neg1.try_atanh(),
2235 Err(ATanHErrors::Input {
2236 source: ATanHInputErrors::OutOfDomain { .. }
2237 })
2238 ));
2239 }
2240 }
2241
2242 } }
2260
2261 mod summation {
2262 use super::*;
2263
2264 const PRECISION: u32 = 53;
2265
2266 type RealValidated = RealRugStrictFinite<PRECISION>;
2267 type ComplexValidated = ComplexRugStrictFinite<PRECISION>;
2268
2269 #[test]
2270 fn sum_real() {
2271 let values = vec![
2272 RealValidated::try_from_f64(1.0).unwrap(),
2273 RealValidated::try_from_f64(2.0).unwrap(),
2274 RealValidated::try_from_f64(3.0).unwrap(),
2275 RealValidated::try_from_f64(4.0).unwrap(),
2276 RealValidated::try_from_f64(5.0).unwrap(),
2277 ];
2278 let sum: RealValidated = values.into_iter().sum();
2279 assert_eq!(sum, RealValidated::try_from_f64(15.0).unwrap());
2280 }
2281
2282 #[test]
2283 fn sum_real_compensated() {
2284 let values = vec![
2286 RealValidated::try_from_f64(1.0e100).unwrap(),
2287 RealValidated::try_from_f64(1.0).unwrap(),
2288 RealValidated::try_from_f64(-1.0e100).unwrap(),
2289 ];
2290 let sum: RealValidated = values.into_iter().sum();
2291 assert_eq!(sum, RealValidated::try_from_f64(1.0).unwrap());
2293 }
2294
2295 #[test]
2296 fn sum_complex() {
2297 let values = vec![
2298 ComplexValidated::try_new_complex(
2299 rug::Float::with_val(PRECISION, 1.),
2300 rug::Float::with_val(PRECISION, 2.),
2301 )
2302 .unwrap(),
2303 ComplexValidated::try_new_complex(
2304 rug::Float::with_val(PRECISION, 3.),
2305 rug::Float::with_val(PRECISION, 4.),
2306 )
2307 .unwrap(),
2308 ComplexValidated::try_new_complex(
2309 rug::Float::with_val(PRECISION, 5.),
2310 rug::Float::with_val(PRECISION, 6.),
2311 )
2312 .unwrap(),
2313 ];
2314 let sum: ComplexValidated = values.into_iter().sum();
2315 assert_eq!(
2316 sum,
2317 ComplexValidated::try_new_complex(
2318 rug::Float::with_val(PRECISION, 9.),
2319 rug::Float::with_val(PRECISION, 12.)
2320 )
2321 .unwrap()
2322 );
2323 }
2324
2325 #[test]
2326 fn sum_complex_compensated() {
2327 let values = [
2328 ComplexValidated::try_new_complex(
2329 rug::Float::with_val(PRECISION, 1.0e100),
2330 rug::Float::with_val(PRECISION, -1.0e100),
2331 )
2332 .unwrap(),
2333 ComplexValidated::try_new_complex(
2334 rug::Float::with_val(PRECISION, 1.),
2335 rug::Float::with_val(PRECISION, 2.),
2336 )
2337 .unwrap(),
2338 ComplexValidated::try_new_complex(
2339 rug::Float::with_val(PRECISION, -1.0e100),
2340 rug::Float::with_val(PRECISION, 1.0e100),
2341 )
2342 .unwrap(),
2343 ];
2344 let sum: ComplexValidated = values.iter().cloned().sum();
2345 assert_eq!(
2346 sum,
2347 ComplexValidated::try_new_complex(
2348 rug::Float::with_val(PRECISION, 1.),
2349 rug::Float::with_val(PRECISION, 2.)
2350 )
2351 .unwrap()
2352 );
2353 }
2354 } mod random {
2357 use super::*;
2358 use crate::{RandomSampleFromF64, new_random_vec};
2359 use rand::{Rng, SeedableRng, distr::Uniform, rngs::StdRng};
2360
2361 const PRECISION: u32 = 53;
2362
2363 type RealValidated = RealRugStrictFinite<PRECISION>;
2364 type ComplexValidated = ComplexRugStrictFinite<PRECISION>;
2365
2366 #[test]
2370 fn test_random_real_validated() {
2371 let seed = [42; 32];
2372 let mut rng = StdRng::from_seed(seed);
2373
2374 let random_real: RealValidated = rng.random();
2375
2376 assert_eq!(random_real, 0.23713468825474326);
2378
2379 let mut rng2 = StdRng::from_seed(seed);
2381 let random_real2: RealValidated = rng2.random();
2382 assert_eq!(random_real, random_real2);
2383 }
2384
2385 #[test]
2390 fn test_random_complex_validated() {
2391 let seed = [99; 32];
2392 let mut rng = StdRng::from_seed(seed);
2393
2394 let random_complex: ComplexValidated = rng.random();
2395
2396 let real_part = random_complex.real_part();
2399 let imag_part = random_complex.imag_part();
2400
2401 assert_eq!(real_part, 0.9995546882627792);
2402 assert_eq!(imag_part, 0.08932180682540247);
2403
2404 let mut rng2 = StdRng::from_seed(seed);
2406 let random_complex2: ComplexValidated = rng2.random();
2407 assert_eq!(random_complex, random_complex2);
2408 }
2409
2410 const SEED: [u8; 32] = [42; 32];
2411
2412 #[test]
2413 fn test_sample_real_validated() {
2414 let mut rng = StdRng::from_seed(SEED);
2415 let dist = Uniform::new(-10.0, 10.0).unwrap();
2416
2417 let val = RealValidated::sample_from(&dist, &mut rng);
2418 assert_eq!(val, -5.257306234905137);
2419
2420 let mut rng2 = StdRng::from_seed(SEED);
2422 let val2 = RealValidated::sample_from(&dist, &mut rng2);
2423 assert_eq!(val, val2);
2424 }
2425
2426 #[test]
2427 fn test_sample_complex_validated() {
2428 let mut rng = StdRng::from_seed(SEED);
2429 let dist = Uniform::new(-10.0, 10.0).unwrap();
2430
2431 let val = ComplexValidated::sample_from(&dist, &mut rng);
2432 assert_eq!(val.real_part(), -5.257306234905137);
2433 assert_eq!(val.imag_part(), 7.212119776268775);
2434
2435 let mut rng2 = StdRng::from_seed(SEED);
2437 let val2 = ComplexValidated::sample_from(&dist, &mut rng2);
2438 assert_eq!(val, val2);
2439 }
2440
2441 #[test]
2442 fn new_random_vec_real() {
2443 let mut rng = StdRng::from_seed(SEED);
2444 let dist = Uniform::new(-10.0, 10.0).unwrap();
2445 let vec: Vec<RealValidated> = new_random_vec(3, &dist, &mut rng);
2446 assert_eq!(vec.len(), 3);
2447 assert_eq!(vec[0], -5.257306234905137);
2448 assert_eq!(vec[1], 7.212119776268775);
2449 assert_eq!(vec[2], -4.666248990558111);
2450
2451 let mut rng2 = StdRng::from_seed(SEED);
2453 let vec2: Vec<RealValidated> = new_random_vec(3, &dist, &mut rng2);
2454 assert_eq!(vec, vec2);
2455 }
2456
2457 #[test]
2458 fn new_random_vec_complex() {
2459 let mut rng = StdRng::from_seed(SEED);
2460 let dist = Uniform::new(-10.0, 10.0).unwrap();
2461 let vec: Vec<ComplexValidated> = new_random_vec(3, &dist, &mut rng);
2462 assert_eq!(vec.len(), 3);
2463 assert_eq!(vec[0].real_part(), -5.257306234905137);
2464 assert_eq!(vec[0].imag_part(), 7.212119776268775);
2465 assert_eq!(vec[1].real_part(), -4.666248990558111);
2466 assert_eq!(vec[1].imag_part(), 9.66047141517383);
2467 assert_eq!(vec[2].real_part(), -9.04279551029691);
2468 assert_eq!(vec[2].imag_part(), -1.026624649331671);
2469
2470 let mut rng2 = StdRng::from_seed(SEED);
2472 let vec2: Vec<ComplexValidated> = new_random_vec(3, &dist, &mut rng2);
2473 assert_eq!(vec, vec2);
2474 }
2475 }
2476}