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