num_valid/functions/
pow.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2
3use crate::{
4    functions::FunctionErrors,
5    kernels::{RawComplexTrait, RawRealTrait, RawScalarTrait},
6    validation::{StrictFinitePolicy, capture_backtrace},
7};
8use duplicate::duplicate_item;
9use num::{Complex, Zero};
10use num_traits::int::PrimInt;
11use std::backtrace::Backtrace;
12use thiserror::Error;
13use try_create::ValidationPolicy;
14
15//------------------------------------------------------------------
16/// A marker trait for types that can be used as integer exponents.
17pub trait IntegerExponent: PrimInt {}
18
19impl IntegerExponent for i8 {}
20impl IntegerExponent for u8 {}
21impl IntegerExponent for i16 {}
22impl IntegerExponent for u16 {}
23impl IntegerExponent for i32 {}
24impl IntegerExponent for u32 {}
25impl IntegerExponent for i64 {}
26impl IntegerExponent for u64 {}
27impl IntegerExponent for i128 {}
28impl IntegerExponent for u128 {}
29impl IntegerExponent for isize {}
30impl IntegerExponent for usize {}
31//------------------------------------------------------------------
32
33//------------------------------------------------------------------
34/// Errors that can occur during input validation when computing `base^exponent`
35/// where both the base and exponent are real numbers.
36///
37/// This enum is typically used as the `InputErrorSource` for a [`FunctionErrors`]
38/// wrapper, such as [`PowRealBaseRealExponentErrors`]. It is generic over
39/// `RawReal`, which must implement [`RawRealTrait`].
40#[derive(Debug, Error)]
41pub enum PowRealBaseRealExponentInputErrors<RawReal: RawRealTrait> {
42    /// The base is negative, and the exponent is a non-integer real number.
43    /// This operation is undefined in the real domain and typically results
44    /// in a complex number or NaN.
45    #[error("detected a negative base ({base}) with a real exponent ({exponent}) !")]
46    NegativeBase {
47        /// The negative base value.
48        base: RawReal,
49
50        /// The exponent value.
51        exponent: RawReal,
52
53        /// A captured backtrace for debugging purposes.
54        backtrace: Backtrace,
55    },
56
57    /// The input base value failed validation according to the active policy.
58    ///
59    /// For example, using [`StrictFinitePolicy`],
60    /// this would trigger if the base is NaN or Infinity.
61    #[error("the base is invalid!")]
62    InvalidBase {
63        /// The underlying validation error for the base.
64        /// The type of this field is `<RawReal as RawScalarTrait>::ValidationErrors`.
65        #[source]
66        #[backtrace]
67        source: <RawReal as RawScalarTrait>::ValidationErrors,
68    },
69
70    /// The input exponent value failed validation according to the active policy.
71    ///
72    /// For example, using [`StrictFinitePolicy`],
73    /// this would trigger if the exponent is NaN or Infinity.
74    #[error("the exponent is invalid!")]
75    InvalidExponent {
76        /// The underlying validation error for the exponent.
77        /// The type of this field is `<RawReal as RawScalarTrait>::ValidationErrors`.
78        #[source]
79        #[backtrace]
80        source: <RawReal as RawScalarTrait>::ValidationErrors,
81    },
82
83    #[error("the base and the exponent are invalid!")]
84    InvalidBaseAndExponent {
85        /// The source error that occurred during validation for the base.
86        error_base: <RawReal as RawScalarTrait>::ValidationErrors,
87
88        /// The source error that occurred during validation for the exponent.
89        error_exponent: <RawReal as RawScalarTrait>::ValidationErrors,
90
91        #[backtrace]
92        backtrace: Backtrace,
93    },
94}
95//------------------------------------------------------------------
96
97//------------------------------------------------------------------
98/// Errors that can occur during input validation when computing `base^exponent`
99/// where the base is a complex number and the exponent is a real number.
100///
101/// This enum is typically used as the `InputErrorSource` for a [`FunctionErrors`]
102/// wrapper, such as [`PowComplexBaseRealExponentErrors`]. It is generic over
103/// `ComplexType`, which must implement [`ComplexScalar`](crate::ComplexScalar).
104#[derive(Debug, Error)]
105pub enum PowComplexBaseRealExponentInputErrors<RawComplex: RawComplexTrait> {
106    /// The input complex base value failed validation according to the active policy.
107    ///
108    /// For example, using [`StrictFinitePolicy`],
109    /// this would trigger if any part of the complex base is NaN or Infinity.
110    #[error("the input complex base is invalid according to validation policy")]
111    InvalidBase {
112        /// The underlying validation error for the complex base.
113        /// The type of this field is `<RawComplex as RawScalarTrait>::ValidationErrors`.
114        #[source]
115        #[backtrace]
116        source: <RawComplex as RawScalarTrait>::ValidationErrors,
117    },
118
119    /// The input real exponent value failed validation according to the active policy.
120    ///
121    /// For example, using [`StrictFinitePolicy`],
122    /// this would trigger if the exponent is NaN or Infinity.
123    #[error("the input real exponent is invalid according to validation policy")]
124    InvalidExponent {
125        /// The underlying validation error for the real exponent.
126        /// The type of this field is `<RawReal as RawScalarTrait>::ValidationErrors`.
127        #[source]
128        #[backtrace]
129        source: <RawComplex::RawReal as RawScalarTrait>::ValidationErrors,
130    },
131
132    /// The input complex base value and the real exponent failed validation according to the active policy.
133    ///
134    /// For example, using [`StrictFinitePolicy`],
135    /// this would trigger if any part of the complex base is NaN or Infinity.
136    #[error(
137        "the input complex base and the real exponent is invalid according to validation policy"
138    )]
139    InvalidBaseAndExponent {
140        /// The source error that occurred during validation for the base.
141        error_base: <RawComplex as RawScalarTrait>::ValidationErrors,
142
143        /// The source error that occurred during validation for the exponent.
144        error_exponent: <RawComplex::RawReal as RawScalarTrait>::ValidationErrors,
145
146        #[backtrace]
147        backtrace: Backtrace,
148    },
149
150    /// The complex base is zero, and the real exponent is negative.
151    /// This operation results in division by zero.
152    #[error("the base is zero and the exponent (={exponent}) is negative!")]
153    ZeroBaseNegativeExponent {
154        /// The negative real exponent value.
155        exponent: RawComplex::RawReal,
156
157        /// A captured backtrace for debugging purposes.
158        backtrace: Backtrace,
159    },
160}
161//------------------------------------------------------------------
162
163/*
164//------------------------------------------------------------------
165/// An enum that unifies input errors for power functions with a real exponent.
166#[derive(Debug, Error)]
167pub enum PowRealExponentInputError<RawReal, RawComplex>
168where
169    RawReal: RawRealTrait,
170    RawComplex: RawComplexTrait<RawReal = RawReal>,
171{
172    #[error("Error with real base")]
173    ForRealBase(#[from] PowRealBaseRealExponentInputErrors<RawReal>),
174
175    #[error("Error with complex base")]
176    ForComplexBase(#[from] PowComplexBaseRealExponentInputErrors<RawComplex>),
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`],
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 RawScalarTrait>::ValidationErrors`.
198        #[source]
199        #[backtrace]
200        source: <RawScalar as RawScalarTrait>::ValidationErrors,
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 RawScalarTrait>::ValidationErrors` 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        source: 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 RawScalarTrait>::ValidationErrors,
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 RawScalarTrait>::ValidationErrors` 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        source: 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 RawScalarTrait>::ValidationErrors,
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 RawScalarTrait>::ValidationErrors` for issues
287///   with the computed result (e.g., overflow).
288pub type PowIntExponentErrors<RawScalar, ExponentType> = FunctionErrors<
289    PowIntExponentInputErrors<RawScalar, ExponentType>,
290    <RawScalar as RawScalarTrait>::ValidationErrors,
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`]).
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    fn try_pow(self, exponent: ExponentType) -> Result<Self, Self::Error>;
323
324    /// Computes `self` (the base) raised to the power of `exponent`.
325    ///
326    /// This method provides a potentially more performant way to compute the power,
327    /// especially in release builds, by possibly omitting some checks performed by
328    /// `try_pow`.
329    ///
330    /// # Behavior
331    ///
332    /// - In **debug builds**, this method typically calls `try_pow(exponent).unwrap()`,
333    ///   meaning it will panic if `try_pow` would return an error.
334    /// - In **release builds**, it may call the underlying power function directly.
335    ///   While input validation might be skipped, output validation (e.g., checking
336    ///   if the result is finite) might still occur implicitly if the underlying
337    ///   power function produces non-finite results (like NaN or Infinity) from
338    ///   finite inputs, which are then caught by policies like
339    ///   [`StrictFinitePolicy`] if applied
340    ///   to the output.
341    ///
342    /// # Arguments
343    ///
344    /// * `exponent`: The exponent to raise `self` to.
345    ///
346    /// # Returns
347    ///
348    /// The result of `self` raised to the power of `exponent`.
349    ///
350    /// # Panics
351    ///
352    /// - Panics in debug builds if `try_pow` would return an error.
353    /// - Behavior regarding panics in release builds depends on the specific
354    ///   implementation and the underlying power function. For example, `f64::powf`
355    ///   itself does not panic but can return `NaN` or `Infinity`.
356    fn pow(self, exponent: ExponentType) -> Self;
357}
358
359impl Pow<&f64> for f64 {
360    type Error = PowRealBaseRealExponentErrors<f64>;
361
362    #[inline(always)]
363    fn try_pow(self, exponent: &f64) -> Result<Self, Self::Error> {
364        let validation_base = StrictFinitePolicy::<f64, 53>::validate(self);
365        let validation_exponent = StrictFinitePolicy::<f64, 53>::validate_ref(exponent);
366        match (validation_base, validation_exponent) {
367            (Ok(base), Ok(())) => {
368                if base < 0.0 {
369                    Err(PowRealBaseRealExponentInputErrors::NegativeBase {
370                        base,
371                        exponent: *exponent,
372                        backtrace: capture_backtrace(),
373                    }
374                    .into())
375                } else {
376                    let result = base.powf(*exponent);
377                    StrictFinitePolicy::<f64, 53>::validate(result)
378                        .map_err(|e| PowRealBaseRealExponentErrors::Output { source: e })
379                }
380            }
381            (Ok(_), Err(error_exponent)) => {
382                Err(PowRealBaseRealExponentInputErrors::InvalidExponent {
383                    source: error_exponent,
384                }
385                .into())
386            }
387            (Err(error_base), Ok(_)) => {
388                Err(PowRealBaseRealExponentInputErrors::InvalidBase { source: error_base }.into())
389            }
390            (Err(error_base), Err(error_exponent)) => {
391                Err(PowRealBaseRealExponentInputErrors::InvalidBaseAndExponent {
392                    error_base,
393                    error_exponent,
394                    backtrace: capture_backtrace(),
395                }
396                .into())
397            }
398        }
399    }
400
401    #[inline(always)]
402    /// Raises th number `self` to the power `exponent`.
403    fn pow(self, exponent: &f64) -> Self {
404        #[cfg(debug_assertions)]
405        {
406            self.try_pow(exponent).unwrap()
407        }
408        #[cfg(not(debug_assertions))]
409        {
410            self.powf(*exponent)
411        }
412    }
413}
414
415impl Pow<&f64> for Complex<f64> {
416    type Error = PowComplexBaseRealExponentErrors<Self>;
417
418    #[inline(always)]
419    fn try_pow(self, exponent: &f64) -> Result<Self, Self::Error> {
420        let validation_base = StrictFinitePolicy::<Complex<f64>, 53>::validate(self);
421        let validation_exponent = StrictFinitePolicy::<f64, 53>::validate_ref(exponent);
422        match (validation_base, validation_exponent) {
423            (Ok(base), Ok(())) => {
424                if Zero::is_zero(&base) {
425                    if *exponent < 0.0 {
426                        Err(
427                            PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent {
428                                exponent: *exponent,
429                                backtrace: capture_backtrace(),
430                            }
431                            .into(),
432                        )
433                    } else if *exponent == 0.0 {
434                        Ok(Complex::new(1.0, 0.0))
435                    } else {
436                        Ok(Complex::new(0.0, 0.0))
437                    }
438                } else {
439                    let result = base.powf(*exponent);
440                    StrictFinitePolicy::<Complex<f64>, 53>::validate(result)
441                        .map_err(|e| PowComplexBaseRealExponentErrors::Output { source: e })
442                }
443            }
444            (Ok(_), Err(error_exponent)) => {
445                Err(PowComplexBaseRealExponentInputErrors::InvalidExponent {
446                    source: error_exponent,
447                }
448                .into())
449            }
450            (Err(error_base), Ok(_)) => {
451                Err(
452                    PowComplexBaseRealExponentInputErrors::InvalidBase { source: error_base }
453                        .into(),
454                )
455            }
456            (Err(error_base), Err(error_exponent)) => Err(
457                PowComplexBaseRealExponentInputErrors::InvalidBaseAndExponent {
458                    error_base,
459                    error_exponent,
460                    backtrace: capture_backtrace(),
461                }
462                .into(),
463            ),
464        }
465    }
466
467    #[inline(always)]
468    /// Raises th number `self` to the power `exponent`.
469    fn pow(self, exponent: &f64) -> Self {
470        #[cfg(debug_assertions)]
471        {
472            self.try_pow(exponent)
473                .expect("Error raised by Pow::try_pow() in the function Pow::pow() (debug mode)")
474        }
475        #[cfg(not(debug_assertions))]
476        {
477            self.powf(*exponent)
478        }
479    }
480}
481
482#[duplicate_item(
483    exponent_type exponent_func;
484    [i8]    [exponent.into()];
485    [i16]   [exponent.into()];
486    [i32]   [exponent];
487    [i64]   [exponent.try_into().unwrap()];
488    [i128]  [exponent.try_into().unwrap()];
489    [isize] [exponent.try_into().unwrap()];
490)]
491impl Pow<exponent_type> for f64 {
492    type Error = PowIntExponentErrors<f64, exponent_type>;
493
494    fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
495        StrictFinitePolicy::<f64, 53>::validate(self)
496            .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
497            .and_then(|base| {
498                if base == 0. && exponent < 0 {
499                    Err(PowIntExponentInputErrors::ZeroBaseNegativeExponent {
500                        exponent,
501                        backtrace: capture_backtrace(),
502                    }
503                    .into())
504                } else {
505                    let res = base.powi(exponent_func);
506                    StrictFinitePolicy::<f64, 53>::validate(res)
507                        .map_err(|e| Self::Error::Output { source: e })
508                }
509            })
510    }
511
512    #[inline(always)]
513    /// Raises th number `self` to the power `exponent`.
514    fn pow(self, exponent: exponent_type) -> Self {
515        #[cfg(debug_assertions)]
516        {
517            self.try_pow(exponent).unwrap()
518        }
519        #[cfg(not(debug_assertions))]
520        {
521            self.powi(exponent_func)
522        }
523    }
524}
525
526#[duplicate_item(
527    exponent_type exponent_func;
528    [u8]    [exponent.into()];
529    [u16]   [exponent.into()];
530    [u32]   [exponent.try_into().unwrap()];
531    [u64]   [exponent.try_into().unwrap()];
532    [u128]  [exponent.try_into().unwrap()];
533    [usize] [exponent.try_into().unwrap()];
534)]
535impl Pow<exponent_type> for f64 {
536    type Error = PowIntExponentErrors<f64, exponent_type>;
537
538    fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
539        StrictFinitePolicy::<f64, 53>::validate(self)
540            .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
541            .and_then(|base| {
542                let res = base.powi(exponent_func);
543                StrictFinitePolicy::<f64, 53>::validate(res)
544                    .map_err(|e| Self::Error::Output { source: e })
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 func_name exponent_func;
564    [i8]    [powi] [exponent.into()];
565    [i16]   [powi] [exponent.into()];
566    [i32]   [powi] [exponent];
567    [i64]   [powi] [exponent.try_into().unwrap()];
568    [i128]  [powi] [exponent.try_into().unwrap()];
569    [isize] [powi] [exponent.try_into().unwrap()];
570)]
571impl Pow<exponent_type> for Complex<f64> {
572    type Error = PowIntExponentErrors<Complex<f64>, exponent_type>;
573
574    #[inline(always)]
575    fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
576        StrictFinitePolicy::<Self, 53>::validate(self)
577            .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
578            .and_then(|base| {
579                if Zero::is_zero(&base) && exponent < 0 {
580                    Err(PowIntExponentInputErrors::ZeroBaseNegativeExponent {
581                        exponent,
582                        backtrace: capture_backtrace(),
583                    }
584                    .into())
585                } else {
586                    StrictFinitePolicy::<Self, 53>::validate(base.func_name(exponent_func))
587                        .map_err(|e| Self::Error::Output { source: e })
588                }
589            })
590    }
591
592    #[inline(always)]
593    /// Raises th number `self` to the power `exponent`.
594    fn pow(self, exponent: exponent_type) -> Self {
595        #[cfg(debug_assertions)]
596        {
597            self.try_pow(exponent).unwrap()
598        }
599        #[cfg(not(debug_assertions))]
600        {
601            self.func_name(exponent_func)
602        }
603    }
604}
605
606#[duplicate_item(
607    exponent_type func_name exponent_func;
608    [u8]    [powu] [exponent.into()];
609    [u16]   [powu] [exponent.into()];
610    [u32]   [powu] [exponent];
611    [u64]   [powu] [exponent.try_into().unwrap()];
612    [u128]  [powu] [exponent.try_into().unwrap()];
613    [usize] [powu] [exponent.try_into().unwrap()];
614)]
615impl Pow<exponent_type> for Complex<f64> {
616    type Error = PowIntExponentErrors<Complex<f64>, exponent_type>;
617
618    #[inline(always)]
619    fn try_pow(self, exponent: exponent_type) -> Result<Self, Self::Error> {
620        StrictFinitePolicy::<Self, 53>::validate(self)
621            .map_err(|e| PowIntExponentInputErrors::InvalidBase { source: e }.into())
622            .and_then(|base| {
623                StrictFinitePolicy::<Self, 53>::validate(base.func_name(exponent_func))
624                    .map_err(|e| Self::Error::Output { source: e })
625            })
626    }
627
628    #[inline(always)]
629    /// Raises th number `self` to the power `exponent`.
630    fn pow(self, exponent: exponent_type) -> Self {
631        #[cfg(debug_assertions)]
632        {
633            self.try_pow(exponent).unwrap()
634        }
635        #[cfg(not(debug_assertions))]
636        {
637            self.func_name(exponent_func)
638        }
639    }
640}
641//------------------------------------------------------------------------------------------------
642
643//------------------------------------------------------------------------------------------------
644/// An aggregate trait for types that can be raised to the power of any primitive integer.
645pub trait PowIntExponent:
646    Pow<i8, Error = PowIntExponentErrors<Self::RawType, i8>>
647    + Pow<u8, Error = PowIntExponentErrors<Self::RawType, u8>>
648    + Pow<i16, Error = PowIntExponentErrors<Self::RawType, i16>>
649    + Pow<u16, Error = PowIntExponentErrors<Self::RawType, u16>>
650    + Pow<i32, Error = PowIntExponentErrors<Self::RawType, i32>>
651    + Pow<u32, Error = PowIntExponentErrors<Self::RawType, u32>>
652    + Pow<i64, Error = PowIntExponentErrors<Self::RawType, i64>>
653    + Pow<u64, Error = PowIntExponentErrors<Self::RawType, u64>>
654    + Pow<i128, Error = PowIntExponentErrors<Self::RawType, i128>>
655    + Pow<u128, Error = PowIntExponentErrors<Self::RawType, u128>>
656    + Pow<isize, Error = PowIntExponentErrors<Self::RawType, isize>>
657    + Pow<usize, Error = PowIntExponentErrors<Self::RawType, usize>>
658{
659    type RawType: RawScalarTrait;
660}
661
662impl PowIntExponent for f64 {
663    type RawType = f64;
664}
665
666impl PowIntExponent for Complex<f64> {
667    type RawType = Complex<f64>;
668}
669
670//------------------------------------------------------------------------------------------------
671
672//------------------------------------------------------------------------------------------------
673#[cfg(test)]
674mod tests {
675    use super::*;
676    use crate::{
677        RealScalar,
678        functions::{
679            Pow, PowIntExponentErrors, PowIntExponentInputErrors,
680            PowRealBaseRealExponentInputErrors,
681        },
682        validation::{ErrorsValidationRawComplex, ErrorsValidationRawReal},
683    };
684    use num::Complex;
685
686    #[cfg(feature = "rug")]
687    use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
688
689    #[cfg(feature = "rug")]
690    use try_create::TryNew;
691
692    mod pow_u32_exponent {
693        use super::*;
694
695        mod real_base {
696            use super::*;
697
698            fn pow_generic_real_u32_valid<RealType: RealScalar>() {
699                let base = RealType::try_from_f64(2.0).unwrap();
700                let exponent = 3u32;
701                let expected_result = RealType::try_from_f64(8.0).unwrap();
702                assert_eq!(Pow::pow(base.clone(), exponent), expected_result);
703                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
704            }
705
706            #[test]
707            fn test_pow_generic_real_u32_valid() {
708                pow_generic_real_u32_valid::<f64>();
709            }
710
711            #[test]
712            fn test_f64_pow_u32_valid() {
713                let base = 2.0;
714                let exponent = 3u32;
715                let expected_result = 8.0;
716                assert_eq!(Pow::pow(base, exponent), expected_result);
717                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
718            }
719
720            #[test]
721            fn test_f64_pow_u32_zero_exponent() {
722                let base = 2.0;
723                let exponent = 0u32;
724                let expected_result = 1.0;
725                assert_eq!(Pow::pow(base, exponent), expected_result);
726                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
727            }
728
729            #[test]
730            fn test_f64_pow_u32_one_exponent() {
731                let base = 2.0;
732                let exponent = 1u32;
733                let expected_result = 2.0;
734                assert_eq!(Pow::pow(base, exponent), expected_result);
735                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
736            }
737
738            #[test]
739            fn test_f64_pow_u32_zero_base() {
740                let base = 0.0;
741                let exponent = 3u32;
742                let expected_result = 0.0;
743                assert_eq!(Pow::pow(base, exponent), expected_result);
744                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
745            }
746
747            #[test]
748            fn test_f64_pow_u32_nan_base() {
749                let base = f64::NAN;
750                let exponent = 3u32;
751                let result = base.try_pow(exponent);
752                assert!(result.is_err());
753            }
754
755            #[test]
756            fn test_f64_pow_u32_infinity_base() {
757                let base = f64::INFINITY;
758                let exponent = 3u32;
759                let result = base.try_pow(exponent);
760                assert!(result.is_err());
761            }
762        }
763
764        mod complex_base {
765            use super::*;
766
767            #[test]
768            fn test_complex_f64_pow_u32_valid() {
769                let base = Complex::new(2.0, 3.0);
770                let exponent = 2u32;
771                let expected_result = Complex::new(-5.0, 12.0);
772                assert_eq!(Pow::pow(base, exponent), expected_result);
773                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
774            }
775
776            #[test]
777            fn test_complex_f64_pow_u32_zero_exponent() {
778                let base = Complex::new(2.0, 3.0);
779                let exponent = 0u32;
780                let expected_result = Complex::new(1.0, 0.0);
781                assert_eq!(Pow::pow(base, exponent), expected_result);
782                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
783            }
784
785            #[test]
786            fn test_complex_f64_pow_u32_one_exponent() {
787                let base = Complex::new(2.0, 3.0);
788                let exponent = 1u32;
789                let expected_result = Complex::new(2.0, 3.0);
790                assert_eq!(Pow::pow(base, exponent), expected_result);
791                assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
792            }
793
794            #[test]
795            fn test_complex_f64_pow_u32_zero_base() {
796                let base = Complex::new(0.0, 0.0);
797                let exponent = 3u32;
798                let expected_result = Complex::new(0.0, 0.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_complex_f64_pow_u32_nan_base() {
805                let base = Complex::new(f64::NAN, 0.0);
806                let exponent = 3u32;
807                let result = base.try_pow(exponent);
808                assert!(result.is_err());
809
810                let base = Complex::new(0.0, f64::NAN);
811                let result = base.try_pow(exponent);
812                assert!(result.is_err());
813            }
814
815            #[test]
816            fn test_complex_f64_pow_u32_infinity_base() {
817                let base = Complex::new(f64::INFINITY, 0.0);
818                let exponent = 3u32;
819                let result = base.try_pow(exponent);
820                assert!(result.is_err());
821
822                let base = Complex::new(0.0, f64::INFINITY);
823                let result = base.try_pow(exponent);
824                assert!(result.is_err());
825            }
826        }
827    }
828
829    mod pow_i32_exponent {
830        use super::*;
831
832        mod native64 {
833            use super::*;
834
835            mod real_base {
836                use super::*;
837
838                #[test]
839                fn test_f64_pow_valid() {
840                    let base = 2.0;
841                    let exponent = 3i32;
842                    let expected_result = 8.0;
843                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
844                    assert_eq!(<f64 as Pow<i32>>::pow(base, exponent), expected_result);
845                }
846
847                #[test]
848                fn test_f64_pow_zero_exponent() {
849                    let base = 2.0;
850                    let exponent = 0i32;
851                    let expected_result = 1.0;
852                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
853                }
854
855                #[test]
856                fn test_f64_pow_negative_exponent() {
857                    let base = 2.0;
858                    let exponent = -3i32;
859                    let expected_result = 0.125;
860                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
861                }
862
863                #[test]
864                fn test_f64_pow_zero_base() {
865                    let base = 0.0;
866                    let exponent = 3i32;
867                    let expected_result = 0.0;
868                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
869                }
870
871                #[test]
872                fn test_f64_pow_zero_base_zero_exponent() {
873                    let base = 0.0;
874                    let exponent = 0i32;
875                    let expected_result = 1.0;
876                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
877                }
878
879                #[test]
880                fn test_f64_pow_zero_base_negative_exponent() {
881                    let base = 0.0;
882                    let err = base.try_pow(-1i32).unwrap_err();
883                    assert!(matches!(
884                        err,
885                        PowIntExponentErrors::Input {
886                            source: PowIntExponentInputErrors::ZeroBaseNegativeExponent {
887                                exponent: -1,
888                                ..
889                            }
890                        }
891                    ));
892                }
893
894                #[test]
895                fn test_f64_pow_negative_base_positive_exponent() {
896                    let base = -2.0;
897                    let exponent = 3i32;
898                    let expected_result = -8.0;
899                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
900                }
901
902                #[test]
903                fn test_f64_pow_negative_base_negative_exponent() {
904                    let base = -2.0;
905                    let exponent = -3i32;
906                    let expected_result = -0.125;
907                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
908                }
909            }
910
911            mod complex_base {
912                use super::*;
913
914                #[test]
915                fn test_complex_f64_pow_valid() {
916                    let base = Complex::new(2.0, 3.0);
917                    let exponent = 2i32;
918                    let expected_result = Complex::new(-5.0, 12.0);
919                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
920                    assert_eq!(
921                        <Complex<f64> as Pow<i32>>::pow(base, exponent),
922                        expected_result
923                    );
924                }
925
926                #[test]
927                fn test_complex_f64_pow_zero_exponent() {
928                    let base = Complex::new(2.0, 3.0);
929                    let exponent = 0i32;
930                    let expected_result = Complex::new(1.0, 0.0);
931                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
932                }
933
934                #[test]
935                fn test_complex_f64_pow_negative_exponent() {
936                    let base = Complex::new(2.0, 3.0);
937                    let exponent = -2i32;
938                    let expected_result = Complex::new(-0.029585798816568053, -0.07100591715976332);
939                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
940                }
941
942                #[test]
943                fn test_complex_f64_pow_zero_base() {
944                    let base = Complex::new(0.0, 0.0);
945                    let exponent = 3i32;
946                    let expected_result = Complex::new(0.0, 0.0);
947                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
948                }
949
950                #[test]
951                fn test_complex_f64_pow_zero_base_zero_exponent() {
952                    let base = Complex::new(0.0, 0.0);
953                    let exponent = 0i32;
954                    let expected_result = Complex::new(1.0, 0.0);
955                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
956                }
957
958                #[test]
959                fn test_complex_f64_pow_zero_base_negative_exponent() {
960                    let base = Complex::new(0.0, 0.0);
961                    let err = base.try_pow(-1i32).unwrap_err();
962                    assert!(matches!(
963                        err,
964                        PowIntExponentErrors::Input {
965                            source: PowIntExponentInputErrors::ZeroBaseNegativeExponent {
966                                exponent: -1,
967                                ..
968                            }
969                        }
970                    ));
971                }
972
973                #[test]
974                fn test_complex_f64_pow_negative_base_positive_exponent() {
975                    let base = Complex::new(-2.0, -3.0);
976                    let exponent = 3i32;
977                    let expected_result = Complex::new(46.0, -9.0);
978                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
979                }
980
981                #[test]
982                fn test_complex_f64_pow_negative_base_negative_exponent() {
983                    let base = Complex::new(-2.0, -3.0);
984                    let exponent = -3i32;
985                    let expected_result = Complex::new(0.02093764223941739, 0.004096495220755574);
986                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
987                }
988            }
989        }
990
991        #[cfg(feature = "rug")]
992        mod rug53 {
993            use super::*;
994            use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
995            use rug::Float;
996
997            mod real {
998                use super::*;
999
1000                #[test]
1001                fn test_rug_float_pow_valid() {
1002                    let base =
1003                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1004                    let exponent = 3;
1005                    let expected_result =
1006                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 8.0)).unwrap();
1007                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1008                }
1009
1010                #[test]
1011                fn test_rug_float_pow_zero_exponent() {
1012                    let base =
1013                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1014                    let exponent = 0;
1015                    let expected_result =
1016                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1017                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1018                }
1019
1020                #[test]
1021                fn test_rug_float_pow_negative_exponent() {
1022                    let base =
1023                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1024                    let exponent = -3;
1025                    let expected_result =
1026                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.125)).unwrap();
1027                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1028                }
1029
1030                #[test]
1031                fn test_rug_float_pow_zero_base() {
1032                    let base =
1033                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1034                    let exponent = 3;
1035                    let expected_result =
1036                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1037                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1038                }
1039
1040                #[test]
1041                fn test_rug_float_pow_zero_base_zero_exponent() {
1042                    let base =
1043                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1044                    let exponent = 0;
1045                    let expected_result =
1046                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1047                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1048                }
1049
1050                #[test]
1051                fn test_rug_float_pow_negative_base_positive_exponent() {
1052                    let base =
1053                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1054                    let exponent = 3;
1055                    let expected_result =
1056                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -8.0)).unwrap();
1057                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1058                }
1059
1060                #[test]
1061                fn test_rug_float_pow_negative_base_negative_exponent() {
1062                    let base =
1063                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1064                    let exponent = -3;
1065                    let expected_result =
1066                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -0.125)).unwrap();
1067                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1068                }
1069            }
1070
1071            mod complex {
1072                use super::*;
1073                use rug::Complex;
1074
1075                #[test]
1076                fn test_complex_rug_float_pow_valid() {
1077                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1078                        53,
1079                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1080                    ))
1081                    .unwrap();
1082                    let exponent = 2;
1083                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1084                        53,
1085                        (Float::with_val(53, -5.0), Float::with_val(53, 12.0)),
1086                    ))
1087                    .unwrap();
1088                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1089                }
1090
1091                #[test]
1092                fn test_complex_rug_float_pow_zero_exponent() {
1093                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1094                        53,
1095                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1096                    ))
1097                    .unwrap();
1098                    let exponent = 0;
1099                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1100                        53,
1101                        (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1102                    ))
1103                    .unwrap();
1104                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1105                }
1106
1107                #[test]
1108                fn test_complex_rug_float_pow_negative_exponent() {
1109                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1110                        53,
1111                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1112                    ))
1113                    .unwrap();
1114                    let exponent = -2;
1115                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1116                        53,
1117                        (
1118                            Float::with_val(53, -2.9585798816568046e-2),
1119                            Float::with_val(53, -7.100591715976332e-2),
1120                        ),
1121                    ))
1122                    .unwrap();
1123                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1124                }
1125
1126                #[test]
1127                fn test_complex_rug_float_pow_zero_base() {
1128                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1129                        53,
1130                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1131                    ))
1132                    .unwrap();
1133                    let exponent = 3;
1134                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1135                        53,
1136                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1137                    ))
1138                    .unwrap();
1139                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1140                }
1141
1142                #[test]
1143                fn test_complex_rug_float_pow_zero_base_zero_exponent() {
1144                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1145                        53,
1146                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1147                    ))
1148                    .unwrap();
1149                    let exponent = 0;
1150                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1151                        53,
1152                        (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1153                    ))
1154                    .unwrap();
1155                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1156                }
1157
1158                #[test]
1159                fn test_complex_rug_float_pow_negative_base_positive_exponent() {
1160                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1161                        53,
1162                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1163                    ))
1164                    .unwrap();
1165                    let exponent = 3;
1166                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1167                        53,
1168                        (Float::with_val(53, 46.0), Float::with_val(53, -9.0)),
1169                    ))
1170                    .unwrap();
1171                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1172                }
1173
1174                #[test]
1175                fn test_complex_rug_float_pow_negative_base_negative_exponent() {
1176                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1177                        53,
1178                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1179                    ))
1180                    .unwrap();
1181                    let exponent = -3;
1182                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1183                        53,
1184                        (
1185                            Float::with_val(53, 2.0937642239417388e-2),
1186                            Float::with_val(53, 4.096495220755576e-3),
1187                        ),
1188                    ))
1189                    .unwrap();
1190                    assert_eq!(base.try_pow(exponent).unwrap(), expected_result);
1191                }
1192            }
1193        }
1194    }
1195
1196    mod pow_real_exponent {
1197        use super::*;
1198
1199        mod native64 {
1200            use super::*;
1201
1202            mod real_base {
1203                use super::*;
1204                use core::f64;
1205
1206                #[test]
1207                fn test_f64_pow_f64_valid() {
1208                    let base = 2.0;
1209                    let exponent = 3.0;
1210                    let expected_result = 8.0;
1211                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1212                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1213                }
1214
1215                #[test]
1216                fn test_f64_pow_f64_zero_exponent() {
1217                    let base = 2.0;
1218                    let exponent = 0.0;
1219                    let expected_result = 1.0;
1220                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1221                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1222                }
1223
1224                #[test]
1225                fn test_f64_pow_f64_invalid_exponent() {
1226                    let base = 2.0;
1227                    let err = base.try_pow(&f64::NAN).unwrap_err();
1228                    assert!(matches!(
1229                        err,
1230                        PowRealBaseRealExponentErrors::Input {
1231                            source: PowRealBaseRealExponentInputErrors::InvalidExponent {
1232                                source: ErrorsValidationRawReal::IsNaN { .. }
1233                            }
1234                        }
1235                    ))
1236                }
1237
1238                #[test]
1239                fn test_f64_pow_f64_invalid_base_invalid_exponent() {
1240                    let err = (f64::INFINITY).try_pow(&f64::NAN).unwrap_err();
1241                    assert!(matches!(
1242                        err,
1243                        PowRealBaseRealExponentErrors::Input {
1244                            source: PowRealBaseRealExponentInputErrors::InvalidBaseAndExponent {
1245                                error_base: ErrorsValidationRawReal::IsPosInfinity { .. },
1246                                error_exponent: ErrorsValidationRawReal::IsNaN { .. },
1247                                ..
1248                            }
1249                        }
1250                    ))
1251                }
1252
1253                #[test]
1254                fn test_f64_pow_f64_one_exponent() {
1255                    let base = 2.0;
1256                    let exponent = 1.0;
1257                    let expected_result = 2.0;
1258                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1259                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1260                }
1261
1262                #[test]
1263                fn test_f64_pow_f64_zero_base() {
1264                    let base = 0.0;
1265                    let exponent = 3.0;
1266                    let expected_result = 0.0;
1267                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1268                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1269                }
1270
1271                #[test]
1272                fn test_f64_pow_f64_nan_base() {
1273                    let base = f64::NAN;
1274                    let exponent = 3.0;
1275                    let result = base.try_pow(&exponent);
1276                    assert!(result.is_err());
1277                }
1278
1279                #[test]
1280                fn test_f64_pow_f64_infinity_base() {
1281                    let base = f64::INFINITY;
1282                    let exponent = 3.0;
1283                    let result = base.try_pow(&exponent);
1284                    assert!(matches!(
1285                        result,
1286                        Err(PowRealBaseRealExponentErrors::Input { .. })
1287                    ));
1288                }
1289
1290                #[test]
1291                fn test_f64_pow_f64_negative_exponent() {
1292                    let base = 2.0;
1293                    let exponent = -2.0;
1294                    let expected_result = 0.25;
1295                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1296                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1297                }
1298
1299                #[test]
1300                fn test_f64_pow_f64_negative_base_positive_exponent() {
1301                    let base = -2.0;
1302                    let exponent = 3.0;
1303                    let result = base.try_pow(&exponent);
1304                    assert!(matches!(
1305                        result,
1306                        Err(PowRealBaseRealExponentErrors::Input { .. })
1307                    ));
1308                }
1309
1310                #[test]
1311                fn test_f64_pow_f64_negative_base_negative_exponent() {
1312                    let base = -2.0;
1313                    let exponent = -3.0;
1314                    let result = base.try_pow(&exponent);
1315                    assert!(result.is_err());
1316                }
1317            }
1318
1319            mod complex_base {
1320                use super::*;
1321
1322                #[test]
1323                fn test_complex_f64_pow_ok_base_ok_exponent() {
1324                    let base = Complex::new(2.0, 3.0);
1325                    let exponent = 2.0;
1326                    let expected_result = Complex::new(-4.999999999999999, 11.999999999999998);
1327                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1328                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1329                }
1330
1331                #[test]
1332                fn test_complex_f64_pow_ok_base_zero_exponent() {
1333                    let base = Complex::new(2.0, 3.0);
1334                    let exponent = 0.0;
1335                    let expected_result = Complex::new(1.0, 0.0);
1336                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1337                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1338                }
1339
1340                #[test]
1341                fn test_complex_f64_pow_zero_base_zero_exponent() {
1342                    let base = Complex::new(0.0, 0.0);
1343                    let exponent = 0.0;
1344                    let expected_result = Complex::new(1.0, 0.0);
1345                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1346                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1347                }
1348
1349                #[test]
1350                fn test_complex_f64_pow_zero_base_negative_exponent() {
1351                    let base = Complex::new(0.0, 0.0);
1352                    let exponent = -1.0;
1353                    let err = base.try_pow(&exponent).unwrap_err();
1354                    assert!(matches!(
1355                        err,
1356                        PowComplexBaseRealExponentErrors::Input {
1357                            source:
1358                                PowComplexBaseRealExponentInputErrors::ZeroBaseNegativeExponent {
1359                                    exponent: -1.,
1360                                    ..
1361                                }
1362                        }
1363                    ));
1364                }
1365
1366                #[test]
1367                fn test_complex_f64_pow_ok_base_nan_exponent() {
1368                    let base = Complex::new(0.0, 0.0);
1369                    let exponent = f64::NAN;
1370                    let err = base.try_pow(&exponent).unwrap_err();
1371                    assert!(matches!(
1372                        err,
1373                        PowComplexBaseRealExponentErrors::Input {
1374                            source: PowComplexBaseRealExponentInputErrors::InvalidExponent {
1375                                source: ErrorsValidationRawReal::IsNaN { .. }
1376                            }
1377                        }
1378                    ));
1379                }
1380
1381                #[test]
1382                fn test_complex_f64_pow_infinity_base_nan_exponent() {
1383                    let base = Complex::new(f64::INFINITY, 0.0);
1384                    let exponent = f64::NAN;
1385                    let err = base.try_pow(&exponent).unwrap_err();
1386                    assert!(matches!(
1387                        err,
1388                        PowComplexBaseRealExponentErrors::Input {
1389                            source: PowComplexBaseRealExponentInputErrors::InvalidBaseAndExponent {
1390                                error_base: ErrorsValidationRawComplex::InvalidRealPart {
1391                                    source: ErrorsValidationRawReal::IsPosInfinity { .. }
1392                                },
1393                                error_exponent: ErrorsValidationRawReal::IsNaN { .. },
1394                                ..
1395                            }
1396                        }
1397                    ));
1398                }
1399
1400                #[test]
1401                fn test_complex_f64_pow_ok_base_one_exponent() {
1402                    let base = Complex::new(2.0, 3.0);
1403                    let exponent = 1.0;
1404                    let expected_result = Complex::new(2.0, 3.0);
1405                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1406                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1407                }
1408
1409                #[test]
1410                fn test_complex_f64_pow_zero_base_ok_exponent() {
1411                    let base = Complex::new(0.0, 0.0);
1412                    let exponent = 3.0;
1413                    let expected_result = Complex::new(0.0, 0.0);
1414                    assert_eq!(Pow::pow(base, &exponent), expected_result);
1415                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1416                }
1417
1418                #[test]
1419                fn test_complex_f64_pow_nan_base_ok_exponent() {
1420                    let base = Complex::new(f64::NAN, 0.0);
1421                    let exponent = 3.0;
1422                    let result = base.try_pow(&exponent);
1423                    assert!(result.is_err());
1424
1425                    let base = Complex::new(0.0, f64::NAN);
1426                    let result = base.try_pow(&exponent);
1427                    assert!(result.is_err());
1428                }
1429
1430                #[test]
1431                fn test_complex_f64_pow_infinity_base_ok_exponent() {
1432                    let base = Complex::new(f64::INFINITY, 0.0);
1433                    let exponent = 3.0;
1434                    let result = base.try_pow(&exponent);
1435                    assert!(result.is_err());
1436
1437                    let base = Complex::new(0.0, f64::INFINITY);
1438                    let result = base.try_pow(&exponent);
1439                    assert!(result.is_err());
1440                }
1441
1442                #[test]
1443                fn test_complex_f64_pow_ok_base_negative_exponent() {
1444                    let base = Complex::new(2.0, 3.0);
1445                    let exponent = -2.0;
1446                    let expected_result = Complex::new(-0.029585798816568046, -0.07100591715976332);
1447                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1448                }
1449
1450                #[test]
1451                fn test_complex_f64_pow_negative_base_positive_exponent() {
1452                    let base = Complex::new(-2.0, -3.0);
1453                    let exponent = 3.0;
1454                    let expected_result = Complex::new(46.0, -8.99999999999999);
1455                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1456                }
1457
1458                #[test]
1459                fn test_complex_f64_pow_negative_base_negative_exponent() {
1460                    let base = Complex::new(-2.0, -3.0);
1461                    let exponent = -3.0;
1462                    let expected_result = Complex::new(0.02093764223941739, 0.004096495220755572);
1463                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1464                }
1465            }
1466        }
1467
1468        #[cfg(feature = "rug")]
1469        mod rug53 {
1470            use super::*;
1471            use rug::{Complex, Float};
1472
1473            mod real_base {
1474                use super::*;
1475
1476                #[test]
1477                fn test_realrug_pow_valid() {
1478                    let base =
1479                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1480                    let exponent =
1481                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1482                    let expected_result =
1483                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 8.0)).unwrap();
1484                    assert_eq!(base.clone().pow(&exponent), expected_result);
1485                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1486                }
1487
1488                #[test]
1489                fn test_realrug_pow_zero_exponent() {
1490                    let base =
1491                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1492                    let exponent =
1493                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1494                    let expected_result =
1495                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1496                    assert_eq!(base.clone().pow(&exponent), expected_result);
1497                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1498                }
1499
1500                #[test]
1501                fn test_realrug_pow_one_exponent() {
1502                    let base =
1503                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1504                    let exponent =
1505                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1506                    let expected_result =
1507                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1508                    assert_eq!(base.clone().pow(&exponent), expected_result);
1509                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1510                }
1511
1512                #[test]
1513                fn test_realrug_pow_zero_base() {
1514                    let base =
1515                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1516                    let exponent =
1517                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1518                    let expected_result =
1519                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1520                    assert_eq!(base.clone().pow(&exponent), expected_result);
1521                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1522                }
1523
1524                #[test]
1525                fn test_realrug_pow_negative_exponent() {
1526                    let base =
1527                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1528                    let exponent =
1529                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1530                    let expected_result =
1531                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.25)).unwrap();
1532                    assert_eq!(base.clone().pow(&exponent), expected_result);
1533                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1534                }
1535
1536                #[test]
1537                fn test_realrug_pow_negative_base_positive_exponent() {
1538                    let base =
1539                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1540                    let exponent =
1541                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1542                    let result = base.try_pow(&exponent);
1543                    assert!(matches!(
1544                        result,
1545                        Err(PowRealBaseRealExponentErrors::Input { .. })
1546                    ));
1547                }
1548
1549                #[test]
1550                fn test_realrug_pow_negative_base_negative_exponent() {
1551                    let base =
1552                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -2.0)).unwrap();
1553                    let exponent =
1554                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -3.0)).unwrap();
1555                    let result = base.try_pow(&exponent);
1556                    assert!(matches!(
1557                        result,
1558                        Err(PowRealBaseRealExponentErrors::Input { .. })
1559                    ));
1560                }
1561            }
1562
1563            mod complex_base {
1564                use super::*;
1565
1566                #[test]
1567                fn test_complex_rug_float_pow_valid() {
1568                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1569                        53,
1570                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1571                    ))
1572                    .unwrap();
1573                    let exponent =
1574                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 2.0)).unwrap();
1575                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1576                        53,
1577                        (Float::with_val(53, -5.0), Float::with_val(53, 12.0)),
1578                    ))
1579                    .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_complex_rug_float_pow_zero_exponent() {
1586                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1587                        53,
1588                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1589                    ))
1590                    .unwrap();
1591                    let exponent =
1592                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 0.0)).unwrap();
1593                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1594                        53,
1595                        (Float::with_val(53, 1.0), Float::with_val(53, 0.0)),
1596                    ))
1597                    .unwrap();
1598                    assert_eq!(base.clone().pow(&exponent), expected_result);
1599                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1600                }
1601
1602                #[test]
1603                fn test_complex_rug_float_pow_one_exponent() {
1604                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1605                        53,
1606                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1607                    ))
1608                    .unwrap();
1609                    let exponent =
1610                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 1.0)).unwrap();
1611                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1612                        53,
1613                        (Float::with_val(53, 2.0), Float::with_val(53, 3.0)),
1614                    ))
1615                    .unwrap();
1616                    assert_eq!(base.clone().pow(&exponent), expected_result);
1617                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1618                }
1619
1620                #[test]
1621                fn test_complex_rug_float_pow_zero_base() {
1622                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1623                        53,
1624                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1625                    ))
1626                    .unwrap();
1627                    let exponent =
1628                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1629                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1630                        53,
1631                        (Float::with_val(53, 0.0), Float::with_val(53, 0.0)),
1632                    ))
1633                    .unwrap();
1634                    assert_eq!(base.clone().pow(&exponent), expected_result);
1635                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1636                }
1637
1638                #[test]
1639                fn test_complex_rug_float_pow_negative_exponent() {
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                        (
1650                            Float::with_val(53, -0.029585798816568046),
1651                            Float::with_val(53, -0.07100591715976332),
1652                        ),
1653                    ))
1654                    .unwrap();
1655                    assert_eq!(base.clone().pow(&exponent), expected_result);
1656                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1657                }
1658
1659                #[test]
1660                fn test_complex_rug_float_pow_negative_base_positive_exponent() {
1661                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1662                        53,
1663                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1664                    ))
1665                    .unwrap();
1666                    let exponent =
1667                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, 3.0)).unwrap();
1668                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1669                        53,
1670                        (Float::with_val(53, 46.0), Float::with_val(53, -9.0)),
1671                    ))
1672                    .unwrap();
1673                    assert_eq!(base.clone().pow(&exponent), expected_result);
1674                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1675                }
1676
1677                #[test]
1678                fn test_complex_rug_float_pow_negative_base_negative_exponent() {
1679                    let base = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1680                        53,
1681                        (Float::with_val(53, -2.0), Float::with_val(53, -3.0)),
1682                    ))
1683                    .unwrap();
1684                    let exponent =
1685                        RealRugStrictFinite::<53>::try_new(Float::with_val(53, -3.0)).unwrap();
1686                    let expected_result = ComplexRugStrictFinite::<53>::try_new(Complex::with_val(
1687                        53,
1688                        (
1689                            Float::with_val(53, 2.0937642239417388e-2),
1690                            Float::with_val(53, 4.096495220755576e-3),
1691                        ),
1692                    ))
1693                    .unwrap();
1694                    assert_eq!(base.clone().pow(&exponent), expected_result);
1695                    assert_eq!(base.try_pow(&exponent).unwrap(), expected_result);
1696                }
1697            }
1698        }
1699    }
1700}
1701//------------------------------------------------------------------------------------------------