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/// An aggregate trait for types that can be raised to the power of any primitive integer.
713pub trait PowIntExponent:
714    Pow<i8, Error = PowIntExponentErrors<Self::RawType, i8>>
715    + Pow<u8, Error = PowIntExponentErrors<Self::RawType, u8>>
716    + Pow<i16, Error = PowIntExponentErrors<Self::RawType, i16>>
717    + Pow<u16, Error = PowIntExponentErrors<Self::RawType, u16>>
718    + Pow<i32, Error = PowIntExponentErrors<Self::RawType, i32>>
719    + Pow<u32, Error = PowIntExponentErrors<Self::RawType, u32>>
720    + Pow<i64, Error = PowIntExponentErrors<Self::RawType, i64>>
721    + Pow<u64, Error = PowIntExponentErrors<Self::RawType, u64>>
722    + Pow<i128, Error = PowIntExponentErrors<Self::RawType, i128>>
723    + Pow<u128, Error = PowIntExponentErrors<Self::RawType, u128>>
724    + Pow<isize, Error = PowIntExponentErrors<Self::RawType, isize>>
725    + Pow<usize, Error = PowIntExponentErrors<Self::RawType, usize>>
726{
727    /// The underlying raw scalar type for this integer-exponent power implementation.
728    ///
729    /// For `f64`, this is `f64`. For `Complex<f64>`, this is `Complex<f64>`.
730    type RawType: RawScalarTrait;
731}
732
733impl<T> PowIntExponent for T
734where
735    T: NativeReal<ValidationError = ErrorsValidationRawReal<T>> + RawRealTrait,
736{
737    type RawType = T;
738}
739
740impl<T> PowIntExponent for Complex<T>
741where
742    T: NativeReal<ValidationError = ErrorsValidationRawReal<T>> + RawRealTrait,
743{
744    type RawType = Complex<T>;
745}
746//------------------------------------------------------------------------------------------------
747
748//------------------------------------------------------------------------------------------------
749#[cfg(test)]
750mod tests {
751    use super::*;
752    use crate::{RealScalar, functions::Pow};
753    use num::Complex;
754
755    #[cfg(debug_assertions)]
756    use std::assert_matches;
757
758    #[cfg(debug_assertions)]
759    use crate::{
760        core::errors::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
761        functions::{PowIntExponentErrors, PowIntExponentInputErrors},
762    };
763
764    #[cfg(feature = "rug")]
765    use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
766
767    #[cfg(feature = "rug")]
768    use try_create::TryNew;
769
770    mod pow_u32_exponent {
771        use super::*;
772
773        mod real_base {
774            use crate::core::traits::raw::TryConvertFromRawReal;
775
776            use super::*;
777
778            fn pow_generic_real_u32_valid<RealType: RealScalar>()
779            where
780                RealType::RawReal: TryConvertFromRawReal<f64>,
781            {
782                let base = RealType::try_from_f64(2.0).unwrap();
783                let exponent = 3u32;
784                let expected_result = RealType::try_from_f64(8.0).unwrap();
785                assert_eq!(Pow::pow(base.clone(), exponent), expected_result);
786                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
787            }
788
789            #[test]
790            fn test_pow_generic_real_u32_valid() {
791                pow_generic_real_u32_valid::<f64>();
792            }
793
794            #[test]
795            fn test_f64_pow_u32_valid() {
796                let base = 2.0;
797                let exponent = 3u32;
798                let expected_result = 8.0;
799                assert_eq!(Pow::pow(base, exponent), expected_result);
800                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
801            }
802
803            #[test]
804            fn test_f64_pow_u32_zero_exponent() {
805                let base = 2.0;
806                let exponent = 0u32;
807                let expected_result = 1.0;
808                assert_eq!(Pow::pow(base, exponent), expected_result);
809                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
810            }
811
812            #[test]
813            fn test_f64_pow_u32_one_exponent() {
814                let base = 2.0;
815                let exponent = 1u32;
816                let expected_result = 2.0;
817                assert_eq!(Pow::pow(base, exponent), expected_result);
818                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
819            }
820
821            #[test]
822            fn test_f64_pow_u32_zero_base() {
823                let base = 0.0;
824                let exponent = 3u32;
825                let expected_result = 0.0;
826                assert_eq!(Pow::pow(base, exponent), expected_result);
827                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
828            }
829
830            #[test]
831            #[cfg(debug_assertions)]
832            fn test_f64_pow_u32_nan_base() {
833                let base = f64::NAN;
834                let exponent = 3u32;
835                let result = base.try_pow(exponent);
836                assert!(result.is_err());
837            }
838
839            #[test]
840            #[cfg(debug_assertions)]
841            fn test_f64_pow_u32_infinity_base() {
842                let base = f64::INFINITY;
843                let exponent = 3u32;
844                let result = base.try_pow(exponent);
845                assert!(result.is_err());
846            }
847        }
848
849        mod complex_base {
850            use super::*;
851
852            #[test]
853            fn test_complex_f64_pow_u32_valid() {
854                let base = Complex::new(2.0, 3.0);
855                let exponent = 2u32;
856                let expected_result = Complex::new(-5.0, 12.0);
857                assert_eq!(Pow::pow(base, exponent), expected_result);
858                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
859            }
860
861            #[test]
862            fn test_complex_f64_pow_u32_zero_exponent() {
863                let base = Complex::new(2.0, 3.0);
864                let exponent = 0u32;
865                let expected_result = Complex::new(1.0, 0.0);
866                assert_eq!(Pow::pow(base, exponent), expected_result);
867                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
868            }
869
870            #[test]
871            fn test_complex_f64_pow_u32_one_exponent() {
872                let base = Complex::new(2.0, 3.0);
873                let exponent = 1u32;
874                let expected_result = Complex::new(2.0, 3.0);
875                assert_eq!(Pow::pow(base, exponent), expected_result);
876                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
877            }
878
879            #[test]
880            fn test_complex_f64_pow_u32_zero_base() {
881                let base = Complex::new(0.0, 0.0);
882                let exponent = 3u32;
883                let expected_result = Complex::new(0.0, 0.0);
884                assert_eq!(Pow::pow(base, exponent), expected_result);
885                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
886            }
887
888            #[test]
889            #[cfg(debug_assertions)]
890            fn test_complex_f64_pow_u32_nan_base() {
891                let base = Complex::new(f64::NAN, 0.0);
892                let exponent = 3u32;
893                let result = base.try_pow(exponent);
894                assert!(result.is_err());
895
896                let base = Complex::new(0.0, f64::NAN);
897                let result = base.try_pow(exponent);
898                assert!(result.is_err());
899            }
900
901            #[test]
902            #[cfg(debug_assertions)]
903            fn test_complex_f64_pow_u32_infinity_base() {
904                let base = Complex::new(f64::INFINITY, 0.0);
905                let exponent = 3u32;
906                let result = base.try_pow(exponent);
907                assert!(result.is_err());
908
909                let base = Complex::new(0.0, f64::INFINITY);
910                let result = base.try_pow(exponent);
911                assert!(result.is_err());
912            }
913        }
914    }
915
916    mod pow_i32_exponent {
917        use super::*;
918
919        mod native {
920            use super::*;
921
922            mod real_base {
923                use super::*;
924
925                #[test]
926                fn test_f64_pow_valid() {
927                    let base = 2.0;
928                    let exponent = 3i32;
929                    let expected_result = 8.0;
930                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
931                    assert_eq!(<f64 as Pow<i32>>::pow(base, exponent), expected_result);
932                }
933
934                #[test]
935                fn test_f64_pow_zero_exponent() {
936                    let base = 2.0;
937                    let exponent = 0i32;
938                    let expected_result = 1.0;
939                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
940                }
941
942                #[test]
943                fn test_f64_pow_negative_exponent() {
944                    let base = 2.0;
945                    let exponent = -3i32;
946                    let expected_result = 0.125;
947                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
948                }
949
950                #[test]
951                fn test_f64_pow_zero_base() {
952                    let base = 0.0;
953                    let exponent = 3i32;
954                    let expected_result = 0.0;
955                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
956                }
957
958                #[test]
959                fn test_f64_pow_zero_base_zero_exponent() {
960                    let base = 0.0;
961                    let exponent = 0i32;
962                    let expected_result = 1.0;
963                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
964                }
965
966                #[test]
967                #[cfg(debug_assertions)]
968                fn test_f64_pow_zero_base_negative_exponent() {
969                    let base = 0.0;
970                    let err = base.try_pow(-1i32).unwrap_err();
971                    assert!(matches!(
972                        err,
973                        PowIntExponentErrors::Input(
974                            PowIntExponentInputErrors::ZeroBaseNegativeExponent {
975                                exponent: -1,
976                                ..
977                            }
978                        )
979                    ));
980                }
981
982                #[test]
983                fn test_f64_pow_negative_base_positive_exponent() {
984                    let base = -2.0;
985                    let exponent = 3i32;
986                    let expected_result = -8.0;
987                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
988                }
989
990                #[test]
991                fn test_f64_pow_negative_base_negative_exponent() {
992                    let base = -2.0;
993                    let exponent = -3i32;
994                    let expected_result = -0.125;
995                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
996                }
997            }
998
999            mod complex_base {
1000                use super::*;
1001
1002                #[test]
1003                fn test_complex_f64_pow_valid() {
1004                    let base = Complex::new(2.0, 3.0);
1005                    let exponent = 2i32;
1006                    let expected_result = Complex::new(-5.0, 12.0);
1007                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1008                    assert_eq!(
1009                        <Complex<f64> as Pow<i32>>::pow(base, exponent),
1010                        expected_result
1011                    );
1012                }
1013
1014                #[test]
1015                fn test_complex_f64_pow_zero_exponent() {
1016                    let base = Complex::new(2.0, 3.0);
1017                    let exponent = 0i32;
1018                    let expected_result = Complex::new(1.0, 0.0);
1019                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1020                }
1021
1022                #[test]
1023                fn test_complex_f64_pow_negative_exponent() {
1024                    let base = Complex::new(2.0, 3.0);
1025                    let exponent = -2i32;
1026                    let expected_result = Complex::new(-0.029585798816568053, -0.07100591715976332);
1027                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1028                }
1029
1030                #[test]
1031                fn test_complex_f64_pow_zero_base() {
1032                    let base = Complex::new(0.0, 0.0);
1033                    let exponent = 3i32;
1034                    let expected_result = Complex::new(0.0, 0.0);
1035                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1036                }
1037
1038                #[test]
1039                fn test_complex_f64_pow_zero_base_zero_exponent() {
1040                    let base = Complex::new(0.0, 0.0);
1041                    let exponent = 0i32;
1042                    let expected_result = Complex::new(1.0, 0.0);
1043                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1044                }
1045
1046                #[test]
1047                #[cfg(debug_assertions)]
1048                fn test_complex_f64_pow_zero_base_negative_exponent() {
1049                    let base = Complex::new(0.0, 0.0);
1050                    let err = base.try_pow(-1i32).unwrap_err();
1051                    assert!(matches!(
1052                        err,
1053                        PowIntExponentErrors::Input(
1054                            PowIntExponentInputErrors::ZeroBaseNegativeExponent {
1055                                exponent: -1,
1056                                ..
1057                            }
1058                        )
1059                    ));
1060                }
1061
1062                #[test]
1063                fn test_complex_f64_pow_negative_base_positive_exponent() {
1064                    let base = Complex::new(-2.0, -3.0);
1065                    let exponent = 3i32;
1066                    let expected_result = Complex::new(46.0, -9.0);
1067                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1068                }
1069
1070                #[test]
1071                fn test_complex_f64_pow_negative_base_negative_exponent() {
1072                    let base = Complex::new(-2.0, -3.0);
1073                    let exponent = -3i32;
1074                    let expected_result = Complex::new(0.02093764223941739, 0.004096495220755574);
1075                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1076                }
1077            }
1078        }
1079
1080        #[cfg(feature = "rug")]
1081        mod rug53 {
1082            use super::*;
1083            use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
1084            use rug::Float;
1085
1086            mod real {
1087                use super::*;
1088
1089                #[test]
1090                fn test_rug_float_pow_valid() {
1091                    let base =
1092                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1093                    let exponent = 3;
1094                    let expected_result =
1095                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 8.0)).unwrap();
1096                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1097                }
1098
1099                #[test]
1100                fn test_rug_float_pow_zero_exponent() {
1101                    let base =
1102                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1103                    let exponent = 0;
1104                    let expected_result =
1105                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1106                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1107                }
1108
1109                #[test]
1110                fn test_rug_float_pow_negative_exponent() {
1111                    let base =
1112                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1113                    let exponent = -3;
1114                    let expected_result =
1115                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.125)).unwrap();
1116                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1117                }
1118
1119                #[test]
1120                fn test_rug_float_pow_zero_base() {
1121                    let base =
1122                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1123                    let exponent = 3;
1124                    let expected_result =
1125                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1126                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1127                }
1128
1129                #[test]
1130                fn test_rug_float_pow_zero_base_zero_exponent() {
1131                    let base =
1132                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1133                    let exponent = 0;
1134                    let expected_result =
1135                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1136                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1137                }
1138
1139                #[test]
1140                fn test_rug_float_pow_negative_base_positive_exponent() {
1141                    let base =
1142                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1143                    let exponent = 3;
1144                    let expected_result =
1145                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -8.0)).unwrap();
1146                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1147                }
1148
1149                #[test]
1150                fn test_rug_float_pow_negative_base_negative_exponent() {
1151                    let base =
1152                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1153                    let exponent = -3;
1154                    let expected_result =
1155                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -0.125)).unwrap();
1156                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1157                }
1158            }
1159
1160            mod complex {
1161                use super::*;
1162                use rug::Complex;
1163
1164                #[test]
1165                fn test_complex_rug_float_pow_valid() {
1166                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1167                        53,
1168                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1169                    ))
1170                    .unwrap();
1171                    let exponent = 2;
1172                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1173                        53,
1174                        (Float::with_val(53, -5.0), Float::with_val(53, 12.0)),
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_exponent() {
1182                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1183                        53,
1184                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1185                    ))
1186                    .unwrap();
1187                    let exponent = 0;
1188                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1189                        53,
1190                        (Float::with_val(53, 1.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_negative_exponent() {
1198                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1199                        53,
1200                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1201                    ))
1202                    .unwrap();
1203                    let exponent = -2;
1204                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1205                        53,
1206                        (
1207                            Float::with_val(53, -2.9585798816568046e-2),
1208                            Float::with_val(53, -7.100591715976332e-2),
1209                        ),
1210                    ))
1211                    .unwrap();
1212                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1213                }
1214
1215                #[test]
1216                fn test_complex_rug_float_pow_zero_base() {
1217                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1218                        53,
1219                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1220                    ))
1221                    .unwrap();
1222                    let exponent = 3;
1223                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1224                        53,
1225                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1226                    ))
1227                    .unwrap();
1228                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1229                }
1230
1231                #[test]
1232                fn test_complex_rug_float_pow_zero_base_zero_exponent() {
1233                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1234                        53,
1235                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1236                    ))
1237                    .unwrap();
1238                    let exponent = 0;
1239                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1240                        53,
1241                        (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1242                    ))
1243                    .unwrap();
1244                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1245                }
1246
1247                #[test]
1248                fn test_complex_rug_float_pow_negative_base_positive_exponent() {
1249                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1250                        53,
1251                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1252                    ))
1253                    .unwrap();
1254                    let exponent = 3;
1255                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1256                        53,
1257                        (Float::with_val(53, 46.0), Float::with_val(53, -9.0)),
1258                    ))
1259                    .unwrap();
1260                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1261                }
1262
1263                #[test]
1264                fn test_complex_rug_float_pow_negative_base_negative_exponent() {
1265                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1266                        53,
1267                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1268                    ))
1269                    .unwrap();
1270                    let exponent = -3;
1271                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1272                        53,
1273                        (
1274                            Float::with_val(53, 2.0937642239417388e-2),
1275                            Float::with_val(53, 4.096495220755576e-3),
1276                        ),
1277                    ))
1278                    .unwrap();
1279                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1280                }
1281            }
1282        }
1283    }
1284
1285    mod pow_real_exponent {
1286        use super::*;
1287
1288        mod native {
1289            use super::*;
1290
1291            mod real_base {
1292                use super::*;
1293
1294                #[test]
1295                fn test_f64_pow_f64_valid() {
1296                    let base = 2.0;
1297                    let exponent = 3.0;
1298                    let expected_result = 8.0;
1299                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1300                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1301                }
1302
1303                #[test]
1304                fn test_f64_pow_f64_zero_exponent() {
1305                    let base = 2.0;
1306                    let exponent = 0.0;
1307                    let expected_result = 1.0;
1308                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1309                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1310                }
1311
1312                #[test]
1313                #[cfg(debug_assertions)]
1314                fn test_f64_pow_f64_invalid_exponent() {
1315                    let base = 2.0;
1316                    let err = base.try_pow(&f64::NAN).unwrap_err();
1317                    assert!(matches!(
1318                        err,
1319                        PowRealBaseRealExponentErrors::Input(
1320                            PowRealBaseRealExponentInputErrors::InvalidExponent {
1321                                source: ErrorsValidationRawReal::IsNaN { .. }
1322                            }
1323                        )
1324                    ))
1325                }
1326
1327                #[test]
1328                #[cfg(debug_assertions)]
1329                fn test_f64_pow_f64_invalid_base_invalid_exponent() {
1330                    let err = (f64::INFINITY).try_pow(&f64::NAN).unwrap_err();
1331                    assert!(matches!(
1332                        err,
1333                        PowRealBaseRealExponentErrors::Input(
1334                            PowRealBaseRealExponentInputErrors::InvalidBaseAndExponent {
1335                                error_base: ErrorsValidationRawReal::IsPosInfinity { .. },
1336                                error_exponent: ErrorsValidationRawReal::IsNaN { .. },
1337                                ..
1338                            }
1339                        )
1340                    ))
1341                }
1342
1343                #[test]
1344                fn test_f64_pow_f64_one_exponent() {
1345                    let base = 2.0;
1346                    let exponent = 1.0;
1347                    let expected_result = 2.0;
1348                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1349                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1350                }
1351
1352                #[test]
1353                fn test_f64_pow_f64_zero_base() {
1354                    let base = 0.0;
1355                    let exponent = 3.0;
1356                    let expected_result = 0.0;
1357                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1358                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1359                }
1360
1361                #[test]
1362                #[cfg(debug_assertions)]
1363                fn test_f64_pow_f64_nan_base() {
1364                    let base = f64::NAN;
1365                    let exponent = 3.0;
1366                    let result = base.try_pow(&exponent);
1367                    assert!(result.is_err());
1368                }
1369
1370                #[test]
1371                #[cfg(debug_assertions)]
1372                fn test_f64_pow_f64_infinity_base() {
1373                    let base = f64::INFINITY;
1374                    let exponent = 3.0;
1375                    let result = base.try_pow(&exponent);
1376                    assert!(matches!(
1377                        result,
1378                        Err(PowRealBaseRealExponentErrors::Input(..))
1379                    ));
1380                }
1381
1382                #[test]
1383                fn test_f64_pow_f64_negative_exponent() {
1384                    let base = 2.0;
1385                    let exponent = -2.0;
1386                    let expected_result = 0.25;
1387                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1388                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1389                }
1390
1391                #[test]
1392                #[cfg(debug_assertions)]
1393                fn test_f64_pow_f64_negative_base_positive_exponent() {
1394                    let base = -2.0;
1395                    let exponent = 3.0;
1396                    let result = base.try_pow(&exponent);
1397                    assert!(matches!(
1398                        result,
1399                        Err(PowRealBaseRealExponentErrors::Input(..))
1400                    ));
1401                }
1402
1403                #[test]
1404                #[cfg(debug_assertions)]
1405                fn test_f64_pow_f64_negative_base_negative_exponent() {
1406                    let base = -2.0;
1407                    let exponent = -3.0;
1408                    let result = base.try_pow(&exponent);
1409                    assert!(result.is_err());
1410                }
1411            }
1412
1413            mod complex_base {
1414                use super::*;
1415
1416                #[test]
1417                fn test_complex_f64_pow_ok_base_ok_exponent() {
1418                    let base = Complex::new(2.0, 3.0);
1419                    let exponent = 2.0;
1420                    let expected_result = Complex::new(-4.999999999999999, 11.999999999999998);
1421                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1422                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1423                }
1424
1425                #[test]
1426                fn test_complex_f64_pow_ok_base_zero_exponent() {
1427                    let base = Complex::new(2.0, 3.0);
1428                    let exponent = 0.0;
1429                    let expected_result = Complex::new(1.0, 0.0);
1430                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1431                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1432                }
1433
1434                #[test]
1435                fn test_complex_f64_pow_zero_base_zero_exponent() {
1436                    let base = Complex::new(0.0, 0.0);
1437                    let exponent = 0.0;
1438                    let expected_result = Complex::new(1.0, 0.0);
1439                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1440                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1441                }
1442
1443                #[test]
1444                #[cfg(debug_assertions)]
1445                fn test_complex_f64_pow_zero_base_negative_exponent() {
1446                    let base = Complex::new(0.0, 0.0);
1447                    let exponent = -1.0;
1448                    let err = base.try_pow(&exponent).unwrap_err();
1449                    assert_matches!(
1450                        err,
1451                        PowComplexBaseRealExponentErrors::Input(
1452                            PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent {
1453                                exponent: -1.,
1454                                ..
1455                            }
1456                        )
1457                    );
1458                }
1459
1460                #[test]
1461                #[cfg(debug_assertions)]
1462                fn test_complex_f64_pow_ok_base_nan_exponent() {
1463                    let base = Complex::new(0.0, 0.0);
1464                    let exponent = f64::NAN;
1465                    let err = base.try_pow(&exponent).unwrap_err();
1466                    assert_matches!(
1467                        err,
1468                        PowComplexBaseRealExponentErrors::Input(
1469                            PowComplexBaseRealExponentInputErrors::InvalidExponent {
1470                                source: ErrorsValidationRawReal::IsNaN { .. }
1471                            }
1472                        )
1473                    );
1474                }
1475
1476                #[test]
1477                #[cfg(debug_assertions)]
1478                fn test_complex_f64_pow_infinity_base_nan_exponent() {
1479                    let base = Complex::new(f64::INFINITY, 0.0);
1480                    let exponent = f64::NAN;
1481                    let err = base.try_pow(&exponent).unwrap_err();
1482                    match err {
1483                        PowComplexBaseRealExponentErrors::Input(
1484                            PowComplexBaseRealExponentInputErrors::InvalidBaseAndExponent {
1485                                error_base,
1486                                error_exponent,
1487                                ..
1488                            },
1489                        ) => {
1490                            assert_matches!(
1491                                error_base,
1492                                ErrorsValidationRawComplex::InvalidRealPart {
1493                                    source
1494                                } if matches!(*source, ErrorsValidationRawReal::IsPosInfinity { .. })
1495                            );
1496                            assert_matches!(error_exponent, ErrorsValidationRawReal::IsNaN { .. });
1497                        }
1498                        _ => {
1499                            unreachable!()
1500                        }
1501                    }
1502                }
1503
1504                #[test]
1505                fn test_complex_f64_pow_ok_base_one_exponent() {
1506                    let base = Complex::new(2.0, 3.0);
1507                    let exponent = 1.0;
1508                    let expected_result = Complex::new(2.0, 3.0);
1509                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1510                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1511                }
1512
1513                #[test]
1514                fn test_complex_f64_pow_zero_base_ok_exponent() {
1515                    let base = Complex::new(0.0, 0.0);
1516                    let exponent = 3.0;
1517                    let expected_result = Complex::new(0.0, 0.0);
1518                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1519                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1520                }
1521
1522                #[test]
1523                #[cfg(debug_assertions)]
1524                fn test_complex_f64_pow_nan_base_ok_exponent() {
1525                    let base = Complex::new(f64::NAN, 0.0);
1526                    let exponent = 3.0;
1527                    let result = base.try_pow(&exponent);
1528                    assert!(result.is_err());
1529
1530                    let base = Complex::new(0.0, f64::NAN);
1531                    let result = base.try_pow(&exponent);
1532                    assert!(result.is_err());
1533                }
1534
1535                #[test]
1536                #[cfg(debug_assertions)]
1537                fn test_complex_f64_pow_infinity_base_ok_exponent() {
1538                    let base = Complex::new(f64::INFINITY, 0.0);
1539                    let exponent = 3.0;
1540                    let result = base.try_pow(&exponent);
1541                    assert!(result.is_err());
1542
1543                    let base = Complex::new(0.0, f64::INFINITY);
1544                    let result = base.try_pow(&exponent);
1545                    assert!(result.is_err());
1546                }
1547
1548                #[test]
1549                fn test_complex_f64_pow_ok_base_negative_exponent() {
1550                    let base = Complex::new(2.0, 3.0);
1551                    let exponent = -2.0;
1552                    let expected_result = Complex::new(-0.029585798816568046, -0.07100591715976332);
1553                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1554                }
1555
1556                #[test]
1557                fn test_complex_f64_pow_negative_base_positive_exponent() {
1558                    let base = Complex::new(-2.0, -3.0);
1559                    let exponent = 3.0;
1560                    let expected_result = Complex::new(46.0, -8.99999999999999);
1561                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1562                }
1563
1564                #[test]
1565                fn test_complex_f64_pow_negative_base_negative_exponent() {
1566                    let base = Complex::new(-2.0, -3.0);
1567                    let exponent = -3.0;
1568                    let expected_result = Complex::new(0.02093764223941739, 0.004096495220755572);
1569                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1570                }
1571            }
1572        }
1573
1574        #[cfg(feature = "rug")]
1575        mod rug53 {
1576            use super::*;
1577            use rug::{Complex, Float};
1578
1579            mod real_base {
1580                use super::*;
1581
1582                #[test]
1583                fn test_realrug_pow_valid() {
1584                    let base =
1585                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1586                    let exponent =
1587                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1588                    let expected_result =
1589                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 8.0)).unwrap();
1590                    assert_eq!(base.clone().pow(&exponent), expected_result);
1591                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1592                }
1593
1594                #[test]
1595                fn test_realrug_pow_zero_exponent() {
1596                    let base =
1597                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1598                    let exponent =
1599                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1600                    let expected_result =
1601                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1602                    assert_eq!(base.clone().pow(&exponent), expected_result);
1603                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1604                }
1605
1606                #[test]
1607                fn test_realrug_pow_one_exponent() {
1608                    let base =
1609                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1610                    let exponent =
1611                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1612                    let expected_result =
1613                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1614                    assert_eq!(base.clone().pow(&exponent), expected_result);
1615                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1616                }
1617
1618                #[test]
1619                fn test_realrug_pow_zero_base() {
1620                    let base =
1621                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1622                    let exponent =
1623                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1624                    let expected_result =
1625                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1626                    assert_eq!(base.clone().pow(&exponent), expected_result);
1627                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1628                }
1629
1630                #[test]
1631                fn test_realrug_pow_negative_exponent() {
1632                    let base =
1633                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1634                    let exponent =
1635                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1636                    let expected_result =
1637                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.25)).unwrap();
1638                    assert_eq!(base.clone().pow(&exponent), expected_result);
1639                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1640                }
1641
1642                #[test]
1643                fn test_realrug_pow_negative_base_positive_exponent() {
1644                    let base =
1645                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1646                    let exponent =
1647                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1648                    let result = base.try_pow(&exponent);
1649                    assert!(matches!(
1650                        result,
1651                        Err(PowRealBaseRealExponentErrors::Input(..))
1652                    ));
1653                }
1654
1655                #[test]
1656                fn test_realrug_pow_negative_base_negative_exponent() {
1657                    let base =
1658                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1659                    let exponent =
1660                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -3.0)).unwrap();
1661                    let result = base.try_pow(&exponent);
1662                    assert!(matches!(
1663                        result,
1664                        Err(PowRealBaseRealExponentErrors::Input(..))
1665                    ));
1666                }
1667            }
1668
1669            mod complex_base {
1670                use super::*;
1671
1672                #[test]
1673                fn test_complex_rug_float_pow_valid() {
1674                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1675                        53,
1676                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1677                    ))
1678                    .unwrap();
1679                    let exponent =
1680                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1681                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1682                        53,
1683                        (Float::with_val(53, -5.0), Float::with_val(53, 12.0)),
1684                    ))
1685                    .unwrap();
1686                    assert_eq!(base.clone().pow(&exponent), expected_result);
1687                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1688                }
1689
1690                #[test]
1691                fn test_complex_rug_float_pow_zero_exponent() {
1692                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1693                        53,
1694                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1695                    ))
1696                    .unwrap();
1697                    let exponent =
1698                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1699                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1700                        53,
1701                        (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1702                    ))
1703                    .unwrap();
1704                    assert_eq!(base.clone().pow(&exponent), expected_result);
1705                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1706                }
1707
1708                #[test]
1709                fn test_complex_rug_float_pow_one_exponent() {
1710                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1711                        53,
1712                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1713                    ))
1714                    .unwrap();
1715                    let exponent =
1716                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1717                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1718                        53,
1719                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1720                    ))
1721                    .unwrap();
1722                    assert_eq!(base.clone().pow(&exponent), expected_result);
1723                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1724                }
1725
1726                #[test]
1727                fn test_complex_rug_float_pow_zero_base() {
1728                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1729                        53,
1730                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1731                    ))
1732                    .unwrap();
1733                    let exponent =
1734                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1735                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1736                        53,
1737                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1738                    ))
1739                    .unwrap();
1740                    assert_eq!(base.clone().pow(&exponent), expected_result);
1741                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1742                }
1743
1744                #[test]
1745                fn test_complex_rug_float_pow_negative_exponent() {
1746                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1747                        53,
1748                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1749                    ))
1750                    .unwrap();
1751                    let exponent =
1752                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1753                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1754                        53,
1755                        (
1756                            Float::with_val(53, -0.029585798816568046),
1757                            Float::with_val(53, -0.07100591715976332),
1758                        ),
1759                    ))
1760                    .unwrap();
1761                    assert_eq!(base.clone().pow(&exponent), expected_result);
1762                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1763                }
1764
1765                #[test]
1766                fn test_complex_rug_float_pow_negative_base_positive_exponent() {
1767                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1768                        53,
1769                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1770                    ))
1771                    .unwrap();
1772                    let exponent =
1773                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1774                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1775                        53,
1776                        (Float::with_val(53, 46.0), Float::with_val(53, -9.0)),
1777                    ))
1778                    .unwrap();
1779                    assert_eq!(base.clone().pow(&exponent), expected_result);
1780                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1781                }
1782
1783                #[test]
1784                fn test_complex_rug_float_pow_negative_base_negative_exponent() {
1785                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1786                        53,
1787                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1788                    ))
1789                    .unwrap();
1790                    let exponent =
1791                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -3.0)).unwrap();
1792                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1793                        53,
1794                        (
1795                            Float::with_val(53, 2.0937642239417388e-2),
1796                            Float::with_val(53, 4.096495220755576e-3),
1797                        ),
1798                    ))
1799                    .unwrap();
1800                    assert_eq!(base.clone().pow(&exponent), expected_result);
1801                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1802                }
1803            }
1804        }
1805    }
1806}
1807//------------------------------------------------------------------------------------------------