Skip to main content

num_valid/functions/
pow.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! Power and exponentiation operations.
4//!
5//! This module provides the [`Pow`] trait for computing powers of validated numbers,
6//! including integer and floating-point exponents.
7
8use 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
28//------------------------------------------------------------------
29/// A marker trait for types that can be used as integer exponents.
30pub 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//------------------------------------------------------------------
45
46//------------------------------------------------------------------
47/// Errors that can occur during input validation when computing `base^exponent`
48/// where both the base and exponent are real numbers.
49///
50/// This enum is typically used as the `InputErrorSource` for a [`FunctionErrors`]
51/// wrapper, such as [`PowRealBaseRealExponentErrors`]. It is generic over
52/// `RawReal`, which must implement [`RawRealTrait`].
53#[derive(Debug, Error)]
54pub enum PowRealBaseRealExponentInputErrors<RawReal: RawRealTrait> {
55    /// The base is negative, and the exponent is a non-integer real number.
56    /// This operation is undefined in the real domain and typically results
57    /// in a complex number or NaN.
58    #[error("detected a negative base ({base}) with a real exponent ({exponent}) !")]
59    NegativeBase {
60        /// The negative base value.
61        base: RawReal,
62
63        /// The exponent value.
64        exponent: RawReal,
65
66        /// A captured backtrace for debugging purposes.
67        backtrace: Backtrace,
68    },
69
70    /// The input base value failed validation according to the active policy.
71    ///
72    /// For example, using [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy),
73    /// this would trigger if the base is NaN or Infinity.
74    #[error("the base is invalid!")]
75    InvalidBase {
76        /// The underlying validation error for the base.
77        /// The type of this field is `<RawReal as RawScalarValidate>::ValidationError`.
78        #[source]
79        #[backtrace]
80        source: <RawReal as RawScalarValidate>::ValidationError,
81    },
82
83    /// The input exponent value failed validation according to the active policy.
84    ///
85    /// For example, using [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy),
86    /// this would trigger if the exponent is NaN or Infinity.
87    #[error("the exponent is invalid!")]
88    InvalidExponent {
89        /// The underlying validation error for the exponent.
90        /// The type of this field is `<RawReal as RawScalarValidate>::ValidationError`.
91        #[source]
92        #[backtrace]
93        source: <RawReal as RawScalarValidate>::ValidationError,
94    },
95
96    /// Both the base and the exponent are invalid according to the validation policy.
97    ///
98    /// This error occurs when both input values fail validation checks simultaneously.
99    #[error("the base and the exponent are invalid!")]
100    InvalidBaseAndExponent {
101        /// The source error that occurred during validation for the base.
102        error_base: <RawReal as RawScalarValidate>::ValidationError,
103
104        /// The source error that occurred during validation for the exponent.
105        error_exponent: <RawReal as RawScalarValidate>::ValidationError,
106
107        /// A captured backtrace for debugging purposes.
108        #[backtrace]
109        backtrace: Backtrace,
110    },
111}
112//------------------------------------------------------------------
113
114//------------------------------------------------------------------
115/// Errors that can occur during input validation when computing `base^exponent`
116/// where the base is a complex number and the exponent is a real number.
117///
118/// This enum is typically used as the `InputErrorSource` for a [`FunctionErrors`]
119/// wrapper, such as [`PowComplexBaseRealExponentErrors`]. It is generic over
120/// `ComplexType`, which must implement [`ComplexScalar`](crate::ComplexScalar).
121#[derive(Debug, Error)]
122pub enum PowComplexBaseRealExponentInputErrors<RawComplex: RawComplexTrait> {
123    /// The input complex base value failed validation according to the active policy.
124    ///
125    /// For example, using [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy),
126    /// this would trigger if any part of the complex base is NaN or Infinity.
127    #[error("the input complex base is invalid according to validation policy")]
128    InvalidBase {
129        /// The underlying validation error for the complex base.
130        /// The type of this field is `<RawComplex as RawScalarValidate>::ValidationError`.
131        #[source]
132        #[backtrace]
133        source: <RawComplex as RawScalarValidate>::ValidationError,
134    },
135
136    /// The input real exponent value failed validation according to the active policy.
137    ///
138    /// For example, using [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy),
139    /// this would trigger if the exponent is NaN or Infinity.
140    #[error("the input real exponent is invalid according to validation policy")]
141    InvalidExponent {
142        /// The underlying validation error for the real exponent.
143        /// The type of this field is `<RawReal as RawScalarValidate>::ValidationError`.
144        #[source]
145        #[backtrace]
146        source: <RawComplex::RawReal as RawScalarValidate>::ValidationError,
147    },
148
149    /// The input complex base value and the real exponent failed validation according to the active policy.
150    ///
151    /// For example, using [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy),
152    /// this would trigger if any part of the complex base is NaN or Infinity.
153    #[error(
154        "the input complex base and the real exponent is invalid according to validation policy"
155    )]
156    InvalidBaseAndExponent {
157        /// The source error that occurred during validation for the base.
158        error_base: <RawComplex as RawScalarValidate>::ValidationError,
159
160        /// The source error that occurred during validation for the exponent.
161        error_exponent: <RawComplex::RawReal as RawScalarValidate>::ValidationError,
162
163        /// A captured backtrace for debugging purposes.
164        #[backtrace]
165        backtrace: Backtrace,
166    },
167
168    /// The complex base is zero, and the real exponent is negative.
169    /// This operation results in division by zero.
170    #[error("the base is zero and the exponent (={exponent}) is negative!")]
171    ZeroBaseNegativeExponent {
172        /// The negative real exponent value.
173        exponent: RawComplex::RawReal,
174
175        /// A captured backtrace for debugging purposes.
176        backtrace: Backtrace,
177    },
178}
179//------------------------------------------------------------------
180
181//------------------------------------------------------------------
182/// Errors that can occur during input validation when computing `base^exponent`
183/// where the exponent is an integer type.
184///
185/// This enum is typically used as the `InputErrorSource` for [`PowIntExponentErrors`].
186/// It is generic over `RawScalar`, which must implement [`RawScalarTrait`],
187/// and `IntExponentType`, which is the integer type of the exponent.
188#[derive(Debug, Error)]
189pub enum PowIntExponentInputErrors<RawScalar: RawScalarTrait, ExponentType: IntegerExponent> {
190    /// The input base value failed validation according to the validation policy.
191    ///
192    /// For example, using [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy),
193    /// this would trigger if the base is NaN or Infinity.
194    #[error("the input base is invalid according to validation policy")]
195    InvalidBase {
196        /// The underlying validation error for the base.
197        /// The type of this field is `<RawScalar as RawScalarValidate>::ValidationError`.
198        #[source]
199        #[backtrace]
200        source: <RawScalar as RawScalarValidate>::ValidationError,
201    },
202
203    /// The base is zero, and the integer exponent is negative.
204    /// This operation results in division by zero.
205    #[error("detected a zero base with a negative integer exponent ({exponent:?})!")]
206    ZeroBaseNegativeExponent {
207        /// The negative integer exponent value.
208        exponent: ExponentType,
209
210        /// A captured backtrace for debugging purposes.
211        backtrace: Backtrace,
212    },
213    // Note: Integer exponents themselves are not typically validated by StrictFinitePolicy,
214    // as they are exact and finite by nature (unless they are too large for conversion
215    // to the type expected by the underlying power function, e.g., i32 for powi).
216    // Such conversion errors might be handled separately or lead to panics if unwrap is used.
217}
218//------------------------------------------------------------------
219
220//------------------------------------------------------------------
221/// Errors that can occur when computing `base^exponent` where both base and exponent
222/// are real numbers.
223///
224/// This type represents failures from [`Pow::try_pow()`] for real base and real exponent.
225/// It is generic over `RawReal: RawRealTrait`.
226/// - The `Input` variant wraps [`PowRealBaseRealExponentInputErrors<RawReal>`].
227/// - The `Output` variant wraps `<RawReal as RawScalarValidate>::ValidationError` for issues
228///   with the computed result (e.g., overflow, NaN from valid inputs if possible).
229#[derive(Debug, Error)]
230pub enum PowRealBaseRealExponentErrors<RawReal: RawRealTrait> {
231    /// The input value is invalid.
232    #[error("the input value is invalid!")]
233    Input(
234        /// The source error that occurred during validation.
235        #[from]
236        PowRealBaseRealExponentInputErrors<RawReal>,
237    ),
238
239    /// The output value is invalid.
240    #[error("the output value is invalid!")]
241    Output {
242        /// The source error that occurred during validation.
243        #[source]
244        #[backtrace]
245        source: <RawReal as RawScalarValidate>::ValidationError,
246    },
247}
248//------------------------------------------------------------------
249
250//------------------------------------------------------------------
251/// Errors that can occur when computing `base^exponent` where the base is complex and the exponent is real.
252///
253/// This type represents failures from [`Pow::try_pow()`] for complex base and real exponent.
254/// It is generic over `RawComplex: RawComplexTrait` and `RawReal: RawRealTrait`.
255/// - The `Input` variant wraps [`PowComplexBaseRealExponentInputErrors<RawComplex>`].
256/// - The `Output` variant wraps `<RawComplex as RawScalarValidate>::ValidationError` for issues
257///   with the computed result.
258#[derive(Debug, Error)]
259pub enum PowComplexBaseRealExponentErrors<RawComplex: RawComplexTrait> {
260    /// The input value is invalid.
261    #[error("the input value is invalid!")]
262    Input(
263        /// The source error that occurred during validation.
264        #[from]
265        PowComplexBaseRealExponentInputErrors<RawComplex>,
266    ),
267
268    /// The output value is invalid.
269    #[error("the output value is invalid!")]
270    Output {
271        /// The source error that occurred during validation.
272        #[source]
273        #[backtrace]
274        source: <RawComplex as RawScalarValidate>::ValidationError,
275    },
276}
277//------------------------------------------------------------------
278
279//------------------------------------------------------------------
280/// A type alias for [`FunctionErrors`], specialized for errors that can occur
281/// when computing `base^exponent` where the exponent is an integer type.
282///
283/// This type represents failures from [`Pow::try_pow()`] when using an integer exponent.
284/// It is generic over `RawScalar: RawScalarTrait` and `IntExponentType: Clone + Debug`.
285/// - The `Input` variant wraps [`PowIntExponentInputErrors<RawScalar, IntExponentType>`].
286/// - The `Output` variant wraps `<RawScalar as RawScalarValidate>::ValidationError` for issues
287///   with the computed result (e.g., overflow).
288pub type PowIntExponentErrors<RawScalar, ExponentType> = FunctionErrors<
289    PowIntExponentInputErrors<RawScalar, ExponentType>,
290    <RawScalar as RawScalarValidate>::ValidationError,
291>;
292//------------------------------------------------------------------
293
294//------------------------------------------------------------------
295/// A trait for computing the power of a number (`base^exponent`).
296///
297/// This trait provides an interface for raising a `Self` type (the base)
298/// to a power specified by `ExponentType`. It includes both a fallible version
299/// (`try_pow`) that performs validation and an infallible version (`pow`) that
300/// may panic in debug builds if validation fails.
301///
302/// # Type Parameters
303///
304/// - `ExponentType`: The type of the exponent. This can be a real number type
305///   (like `f64` or `RealRugStrictFinite<P>`) or an integer type (like `i32`, `u32`, etc.).
306pub trait Pow<ExponentType>: Sized {
307    /// The error type that can be returned by the `try_pow` method.
308    /// This type must implement `std::error::Error` for proper error handling.
309    type Error: std::error::Error;
310
311    /// Attempts to compute `self` (the base) raised to the power of `exponent`.
312    ///
313    /// This method performs validation on the base and exponent according to
314    /// defined policies (e.g., [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy)).
315    /// It also checks for domain errors specific to the power operation, such as
316    /// a negative real base with a non-integer real exponent, or a zero base
317    /// with a negative exponent. Finally, it validates the computed result.
318    ///
319    /// # Arguments
320    ///
321    /// * `exponent`: The exponent to raise `self` to.
322    #[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    /// Computes `self` (the base) raised to the power of `exponent`.
326    ///
327    /// This method provides a potentially more performant way to compute the power,
328    /// especially in release builds, by possibly omitting some checks performed by
329    /// `try_pow`.
330    ///
331    /// # Behavior
332    ///
333    /// - In **debug builds**, this method typically calls `try_pow(exponent).unwrap()`,
334    ///   meaning it will panic if `try_pow` would return an error.
335    /// - In **release builds**, it may call the underlying power function directly.
336    ///   While input validation might be skipped, output validation (e.g., checking
337    ///   if the result is finite) might still occur implicitly if the underlying
338    ///   power function produces non-finite results (like NaN or Infinity) from
339    ///   finite inputs, which are then caught by policies like
340    ///   [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy) if applied
341    ///   to the output.
342    ///
343    /// # Arguments
344    ///
345    /// * `exponent`: The exponent to raise `self` to.
346    ///
347    /// # Returns
348    ///
349    /// The result of `self` raised to the power of `exponent`.
350    ///
351    /// # Panics
352    ///
353    /// - Panics in debug builds if `try_pow` would return an error.
354    /// - Behavior regarding panics in release builds depends on the specific
355    ///   implementation and the underlying power function. For example, `f64::powf`
356    ///   itself does not panic but can return `NaN` or `Infinity`.
357    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    /// Raises th number `self` to the power `exponent`.
418    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    /// Raises th number `self` to the power `exponent`.
494    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    //    Self: RawComplexTrait<RawReal = T>,
519    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    /// Raises th number `self` to the power `exponent`.
550    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    /// Raises th number `self` to the power `exponent`.
596    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    /// Raises th number `self` to the power `exponent`.
651    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    /// Raises th number `self` to the power `exponent`.
698    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//------------------------------------------------------------------------------------------------
710
711//------------------------------------------------------------------------------------------------
712#[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//------------------------------------------------------------------------------------------------