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 ErrorsRawRealToInteger, ErrorsTryFromf64, ErrorsValidationRawComplex,
12 ErrorsValidationRawReal, FpChecks, 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::{
20 backtrace::Backtrace,
21 cmp::Ordering,
22 hash::{Hash, Hasher},
23 marker::PhantomData,
24 num::FpCategory,
25};
26use try_create::IntoInner;
27
28impl RawScalarTrait for rug::Float {
29 type ValidationErrors = ErrorsValidationRawReal<rug::Float>;
30
31 fn raw_zero(precision: u32) -> Self {
32 rug::Float::with_val(precision, 0.)
33 }
34
35 fn is_zero(&self) -> bool {
36 rug::Float::is_zero(self)
37 }
38
39 fn raw_one(precision: u32) -> Self {
40 rug::Float::with_val(precision, 1.)
41 }
42
43 #[duplicate_item(
44 unchecked_method method;
45 [unchecked_reciprocal] [recip];
46 [unchecked_exp] [exp];
47 [unchecked_sqrt] [sqrt];
48 [unchecked_sin] [sin];
49 [unchecked_asin] [asin];
50 [unchecked_cos] [cos];
51 [unchecked_acos] [acos];
52 [unchecked_tan] [tan];
53 [unchecked_atan] [atan];
54 [unchecked_sinh] [sinh];
55 [unchecked_asinh] [asinh];
56 [unchecked_cosh] [cosh];
57 [unchecked_acosh] [acosh];
58 [unchecked_tanh] [tanh];
59 [unchecked_atanh] [atanh];
60 [unchecked_ln] [ln];
61 [unchecked_log2] [log2];
62 [unchecked_log10] [log10];
63 )]
64 #[inline(always)]
65 fn unchecked_method(self) -> Self {
66 rug::Float::method(self)
67 }
68
69 #[duplicate_item(
70 unchecked_method exponent_type;
71 [unchecked_pow_exponent_i8] [i8];
72 [unchecked_pow_exponent_i16] [i16];
73 [unchecked_pow_exponent_i32] [i32];
74 [unchecked_pow_exponent_i64] [i64];
75 [unchecked_pow_exponent_i128] [i128];
76 [unchecked_pow_exponent_isize] [isize];
77 [unchecked_pow_exponent_u8] [u8];
78 [unchecked_pow_exponent_u16] [u16];
79 [unchecked_pow_exponent_u32] [u32];
80 [unchecked_pow_exponent_u64] [u64];
81 [unchecked_pow_exponent_u128] [u128];
82 [unchecked_pow_exponent_usize] [usize];
83 )]
84 #[inline(always)]
85 fn unchecked_method(self, exponent: &exponent_type) -> Self {
86 rug::Float::pow(self, exponent)
87 }
88
89 #[inline(always)]
93 fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
94 rug::Float::mul_add(self, b, c)
95 }
96}
97
98impl RawRealTrait for rug::Float {
99 type RawComplex = rug::Complex;
100
101 #[inline(always)]
102 fn unchecked_abs(self) -> rug::Float {
103 rug::Float::abs(self)
104 }
105
106 #[inline(always)]
107 fn unchecked_atan2(self, denominator: &Self) -> Self {
108 rug::Float::atan2(self, denominator)
109 }
110
111 #[inline(always)]
112 fn unchecked_pow_exponent_real(self, exponent: &Self) -> Self {
113 rug::Float::pow(self, exponent)
114 }
115
116 #[inline(always)]
117 fn unchecked_hypot(self, other: &Self) -> Self {
118 rug::Float::hypot(self, other)
119 }
120
121 #[inline(always)]
122 fn unchecked_ln_1p(self) -> Self {
123 rug::Float::ln_1p(self)
124 }
125
126 #[inline(always)]
127 fn unchecked_exp_m1(self) -> Self {
128 rug::Float::exp_m1(self)
129 }
130
131 #[inline(always)]
134 fn unchecked_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
135 self.mul_add_mul_mut(mul, add_mul1, add_mul2);
136 }
137
138 #[inline(always)]
141 fn unchecked_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
142 self.mul_sub_mul_mut(mul, sub_mul1, sub_mul2);
143 }
144
145 #[inline(always)]
146 fn raw_total_cmp(&self, other: &Self) -> Ordering {
147 rug::Float::total_cmp(self, other)
148 }
149
150 #[inline(always)]
152 fn raw_clamp(self, min: &Self, max: &Self) -> Self {
153 rug::Float::clamp(self, min, max)
154 }
155
156 #[inline(always)]
157 fn raw_classify(&self) -> FpCategory {
158 rug::Float::classify(self)
159 }
160
161 #[inline(always)]
162 fn raw_two(precision: u32) -> Self {
163 rug::Float::with_val(precision, 2.)
164 }
165
166 #[inline(always)]
167 fn raw_one_div_2(precision: u32) -> Self {
168 rug::Float::with_val(precision, 0.5)
169 }
170
171 #[inline(always)]
172 fn raw_pi(precision: u32) -> Self {
173 rug::Float::with_val(precision, -1.).acos()
174 }
175
176 #[inline(always)]
177 fn raw_two_pi(precision: u32) -> Self {
178 Self::raw_pi(precision) * rug::Float::with_val(precision, 2.)
179 }
180
181 #[inline(always)]
182 fn raw_pi_div_2(precision: u32) -> Self {
183 rug::Float::with_val(precision, 1.).asin()
184 }
185
186 #[inline(always)]
187 fn raw_max_finite(precision: u32) -> Self {
188 let one = rug::Float::with_val(precision, 1);
194 let eps = rug::Float::with_val(precision, rug::Float::u_pow_u(2, precision)).recip();
195 let significand = one - &eps;
196
197 let max_exp = rug::float::exp_max() - 1;
199 significand * rug::Float::with_val(precision, rug::Float::u_pow_u(2, max_exp as u32))
201 }
202
203 #[inline(always)]
204 fn raw_min_finite(precision: u32) -> Self {
205 Self::raw_max_finite(precision).neg()
206 }
207
208 #[inline(always)]
209 fn raw_epsilon(precision: u32) -> Self {
210 rug::Float::u_pow_u(2, precision - 1)
211 .complete(precision)
212 .recip()
213 }
214
215 #[inline(always)]
216 fn raw_ln_2(precision: u32) -> Self {
217 rug::Float::with_val(precision, 2.).ln()
218 }
219
220 #[inline(always)]
221 fn raw_ln_10(precision: u32) -> Self {
222 rug::Float::with_val(precision, 10.).ln()
223 }
224
225 #[inline(always)]
226 fn raw_log10_2(precision: u32) -> Self {
227 rug::Float::with_val(precision, 2.).log10()
228 }
229
230 #[inline(always)]
231 fn raw_log2_10(precision: u32) -> Self {
232 rug::Float::with_val(precision, 10.).log2()
233 }
234
235 #[inline(always)]
236 fn raw_log2_e(precision: u32) -> Self {
237 Self::raw_e(precision).log2()
238 }
239
240 #[inline(always)]
241 fn raw_log10_e(precision: u32) -> Self {
242 Self::raw_e(precision).log10()
243 }
244
245 #[inline(always)]
246 fn raw_e(precision: u32) -> Self {
247 rug::Float::with_val(precision, 1.).exp()
248 }
249
250 #[inline(always)]
251 fn try_new_raw_real_from_f64<RealPolicy: ValidationPolicyReal<Value = Self>>(
252 value: f64,
253 ) -> Result<Self, ErrorsTryFromf64<Self>> {
254 let precision = RealPolicy::PRECISION;
255 let value_rug = RealPolicy::validate(rug::Float::with_val(precision, value))
256 .map_err(|e| ErrorsTryFromf64::Output { source: e })?;
257 if value_rug == value {
258 Ok(value_rug)
259 } else {
260 Err(ErrorsTryFromf64::NonRepresentableExactly {
261 value_in: value,
262 value_converted_from_f64: value_rug,
263 precision,
264 backtrace: Backtrace::force_capture(),
265 })
266 }
267 }
268
269 #[inline(always)]
270 fn precision(&self) -> u32 {
271 rug::Float::prec(self)
272 }
273
274 #[inline(always)]
275 fn compute_hash<H: Hasher>(&self, state: &mut H) {
276 debug_assert!(
277 self.is_finite(),
278 "Hashing a non-finite f64 value (i.e., NaN or Infinity) may lead to inconsistent results."
279 );
280 self.prec().hash(state);
282
283 if self.is_zero() {
285 rug::Float::with_val(self.prec(), 0.0)
287 .to_string_radix(10, None)
288 .hash(state);
289 } else {
290 self.to_string_radix(10, None).hash(state)
293 }
294 }
295
296 #[inline(always)]
297 fn truncate_to_usize(self) -> Result<usize, ErrorsRawRealToInteger<rug::Float, usize>> {
298 if !self.is_finite() {
299 return Err(ErrorsRawRealToInteger::NotFinite {
300 value: self,
301 backtrace: Backtrace::force_capture(),
302 });
303 }
304
305 let truncation = self.clone().trunc();
306
307 let out_of_range = || ErrorsRawRealToInteger::OutOfRange {
308 value: self,
309 min: usize::MIN,
310 max: usize::MAX,
311 backtrace: Backtrace::force_capture(),
312 };
313
314 let truncation_as_rug_integer = truncation.to_integer().ok_or_else(out_of_range.clone())?;
315
316 truncation_as_rug_integer
317 .to_usize()
318 .ok_or_else(out_of_range)
319 }
320}
321
322impl RawScalarTrait for rug::Complex {
323 type ValidationErrors = ErrorsValidationRawComplex<ErrorsValidationRawReal<rug::Float>>;
324
325 fn raw_zero(precision: u32) -> Self {
326 rug::Complex::with_val(precision, (0., 0.))
327 }
328
329 fn is_zero(&self) -> bool {
330 rug::Complex::is_zero(self)
331 }
332
333 fn raw_one(precision: u32) -> Self {
334 rug::Complex::with_val(precision, (1., 0.))
335 }
336
337 #[duplicate_item(
338 unchecked_method method;
339 [unchecked_reciprocal] [recip];
340 [unchecked_exp] [exp];
341 [unchecked_sqrt] [sqrt];
342 [unchecked_sin] [sin];
343 [unchecked_asin] [asin];
344 [unchecked_cos] [cos];
345 [unchecked_acos] [acos];
346 [unchecked_tan] [tan];
347 [unchecked_atan] [atan];
348 [unchecked_sinh] [sinh];
349 [unchecked_asinh] [asinh];
350 [unchecked_cosh] [cosh];
351 [unchecked_acosh] [acosh];
352 [unchecked_tanh] [tanh];
353 [unchecked_atanh] [atanh];
354 [unchecked_ln] [ln];
355 [unchecked_log10] [log10];
356 )]
357 #[inline(always)]
358 fn unchecked_method(self) -> Self {
359 rug::Complex::method(self)
360 }
361
362 #[inline(always)]
363 fn unchecked_log2(self) -> Self {
364 let ln_2 = rug::Float::with_val(self.real().prec(), 2.).ln();
365 rug::Complex::ln(self) / ln_2
366 }
367
368 #[duplicate_item(
369 unchecked_method exponent_type;
370 [unchecked_pow_exponent_i8] [i8];
371 [unchecked_pow_exponent_i16] [i16];
372 [unchecked_pow_exponent_i32] [i32];
373 [unchecked_pow_exponent_i64] [i64];
374 [unchecked_pow_exponent_i128] [i128];
375 [unchecked_pow_exponent_isize] [isize];
376 [unchecked_pow_exponent_u8] [u8];
377 [unchecked_pow_exponent_u16] [u16];
378 [unchecked_pow_exponent_u32] [u32];
379 [unchecked_pow_exponent_u64] [u64];
380 [unchecked_pow_exponent_u128] [u128];
381 [unchecked_pow_exponent_usize] [usize];
382 )]
383 #[inline(always)]
384 fn unchecked_method(self, exponent: &exponent_type) -> Self {
385 rug::Complex::pow(self, exponent)
386 }
387
388 #[inline(always)]
392 fn unchecked_mul_add(self, b: &Self, c: &Self) -> Self {
393 rug::Complex::mul_add(self, b, c)
394 }
395}
396
397impl Conjugate for rug::Complex {
398 #[inline(always)]
399 fn conjugate(self) -> Self {
400 rug::Complex::conj(self)
401 }
402}
403
404impl RawComplexTrait for rug::Complex {
405 type RawReal = rug::Float;
406
407 fn new_unchecked_raw_complex(real: rug::Float, imag: rug::Float) -> Self {
408 debug_assert_eq!(
409 real.prec(),
410 imag.prec(),
411 "Different precision between real and imaginary part!"
412 );
413 rug::Complex::with_val(real.prec(), (real, imag))
414 }
415
416 fn mut_raw_real_part(&mut self) -> &mut rug::Float {
418 self.mut_real()
419 }
420
421 fn mut_raw_imag_part(&mut self) -> &mut rug::Float {
423 self.mut_imag()
424 }
425
426 #[inline(always)]
427 fn unchecked_abs(self) -> rug::Float {
428 rug::Complex::abs(self).into_real_imag().0
429 }
430
431 #[inline(always)]
432 fn raw_real_part(&self) -> &rug::Float {
433 self.real()
434 }
435
436 #[inline(always)]
437 fn raw_imag_part(&self) -> &rug::Float {
438 self.imag()
439 }
440
441 #[inline(always)]
442 fn unchecked_arg(self) -> rug::Float {
443 rug::Complex::arg(self).into_real_imag().0
444 }
445
446 #[inline(always)]
447 fn unchecked_pow_exponent_real(self, exponent: &rug::Float) -> Self {
448 rug::Complex::pow(self, exponent)
449 }
450}
451
452impl FpChecks for rug::Float {
453 fn is_finite(&self) -> bool {
454 rug::Float::is_finite(self)
455 }
456
457 fn is_infinite(&self) -> bool {
458 rug::Float::is_infinite(self)
459 }
460
461 fn is_nan(&self) -> bool {
462 rug::Float::is_nan(self)
463 }
464 fn is_normal(&self) -> bool {
465 rug::Float::is_normal(self)
466 }
467}
468
469impl FpChecks for rug::Complex {
470 #[inline(always)]
472 fn is_finite(&self) -> bool {
473 self.real().is_finite() && self.imag().is_finite()
474 }
475
476 #[inline(always)]
478 fn is_infinite(&self) -> bool {
479 !self.is_nan() && (self.real().is_infinite() || self.imag().is_infinite())
480 }
481
482 #[inline(always)]
484 fn is_nan(&self) -> bool {
485 self.real().is_nan() || self.imag().is_nan()
486 }
487
488 #[inline(always)]
490 fn is_normal(&self) -> bool {
491 self.real().is_normal() && self.imag().is_normal()
492 }
493}
494
495pub type RugStrictFinite<const PRECISION: u32> = NumKernelStrictFinite<rug::Float, PRECISION>;
549pub type RealRugStrictFinite<const PRECISION: u32> = RealValidated<RugStrictFinite<PRECISION>>;
554
555pub type ComplexRugStrictFinite<const PRECISION: u32> =
557 ComplexValidated<RugStrictFinite<PRECISION>>;
558
559impl Sign for rug::Float {
560 #[inline(always)]
562 fn kernel_copysign(self, sign: &Self) -> Self {
563 self.copysign(sign)
564 }
565
566 #[inline(always)]
568 fn kernel_is_sign_negative(&self) -> bool {
569 self.is_sign_negative()
570 }
571
572 #[inline(always)]
574 fn kernel_is_sign_positive(&self) -> bool {
575 self.is_sign_positive()
576 }
577
578 #[inline(always)]
586 fn kernel_signum(self) -> Self {
587 self.signum()
588 }
589}
590
591impl Rounding for rug::Float {
592 #[inline(always)]
594 fn kernel_ceil(self) -> Self {
595 self.ceil()
596 }
597
598 #[inline(always)]
600 fn kernel_floor(self) -> Self {
601 self.floor()
602 }
603
604 #[inline(always)]
606 fn kernel_fract(self) -> Self {
607 self.fract()
608 }
609
610 #[inline(always)]
612 fn kernel_round(self) -> Self {
613 self.round()
614 }
615
616 #[inline(always)]
637 fn kernel_round_ties_even(self) -> Self {
638 self.round_even()
639 }
640
641 #[inline(always)]
658 fn kernel_trunc(self) -> Self {
659 self.trunc()
660 }
661}
662
663impl<const PRECISION: u32> TryFrom<Complex<f64>> for ComplexRugStrictFinite<PRECISION> {
667 type Error = ErrorsValidationRawComplex<ErrorsTryFromf64<rug::Float>>;
668
669 fn try_from(value: Complex<f64>) -> Result<Self, Self::Error> {
670 let real_part = RealRugStrictFinite::<PRECISION>::try_from_f64(value.re);
671 let imag_part = RealRugStrictFinite::<PRECISION>::try_from_f64(value.im);
672
673 match (real_part, imag_part) {
674 (Ok(real_part), Ok(imag_part)) => Ok(Self {
675 value: rug::Complex::with_val(
676 PRECISION,
677 (real_part.into_inner(), imag_part.into_inner()),
678 ),
679 _phantom: PhantomData,
680 }),
681 (Err(error_real_part), Ok(_)) => Err(ErrorsValidationRawComplex::InvalidRealPart {
682 source: error_real_part,
683 }),
684 (Ok(_), Err(error_imaginary_part)) => {
685 Err(ErrorsValidationRawComplex::InvalidImaginaryPart {
686 source: error_imaginary_part,
687 })
688 }
689 (Err(error_real_part), Err(error_imaginary_part)) => {
690 Err(ErrorsValidationRawComplex::InvalidBothParts {
691 real_error: error_real_part,
692 imag_error: error_imaginary_part,
693 })
694 }
695 }
696 }
697}
698#[duplicate::duplicate_item(
703 T;
704 [rug::Float];
705 [rug::Complex];
706)]
707impl NegAssign for T {
709 fn neg_assign(&mut self) {
711 <T as rug::ops::NegAssign>::neg_assign(self);
712 }
713}
714#[cfg(test)]
719mod tests {
720 use super::*;
721 use crate::{
722 ACosH, ComplexRugStrictFinite, ComplexScalarConstructors, ComplexScalarGetParts,
723 ComplexScalarMutateParts, ComplexScalarSetParts, Constants, Max, Min,
724 functions::{
725 ACos, ACosHErrors, ACosHInputErrors, ACosRealErrors, ACosRealInputErrors, ASin,
726 ASinRealErrors, ASinRealInputErrors, ATan, ATan2, ATan2Errors, ATanComplexErrors,
727 ATanComplexInputErrors, ATanH, ATanHErrors, ATanHInputErrors, Abs, Clamp, Exp,
728 ExpErrors, Hypot, Ln, Log2, LogarithmComplexErrors, LogarithmComplexInputErrors,
729 NegAssign, Pow, PowComplexBaseRealExponentErrors, PowIntExponentErrors,
730 PowIntExponentInputErrors, PowRealBaseRealExponentErrors, Reciprocal, ReciprocalErrors,
731 Sqrt, SqrtRealErrors, TotalCmp,
732 },
733 validation::ErrorsValidationRawReal,
734 };
735 use num::{One, Zero};
736 use rug::Float;
737 use try_create::{TryNew, TryNewValidated};
738
739 const PRECISION: u32 = 53;
740
741 mod fp_checks {
742 use super::*;
743 use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
744 use rug::Float;
745
746 #[test]
747 fn is_finite() {
748 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
749 assert!(real.is_finite());
750
751 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, f64::INFINITY));
752 assert!(real.is_err());
753
754 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
755 53,
756 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
757 ))
758 .unwrap();
759 assert!(complex.is_finite());
760
761 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
762 53,
763 (Float::with_val(53, f64::INFINITY), Float::with_val(53, 1.0)),
764 ));
765 assert!(complex.is_err());
766 }
767
768 #[test]
769 fn is_infinite() {
770 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
771 assert!(!real.is_infinite());
772
773 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, f64::INFINITY));
774 assert!(real.is_err());
775
776 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
777 53,
778 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
779 ))
780 .unwrap();
781 assert!(!complex.is_infinite());
782
783 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
784 53,
785 (Float::with_val(53, f64::INFINITY), Float::with_val(53, 1.0)),
786 ));
787 assert!(complex.is_err());
788 }
789
790 #[test]
791 fn is_nan() {
792 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
793 assert!(!real.is_nan());
794
795 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, f64::NAN));
796 assert!(matches!(real, Err(ErrorsValidationRawReal::IsNaN { .. })));
797
798 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
799 53,
800 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
801 ))
802 .unwrap();
803 assert!(!complex.is_nan());
804
805 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
806 53,
807 (Float::with_val(53, f64::NAN), Float::with_val(53, 1.0)),
808 ));
809 assert!(matches!(
810 complex,
811 Err(ErrorsValidationRawComplex::InvalidRealPart {
812 source: ErrorsValidationRawReal::IsNaN { .. }
813 })
814 ));
815 }
816
817 #[test]
818 fn is_normal() {
819 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
820 assert!(real.is_normal());
821
822 let real = RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
823 assert!(!real.is_normal());
824
825 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
826 53,
827 (Float::with_val(53, 1.0), Float::with_val(53, 1.0)),
828 ))
829 .unwrap();
830 assert!(complex.is_normal());
831
832 let complex = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
833 53,
834 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
835 ))
836 .unwrap();
837 assert!(!complex.is_normal());
838 }
839 }
840
841 mod abs {
842 use super::*;
843
844 mod real {
845 use super::*;
846
847 #[test]
848 fn abs_valid() {
849 let value =
850 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, -4.0)).unwrap();
851
852 let expected_result =
853 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 4.0)).unwrap();
854 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
855 assert_eq!(value.abs(), expected_result);
856 }
857
858 #[test]
859 fn abs_zero() {
860 let value =
861 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
862
863 let expected_result =
864 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
865 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
866 assert_eq!(value.abs(), expected_result);
867 }
868
869 }
893
894 mod complex {
895 use super::*;
896
897 #[test]
898 fn abs_valid() {
899 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
900 53,
901 (rug::Float::with_val(53, 3.0), rug::Float::with_val(53, 4.0)),
902 ))
903 .unwrap();
904
905 let expected_result =
906 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 5.0)).unwrap();
907 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
908 assert_eq!(value.abs(), expected_result);
909 }
910
911 #[test]
912 fn abs_zero() {
913 let value = ComplexRugStrictFinite::<53>::try_new(rug::Complex::with_val(
914 53,
915 (rug::Float::with_val(53, 0.0), rug::Float::with_val(53, 0.0)),
916 ))
917 .unwrap();
918
919 let expected_result =
920 RealRugStrictFinite::<53>::try_new(rug::Float::with_val(53, 0.0)).unwrap();
921 assert_eq!(value.clone().try_abs().unwrap(), expected_result);
922 assert_eq!(value.abs(), expected_result);
923 }
924 }
958 }
959
960 mod max_min {
961 use super::*;
962
963 #[test]
964 fn test_realrug_max() {
965 let value =
966 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0)).unwrap();
967 let other =
968 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0)).unwrap();
969 let expected =
970 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0)).unwrap();
971 assert_eq!(Max::max(&value, &other), &expected);
972
973 let neg_value =
974 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.0))
975 .unwrap();
976 let neg_other =
977 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -5.0))
978 .unwrap();
979 let neg_expected =
980 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.0))
981 .unwrap();
982 assert_eq!(Max::max(&neg_value, &neg_other), &neg_expected);
983 }
984
985 #[test]
986 fn test_realrug_min() {
987 let value =
988 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0)).unwrap();
989 let other =
990 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0)).unwrap();
991 let expected =
992 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0)).unwrap();
993 assert_eq!(Min::min(&value, &other), &expected);
994
995 let neg_value =
996 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.0))
997 .unwrap();
998 let neg_other =
999 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -5.0))
1000 .unwrap();
1001 let neg_expected =
1002 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -5.0))
1003 .unwrap();
1004 assert_eq!(Min::min(&neg_value, &neg_other), &neg_expected);
1005 }
1006 }
1007
1008 mod builders {
1009 use super::*;
1010
1011 mod real {
1012 use super::*;
1013
1014 #[test]
1015 fn try_new_nan() {
1016 let nan = rug::Float::with_val(PRECISION, f64::NAN);
1017 let err = RealRugStrictFinite::<PRECISION>::try_new(nan).unwrap_err();
1018 assert!(matches!(err, ErrorsValidationRawReal::IsNaN { .. }));
1019 }
1020
1021 #[test]
1022 fn try_new_pos_infinity() {
1023 let pos_infinity = rug::Float::with_val(PRECISION, f64::INFINITY);
1024 let err = RealRugStrictFinite::<PRECISION>::try_new(pos_infinity).unwrap_err();
1025 assert!(matches!(err, ErrorsValidationRawReal::IsPosInfinity { .. }));
1026 }
1027
1028 #[test]
1029 fn try_new_neg_infinity() {
1030 let neg_infinity = rug::Float::with_val(PRECISION, f64::NEG_INFINITY);
1031 let err = RealRugStrictFinite::<PRECISION>::try_new(neg_infinity).unwrap_err();
1032 assert!(matches!(err, ErrorsValidationRawReal::IsNegInfinity { .. }));
1033 }
1034 }
1035
1036 mod complex {
1037 use super::*;
1038
1039 #[test]
1040 fn real_part() {
1041 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1042 rug::Complex::with_val(PRECISION, (1.23, 4.56)),
1043 )
1044 .unwrap();
1045 assert_eq!(c1.real_part(), 1.23);
1046
1047 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1048 rug::Complex::with_val(PRECISION, (-7.89, 0.12)),
1049 )
1050 .unwrap();
1051 assert_eq!(c2.real_part(), -7.89);
1052
1053 let c3 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1054 rug::Complex::with_val(PRECISION, (0.0, 10.0)),
1055 )
1056 .unwrap();
1057 assert_eq!(c3.real_part(), 0.0);
1058
1059 let c_nan_re = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1060 rug::Complex::with_val(PRECISION, (f64::NAN, 5.0)),
1061 )
1062 .unwrap_err();
1063 assert!(matches!(
1064 c_nan_re,
1065 ErrorsValidationRawComplex::InvalidRealPart {
1066 source: ErrorsValidationRawReal::IsNaN { .. }
1067 }
1068 ));
1069
1070 let c_inf_re = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1071 rug::Complex::with_val(PRECISION, (f64::INFINITY, 5.0)),
1072 )
1073 .unwrap_err();
1074 assert!(matches!(
1075 c_inf_re,
1076 ErrorsValidationRawComplex::InvalidRealPart {
1077 source: ErrorsValidationRawReal::IsPosInfinity { .. }
1078 }
1079 ));
1080
1081 let c_neg_inf_re = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1082 rug::Complex::with_val(PRECISION, (f64::NEG_INFINITY, 5.0)),
1083 )
1084 .unwrap_err();
1085 assert!(matches!(
1086 c_neg_inf_re,
1087 ErrorsValidationRawComplex::InvalidRealPart {
1088 source: ErrorsValidationRawReal::IsNegInfinity { .. }
1089 }
1090 ));
1091 }
1092
1093 #[test]
1094 fn imag_part() {
1095 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1096 rug::Complex::with_val(PRECISION, (1.23, 4.56)),
1097 )
1098 .unwrap();
1099 assert_eq!(c1.imag_part(), 4.56);
1100
1101 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1102 rug::Complex::with_val(PRECISION, (-7.89, 0.12)),
1103 )
1104 .unwrap();
1105 assert_eq!(c2.imag_part(), 0.12);
1106
1107 let c3 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1108 rug::Complex::with_val(PRECISION, (10.0, 0.0)),
1109 )
1110 .unwrap();
1111 assert_eq!(c3.imag_part(), 0.0);
1112
1113 let c_nan_im = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1114 rug::Complex::with_val(PRECISION, (5.0, f64::NAN)),
1115 )
1116 .unwrap_err();
1117 assert!(matches!(
1118 c_nan_im,
1119 ErrorsValidationRawComplex::InvalidImaginaryPart {
1120 source: ErrorsValidationRawReal::IsNaN { .. }
1121 }
1122 ));
1123
1124 let c_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1125 rug::Complex::with_val(PRECISION, (5.0, f64::INFINITY)),
1126 )
1127 .unwrap_err();
1128 assert!(matches!(
1129 c_inf_im,
1130 ErrorsValidationRawComplex::InvalidImaginaryPart {
1131 source: ErrorsValidationRawReal::IsPosInfinity { .. }
1132 }
1133 ));
1134
1135 let c_neg_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1136 rug::Complex::with_val(PRECISION, (5.0, f64::NEG_INFINITY)),
1137 )
1138 .unwrap_err();
1139 assert!(matches!(
1140 c_neg_inf_im,
1141 ErrorsValidationRawComplex::InvalidImaginaryPart {
1142 source: ErrorsValidationRawReal::IsNegInfinity { .. }
1143 }
1144 ));
1145 }
1146
1147 #[test]
1148 fn try_new_complex() {
1149 let r1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.23).unwrap();
1150 let i1 = RealRugStrictFinite::<PRECISION>::try_from_f64(4.56).unwrap();
1151 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1152 r1.as_ref().clone(),
1153 i1.as_ref().clone(),
1154 )
1155 .unwrap();
1156 assert_eq!(c1.real_part(), r1);
1157 assert_eq!(c1.imag_part(), i1);
1158
1159 let r2 = RealRugStrictFinite::<PRECISION>::try_from_f64(-7.89).unwrap();
1160 let i2 = RealRugStrictFinite::<PRECISION>::try_from_f64(-0.12).unwrap();
1161 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1162 r2.as_ref().clone(),
1163 i2.as_ref().clone(),
1164 )
1165 .unwrap();
1166 assert_eq!(c2.real_part(), r2);
1167 assert_eq!(c2.imag_part(), i2);
1168
1169 let r3 = RealRugStrictFinite::<PRECISION>::try_from_f64(0.0).unwrap();
1170 let i3 = RealRugStrictFinite::<PRECISION>::try_from_f64(0.0).unwrap();
1171 let c3 = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1172 r3.as_ref().clone(),
1173 i3.as_ref().clone(),
1174 )
1175 .unwrap();
1176 assert_eq!(c3.real_part(), r3);
1177 assert_eq!(c3.real_part(), i3);
1178 assert!(c3.is_zero());
1179
1180 let c_nan_re = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1181 Float::with_val(PRECISION, f64::NAN),
1182 Float::with_val(PRECISION, 5.0),
1183 )
1184 .unwrap_err();
1185 assert!(matches!(
1186 c_nan_re,
1187 ErrorsValidationRawComplex::InvalidRealPart { .. }
1188 ));
1189
1190 let c_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1191 Float::with_val(PRECISION, 10.0),
1192 Float::with_val(PRECISION, f64::INFINITY),
1193 )
1194 .unwrap_err();
1195 assert!(matches!(
1196 c_inf_im,
1197 ErrorsValidationRawComplex::InvalidImaginaryPart { .. }
1198 ));
1199
1200 let c_nan_re_inf_im = ComplexRugStrictFinite::<PRECISION>::try_new_complex(
1201 Float::with_val(PRECISION, f64::NAN),
1202 Float::with_val(PRECISION, f64::INFINITY),
1203 )
1204 .unwrap_err();
1205 assert!(matches!(
1206 c_nan_re_inf_im,
1207 ErrorsValidationRawComplex::InvalidBothParts { .. }
1208 ));
1209 }
1210
1211 #[test]
1212 fn try_from_complexf64() {
1213 let c1_in = num::Complex::new(1.23, 4.56);
1214 let c1 = ComplexRugStrictFinite::<PRECISION>::try_from(c1_in).unwrap();
1215 assert_eq!(c1.real_part(), c1_in.re);
1216 assert_eq!(c1.imag_part(), c1_in.im);
1217
1218 let c2_in = num::Complex::new(-7.89, -0.12);
1219 let c2 = ComplexRugStrictFinite::<PRECISION>::try_from(c2_in).unwrap();
1220 assert_eq!(c2.real_part(), c2_in.re);
1221 assert_eq!(c2.imag_part(), c2_in.im);
1222
1223 let c3_in = num::Complex::new(0., 0.);
1224 let c3 = ComplexRugStrictFinite::<PRECISION>::try_from(c3_in).unwrap();
1225 assert_eq!(c3.real_part(), c3_in.re);
1226 assert_eq!(c3.imag_part(), c3_in.im);
1227
1228 let c_nan_re =
1229 ComplexRugStrictFinite::<PRECISION>::try_from(num::Complex::new(f64::NAN, 5.0))
1230 .unwrap_err();
1231 assert!(matches!(
1232 c_nan_re,
1233 ErrorsValidationRawComplex::InvalidRealPart { .. }
1234 ));
1235
1236 let c_inf_im = ComplexRugStrictFinite::<PRECISION>::try_from(num::Complex::new(
1237 10.0,
1238 f64::INFINITY,
1239 ))
1240 .unwrap_err();
1241 assert!(matches!(
1242 c_inf_im,
1243 ErrorsValidationRawComplex::InvalidImaginaryPart { .. }
1244 ));
1245
1246 let c_nan_re_inf_im = ComplexRugStrictFinite::<PRECISION>::try_from(
1247 num::Complex::new(f64::NAN, f64::INFINITY),
1248 )
1249 .unwrap_err();
1250 assert!(matches!(
1251 c_nan_re_inf_im,
1252 ErrorsValidationRawComplex::InvalidBothParts { .. }
1253 ));
1254 }
1255
1256 #[test]
1257 fn try_new_pure_real() {
1258 let r1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.23).unwrap();
1259 let c1 =
1260 ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(r1.as_ref().clone())
1261 .unwrap();
1262 assert_eq!(c1.real_part(), r1);
1263 assert!(c1.imag_part().is_zero());
1264
1265 let c_nan = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
1266 Float::with_val(PRECISION, f64::NAN),
1267 )
1268 .unwrap_err();
1269 assert!(matches!(
1270 c_nan,
1271 ErrorsValidationRawComplex::InvalidRealPart {
1272 source: ErrorsValidationRawReal::IsNaN { .. }
1273 }
1274 ));
1275 }
1276
1277 #[test]
1278 fn try_new_pure_imaginary() {
1279 let i1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.23).unwrap();
1280 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
1281 i1.as_ref().clone(),
1282 )
1283 .unwrap();
1284 assert!(c1.real_part().is_zero());
1285 assert_eq!(c1.imag_part(), i1);
1286
1287 let c_nan = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
1288 Float::with_val(PRECISION, f64::NAN),
1289 )
1290 .unwrap_err();
1291 assert!(matches!(
1292 c_nan,
1293 ErrorsValidationRawComplex::InvalidImaginaryPart {
1294 source: ErrorsValidationRawReal::IsNaN { .. }
1295 }
1296 ));
1297 }
1298
1299 #[test]
1300 fn add_to_real_part() {
1301 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1302 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1303 )
1304 .unwrap();
1305 c.add_to_real_part(&RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1306 assert_eq!(c.real_part(), 4.0);
1307 assert_eq!(c.imag_part(), 2.0);
1308
1309 c.add_to_real_part(&RealRugStrictFinite::<PRECISION>::try_from_f64(-5.0).unwrap());
1310 assert_eq!(c.real_part(), -1.0);
1311 assert_eq!(c.imag_part(), 2.0);
1312 }
1313
1314 #[test]
1315 fn add_to_imaginary_part() {
1316 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1317 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1318 )
1319 .unwrap();
1320 c.add_to_imaginary_part(
1321 &RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap(),
1322 );
1323 assert_eq!(c.real_part(), 1.0);
1324 assert_eq!(c.imag_part(), 5.0);
1325
1326 c.add_to_imaginary_part(
1327 &RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap(),
1328 );
1329 assert_eq!(c.real_part(), 1.0);
1330 assert_eq!(c.imag_part(), 1.0);
1331 }
1332
1333 #[test]
1334 fn multiply_real_part() {
1335 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1336 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1337 )
1338 .unwrap();
1339 c.multiply_real_part(&RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1340 assert_eq!(c.real_part(), 3.0);
1341 assert_eq!(c.imag_part(), 2.0);
1342
1343 c.multiply_real_part(
1344 &RealRugStrictFinite::<PRECISION>::try_from_f64(-2.0).unwrap(),
1345 );
1346 assert_eq!(c.real_part(), -6.0);
1347 assert_eq!(c.imag_part(), 2.0);
1348 }
1349
1350 #[test]
1351 fn multiply_imaginary_part() {
1352 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1353 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1354 )
1355 .unwrap();
1356 c.multiply_imaginary_part(
1357 &RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap(),
1358 );
1359 assert_eq!(c.real_part(), 1.0);
1360 assert_eq!(c.imag_part(), 6.0);
1361
1362 c.multiply_imaginary_part(
1363 &RealRugStrictFinite::<PRECISION>::try_from_f64(-0.5).unwrap(),
1364 );
1365 assert_eq!(c.real_part(), 1.0);
1366 assert_eq!(c.imag_part(), -3.0);
1367 }
1368
1369 #[test]
1370 fn set_real_part() {
1371 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1372 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1373 )
1374 .unwrap();
1375 c.set_real_part(RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1376 assert_eq!(c.real_part(), 3.0);
1377 assert_eq!(c.imag_part(), 2.0);
1378
1379 c.set_real_part(RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap());
1380 assert_eq!(c.real_part(), -4.0);
1381 assert_eq!(c.imag_part(), 2.0);
1382 }
1383
1384 #[test]
1385 fn set_imaginary_part() {
1386 let mut c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1387 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1388 )
1389 .unwrap();
1390 c.set_imaginary_part(RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap());
1391 assert_eq!(c.real_part(), 1.0);
1392 assert_eq!(c.imag_part(), 3.0);
1393
1394 c.set_imaginary_part(RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap());
1395 assert_eq!(c.real_part(), 1.0);
1396 assert_eq!(c.imag_part(), -4.0);
1397 }
1398 }
1399 }
1400
1401 mod mul {
1402 use super::*;
1403
1404 mod real {
1405 use super::*;
1406
1407 #[test]
1408 fn multiply_ref() {
1409 let r1 = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1410 PRECISION, 3.0,
1411 ))
1412 .unwrap();
1413 let r2 = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1414 PRECISION, 4.0,
1415 ))
1416 .unwrap();
1417 let result = r1 * &r2;
1418 assert_eq!(
1419 result,
1420 RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1421 PRECISION, 12.0
1422 ))
1423 .unwrap()
1424 );
1425 }
1426 }
1427
1428 mod complex {
1429 use super::*;
1430
1431 #[test]
1432 fn multiply_ref() {
1433 let c1 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1434 rug::Complex::with_val(PRECISION, (1.0, 2.0)),
1435 )
1436 .unwrap();
1437 let c2 = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1438 rug::Complex::with_val(PRECISION, (3.0, 4.0)),
1439 )
1440 .unwrap();
1441 let result = c1 * &c2;
1442 assert_eq!(
1443 result,
1444 ComplexRugStrictFinite::<PRECISION>::try_new_validated(rug::Complex::with_val(
1445 PRECISION,
1446 (-5.0, 10.0),
1447 ))
1448 .unwrap()
1449 ); }
1451
1452 #[test]
1453 fn complex_times_real() {
1454 let r = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1455 PRECISION, 2.0,
1456 ))
1457 .unwrap();
1458 let c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1459 rug::Complex::with_val(PRECISION, (3.0, 4.0)),
1460 )
1461 .unwrap();
1462
1463 let result_expected = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1464 rug::Complex::with_val(PRECISION, (6.0, 8.0)),
1465 )
1466 .unwrap(); let result = c.clone() * &r;
1469 assert_eq!(&result, &result_expected);
1470
1471 let result = c.clone() * r.clone();
1472 assert_eq!(&result, &result_expected);
1473
1474 let mut result = c.clone();
1475 result *= &r;
1476 assert_eq!(&result, &result_expected);
1477
1478 let mut result = c.clone();
1479 result *= r;
1480 assert_eq!(&result, &result_expected);
1481 }
1482
1483 #[test]
1484 fn real_times_complex() {
1485 let r = RealRugStrictFinite::<PRECISION>::try_new_validated(rug::Float::with_val(
1486 PRECISION, 2.0,
1487 ))
1488 .unwrap();
1489 let c = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1490 rug::Complex::with_val(PRECISION, (3.0, 4.0)),
1491 )
1492 .unwrap();
1493
1494 let result_expected = ComplexRugStrictFinite::<PRECISION>::try_new_validated(
1495 rug::Complex::with_val(PRECISION, (6.0, 8.0)),
1496 )
1497 .unwrap(); let result = &r * c.clone();
1500 assert_eq!(&result, &result_expected);
1501
1502 let result = r * c.clone();
1503 assert_eq!(&result, &result_expected);
1504 }
1505 }
1506 }
1507
1508 mod arithmetic {
1509 use super::*;
1510
1511 mod real {
1512 use super::*;
1513
1514 #[test]
1515 fn neg_assign() {
1516 let mut a = rug::Float::with_val(PRECISION, 1.);
1517 a.neg_assign();
1518 let a_expected = rug::Float::with_val(PRECISION, -1.);
1519 assert_eq!(a, a_expected);
1520
1521 let mut b = RealRugStrictFinite::<PRECISION>::one();
1522 b.neg_assign();
1523 let b_expected = RealRugStrictFinite::<PRECISION>::try_new_validated(
1524 rug::Float::with_val(PRECISION, -1.),
1525 )
1526 .unwrap();
1527 assert_eq!(&b, &b_expected);
1528 }
1529
1530 #[test]
1531 #[should_panic(expected = "Division failed validation")]
1532 fn div_by_zero() {
1533 let one = RealRugStrictFinite::<PRECISION>::one();
1534 let zero = RealRugStrictFinite::<PRECISION>::zero();
1535 let _ = &one / &zero;
1536 }
1537
1538 #[test]
1539 #[should_panic(expected = "Division failed validation")]
1540 fn div_assign_by_zero() {
1541 let mut num = RealRugStrictFinite::<PRECISION>::one();
1542 let zero_ref = &RealRugStrictFinite::<PRECISION>::zero();
1543 num /= zero_ref;
1544 }
1545 }
1546
1547 mod complex {
1548 use super::*;
1549
1550 #[test]
1551 fn neg_assign() {
1552 let re = rug::Float::with_val(PRECISION, 1.);
1553 let im = rug::Float::with_val(PRECISION, 2.);
1554 let mut num = rug::Complex::with_val(PRECISION, (re, im));
1555 num.neg_assign();
1556 let expected = rug::Complex::with_val(
1557 PRECISION,
1558 (
1559 rug::Float::with_val(PRECISION, -1.),
1560 rug::Float::with_val(PRECISION, -2.),
1561 ),
1562 );
1563 assert_eq!(&num, &expected);
1564
1565 let mut num = ComplexRugStrictFinite::<PRECISION>::try_new_validated(num).unwrap();
1566 let expected = num.clone().neg();
1567 num.neg_assign();
1568 assert_eq!(&num, &expected);
1569 }
1570
1571 #[test]
1572 #[should_panic(expected = "Division failed validation")]
1573 fn div_by_zero() {
1574 let one = ComplexRugStrictFinite::<PRECISION>::one();
1575 let zero = ComplexRugStrictFinite::<PRECISION>::zero();
1576 let _ = &one / &zero;
1577 }
1578
1579 #[test]
1580 #[should_panic(expected = "Division failed validation")]
1581 fn div_assign_by_zero() {
1582 let mut num = ComplexRugStrictFinite::<PRECISION>::one();
1583 let zero_ref = &ComplexRugStrictFinite::<PRECISION>::zero();
1584 num /= zero_ref;
1585 }
1586 }
1587 }
1588
1589 mod real_scalar_methods {
1590 use super::*;
1591
1592 #[test]
1593 fn epsilon() {
1594 let eps = RealRugStrictFinite::<PRECISION>::epsilon();
1595 assert!(eps.is_finite() && eps > RealRugStrictFinite::<PRECISION>::zero());
1596 let expected_eps_val =
1597 rug::Float::with_val(PRECISION, 2.0).pow(1i32 - PRECISION as i32);
1598 let expected_eps = RealRugStrictFinite::<PRECISION>::try_new(expected_eps_val).unwrap();
1599 assert_eq!(eps, expected_eps, "Epsilon value mismatch");
1600 }
1601
1602 #[test]
1603 fn clamp() {
1604 let val = RealRugStrictFinite::<PRECISION>::try_from_f64(5.0).unwrap();
1605 let min_val = RealRugStrictFinite::<PRECISION>::try_from_f64(0.0).unwrap();
1606 let max_val = RealRugStrictFinite::<PRECISION>::try_from_f64(10.0).unwrap();
1607
1608 assert_eq!(val.clone().kernel_clamp(&min_val, &max_val), val);
1609 assert_eq!(
1610 RealRugStrictFinite::<PRECISION>::try_from_f64(-5.0)
1611 .unwrap()
1612 .kernel_clamp(&min_val, &max_val),
1613 min_val
1614 );
1615 assert_eq!(
1616 RealRugStrictFinite::<PRECISION>::try_from_f64(15.0)
1617 .unwrap()
1618 .kernel_clamp(&min_val, &max_val),
1619 max_val
1620 );
1621 }
1622
1623 #[test]
1624 fn hypot() {
1625 let a = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
1626 let b = RealRugStrictFinite::<PRECISION>::try_from_f64(4.0).unwrap();
1627 let expected = RealRugStrictFinite::<PRECISION>::try_from_f64(5.0).unwrap();
1628 assert_eq!(a.kernel_hypot(&b), expected);
1629 }
1630
1631 #[test]
1632 fn signum() {
1633 assert_eq!(
1634 RealRugStrictFinite::<PRECISION>::try_from_f64(5.0)
1635 .unwrap()
1636 .kernel_signum(),
1637 RealRugStrictFinite::<PRECISION>::one()
1638 );
1639 assert_eq!(
1640 RealRugStrictFinite::<PRECISION>::try_from_f64(-5.0)
1641 .unwrap()
1642 .kernel_signum(),
1643 RealRugStrictFinite::<PRECISION>::negative_one()
1644 );
1645 assert_eq!(
1647 RealRugStrictFinite::<PRECISION>::zero().kernel_signum(),
1648 RealRugStrictFinite::<PRECISION>::one()
1649 );
1650 }
1651
1652 #[test]
1653 fn total_cmp() {
1654 let r1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
1655 let r2 = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1656 assert_eq!(r1.total_cmp(&r1), Ordering::Equal);
1657 assert_eq!(r1.total_cmp(&r2), Ordering::Less);
1658 assert_eq!(r2.total_cmp(&r1), Ordering::Greater);
1659 }
1660
1661 #[test]
1662 fn mul_add_mul_mut() {
1663 let mut a = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1664 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);
1669 assert_eq!(
1670 a,
1671 RealRugStrictFinite::<PRECISION>::try_from_f64(26.0).unwrap()
1672 );
1673 }
1674
1675 #[test]
1676 fn mul_sub_mul_mut() {
1677 let mut a = RealRugStrictFinite::<PRECISION>::try_from_f64(10.0).unwrap();
1678 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);
1683 assert_eq!(
1684 a,
1685 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1686 );
1687 }
1688
1689 #[test]
1690 fn test_real_rug_constants() {
1691 let raw_float = |f: f64| Float::with_val(PRECISION, f);
1693
1694 let pi = RealRugStrictFinite::<PRECISION>::pi();
1696 let expected_pi = raw_float(-1.0).acos();
1697 assert_eq!(pi.as_ref(), &expected_pi);
1698
1699 let two_pi = RealRugStrictFinite::<PRECISION>::two_pi();
1701 let expected_two_pi = &expected_pi * raw_float(2.0);
1702 assert_eq!(two_pi.as_ref(), &expected_two_pi);
1703
1704 let pi_div_2 = RealRugStrictFinite::<PRECISION>::pi_div_2();
1706 let expected_pi_div_2 = raw_float(1.0).asin();
1707 assert_eq!(pi_div_2.as_ref(), &expected_pi_div_2);
1708
1709 let e = RealRugStrictFinite::<PRECISION>::e();
1711 let expected_e = raw_float(1.0).exp();
1712 assert_eq!(e.as_ref(), &expected_e);
1713
1714 let log2_e = RealRugStrictFinite::<PRECISION>::log2_e();
1716 let expected_log2_e = expected_e.clone().log2();
1717 assert_eq!(log2_e.as_ref(), &expected_log2_e);
1718
1719 let log10_e = RealRugStrictFinite::<PRECISION>::log10_e();
1721 let expected_log10_e = expected_e.log10();
1722 assert_eq!(log10_e.as_ref(), &expected_log10_e);
1723
1724 let ln_2 = RealRugStrictFinite::<PRECISION>::ln_2();
1726 let expected_ln_2 = raw_float(2.0).ln();
1727 assert_eq!(ln_2.as_ref(), &expected_ln_2);
1728
1729 let ln_10 = RealRugStrictFinite::<PRECISION>::ln_10();
1731 let expected_ln_10 = raw_float(10.0).ln();
1732 assert_eq!(ln_10.as_ref(), &expected_ln_10);
1733
1734 let log2_10 = RealRugStrictFinite::<PRECISION>::log2_10();
1736 let expected_log2_10 = raw_float(10.0).log2();
1737 assert_eq!(log2_10.as_ref(), &expected_log2_10);
1738
1739 let log10_2 = RealRugStrictFinite::<PRECISION>::log10_2();
1741 let expected_log10_2 = raw_float(2.0).log10();
1742 assert_eq!(log10_2.as_ref(), &expected_log10_2);
1743
1744 let max_finite = RealRugStrictFinite::<PRECISION>::max_finite();
1746 let expected_max_finite = <rug::Float as RawRealTrait>::raw_max_finite(PRECISION);
1747 assert_eq!(max_finite.as_ref(), &expected_max_finite);
1748
1749 let min_finite = RealRugStrictFinite::<PRECISION>::min_finite();
1751 let expected_min_finite = <rug::Float as RawRealTrait>::raw_min_finite(PRECISION);
1752 assert_eq!(min_finite.as_ref(), &expected_min_finite);
1753
1754 let epsilon = RealRugStrictFinite::<PRECISION>::epsilon();
1756 let expected_epsilon = <rug::Float as RawRealTrait>::raw_epsilon(PRECISION);
1757 assert_eq!(epsilon.as_ref(), &expected_epsilon);
1758
1759 assert_eq!(
1761 RealRugStrictFinite::<PRECISION>::negative_one().as_ref(),
1762 &raw_float(-1.0)
1763 );
1764
1765 assert_eq!(
1767 RealRugStrictFinite::<PRECISION>::two().as_ref(),
1768 &raw_float(2.0)
1769 );
1770
1771 assert_eq!(
1773 RealRugStrictFinite::<PRECISION>::one_div_2().as_ref(),
1774 &raw_float(0.5)
1775 );
1776 }
1777 }
1778
1779 mod function_traits {
1780 use super::*;
1781 use crate::{
1782 functions::{
1783 ATan2InputErrors, LogarithmRealErrors, LogarithmRealInputErrors,
1784 PowComplexBaseRealExponentInputErrors, PowRealBaseRealExponentInputErrors,
1785 ReciprocalInputErrors, SqrtRealInputErrors,
1786 },
1787 validation::ErrorsValidationRawReal,
1788 };
1789
1790 mod real {
1791 use super::*;
1792
1793 #[test]
1794 fn exp_overflow() {
1795 let large_val = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0e60).unwrap(); let res_large = large_val.try_exp();
1797 assert!(matches!(
1798 res_large,
1799 Err(ExpErrors::Output {
1800 source: ErrorsValidationRawReal::IsPosInfinity { .. }
1801 })
1802 ),);
1803 }
1804
1805 #[test]
1806 fn ln_domain_errors() {
1807 let neg_val = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.0).unwrap();
1808 assert!(matches!(
1809 neg_val.try_ln(),
1810 Err(LogarithmRealErrors::Input {
1811 source: LogarithmRealInputErrors::NegativeArgument { .. }
1812 })
1813 ));
1814
1815 let zero_val = RealRugStrictFinite::<PRECISION>::zero();
1816 assert!(matches!(
1817 zero_val.try_ln(),
1818 Err(LogarithmRealErrors::Input {
1819 source: LogarithmRealInputErrors::ZeroArgument { .. }
1820 })
1821 ));
1822 }
1823 } mod complex {
1826 use super::*;
1827
1828 #[test]
1829 fn log2_zero() {
1830 let zero_val = ComplexRugStrictFinite::<PRECISION>::zero();
1831 assert!(matches!(
1832 zero_val.try_log2(),
1833 Err(LogarithmComplexErrors::Input {
1834 source: LogarithmComplexInputErrors::ZeroArgument { .. }
1835 })
1836 ));
1837 }
1838 } mod pow {
1841 use super::*;
1842
1843 mod real_base {
1844 use super::*;
1845
1846 #[test]
1847 fn negative_base_real_exponent_error() {
1848 let base = RealRugStrictFinite::<PRECISION>::try_from_f64(-2.0).unwrap();
1849 let exponent = RealRugStrictFinite::<PRECISION>::try_from_f64(0.5).unwrap();
1850 let res = base.try_pow(&exponent);
1851 assert!(matches!(
1852 res,
1853 Err(PowRealBaseRealExponentErrors::Input {
1854 source: PowRealBaseRealExponentInputErrors::NegativeBase { .. }
1855 })
1856 ));
1857 }
1858
1859 #[test]
1860 fn real_base_uint_exponent() {
1861 let base = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1862 assert_eq!(
1863 base.clone().try_pow(3u8).unwrap(),
1864 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1865 );
1866 assert_eq!(
1867 base.clone().try_pow(3u16).unwrap(),
1868 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1869 );
1870 assert_eq!(
1871 base.clone().try_pow(3u32).unwrap(),
1872 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1873 );
1874 assert_eq!(
1875 base.clone().try_pow(3u64).unwrap(),
1876 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1877 );
1878 assert_eq!(
1879 base.clone().try_pow(3u128).unwrap(),
1880 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1881 );
1882 assert_eq!(
1883 base.clone().try_pow(3usize).unwrap(),
1884 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1885 );
1886
1887 assert_eq!(
1888 base.clone().pow(3u8),
1889 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1890 );
1891 assert_eq!(
1892 base.clone().pow(3u16),
1893 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1894 );
1895 assert_eq!(
1896 base.clone().pow(3u32),
1897 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1898 );
1899 assert_eq!(
1900 base.clone().pow(3u64),
1901 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1902 );
1903 assert_eq!(
1904 base.clone().pow(3u128),
1905 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1906 );
1907 assert_eq!(
1908 base.clone().pow(3usize),
1909 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1910 );
1911 }
1912
1913 #[test]
1914 fn real_base_int_exponent() {
1915 let base = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1916 assert_eq!(
1917 base.clone().try_pow(3i8).unwrap(),
1918 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1919 );
1920 assert_eq!(
1921 base.clone().try_pow(3i16).unwrap(),
1922 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1923 );
1924 assert_eq!(
1925 base.clone().try_pow(3i32).unwrap(),
1926 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1927 );
1928 assert_eq!(
1929 base.clone().try_pow(3i64).unwrap(),
1930 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1931 );
1932 assert_eq!(
1933 base.clone().try_pow(3i128).unwrap(),
1934 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1935 );
1936 assert_eq!(
1937 base.clone().try_pow(3isize).unwrap(),
1938 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1939 );
1940
1941 assert_eq!(
1942 base.clone().pow(3i8),
1943 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1944 );
1945 assert_eq!(
1946 base.clone().pow(3i16),
1947 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1948 );
1949 assert_eq!(
1950 base.clone().pow(3i32),
1951 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1952 );
1953 assert_eq!(
1954 base.clone().pow(3i64),
1955 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1956 );
1957 assert_eq!(
1958 base.clone().pow(3i128),
1959 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1960 );
1961 assert_eq!(
1962 base.clone().pow(3isize),
1963 RealRugStrictFinite::<PRECISION>::try_from_f64(8.0).unwrap()
1964 );
1965 }
1966
1967 #[test]
1968 fn real_base_int_exponent_zero_neg_exp_error() {
1969 let base = RealRugStrictFinite::<PRECISION>::zero();
1970 let exponent: i32 = -2;
1971 let res = base.try_pow(exponent);
1972 assert!(matches!(
1973 res,
1974 Err(PowIntExponentErrors::Input {
1975 source: PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
1976 })
1977 ));
1978 }
1979 }
1980
1981 mod complex_base {
1982 use super::*;
1983
1984 #[test]
1985 fn complex_base_uint_exponent() {
1986 let base = ComplexRugStrictFinite::<PRECISION>::try_new(
1987 rug::Complex::with_val(PRECISION, (2.0, 3.0)),
1988 )
1989 .unwrap();
1990 let expected_res = ComplexRugStrictFinite::<PRECISION>::try_new(
1991 rug::Complex::with_val(PRECISION, (-46.0, 9.0)),
1992 )
1993 .unwrap();
1994
1995 assert_eq!(&base.clone().try_pow(3u8).unwrap(), &expected_res);
1996 assert_eq!(&base.clone().try_pow(3u16).unwrap(), &expected_res);
1997 assert_eq!(&base.clone().try_pow(3u32).unwrap(), &expected_res);
1998 assert_eq!(&base.clone().try_pow(3u64).unwrap(), &expected_res);
1999 assert_eq!(&base.clone().try_pow(3u128).unwrap(), &expected_res);
2000 assert_eq!(&base.clone().try_pow(3usize).unwrap(), &expected_res);
2001
2002 assert_eq!(&base.clone().pow(3u8), &expected_res);
2003 assert_eq!(&base.clone().pow(3u16), &expected_res);
2004 assert_eq!(&base.clone().pow(3u32), &expected_res);
2005 assert_eq!(&base.clone().pow(3u64), &expected_res);
2006 assert_eq!(&base.clone().pow(3u128), &expected_res);
2007 assert_eq!(&base.clone().pow(3usize), &expected_res);
2008 }
2009
2010 #[test]
2011 fn complex_base_int_exponent() {
2012 let base = ComplexRugStrictFinite::<PRECISION>::try_new(
2013 rug::Complex::with_val(PRECISION, (2.0, 3.0)),
2014 )
2015 .unwrap();
2016 let expected_res = ComplexRugStrictFinite::<PRECISION>::try_new(
2017 rug::Complex::with_val(PRECISION, (-46.0, 9.0)),
2018 )
2019 .unwrap();
2020
2021 assert_eq!(&base.clone().try_pow(3i8).unwrap(), &expected_res);
2022 assert_eq!(&base.clone().try_pow(3i16).unwrap(), &expected_res);
2023 assert_eq!(&base.clone().try_pow(3i32).unwrap(), &expected_res);
2024 assert_eq!(&base.clone().try_pow(3i64).unwrap(), &expected_res);
2025 assert_eq!(&base.clone().try_pow(3i128).unwrap(), &expected_res);
2026 assert_eq!(&base.clone().try_pow(3isize).unwrap(), &expected_res);
2027
2028 assert_eq!(&base.clone().pow(3i8), &expected_res);
2029 assert_eq!(&base.clone().pow(3i16), &expected_res);
2030 assert_eq!(&base.clone().pow(3i32), &expected_res);
2031 assert_eq!(&base.clone().pow(3i64), &expected_res);
2032 assert_eq!(&base.clone().pow(3i128), &expected_res);
2033 assert_eq!(&base.clone().pow(3isize), &expected_res);
2034 }
2035
2036 #[test]
2037 fn complex_zero_base_negative_real_exponent_error() {
2038 let base = ComplexRugStrictFinite::<PRECISION>::zero();
2039 let exponent = RealRugStrictFinite::<PRECISION>::try_from_f64(-2.0).unwrap();
2040 let res = base.try_pow(&exponent);
2041 assert!(matches!(
2042 res,
2043 Err(PowComplexBaseRealExponentErrors::Input {
2044 source:
2045 PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent { .. }
2046 })
2047 ));
2048 }
2049
2050 #[test]
2051 fn complex_zero_base_zero_real_exponent() {
2052 let base = ComplexRugStrictFinite::<PRECISION>::zero();
2053 let exponent = RealRugStrictFinite::<PRECISION>::zero();
2054 let res = base.try_pow(&exponent).unwrap();
2055 assert_eq!(res, ComplexRugStrictFinite::<PRECISION>::one());
2056 }
2057
2058 #[test]
2059 fn complex_base_int_exponent_zero_neg_exp_error() {
2060 let base = ComplexRugStrictFinite::<PRECISION>::zero();
2061 let exponent: i32 = -2;
2062 let res = base.try_pow(exponent);
2063 assert!(matches!(
2064 res,
2065 Err(PowIntExponentErrors::Input {
2066 source: PowIntExponentInputErrors::ZeroBaseNegativeExponent { .. }
2067 })
2068 ));
2069 }
2070 }
2071 }
2072
2073 #[test]
2074 fn reciprocal_real_rug_zero() {
2075 let zero_val = RealRugStrictFinite::<PRECISION>::zero();
2076 let res = zero_val.try_reciprocal();
2077 assert!(matches!(
2078 res,
2079 Err(ReciprocalErrors::Input {
2080 source: ReciprocalInputErrors::DivisionByZero { .. }
2081 })
2082 ));
2083 }
2084
2085 #[test]
2086 fn reciprocal_complex_rug_zero() {
2087 let zero_val = ComplexRugStrictFinite::<PRECISION>::zero();
2088 let res = zero_val.try_reciprocal();
2089 assert!(matches!(
2090 res,
2091 Err(ReciprocalErrors::Input {
2092 source: ReciprocalInputErrors::DivisionByZero { .. }
2093 })
2094 ));
2095 }
2096
2097 #[test]
2098 fn sqrt_real_rug_negative_input() {
2099 let neg_val = RealRugStrictFinite::<PRECISION>::try_from_f64(-4.0).unwrap();
2100 let res = neg_val.try_sqrt();
2101 assert!(matches!(
2102 res,
2103 Err(SqrtRealErrors::Input {
2104 source: SqrtRealInputErrors::NegativeValue { .. }
2105 })
2106 ));
2107 }
2108
2109 mod trigonometric {
2110 use super::*;
2111
2112 #[test]
2113 fn atan2_real_rug_zero_over_zero() {
2114 let zero_val = RealRugStrictFinite::<PRECISION>::zero();
2115 let res = zero_val.try_atan2(&RealRugStrictFinite::<PRECISION>::zero());
2116 assert!(matches!(
2117 res,
2118 Err(ATan2Errors::Input {
2119 source: ATan2InputErrors::ZeroOverZero { .. }
2120 })
2121 ));
2122 }
2123
2124 #[test]
2142 fn asin_real_rug_out_of_domain() {
2143 let val_gt_1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.5).unwrap();
2144 assert!(matches!(
2145 val_gt_1.try_asin(),
2146 Err(ASinRealErrors::Input {
2147 source: ASinRealInputErrors::OutOfDomain { .. }
2148 })
2149 ));
2150 let val_lt_neg1 = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.5).unwrap();
2151 assert!(matches!(
2152 val_lt_neg1.try_asin(),
2153 Err(ASinRealErrors::Input {
2154 source: ASinRealInputErrors::OutOfDomain { .. }
2155 })
2156 ));
2157 }
2158
2159 #[test]
2160 fn acos_real_rug_out_of_domain() {
2161 let val_gt_1 = RealRugStrictFinite::<PRECISION>::try_from_f64(1.5).unwrap();
2162 assert!(matches!(
2163 val_gt_1.try_acos(),
2164 Err(ACosRealErrors::Input {
2165 source: ACosRealInputErrors::OutOfDomain { .. }
2166 })
2167 ));
2168 let val_lt_neg1 = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.5).unwrap();
2169 assert!(matches!(
2170 val_lt_neg1.try_acos(),
2171 Err(ACosRealErrors::Input {
2172 source: ACosRealInputErrors::OutOfDomain { .. }
2173 })
2174 ));
2175 }
2176
2177 #[test]
2178 fn atan_complex_rug_pole() {
2179 let i_val = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
2181 Float::with_val(PRECISION, 1.0),
2182 )
2183 .unwrap();
2184 assert!(matches!(
2185 i_val.try_atan(),
2186 Err(ATanComplexErrors::Input {
2187 source: ATanComplexInputErrors::ArgumentIsPole { .. }
2188 })
2189 ));
2190
2191 let neg_i_val = ComplexRugStrictFinite::<PRECISION>::try_new_pure_imaginary(
2192 Float::with_val(PRECISION, -1.0),
2193 )
2194 .unwrap();
2195 assert!(matches!(
2196 neg_i_val.try_atan(),
2197 Err(ATanComplexErrors::Input {
2198 source: ATanComplexInputErrors::ArgumentIsPole { .. }
2199 })
2200 ));
2201 }
2202 } mod hyperbolic {
2205 use super::*;
2206
2207 mod real {
2208 use super::*;
2209
2210 #[test]
2211 fn atanh_real_rug_out_of_domain() {
2212 let val_ge_1 = RealRugStrictFinite::<PRECISION>::one(); assert!(matches!(
2214 val_ge_1.try_atanh(),
2215 Err(ATanHErrors::Input {
2216 source: ATanHInputErrors::OutOfDomain { .. }
2217 })
2218 ));
2219
2220 let val_le_neg1 = RealRugStrictFinite::<PRECISION>::negative_one(); assert!(matches!(
2222 val_le_neg1.try_atanh(),
2223 Err(ATanHErrors::Input {
2224 source: ATanHInputErrors::OutOfDomain { .. }
2225 })
2226 ));
2227 }
2228
2229 #[test]
2230 fn acosh_real_rug_out_of_domain() {
2231 let val_lt_1 = RealRugStrictFinite::<PRECISION>::try_from_f64(0.5).unwrap();
2232 assert!(matches!(
2233 val_lt_1.try_acosh(),
2234 Err(ACosHErrors::Input {
2235 source: ACosHInputErrors::OutOfDomain { .. }
2236 })
2237 ));
2238 }
2239 }
2240
2241 mod complex {
2242 use super::*;
2243
2244 #[test]
2263 fn acosh_out_of_domain() {
2264 let val_on_branch_cut = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
2266 Float::with_val(PRECISION, 0.5),
2267 )
2268 .unwrap();
2269 assert!(matches!(
2270 val_on_branch_cut.try_acosh(),
2271 Err(ACosHErrors::Input {
2272 source: ACosHInputErrors::OutOfDomain { .. }
2273 })
2274 ));
2275
2276 let val_on_branch_cut_neg =
2277 ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(Float::with_val(
2278 PRECISION, -5.0,
2279 ))
2280 .unwrap();
2281 assert!(matches!(
2282 val_on_branch_cut_neg.try_acosh(),
2283 Err(ACosHErrors::Input {
2284 source: ACosHInputErrors::OutOfDomain { .. }
2285 })
2286 ));
2287 }
2288
2289 #[test]
2290 fn atanh_out_of_domain() {
2291 let val_ge_1 = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
2292 Float::with_val(PRECISION, 1.0),
2293 )
2294 .unwrap();
2295 assert!(matches!(
2296 val_ge_1.try_atanh(),
2297 Err(ATanHErrors::Input {
2298 source: ATanHInputErrors::OutOfDomain { .. }
2299 })
2300 ));
2301
2302 let val_le_neg1 = ComplexRugStrictFinite::<PRECISION>::try_new_pure_real(
2303 Float::with_val(PRECISION, -1.0),
2304 )
2305 .unwrap();
2306 assert!(matches!(
2307 val_le_neg1.try_atanh(),
2308 Err(ATanHErrors::Input {
2309 source: ATanHInputErrors::OutOfDomain { .. }
2310 })
2311 ));
2312 }
2313 }
2314
2315 } }
2333
2334 mod summation {
2335 use super::*;
2336
2337 const PRECISION: u32 = 53;
2338
2339 type RealValidated = RealRugStrictFinite<PRECISION>;
2340 type ComplexValidated = ComplexRugStrictFinite<PRECISION>;
2341
2342 #[test]
2343 fn sum_real() {
2344 let values = vec![
2345 RealValidated::try_from_f64(1.0).unwrap(),
2346 RealValidated::try_from_f64(2.0).unwrap(),
2347 RealValidated::try_from_f64(3.0).unwrap(),
2348 RealValidated::try_from_f64(4.0).unwrap(),
2349 RealValidated::try_from_f64(5.0).unwrap(),
2350 ];
2351 let sum: RealValidated = values.into_iter().sum();
2352 assert_eq!(sum, RealValidated::try_from_f64(15.0).unwrap());
2353 }
2354
2355 #[test]
2356 fn sum_real_compensated() {
2357 let values = vec![
2359 RealValidated::try_from_f64(1.0e100).unwrap(),
2360 RealValidated::try_from_f64(1.0).unwrap(),
2361 RealValidated::try_from_f64(-1.0e100).unwrap(),
2362 ];
2363 let sum: RealValidated = values.into_iter().sum();
2364 assert_eq!(sum, RealValidated::try_from_f64(1.0).unwrap());
2366 }
2367
2368 #[test]
2369 fn sum_complex() {
2370 let values = vec![
2371 ComplexValidated::try_new_complex(
2372 rug::Float::with_val(PRECISION, 1.),
2373 rug::Float::with_val(PRECISION, 2.),
2374 )
2375 .unwrap(),
2376 ComplexValidated::try_new_complex(
2377 rug::Float::with_val(PRECISION, 3.),
2378 rug::Float::with_val(PRECISION, 4.),
2379 )
2380 .unwrap(),
2381 ComplexValidated::try_new_complex(
2382 rug::Float::with_val(PRECISION, 5.),
2383 rug::Float::with_val(PRECISION, 6.),
2384 )
2385 .unwrap(),
2386 ];
2387 let sum: ComplexValidated = values.into_iter().sum();
2388 assert_eq!(
2389 sum,
2390 ComplexValidated::try_new_complex(
2391 rug::Float::with_val(PRECISION, 9.),
2392 rug::Float::with_val(PRECISION, 12.)
2393 )
2394 .unwrap()
2395 );
2396 }
2397
2398 #[test]
2399 fn sum_complex_compensated() {
2400 let values = [
2401 ComplexValidated::try_new_complex(
2402 rug::Float::with_val(PRECISION, 1.0e100),
2403 rug::Float::with_val(PRECISION, -1.0e100),
2404 )
2405 .unwrap(),
2406 ComplexValidated::try_new_complex(
2407 rug::Float::with_val(PRECISION, 1.),
2408 rug::Float::with_val(PRECISION, 2.),
2409 )
2410 .unwrap(),
2411 ComplexValidated::try_new_complex(
2412 rug::Float::with_val(PRECISION, -1.0e100),
2413 rug::Float::with_val(PRECISION, 1.0e100),
2414 )
2415 .unwrap(),
2416 ];
2417 let sum: ComplexValidated = values.iter().cloned().sum();
2418 assert_eq!(
2419 sum,
2420 ComplexValidated::try_new_complex(
2421 rug::Float::with_val(PRECISION, 1.),
2422 rug::Float::with_val(PRECISION, 2.)
2423 )
2424 .unwrap()
2425 );
2426 }
2427 } mod random {
2430 use super::*;
2431 use crate::{RandomSampleFromF64, new_random_vec};
2432 use rand::{Rng, SeedableRng, distr::Uniform, rngs::StdRng};
2433
2434 const PRECISION: u32 = 53;
2435
2436 type RealValidated = RealRugStrictFinite<PRECISION>;
2437 type ComplexValidated = ComplexRugStrictFinite<PRECISION>;
2438
2439 #[test]
2443 fn test_random_real_validated() {
2444 let seed = [42; 32];
2445 let mut rng = StdRng::from_seed(seed);
2446
2447 let random_real: RealValidated = rng.random();
2448
2449 assert_eq!(random_real, 0.23713468825474326);
2451
2452 let mut rng2 = StdRng::from_seed(seed);
2454 let random_real2: RealValidated = rng2.random();
2455 assert_eq!(random_real, random_real2);
2456 }
2457
2458 #[test]
2463 fn test_random_complex_validated() {
2464 let seed = [99; 32];
2465 let mut rng = StdRng::from_seed(seed);
2466
2467 let random_complex: ComplexValidated = rng.random();
2468
2469 let real_part = random_complex.real_part();
2472 let imag_part = random_complex.imag_part();
2473
2474 assert_eq!(real_part, 0.9995546882627792);
2475 assert_eq!(imag_part, 0.08932180682540247);
2476
2477 let mut rng2 = StdRng::from_seed(seed);
2479 let random_complex2: ComplexValidated = rng2.random();
2480 assert_eq!(random_complex, random_complex2);
2481 }
2482
2483 const SEED: [u8; 32] = [42; 32];
2484
2485 #[test]
2486 fn test_sample_real_validated() {
2487 let mut rng = StdRng::from_seed(SEED);
2488 let dist = Uniform::new(-10.0, 10.0).unwrap();
2489
2490 let val = RealValidated::sample_from(&dist, &mut rng);
2491 assert_eq!(val, -5.257306234905137);
2492
2493 let mut rng2 = StdRng::from_seed(SEED);
2495 let val2 = RealValidated::sample_from(&dist, &mut rng2);
2496 assert_eq!(val, val2);
2497 }
2498
2499 #[test]
2500 fn test_sample_complex_validated() {
2501 let mut rng = StdRng::from_seed(SEED);
2502 let dist = Uniform::new(-10.0, 10.0).unwrap();
2503
2504 let val = ComplexValidated::sample_from(&dist, &mut rng);
2505 assert_eq!(val.real_part(), -5.257306234905137);
2506 assert_eq!(val.imag_part(), 7.212119776268775);
2507
2508 let mut rng2 = StdRng::from_seed(SEED);
2510 let val2 = ComplexValidated::sample_from(&dist, &mut rng2);
2511 assert_eq!(val, val2);
2512 }
2513
2514 #[test]
2515 fn new_random_vec_real() {
2516 let mut rng = StdRng::from_seed(SEED);
2517 let dist = Uniform::new(-10.0, 10.0).unwrap();
2518 let vec: Vec<RealValidated> = new_random_vec(3, &dist, &mut rng);
2519 assert_eq!(vec.len(), 3);
2520 assert_eq!(vec[0], -5.257306234905137);
2521 assert_eq!(vec[1], 7.212119776268775);
2522 assert_eq!(vec[2], -4.666248990558111);
2523
2524 let mut rng2 = StdRng::from_seed(SEED);
2526 let vec2: Vec<RealValidated> = new_random_vec(3, &dist, &mut rng2);
2527 assert_eq!(vec, vec2);
2528 }
2529
2530 #[test]
2531 fn new_random_vec_complex() {
2532 let mut rng = StdRng::from_seed(SEED);
2533 let dist = Uniform::new(-10.0, 10.0).unwrap();
2534 let vec: Vec<ComplexValidated> = new_random_vec(3, &dist, &mut rng);
2535 assert_eq!(vec.len(), 3);
2536 assert_eq!(vec[0].real_part(), -5.257306234905137);
2537 assert_eq!(vec[0].imag_part(), 7.212119776268775);
2538 assert_eq!(vec[1].real_part(), -4.666248990558111);
2539 assert_eq!(vec[1].imag_part(), 9.66047141517383);
2540 assert_eq!(vec[2].real_part(), -9.04279551029691);
2541 assert_eq!(vec[2].imag_part(), -1.026624649331671);
2542
2543 let mut rng2 = StdRng::from_seed(SEED);
2545 let vec2: Vec<ComplexValidated> = new_random_vec(3, &dist, &mut rng2);
2546 assert_eq!(vec, vec2);
2547 }
2548 }
2549
2550 mod hash_map_key_usage {
2551 use crate::kernels::rug::RealRugStrictFinite;
2552 use rug::Float;
2553 use std::collections::HashMap;
2554 use try_create::TryNew;
2555
2556 const PRECISION: u32 = 128;
2557 type RealRugValidated = RealRugStrictFinite<PRECISION>;
2558
2559 #[test]
2560 fn test_rug_as_hashmap_key() {
2561 let mut map = HashMap::new();
2562 let key1 = RealRugValidated::try_new(Float::with_val(PRECISION, 1.0)).unwrap();
2563 let key2 = RealRugValidated::try_new(Float::with_val(PRECISION, 2.5)).unwrap();
2564
2565 map.insert(key1.clone(), "one_rug");
2566 map.insert(key2.clone(), "two_point_five_rug");
2567
2568 assert_eq!(map.get(&key1), Some(&"one_rug"));
2569 assert_eq!(map.len(), 2);
2570
2571 let old_value = map.insert(key1.clone(), "new_one_rug");
2573 assert_eq!(old_value, Some("one_rug"));
2574 assert_eq!(map.get(&key1), Some(&"new_one_rug"));
2575 }
2576
2577 #[test]
2578 fn test_hash_signed_zero() {
2579 use crate::functions::Sign;
2580 use std::collections::hash_map::DefaultHasher;
2581 use std::hash::{Hash, Hasher};
2582
2583 let val1 = RealRugValidated::try_new(Float::with_val(PRECISION, 0.0)).unwrap();
2584 assert!(val1.kernel_is_sign_positive());
2585 let val2 = RealRugValidated::try_new(Float::with_val(PRECISION, -0.0)).unwrap();
2586 assert!(val2.kernel_is_sign_negative());
2587
2588 let mut hasher1 = DefaultHasher::new();
2590 let mut hasher2 = DefaultHasher::new();
2591
2592 val1.hash(&mut hasher1);
2593 val2.hash(&mut hasher2);
2594
2595 assert_eq!(hasher1.finish(), hasher2.finish());
2596 assert_eq!(val1, val2); }
2598 }
2599
2600 mod rug_float {
2601
2602 mod truncate_to_usize {
2603 use crate::kernels::RawRealTrait;
2604 use crate::validation::ErrorsRawRealToInteger;
2605 use rug::Float;
2606
2607 const PRECISION: u32 = 128;
2608
2609 #[test]
2610 fn test_rug_truncate_to_usize_valid() {
2611 assert_eq!(
2612 Float::with_val(PRECISION, 42.0)
2613 .truncate_to_usize()
2614 .unwrap(),
2615 42
2616 );
2617 assert_eq!(
2618 Float::with_val(PRECISION, 42.9)
2619 .truncate_to_usize()
2620 .unwrap(),
2621 42
2622 );
2623 assert_eq!(
2624 Float::with_val(PRECISION, 0.0).truncate_to_usize().unwrap(),
2625 0
2626 );
2627 assert_eq!(
2628 Float::with_val(PRECISION, usize::MAX)
2629 .truncate_to_usize()
2630 .unwrap(),
2631 usize::MAX
2632 );
2633 }
2634
2635 #[test]
2636 fn test_rug_truncate_to_usize_not_finite() {
2637 assert!(matches!(
2638 Float::with_val(PRECISION, f64::NAN).truncate_to_usize(),
2639 Err(ErrorsRawRealToInteger::NotFinite { .. })
2640 ));
2641 assert!(matches!(
2642 Float::with_val(PRECISION, f64::INFINITY).truncate_to_usize(),
2643 Err(ErrorsRawRealToInteger::NotFinite { .. })
2644 ));
2645 assert!(matches!(
2646 Float::with_val(PRECISION, f64::NEG_INFINITY).truncate_to_usize(),
2647 Err(ErrorsRawRealToInteger::NotFinite { .. })
2648 ));
2649 }
2650
2651 #[test]
2652 fn test_rug_truncate_to_usize_out_of_range() {
2653 assert!(matches!(
2655 Float::with_val(PRECISION, -1.0).truncate_to_usize(),
2656 Err(ErrorsRawRealToInteger::OutOfRange { .. })
2657 ));
2658
2659 let mut too_large = Float::with_val(PRECISION, usize::MAX);
2661 too_large += 1;
2662 assert!(matches!(
2663 too_large.truncate_to_usize(),
2664 Err(ErrorsRawRealToInteger::OutOfRange { .. })
2665 ));
2666 }
2667 }
2668 }
2669
2670 mod truncate_to_usize {
2671 use super::*;
2672 use crate::kernels::rug::RealRugStrictFinite;
2673 use rug::Float;
2674 use try_create::TryNew;
2675
2676 const PRECISION: u32 = 1000;
2677
2678 #[test]
2679 fn test_positive_integers() {
2680 let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 42.0))
2681 .unwrap();
2682 assert_eq!(value.truncate_to_usize().unwrap(), 42);
2683
2684 let value =
2685 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0)).unwrap();
2686 assert_eq!(value.truncate_to_usize().unwrap(), 1);
2687 }
2688
2689 #[test]
2690 fn test_positive_fractionals_truncate() {
2691 let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 42.9))
2692 .unwrap();
2693 assert_eq!(value.truncate_to_usize().unwrap(), 42);
2694
2695 let value =
2696 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.9)).unwrap();
2697 assert_eq!(value.truncate_to_usize().unwrap(), 0);
2698 }
2699
2700 #[test]
2701 fn test_zero_cases() {
2702 let value =
2703 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0)).unwrap();
2704 assert_eq!(value.truncate_to_usize().unwrap(), 0);
2705 }
2706
2707 #[test]
2708 fn test_negative_values_error() {
2709 let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
2710 .unwrap();
2711 let result = value.truncate_to_usize();
2712 assert!(matches!(
2713 result,
2714 Err(ErrorsRawRealToInteger::OutOfRange { .. })
2715 ));
2716
2717 let value =
2718 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -10.5))
2719 .unwrap();
2720 let result = value.truncate_to_usize();
2721 assert!(matches!(
2722 result,
2723 Err(ErrorsRawRealToInteger::OutOfRange { .. })
2724 ));
2725 }
2726
2727 #[test]
2728 fn test_large_values() {
2729 let value =
2731 RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1_000_000.0))
2732 .unwrap();
2733 assert_eq!(value.truncate_to_usize().unwrap(), 1_000_000);
2734
2735 let value = RealRugStrictFinite::<PRECISION>::try_new(
2737 Float::with_val(PRECISION, 1e50), )
2739 .unwrap();
2740 let result = value.truncate_to_usize();
2741 assert!(matches!(
2742 result,
2743 Err(ErrorsRawRealToInteger::OutOfRange { .. })
2744 ));
2745 }
2746
2747 #[test]
2748 fn test_high_precision_truncation() {
2749 let value = RealRugStrictFinite::<PRECISION>::try_new(
2751 Float::parse("42.99999999999999999999999999999")
2752 .unwrap()
2753 .complete(PRECISION),
2754 )
2755 .unwrap();
2756 assert_eq!(value.truncate_to_usize().unwrap(), 42);
2757
2758 let value = RealRugStrictFinite::<PRECISION>::try_new(
2760 Float::parse("0.99999999999999999999999999999")
2761 .unwrap()
2762 .complete(PRECISION),
2763 )
2764 .unwrap();
2765 assert_eq!(value.truncate_to_usize().unwrap(), 0);
2766 }
2767
2768 #[test]
2769 fn test_conversion_from_f64() {
2770 let value = RealRugStrictFinite::<PRECISION>::try_from_f64(42.7).unwrap();
2772 assert_eq!(value.truncate_to_usize().unwrap(), 42);
2773
2774 let value = RealRugStrictFinite::<PRECISION>::try_from_f64(0.5).unwrap();
2775 assert_eq!(value.truncate_to_usize().unwrap(), 0);
2776 }
2777 }
2778}