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