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