1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
9 core::{
10 errors::ErrorsValidationRawReal,
11 traits::{raw::RawScalarValidate, validation::sealed::NativeReal},
12 },
13 functions::FunctionErrors,
14 kernels::{RawComplexTrait, RawRealTrait, RawScalarTrait},
15};
16use duplicate::duplicate_item;
17use num::Complex;
18use num_traits::int::PrimInt;
19use std::backtrace::Backtrace;
20use thiserror::Error;
21
22#[cfg(debug_assertions)]
23use crate::core::errors::capture_backtrace;
24
25#[cfg(debug_assertions)]
26use num::{One, Zero};
27
28pub trait IntegerExponent: PrimInt {}
31
32impl IntegerExponent for i8 {}
33impl IntegerExponent for u8 {}
34impl IntegerExponent for i16 {}
35impl IntegerExponent for u16 {}
36impl IntegerExponent for i32 {}
37impl IntegerExponent for u32 {}
38impl IntegerExponent for i64 {}
39impl IntegerExponent for u64 {}
40impl IntegerExponent for i128 {}
41impl IntegerExponent for u128 {}
42impl IntegerExponent for isize {}
43impl IntegerExponent for usize {}
44#[derive(Debug, Error)]
54pub enum PowRealBaseRealExponentInputErrors<RawReal: RawRealTrait> {
55 #[error("detected a negative base ({base}) with a real exponent ({exponent}) !")]
59 NegativeBase {
60 base: RawReal,
62
63 exponent: RawReal,
65
66 backtrace: Backtrace,
68 },
69
70 #[error("the base is invalid!")]
75 InvalidBase {
76 #[source]
79 #[backtrace]
80 source: <RawReal as RawScalarValidate>::ValidationError,
81 },
82
83 #[error("the exponent is invalid!")]
88 InvalidExponent {
89 #[source]
92 #[backtrace]
93 source: <RawReal as RawScalarValidate>::ValidationError,
94 },
95
96 #[error("the base and the exponent are invalid!")]
100 InvalidBaseAndExponent {
101 error_base: <RawReal as RawScalarValidate>::ValidationError,
103
104 error_exponent: <RawReal as RawScalarValidate>::ValidationError,
106
107 #[backtrace]
109 backtrace: Backtrace,
110 },
111}
112#[derive(Debug, Error)]
122pub enum PowComplexBaseRealExponentInputErrors<RawComplex: RawComplexTrait> {
123 #[error("the input complex base is invalid according to validation policy")]
128 InvalidBase {
129 #[source]
132 #[backtrace]
133 source: <RawComplex as RawScalarValidate>::ValidationError,
134 },
135
136 #[error("the input real exponent is invalid according to validation policy")]
141 InvalidExponent {
142 #[source]
145 #[backtrace]
146 source: <RawComplex::RawReal as RawScalarValidate>::ValidationError,
147 },
148
149 #[error(
154 "the input complex base and the real exponent is invalid according to validation policy"
155 )]
156 InvalidBaseAndExponent {
157 error_base: <RawComplex as RawScalarValidate>::ValidationError,
159
160 error_exponent: <RawComplex::RawReal as RawScalarValidate>::ValidationError,
162
163 #[backtrace]
165 backtrace: Backtrace,
166 },
167
168 #[error("the base is zero and the exponent (={exponent}) is negative!")]
171 ZeroBaseNegativeExponent {
172 exponent: RawComplex::RawReal,
174
175 backtrace: Backtrace,
177 },
178}
179#[derive(Debug, Error)]
189pub enum PowIntExponentInputErrors<RawScalar: RawScalarTrait, ExponentType: IntegerExponent> {
190 #[error("the input base is invalid according to validation policy")]
195 InvalidBase {
196 #[source]
199 #[backtrace]
200 source: <RawScalar as RawScalarValidate>::ValidationError,
201 },
202
203 #[error("detected a zero base with a negative integer exponent ({exponent:?})!")]
206 ZeroBaseNegativeExponent {
207 exponent: ExponentType,
209
210 backtrace: Backtrace,
212 },
213 }
218#[derive(Debug, Error)]
230pub enum PowRealBaseRealExponentErrors<RawReal: RawRealTrait> {
231 #[error("the input value is invalid!")]
233 Input(
234 #[from]
236 PowRealBaseRealExponentInputErrors<RawReal>,
237 ),
238
239 #[error("the output value is invalid!")]
241 Output {
242 #[source]
244 #[backtrace]
245 source: <RawReal as RawScalarValidate>::ValidationError,
246 },
247}
248#[derive(Debug, Error)]
259pub enum PowComplexBaseRealExponentErrors<RawComplex: RawComplexTrait> {
260 #[error("the input value is invalid!")]
262 Input(
263 #[from]
265 PowComplexBaseRealExponentInputErrors<RawComplex>,
266 ),
267
268 #[error("the output value is invalid!")]
270 Output {
271 #[source]
273 #[backtrace]
274 source: <RawComplex as RawScalarValidate>::ValidationError,
275 },
276}
277pub type PowIntExponentErrors<RawScalar, ExponentType> = FunctionErrors<
289 PowIntExponentInputErrors<RawScalar, ExponentType>,
290 <RawScalar as RawScalarValidate>::ValidationError,
291>;
292pub trait Pow<ExponentType>: Sized {
307 type Error: std::error::Error;
310
311 #[must_use = "this `Result` may contain an error that should be handled"]
323 fn try_pow(self, exponent: ExponentType) -> Result<Self, Self::Error>;
324
325 fn pow(self, exponent: ExponentType) -> Self;
358}
359
360impl<T> Pow<&T> for T
361where
362 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
363{
364 type Error = PowRealBaseRealExponentErrors<T>;
365
366 #[inline(always)]
367 fn try_pow(self, exponent: &T) -> Result<Self, Self::Error> {
368 #[cfg(debug_assertions)]
369 {
370 let validation_base = self.validate_raw_scalar();
371 let validation_exponent = exponent.validate_raw_scalar_ref();
372 match (validation_base, validation_exponent) {
373 (Ok(base), Ok(())) => {
374 if base < T::zero() {
375 Err(PowRealBaseRealExponentInputErrors::NegativeBase {
376 base,
377 exponent: *exponent,
378 backtrace: capture_backtrace(),
379 }
380 .into())
381 } else {
382 let result = base.powf(*exponent);
383 result
384 .validate_raw_scalar()
385 .map_err(|e| PowRealBaseRealExponentErrors::Output { source: e })
386 }
387 }
388 (Ok(_), Err(error_exponent)) => {
389 Err(PowRealBaseRealExponentInputErrors::InvalidExponent {
390 source: error_exponent,
391 }
392 .into())
393 }
394 (Err(error_base), Ok(_)) => {
395 Err(
396 PowRealBaseRealExponentInputErrors::InvalidBase { source: error_base }
397 .into(),
398 )
399 }
400 (Err(error_base), Err(error_exponent)) => {
401 Err(PowRealBaseRealExponentInputErrors::InvalidBaseAndExponent {
402 error_base,
403 error_exponent,
404 backtrace: capture_backtrace(),
405 }
406 .into())
407 }
408 }
409 }
410 #[cfg(not(debug_assertions))]
411 {
412 Ok(self.powf(*exponent))
413 }
414 }
415
416 #[inline(always)]
417 fn pow(self, exponent: &T) -> Self {
419 #[cfg(debug_assertions)]
420 {
421 self.try_pow(exponent).unwrap()
422 }
423 #[cfg(not(debug_assertions))]
424 {
425 self.powf(*exponent)
426 }
427 }
428}
429
430impl<T> Pow<&T> for Complex<T>
431where
432 Self: RawComplexTrait<RawReal = T>,
433 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
434{
435 type Error = PowComplexBaseRealExponentErrors<Self>;
436
437 #[inline(always)]
438 fn try_pow(self, exponent: &T) -> Result<Self, Self::Error> {
439 #[cfg(debug_assertions)]
440 {
441 let validation_base = self.validate_raw_scalar();
442 let validation_exponent = exponent.validate_raw_scalar_ref();
443 match (validation_base, validation_exponent) {
444 (Ok(base), Ok(())) => {
445 let zero = T::zero();
446 if Zero::is_zero(&base) {
447 if *exponent < zero {
448 Err(
449 PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent {
450 exponent: *exponent,
451 backtrace: capture_backtrace(),
452 }
453 .into(),
454 )
455 } else if *exponent == zero {
456 Ok(Complex::one())
457 } else {
458 Ok(Complex::zero())
459 }
460 } else {
461 base.powf(*exponent)
462 .validate_raw_scalar()
463 .map_err(|e| PowComplexBaseRealExponentErrors::Output { source: e })
464 }
465 }
466 (Ok(_), Err(error_exponent)) => {
467 Err(PowComplexBaseRealExponentInputErrors::InvalidExponent {
468 source: error_exponent,
469 }
470 .into())
471 }
472 (Err(error_base), Ok(_)) => Err(
473 PowComplexBaseRealExponentInputErrors::InvalidBase { source: error_base }
474 .into(),
475 ),
476 (Err(error_base), Err(error_exponent)) => Err(
477 PowComplexBaseRealExponentInputErrors::InvalidBaseAndExponent {
478 error_base,
479 error_exponent,
480 backtrace: capture_backtrace(),
481 }
482 .into(),
483 ),
484 }
485 }
486 #[cfg(not(debug_assertions))]
487 {
488 Ok(self.powf(*exponent))
489 }
490 }
491
492 #[inline(always)]
493 fn pow(self, exponent: &T) -> Self {
495 #[cfg(debug_assertions)]
496 {
497 self.try_pow(exponent)
498 .expect("Error raised by Pow::try_pow() in the function Pow::pow() (debug mode)")
499 }
500 #[cfg(not(debug_assertions))]
501 {
502 self.powf(*exponent)
503 }
504 }
505}
506
507#[duplicate_item(
508 exponent_type exponent_func;
509 [i8] [exponent.into()];
510 [i16] [exponent.into()];
511 [i32] [exponent];
512 [i64] [exponent.try_into().unwrap()];
513 [i128] [exponent.try_into().unwrap()];
514 [isize] [exponent.try_into().unwrap()];
515)]
516impl<T> Pow<exponent_type> for T
517where
518 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
520{
521 type Error = PowIntExponentErrors<T, exponent_type>;
522
523 fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
524 #[cfg(debug_assertions)]
525 {
526 self.validate_raw_scalar()
527 .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
528 .and_then(|base| {
529 if base == T::zero() && exponent < 0 {
530 Err(PowIntExponentInputErrors::ZeroBaseNegativeExponent {
531 exponent,
532 backtrace: capture_backtrace(),
533 }
534 .into())
535 } else {
536 base.powi(exponent_func)
537 .validate_raw_scalar()
538 .map_err(|e| Self::Error::Output { source: e })
539 }
540 })
541 }
542 #[cfg(not(debug_assertions))]
543 {
544 Ok(self.powi(exponent_func))
545 }
546 }
547
548 #[inline(always)]
549 fn pow(self, exponent: exponent_type) -> Self {
551 #[cfg(debug_assertions)]
552 {
553 self.try_pow(exponent).unwrap()
554 }
555 #[cfg(not(debug_assertions))]
556 {
557 self.powi(exponent_func)
558 }
559 }
560}
561
562#[duplicate_item(
563 exponent_type exponent_func;
564 [u8] [exponent.into()];
565 [u16] [exponent.into()];
566 [u32] [exponent.try_into().unwrap()];
567 [u64] [exponent.try_into().unwrap()];
568 [u128] [exponent.try_into().unwrap()];
569 [usize] [exponent.try_into().unwrap()];
570)]
571impl<T> Pow<exponent_type> for T
572where
573 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
574{
575 type Error = PowIntExponentErrors<T, exponent_type>;
576
577 fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
578 #[cfg(debug_assertions)]
579 {
580 self.validate_raw_scalar()
581 .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
582 .and_then(|base| {
583 let res = base.powi(exponent_func);
584 res.validate_raw_scalar()
585 .map_err(|e| Self::Error::Output { source: e })
586 })
587 }
588 #[cfg(not(debug_assertions))]
589 {
590 Ok(self.powi(exponent_func))
591 }
592 }
593
594 #[inline(always)]
595 fn pow(self, exponent: exponent_type) -> Self {
597 #[cfg(debug_assertions)]
598 {
599 self.try_pow(exponent).unwrap()
600 }
601 #[cfg(not(debug_assertions))]
602 {
603 self.powi(exponent_func)
604 }
605 }
606}
607
608#[duplicate_item(
609 exponent_type func_name exponent_func;
610 [i8] [powi] [exponent.into()];
611 [i16] [powi] [exponent.into()];
612 [i32] [powi] [exponent];
613 [i64] [powi] [exponent.try_into().unwrap()];
614 [i128] [powi] [exponent.try_into().unwrap()];
615 [isize] [powi] [exponent.try_into().unwrap()];
616)]
617impl<T> Pow<exponent_type> for Complex<T>
618where
619 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
620{
621 type Error = PowIntExponentErrors<Complex<T>, exponent_type>;
622
623 #[inline(always)]
624 fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
625 #[cfg(debug_assertions)]
626 {
627 self.validate_raw_scalar()
628 .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
629 .and_then(|base| {
630 if Zero::is_zero(&base) && exponent < 0 {
631 Err(PowIntExponentInputErrors::ZeroBaseNegativeExponent {
632 exponent,
633 backtrace: capture_backtrace(),
634 }
635 .into())
636 } else {
637 base.func_name(exponent_func)
638 .validate_raw_scalar()
639 .map_err(|e| Self::Error::Output { source: e })
640 }
641 })
642 }
643 #[cfg(not(debug_assertions))]
644 {
645 Ok(self.func_name(exponent_func))
646 }
647 }
648
649 #[inline(always)]
650 fn pow(self, exponent: exponent_type) -> Self {
652 #[cfg(debug_assertions)]
653 {
654 self.try_pow(exponent).unwrap()
655 }
656 #[cfg(not(debug_assertions))]
657 {
658 self.func_name(exponent_func)
659 }
660 }
661}
662
663#[duplicate_item(
664 exponent_type func_name exponent_func;
665 [u8] [powu] [exponent.into()];
666 [u16] [powu] [exponent.into()];
667 [u32] [powu] [exponent];
668 [u64] [powu] [exponent.try_into().unwrap()];
669 [u128] [powu] [exponent.try_into().unwrap()];
670 [usize] [powu] [exponent.try_into().unwrap()];
671)]
672impl<T> Pow<exponent_type> for Complex<T>
673where
674 T: NativeReal<ValidationError = ErrorsValidationRawReal<T>>,
675{
676 type Error = PowIntExponentErrors<Complex<T>, exponent_type>;
677
678 #[inline(always)]
679 fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
680 #[cfg(debug_assertions)]
681 {
682 self.validate_raw_scalar()
683 .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
684 .and_then(|base| {
685 base.func_name(exponent_func)
686 .validate_raw_scalar()
687 .map_err(|e| Self::Error::Output { source: e })
688 })
689 }
690 #[cfg(not(debug_assertions))]
691 {
692 Ok(self.func_name(exponent_func))
693 }
694 }
695
696 #[inline(always)]
697 fn pow(self, exponent: exponent_type) -> Self {
699 #[cfg(debug_assertions)]
700 {
701 self.try_pow(exponent).unwrap()
702 }
703 #[cfg(not(debug_assertions))]
704 {
705 self.func_name(exponent_func)
706 }
707 }
708}
709#[cfg(test)]
713mod tests {
714 #[cfg(debug_assertions)]
715 use super::*;
716
717 use crate::{RealScalar, functions::Pow};
718 use num::Complex;
719
720 #[cfg(debug_assertions)]
721 use std::assert_matches;
722
723 #[cfg(debug_assertions)]
724 use crate::{
725 core::errors::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
726 functions::{PowIntExponentErrors, PowIntExponentInputErrors},
727 };
728
729 #[cfg(feature = "rug")]
730 use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
731
732 #[cfg(feature = "rug")]
733 use try_create::TryNew;
734
735 mod pow_u32_exponent {
736 use super::*;
737
738 mod real_base {
739 use crate::core::traits::raw::TryConvertFromRawReal;
740
741 use super::*;
742
743 fn pow_generic_real_u32_valid<RealType: RealScalar>()
744 where
745 RealType::RawReal: TryConvertFromRawReal<f64>,
746 {
747 let base = RealType::try_from_f64(2.0).unwrap();
748 let exponent = 3u32;
749 let expected_result = RealType::try_from_f64(8.0).unwrap();
750 assert_eq!(Pow::pow(base.clone(), exponent), expected_result);
751 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
752 }
753
754 #[test]
755 fn test_pow_generic_real_u32_valid() {
756 pow_generic_real_u32_valid::<f64>();
757 }
758
759 #[test]
760 fn test_f64_pow_u32_valid() {
761 let base = 2.0;
762 let exponent = 3u32;
763 let expected_result = 8.0;
764 assert_eq!(Pow::pow(base, exponent), expected_result);
765 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
766 }
767
768 #[test]
769 fn test_f64_pow_u32_zero_exponent() {
770 let base = 2.0;
771 let exponent = 0u32;
772 let expected_result = 1.0;
773 assert_eq!(Pow::pow(base, exponent), expected_result);
774 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
775 }
776
777 #[test]
778 fn test_f64_pow_u32_one_exponent() {
779 let base = 2.0;
780 let exponent = 1u32;
781 let expected_result = 2.0;
782 assert_eq!(Pow::pow(base, exponent), expected_result);
783 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
784 }
785
786 #[test]
787 fn test_f64_pow_u32_zero_base() {
788 let base = 0.0;
789 let exponent = 3u32;
790 let expected_result = 0.0;
791 assert_eq!(Pow::pow(base, exponent), expected_result);
792 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
793 }
794
795 #[test]
796 #[cfg(debug_assertions)]
797 fn test_f64_pow_u32_nan_base() {
798 let base = f64::NAN;
799 let exponent = 3u32;
800 let result = base.try_pow(exponent);
801 assert!(result.is_err());
802 }
803
804 #[test]
805 #[cfg(debug_assertions)]
806 fn test_f64_pow_u32_infinity_base() {
807 let base = f64::INFINITY;
808 let exponent = 3u32;
809 let result = base.try_pow(exponent);
810 assert!(result.is_err());
811 }
812 }
813
814 mod complex_base {
815 use super::*;
816
817 #[test]
818 fn test_complex_f64_pow_u32_valid() {
819 let base = Complex::new(2.0, 3.0);
820 let exponent = 2u32;
821 let expected_result = Complex::new(-5.0, 12.0);
822 assert_eq!(Pow::pow(base, exponent), expected_result);
823 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
824 }
825
826 #[test]
827 fn test_complex_f64_pow_u32_zero_exponent() {
828 let base = Complex::new(2.0, 3.0);
829 let exponent = 0u32;
830 let expected_result = Complex::new(1.0, 0.0);
831 assert_eq!(Pow::pow(base, exponent), expected_result);
832 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
833 }
834
835 #[test]
836 fn test_complex_f64_pow_u32_one_exponent() {
837 let base = Complex::new(2.0, 3.0);
838 let exponent = 1u32;
839 let expected_result = Complex::new(2.0, 3.0);
840 assert_eq!(Pow::pow(base, exponent), expected_result);
841 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
842 }
843
844 #[test]
845 fn test_complex_f64_pow_u32_zero_base() {
846 let base = Complex::new(0.0, 0.0);
847 let exponent = 3u32;
848 let expected_result = Complex::new(0.0, 0.0);
849 assert_eq!(Pow::pow(base, exponent), expected_result);
850 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
851 }
852
853 #[test]
854 #[cfg(debug_assertions)]
855 fn test_complex_f64_pow_u32_nan_base() {
856 let base = Complex::new(f64::NAN, 0.0);
857 let exponent = 3u32;
858 let result = base.try_pow(exponent);
859 assert!(result.is_err());
860
861 let base = Complex::new(0.0, f64::NAN);
862 let result = base.try_pow(exponent);
863 assert!(result.is_err());
864 }
865
866 #[test]
867 #[cfg(debug_assertions)]
868 fn test_complex_f64_pow_u32_infinity_base() {
869 let base = Complex::new(f64::INFINITY, 0.0);
870 let exponent = 3u32;
871 let result = base.try_pow(exponent);
872 assert!(result.is_err());
873
874 let base = Complex::new(0.0, f64::INFINITY);
875 let result = base.try_pow(exponent);
876 assert!(result.is_err());
877 }
878 }
879 }
880
881 mod pow_i32_exponent {
882 use super::*;
883
884 mod native {
885 use super::*;
886
887 mod real_base {
888 use super::*;
889
890 #[test]
891 fn test_f64_pow_valid() {
892 let base = 2.0;
893 let exponent = 3i32;
894 let expected_result = 8.0;
895 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
896 assert_eq!(<f64 as Pow<i32>>::pow(base, exponent), expected_result);
897 }
898
899 #[test]
900 fn test_f64_pow_zero_exponent() {
901 let base = 2.0;
902 let exponent = 0i32;
903 let expected_result = 1.0;
904 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
905 }
906
907 #[test]
908 fn test_f64_pow_negative_exponent() {
909 let base = 2.0;
910 let exponent = -3i32;
911 let expected_result = 0.125;
912 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
913 }
914
915 #[test]
916 fn test_f64_pow_zero_base() {
917 let base = 0.0;
918 let exponent = 3i32;
919 let expected_result = 0.0;
920 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
921 }
922
923 #[test]
924 fn test_f64_pow_zero_base_zero_exponent() {
925 let base = 0.0;
926 let exponent = 0i32;
927 let expected_result = 1.0;
928 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
929 }
930
931 #[test]
932 #[cfg(debug_assertions)]
933 fn test_f64_pow_zero_base_negative_exponent() {
934 let base = 0.0;
935 let err = base.try_pow(-1i32).unwrap_err();
936 assert!(matches!(
937 err,
938 PowIntExponentErrors::Input(
939 PowIntExponentInputErrors::ZeroBaseNegativeExponent {
940 exponent: -1,
941 ..
942 }
943 )
944 ));
945 }
946
947 #[test]
948 fn test_f64_pow_negative_base_positive_exponent() {
949 let base = -2.0;
950 let exponent = 3i32;
951 let expected_result = -8.0;
952 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
953 }
954
955 #[test]
956 fn test_f64_pow_negative_base_negative_exponent() {
957 let base = -2.0;
958 let exponent = -3i32;
959 let expected_result = -0.125;
960 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
961 }
962 }
963
964 mod complex_base {
965 use super::*;
966
967 #[test]
968 fn test_complex_f64_pow_valid() {
969 let base = Complex::new(2.0, 3.0);
970 let exponent = 2i32;
971 let expected_result = Complex::new(-5.0, 12.0);
972 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
973 assert_eq!(
974 <Complex<f64> as Pow<i32>>::pow(base, exponent),
975 expected_result
976 );
977 }
978
979 #[test]
980 fn test_complex_f64_pow_zero_exponent() {
981 let base = Complex::new(2.0, 3.0);
982 let exponent = 0i32;
983 let expected_result = Complex::new(1.0, 0.0);
984 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
985 }
986
987 #[test]
988 fn test_complex_f64_pow_negative_exponent() {
989 let base = Complex::new(2.0, 3.0);
990 let exponent = -2i32;
991 let expected_result = Complex::new(-0.029585798816568053, -0.07100591715976332);
992 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
993 }
994
995 #[test]
996 fn test_complex_f64_pow_zero_base() {
997 let base = Complex::new(0.0, 0.0);
998 let exponent = 3i32;
999 let expected_result = Complex::new(0.0, 0.0);
1000 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1001 }
1002
1003 #[test]
1004 fn test_complex_f64_pow_zero_base_zero_exponent() {
1005 let base = Complex::new(0.0, 0.0);
1006 let exponent = 0i32;
1007 let expected_result = Complex::new(1.0, 0.0);
1008 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1009 }
1010
1011 #[test]
1012 #[cfg(debug_assertions)]
1013 fn test_complex_f64_pow_zero_base_negative_exponent() {
1014 let base = Complex::new(0.0, 0.0);
1015 let err = base.try_pow(-1i32).unwrap_err();
1016 assert!(matches!(
1017 err,
1018 PowIntExponentErrors::Input(
1019 PowIntExponentInputErrors::ZeroBaseNegativeExponent {
1020 exponent: -1,
1021 ..
1022 }
1023 )
1024 ));
1025 }
1026
1027 #[test]
1028 fn test_complex_f64_pow_negative_base_positive_exponent() {
1029 let base = Complex::new(-2.0, -3.0);
1030 let exponent = 3i32;
1031 let expected_result = Complex::new(46.0, -9.0);
1032 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1033 }
1034
1035 #[test]
1036 fn test_complex_f64_pow_negative_base_negative_exponent() {
1037 let base = Complex::new(-2.0, -3.0);
1038 let exponent = -3i32;
1039 let expected_result = Complex::new(0.02093764223941739, 0.004096495220755574);
1040 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1041 }
1042 }
1043 }
1044
1045 #[cfg(feature = "rug")]
1046 mod rug53 {
1047 use super::*;
1048 use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
1049 use rug::Float;
1050
1051 mod real {
1052 use super::*;
1053
1054 #[test]
1055 fn test_rug_float_pow_valid() {
1056 let base =
1057 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1058 let exponent = 3;
1059 let expected_result =
1060 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 8.0)).unwrap();
1061 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1062 }
1063
1064 #[test]
1065 fn test_rug_float_pow_zero_exponent() {
1066 let base =
1067 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1068 let exponent = 0;
1069 let expected_result =
1070 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1071 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1072 }
1073
1074 #[test]
1075 fn test_rug_float_pow_negative_exponent() {
1076 let base =
1077 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1078 let exponent = -3;
1079 let expected_result =
1080 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.125)).unwrap();
1081 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1082 }
1083
1084 #[test]
1085 fn test_rug_float_pow_zero_base() {
1086 let base =
1087 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1088 let exponent = 3;
1089 let expected_result =
1090 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1091 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1092 }
1093
1094 #[test]
1095 fn test_rug_float_pow_zero_base_zero_exponent() {
1096 let base =
1097 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1098 let exponent = 0;
1099 let expected_result =
1100 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1101 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1102 }
1103
1104 #[test]
1105 fn test_rug_float_pow_negative_base_positive_exponent() {
1106 let base =
1107 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1108 let exponent = 3;
1109 let expected_result =
1110 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -8.0)).unwrap();
1111 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1112 }
1113
1114 #[test]
1115 fn test_rug_float_pow_negative_base_negative_exponent() {
1116 let base =
1117 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1118 let exponent = -3;
1119 let expected_result =
1120 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -0.125)).unwrap();
1121 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1122 }
1123 }
1124
1125 mod complex {
1126 use super::*;
1127 use rug::Complex;
1128
1129 #[test]
1130 fn test_complex_rug_float_pow_valid() {
1131 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1132 53,
1133 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1134 ))
1135 .unwrap();
1136 let exponent = 2;
1137 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1138 53,
1139 (Float::with_val(53, -5.0), Float::with_val(53, 12.0)),
1140 ))
1141 .unwrap();
1142 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1143 }
1144
1145 #[test]
1146 fn test_complex_rug_float_pow_zero_exponent() {
1147 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1148 53,
1149 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1150 ))
1151 .unwrap();
1152 let exponent = 0;
1153 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1154 53,
1155 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1156 ))
1157 .unwrap();
1158 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1159 }
1160
1161 #[test]
1162 fn test_complex_rug_float_pow_negative_exponent() {
1163 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1164 53,
1165 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1166 ))
1167 .unwrap();
1168 let exponent = -2;
1169 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1170 53,
1171 (
1172 Float::with_val(53, -2.9585798816568046e-2),
1173 Float::with_val(53, -7.100591715976332e-2),
1174 ),
1175 ))
1176 .unwrap();
1177 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1178 }
1179
1180 #[test]
1181 fn test_complex_rug_float_pow_zero_base() {
1182 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1183 53,
1184 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1185 ))
1186 .unwrap();
1187 let exponent = 3;
1188 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1189 53,
1190 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1191 ))
1192 .unwrap();
1193 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1194 }
1195
1196 #[test]
1197 fn test_complex_rug_float_pow_zero_base_zero_exponent() {
1198 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1199 53,
1200 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1201 ))
1202 .unwrap();
1203 let exponent = 0;
1204 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1205 53,
1206 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1207 ))
1208 .unwrap();
1209 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1210 }
1211
1212 #[test]
1213 fn test_complex_rug_float_pow_negative_base_positive_exponent() {
1214 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1215 53,
1216 (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1217 ))
1218 .unwrap();
1219 let exponent = 3;
1220 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1221 53,
1222 (Float::with_val(53, 46.0), Float::with_val(53, -9.0)),
1223 ))
1224 .unwrap();
1225 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1226 }
1227
1228 #[test]
1229 fn test_complex_rug_float_pow_negative_base_negative_exponent() {
1230 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1231 53,
1232 (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1233 ))
1234 .unwrap();
1235 let exponent = -3;
1236 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1237 53,
1238 (
1239 Float::with_val(53, 2.0937642239417388e-2),
1240 Float::with_val(53, 4.096495220755576e-3),
1241 ),
1242 ))
1243 .unwrap();
1244 assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1245 }
1246 }
1247 }
1248 }
1249
1250 mod pow_real_exponent {
1251 use super::*;
1252
1253 mod native {
1254 use super::*;
1255
1256 mod real_base {
1257 use super::*;
1258
1259 #[test]
1260 fn test_f64_pow_f64_valid() {
1261 let base = 2.0;
1262 let exponent = 3.0;
1263 let expected_result = 8.0;
1264 assert_eq!(Pow::pow(base, &exponent), expected_result);
1265 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1266 }
1267
1268 #[test]
1269 fn test_f64_pow_f64_zero_exponent() {
1270 let base = 2.0;
1271 let exponent = 0.0;
1272 let expected_result = 1.0;
1273 assert_eq!(Pow::pow(base, &exponent), expected_result);
1274 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1275 }
1276
1277 #[test]
1278 #[cfg(debug_assertions)]
1279 fn test_f64_pow_f64_invalid_exponent() {
1280 let base = 2.0;
1281 let err = base.try_pow(&f64::NAN).unwrap_err();
1282 assert!(matches!(
1283 err,
1284 PowRealBaseRealExponentErrors::Input(
1285 PowRealBaseRealExponentInputErrors::InvalidExponent {
1286 source: ErrorsValidationRawReal::IsNaN { .. }
1287 }
1288 )
1289 ))
1290 }
1291
1292 #[test]
1293 #[cfg(debug_assertions)]
1294 fn test_f64_pow_f64_invalid_base_invalid_exponent() {
1295 let err = (f64::INFINITY).try_pow(&f64::NAN).unwrap_err();
1296 assert!(matches!(
1297 err,
1298 PowRealBaseRealExponentErrors::Input(
1299 PowRealBaseRealExponentInputErrors::InvalidBaseAndExponent {
1300 error_base: ErrorsValidationRawReal::IsPosInfinity { .. },
1301 error_exponent: ErrorsValidationRawReal::IsNaN { .. },
1302 ..
1303 }
1304 )
1305 ))
1306 }
1307
1308 #[test]
1309 fn test_f64_pow_f64_one_exponent() {
1310 let base = 2.0;
1311 let exponent = 1.0;
1312 let expected_result = 2.0;
1313 assert_eq!(Pow::pow(base, &exponent), expected_result);
1314 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1315 }
1316
1317 #[test]
1318 fn test_f64_pow_f64_zero_base() {
1319 let base = 0.0;
1320 let exponent = 3.0;
1321 let expected_result = 0.0;
1322 assert_eq!(Pow::pow(base, &exponent), expected_result);
1323 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1324 }
1325
1326 #[test]
1327 #[cfg(debug_assertions)]
1328 fn test_f64_pow_f64_nan_base() {
1329 let base = f64::NAN;
1330 let exponent = 3.0;
1331 let result = base.try_pow(&exponent);
1332 assert!(result.is_err());
1333 }
1334
1335 #[test]
1336 #[cfg(debug_assertions)]
1337 fn test_f64_pow_f64_infinity_base() {
1338 let base = f64::INFINITY;
1339 let exponent = 3.0;
1340 let result = base.try_pow(&exponent);
1341 assert!(matches!(
1342 result,
1343 Err(PowRealBaseRealExponentErrors::Input(..))
1344 ));
1345 }
1346
1347 #[test]
1348 fn test_f64_pow_f64_negative_exponent() {
1349 let base = 2.0;
1350 let exponent = -2.0;
1351 let expected_result = 0.25;
1352 assert_eq!(Pow::pow(base, &exponent), expected_result);
1353 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1354 }
1355
1356 #[test]
1357 #[cfg(debug_assertions)]
1358 fn test_f64_pow_f64_negative_base_positive_exponent() {
1359 let base = -2.0;
1360 let exponent = 3.0;
1361 let result = base.try_pow(&exponent);
1362 assert!(matches!(
1363 result,
1364 Err(PowRealBaseRealExponentErrors::Input(..))
1365 ));
1366 }
1367
1368 #[test]
1369 #[cfg(debug_assertions)]
1370 fn test_f64_pow_f64_negative_base_negative_exponent() {
1371 let base = -2.0;
1372 let exponent = -3.0;
1373 let result = base.try_pow(&exponent);
1374 assert!(result.is_err());
1375 }
1376 }
1377
1378 mod complex_base {
1379 use super::*;
1380
1381 #[test]
1382 fn test_complex_f64_pow_ok_base_ok_exponent() {
1383 let base = Complex::new(2.0, 3.0);
1384 let exponent = 2.0;
1385 let expected_result = Complex::new(-4.999999999999999, 11.999999999999998);
1386 assert_eq!(Pow::pow(base, &exponent), expected_result);
1387 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1388 }
1389
1390 #[test]
1391 fn test_complex_f64_pow_ok_base_zero_exponent() {
1392 let base = Complex::new(2.0, 3.0);
1393 let exponent = 0.0;
1394 let expected_result = Complex::new(1.0, 0.0);
1395 assert_eq!(Pow::pow(base, &exponent), expected_result);
1396 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1397 }
1398
1399 #[test]
1400 fn test_complex_f64_pow_zero_base_zero_exponent() {
1401 let base = Complex::new(0.0, 0.0);
1402 let exponent = 0.0;
1403 let expected_result = Complex::new(1.0, 0.0);
1404 assert_eq!(Pow::pow(base, &exponent), expected_result);
1405 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1406 }
1407
1408 #[test]
1409 #[cfg(debug_assertions)]
1410 fn test_complex_f64_pow_zero_base_negative_exponent() {
1411 let base = Complex::new(0.0, 0.0);
1412 let exponent = -1.0;
1413 let err = base.try_pow(&exponent).unwrap_err();
1414 assert_matches!(
1415 err,
1416 PowComplexBaseRealExponentErrors::Input(
1417 PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent {
1418 exponent: -1.,
1419 ..
1420 }
1421 )
1422 );
1423 }
1424
1425 #[test]
1426 #[cfg(debug_assertions)]
1427 fn test_complex_f64_pow_ok_base_nan_exponent() {
1428 let base = Complex::new(0.0, 0.0);
1429 let exponent = f64::NAN;
1430 let err = base.try_pow(&exponent).unwrap_err();
1431 assert_matches!(
1432 err,
1433 PowComplexBaseRealExponentErrors::Input(
1434 PowComplexBaseRealExponentInputErrors::InvalidExponent {
1435 source: ErrorsValidationRawReal::IsNaN { .. }
1436 }
1437 )
1438 );
1439 }
1440
1441 #[test]
1442 #[cfg(debug_assertions)]
1443 fn test_complex_f64_pow_infinity_base_nan_exponent() {
1444 let base = Complex::new(f64::INFINITY, 0.0);
1445 let exponent = f64::NAN;
1446 let err = base.try_pow(&exponent).unwrap_err();
1447 match err {
1448 PowComplexBaseRealExponentErrors::Input(
1449 PowComplexBaseRealExponentInputErrors::InvalidBaseAndExponent {
1450 error_base,
1451 error_exponent,
1452 ..
1453 },
1454 ) => {
1455 assert_matches!(
1456 error_base,
1457 ErrorsValidationRawComplex::InvalidRealPart {
1458 source
1459 } if matches!(*source, ErrorsValidationRawReal::IsPosInfinity { .. })
1460 );
1461 assert_matches!(error_exponent, ErrorsValidationRawReal::IsNaN { .. });
1462 }
1463 _ => {
1464 unreachable!()
1465 }
1466 }
1467 }
1468
1469 #[test]
1470 fn test_complex_f64_pow_ok_base_one_exponent() {
1471 let base = Complex::new(2.0, 3.0);
1472 let exponent = 1.0;
1473 let expected_result = Complex::new(2.0, 3.0);
1474 assert_eq!(Pow::pow(base, &exponent), expected_result);
1475 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1476 }
1477
1478 #[test]
1479 fn test_complex_f64_pow_zero_base_ok_exponent() {
1480 let base = Complex::new(0.0, 0.0);
1481 let exponent = 3.0;
1482 let expected_result = Complex::new(0.0, 0.0);
1483 assert_eq!(Pow::pow(base, &exponent), expected_result);
1484 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1485 }
1486
1487 #[test]
1488 #[cfg(debug_assertions)]
1489 fn test_complex_f64_pow_nan_base_ok_exponent() {
1490 let base = Complex::new(f64::NAN, 0.0);
1491 let exponent = 3.0;
1492 let result = base.try_pow(&exponent);
1493 assert!(result.is_err());
1494
1495 let base = Complex::new(0.0, f64::NAN);
1496 let result = base.try_pow(&exponent);
1497 assert!(result.is_err());
1498 }
1499
1500 #[test]
1501 #[cfg(debug_assertions)]
1502 fn test_complex_f64_pow_infinity_base_ok_exponent() {
1503 let base = Complex::new(f64::INFINITY, 0.0);
1504 let exponent = 3.0;
1505 let result = base.try_pow(&exponent);
1506 assert!(result.is_err());
1507
1508 let base = Complex::new(0.0, f64::INFINITY);
1509 let result = base.try_pow(&exponent);
1510 assert!(result.is_err());
1511 }
1512
1513 #[test]
1514 fn test_complex_f64_pow_ok_base_negative_exponent() {
1515 let base = Complex::new(2.0, 3.0);
1516 let exponent = -2.0;
1517 let expected_result = Complex::new(-0.029585798816568046, -0.07100591715976332);
1518 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1519 }
1520
1521 #[test]
1522 fn test_complex_f64_pow_negative_base_positive_exponent() {
1523 let base = Complex::new(-2.0, -3.0);
1524 let exponent = 3.0;
1525 let expected_result = Complex::new(46.0, -8.99999999999999);
1526 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1527 }
1528
1529 #[test]
1530 fn test_complex_f64_pow_negative_base_negative_exponent() {
1531 let base = Complex::new(-2.0, -3.0);
1532 let exponent = -3.0;
1533 let expected_result = Complex::new(0.02093764223941739, 0.004096495220755572);
1534 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1535 }
1536 }
1537 }
1538
1539 #[cfg(feature = "rug")]
1540 mod rug53 {
1541 use super::*;
1542 use crate::PowRealBaseRealExponentErrors;
1543 use rug::{Complex, Float};
1544
1545 mod real_base {
1546 use super::*;
1547
1548 #[test]
1549 fn test_realrug_pow_valid() {
1550 let base =
1551 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1552 let exponent =
1553 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1554 let expected_result =
1555 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 8.0)).unwrap();
1556 assert_eq!(base.clone().pow(&exponent), expected_result);
1557 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1558 }
1559
1560 #[test]
1561 fn test_realrug_pow_zero_exponent() {
1562 let base =
1563 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1564 let exponent =
1565 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1566 let expected_result =
1567 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1568 assert_eq!(base.clone().pow(&exponent), expected_result);
1569 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1570 }
1571
1572 #[test]
1573 fn test_realrug_pow_one_exponent() {
1574 let base =
1575 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1576 let exponent =
1577 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1578 let expected_result =
1579 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1580 assert_eq!(base.clone().pow(&exponent), expected_result);
1581 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1582 }
1583
1584 #[test]
1585 fn test_realrug_pow_zero_base() {
1586 let base =
1587 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1588 let exponent =
1589 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1590 let expected_result =
1591 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1592 assert_eq!(base.clone().pow(&exponent), expected_result);
1593 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1594 }
1595
1596 #[test]
1597 fn test_realrug_pow_negative_exponent() {
1598 let base =
1599 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1600 let exponent =
1601 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1602 let expected_result =
1603 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.25)).unwrap();
1604 assert_eq!(base.clone().pow(&exponent), expected_result);
1605 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1606 }
1607
1608 #[test]
1609 fn test_realrug_pow_negative_base_positive_exponent() {
1610 let base =
1611 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1612 let exponent =
1613 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1614 let result = base.try_pow(&exponent);
1615 assert!(matches!(
1616 result,
1617 Err(PowRealBaseRealExponentErrors::Input(..))
1618 ));
1619 }
1620
1621 #[test]
1622 fn test_realrug_pow_negative_base_negative_exponent() {
1623 let base =
1624 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1625 let exponent =
1626 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -3.0)).unwrap();
1627 let result = base.try_pow(&exponent);
1628 assert!(matches!(
1629 result,
1630 Err(PowRealBaseRealExponentErrors::Input(..))
1631 ));
1632 }
1633 }
1634
1635 mod complex_base {
1636 use super::*;
1637
1638 #[test]
1639 fn test_complex_rug_float_pow_valid() {
1640 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1641 53,
1642 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1643 ))
1644 .unwrap();
1645 let exponent =
1646 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1647 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1648 53,
1649 (Float::with_val(53, -5.0), Float::with_val(53, 12.0)),
1650 ))
1651 .unwrap();
1652 assert_eq!(base.clone().pow(&exponent), expected_result);
1653 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1654 }
1655
1656 #[test]
1657 fn test_complex_rug_float_pow_zero_exponent() {
1658 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1659 53,
1660 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1661 ))
1662 .unwrap();
1663 let exponent =
1664 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1665 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1666 53,
1667 (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1668 ))
1669 .unwrap();
1670 assert_eq!(base.clone().pow(&exponent), expected_result);
1671 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1672 }
1673
1674 #[test]
1675 fn test_complex_rug_float_pow_one_exponent() {
1676 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1677 53,
1678 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1679 ))
1680 .unwrap();
1681 let exponent =
1682 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1683 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1684 53,
1685 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1686 ))
1687 .unwrap();
1688 assert_eq!(base.clone().pow(&exponent), expected_result);
1689 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1690 }
1691
1692 #[test]
1693 fn test_complex_rug_float_pow_zero_base() {
1694 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1695 53,
1696 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1697 ))
1698 .unwrap();
1699 let exponent =
1700 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1701 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1702 53,
1703 (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1704 ))
1705 .unwrap();
1706 assert_eq!(base.clone().pow(&exponent), expected_result);
1707 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1708 }
1709
1710 #[test]
1711 fn test_complex_rug_float_pow_negative_exponent() {
1712 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1713 53,
1714 (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1715 ))
1716 .unwrap();
1717 let exponent =
1718 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1719 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1720 53,
1721 (
1722 Float::with_val(53, -0.029585798816568046),
1723 Float::with_val(53, -0.07100591715976332),
1724 ),
1725 ))
1726 .unwrap();
1727 assert_eq!(base.clone().pow(&exponent), expected_result);
1728 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1729 }
1730
1731 #[test]
1732 fn test_complex_rug_float_pow_negative_base_positive_exponent() {
1733 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1734 53,
1735 (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1736 ))
1737 .unwrap();
1738 let exponent =
1739 RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1740 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1741 53,
1742 (Float::with_val(53, 46.0), Float::with_val(53, -9.0)),
1743 ))
1744 .unwrap();
1745 assert_eq!(base.clone().pow(&exponent), expected_result);
1746 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1747 }
1748
1749 #[test]
1750 fn test_complex_rug_float_pow_negative_base_negative_exponent() {
1751 let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1752 53,
1753 (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1754 ))
1755 .unwrap();
1756 let exponent =
1757 RealRugStrictFinite::<53>::try_new(Float::with_val(53, -3.0)).unwrap();
1758 let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1759 53,
1760 (
1761 Float::with_val(53, 2.0937642239417388e-2),
1762 Float::with_val(53, 4.096495220755576e-3),
1763 ),
1764 ))
1765 .unwrap();
1766 assert_eq!(base.clone().pow(&exponent), expected_result);
1767 assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1768 }
1769 }
1770 }
1771 }
1772}
1773