Skip to main content

num_valid/functions/
pow.rs

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