#![deny(rustdoc::broken_intra_doc_links)]
use crate::{
errors::{ComplexValueErrors, ComplexValueValidator, RealValueErrors, RealValueValidator},
Native64, NumKernel, TryNew, Zero,
};
use num::Complex;
use std::{backtrace::Backtrace, fmt};
use thiserror::Error;
#[cfg(feature = "rug")]
use crate::{ComplexRug, RealRug, Rug};
#[derive(Debug, Error)]
pub enum SqrtRealInputErrors<T: NumKernel + 'static> {
#[error("the input value ({value:?}) is negative!")]
NegativeValue {
value: T::RawRealType,
backtrace: Backtrace,
},
#[error("the input value is invalid!")]
ValidationError {
#[from]
source: RealValueErrors<T::RawRealType>,
},
}
#[derive(Debug, Error)]
pub enum SqrtComplexInputErrors<T: NumKernel + 'static> {
#[error("the input value is invalid!")]
ValidationError {
#[from]
source: ComplexValueErrors<T::RawRealType, T::RawComplexType>,
},
}
#[derive(Debug, Error)]
pub enum SqrtRealErrors<T: NumKernel + 'static> {
#[error("the input value is invalid!")]
Input {
#[from]
source: SqrtRealInputErrors<T>,
},
#[error("the output value is invalid!")]
Output {
#[from]
source: RealValueErrors<T::RawRealType>,
},
}
#[derive(Debug, Error)]
pub enum SqrtComplexErrors<T: NumKernel + 'static> {
#[error("the input value is invalid!")]
Input {
#[from]
source: SqrtComplexInputErrors<T>,
},
#[error("the output value is invalid!")]
Output {
#[from]
source: ComplexValueErrors<T::RawRealType, T::RawComplexType>,
},
}
fn sqrt_real_validate_input<T: NumKernel>(
value: T::RawRealType,
) -> Result<T::RawRealType, SqrtRealInputErrors<T>> {
let v = value.validate();
match v {
Ok(value) => {
if value < 0. {
Err(SqrtRealInputErrors::NegativeValue {
value,
backtrace: Backtrace::force_capture(),
})
} else {
Ok(value)
}
}
Err(e) => Err(SqrtRealInputErrors::ValidationError { source: e }),
}
}
fn sqrt_complex_validate_input<T: NumKernel>(
value: T::RawComplexType,
) -> Result<T::RawComplexType, SqrtComplexInputErrors<T>> {
Ok(value.validate()?)
}
pub trait Sqrt: TryNew {
type Error: fmt::Debug;
fn try_sqrt(self) -> Result<Self, <Self as Sqrt>::Error>;
fn sqrt(self) -> Self;
}
#[duplicate::duplicate_item(
T E input_validation trait_comment;
[f64] [SqrtRealErrors::<Native64>] [sqrt_real_validate_input] ["Implementation of the [`Sqrt`] trait for [`f64`]."];
[Complex::<f64>] [SqrtComplexErrors::<Native64>] [sqrt_complex_validate_input] ["Implementation of the [`Sqrt`] trait for [`Complex`]."];
)]
#[doc = trait_comment]
impl Sqrt for T {
type Error = E;
#[inline(always)]
fn try_sqrt(self) -> Result<Self, <Self as Sqrt>::Error> {
let value = input_validation(self)?;
match T::try_new(value.sqrt()) {
Ok(sqrt) => Ok(sqrt),
Err(e) => Err(E::Output { source: e }),
}
}
#[inline(always)]
fn sqrt(self) -> Self {
if cfg!(debug_assertions) {
self.try_sqrt().unwrap()
} else {
self.sqrt()
}
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
T E input_validation trait_comment;
[RealRug::<PRECISION>] [SqrtRealErrors::<Rug<PRECISION>>] [sqrt_real_validate_input] ["Implementation of the [`Sqrt`] trait for [`RealRug`]."];
[ComplexRug::<PRECISION>] [SqrtComplexErrors::<Rug<PRECISION>>] [sqrt_complex_validate_input] ["Implementation of the [`Sqrt`] trait for [`ComplexRug`]."];
)]
#[doc = trait_comment]
impl<const PRECISION: u32> Sqrt for T {
type Error = E;
#[inline(always)]
fn try_sqrt(self) -> Result<Self, <Self as Sqrt>::Error> {
let value = input_validation(self.0)?;
match T::try_new(value.sqrt()) {
Ok(sqrt) => Ok(sqrt),
Err(e) => Err(E::Output { source: e }),
}
}
#[inline(always)]
fn sqrt(self) -> Self {
if cfg!(debug_assertions) {
self.try_sqrt().unwrap()
} else {
Self(self.0.sqrt())
}
}
}
#[derive(Debug, Error)]
pub enum RecipRealInputErrors<T: NumKernel + 'static> {
#[error("division by zero!")]
DivisionByZero {
backtrace: Backtrace,
},
#[error("the input value is invalid!")]
ValidationError {
#[from]
source: RealValueErrors<T::RawRealType>,
},
}
#[derive(Debug, Error)]
pub enum RecipComplexInputErrors<T: NumKernel + 'static> {
#[error("division by zero!")]
DivisionByZero {
backtrace: Backtrace,
},
#[error("the input value is invalid!")]
ValidationError {
#[from]
source: ComplexValueErrors<T::RawRealType, T::RawComplexType>,
},
}
#[derive(Debug, Error)]
pub enum RecipRealErrors<T: NumKernel + 'static> {
#[error("the input value is invalid!")]
Input {
#[from]
source: RecipRealInputErrors<T>,
},
#[error("the output value is invalid!")]
Output {
#[from]
source: RealValueErrors<T::RawRealType>,
},
}
#[derive(Debug, Error)]
pub enum RecipComplexErrors<T: NumKernel + 'static> {
#[error("the input value is invalid!")]
Input {
#[from]
source: RecipComplexInputErrors<T>,
},
#[error("the output value is invalid!")]
Output {
#[from]
source: ComplexValueErrors<T::RawRealType, T::RawComplexType>,
},
}
pub trait Reciprocal: TryNew {
type Error: fmt::Debug;
fn try_reciprocal(self) -> Result<Self, <Self as Reciprocal>::Error>;
fn reciprocal(self) -> Self;
}
#[duplicate::duplicate_item(
T implementation E InputError trait_comment;
[f64] [recip()] [RecipRealErrors::<Native64>] [RecipRealInputErrors] ["Implementation of the [`Reciprocal`] trait for [`f64`]."];
[Complex::<f64>] [inv()] [RecipComplexErrors::<Native64>] [RecipComplexInputErrors] ["Implementation of the [`Reciprocal`] trait for [`Complex`]."];
)]
impl Reciprocal for T {
type Error = E;
#[inline(always)]
fn try_reciprocal(self) -> Result<Self, <Self as Reciprocal>::Error> {
match self.validate() {
Ok(value) => {
if value.is_zero() {
Err(E::Input {
source: InputError::DivisionByZero {
backtrace: Backtrace::force_capture(),
},
})
} else {
match Self::try_new(value.implementation) {
Ok(recip) => Ok(recip),
Err(e) => Err(E::Output { source: e }),
}
}
}
Err(e) => Err(E::Input {
source: InputError::ValidationError { source: e },
}),
}
}
#[inline(always)]
fn reciprocal(self) -> Self {
if cfg!(debug_assertions) {
self.try_reciprocal().unwrap()
} else {
self.implementation
}
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
T E InputError trait_comment;
[RealRug::<PRECISION>] [RecipRealErrors::<Rug<PRECISION>>] [RecipRealInputErrors] ["Implementation of the [`Reciprocal`] trait for [`f64`]."];
[ComplexRug::<PRECISION>] [RecipComplexErrors::<Rug<PRECISION>>] [RecipComplexInputErrors] ["Implementation of the [`Reciprocal`] trait for [`Complex`]."];
)]
impl<const PRECISION: u32> Reciprocal for T {
type Error = E;
#[inline(always)]
fn try_reciprocal(self) -> Result<Self, <Self as Reciprocal>::Error> {
match self.0.validate() {
Ok(value) => {
if value.is_zero() {
Err(E::Input {
source: InputError::DivisionByZero {
backtrace: Backtrace::force_capture(),
},
})
} else {
match Self::try_new(value.recip()) {
Ok(recip) => Ok(recip),
Err(e) => Err(E::Output { source: e }),
}
}
}
Err(e) => Err(E::Input {
source: InputError::ValidationError { source: e },
}),
}
}
#[inline(always)]
fn reciprocal(self) -> Self {
if cfg!(debug_assertions) {
self.try_reciprocal().unwrap()
} else {
Self(self.0.recip())
}
}
}
pub trait Abs {
type Output;
fn abs(self) -> Self::Output;
}
#[duplicate::duplicate_item(
T implementation trait_comment;
[f64] [self.abs()] ["Implementation of the [`Abs`] trait for `f64`."];
[Complex<f64>] [self.norm()] ["Implementation of the [`Abs`] trait for `Complex<f64>`."];
)]
#[doc = trait_comment]
impl Abs for T {
type Output = f64;
#[inline(always)]
fn abs(self) -> Self::Output {
implementation
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
T implementation trait_comment;
[RealRug<PRECISION>] [RealRug(self.0.abs())] ["Implementation of the [`Abs`] trait for [`RealRug`]."];
[ComplexRug<PRECISION>] [RealRug(self.0.abs().real().clone())] ["Implementation of the [`Abs`] trait for [`ComplexRug`]."];
)]
#[doc = trait_comment]
impl<const PRECISION: u32> Abs for T {
type Output = RealRug<PRECISION>;
#[inline(always)]
fn abs(self) -> Self::Output {
implementation
}
}