#![deny(rustdoc::broken_intra_doc_links)]
#![feature(error_generic_member_access)]
pub mod errors;
pub mod functions;
pub mod neumaier_compensated_sum;
use crate::{
errors::{
ComplexValueErrors, ComplexValueValidator, RealValueErrors, RealValueValidator,
TryFromf64Errors,
},
functions::{Abs, Reciprocal, Sqrt},
};
use num::{Complex, One, Zero};
use num_traits::ops::mul_add::MulAddAssign;
use serde::{de::DeserializeOwned, Serialize};
use std::{
backtrace::Backtrace,
cmp::Ordering,
fmt::{self},
num::FpCategory,
};
use thiserror::Error;
#[cfg(feature = "rug")]
use derive_more::{
Add, AddAssign, AsRef, Display, Div, DivAssign, LowerExp, Mul, MulAssign, Neg, Sub, SubAssign,
};
#[cfg(not(feature = "rug"))]
use std::{
fmt::LowerExp,
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
#[cfg(feature = "rug")]
use duplicate::duplicate_item;
#[cfg(feature = "rug")]
use rug::ops::{CompleteRound, Pow as RugPow};
#[cfg(feature = "rug")]
use serde::Deserialize;
pub trait IntoInner {
type Target;
fn into_inner(self) -> Self::Target;
}
#[derive(Debug, Error)]
pub enum RecipErrors<ValueType: Sized> {
#[error("the input value is NaN!")]
NanInput { backtrace: Backtrace },
#[error("the output value is NaN!")]
NanOutput { backtrace: Backtrace },
#[error("the input value is zero!")]
DivisionByZero { backtrace: Backtrace },
#[error("the output value ({value:?}) is subnormal!")]
Underflow {
value: ValueType,
backtrace: Backtrace,
},
#[error("The output value cannot be represented becaus an overflow has occourred")]
Overflow { backtrace: Backtrace },
}
pub trait NegAssign {
fn neg_assign(&mut self);
}
#[duplicate::duplicate_item(
T;
[f64];
[Complex<f64>];
)]
impl NegAssign for T {
fn neg_assign(&mut self) {
*self = -*self;
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
T;
[rug::Float];
[rug::Complex];
)]
impl NegAssign for T {
fn neg_assign(&mut self) {
<T as rug::ops::NegAssign>::neg_assign(self);
}
}
pub trait Pow<ExponentType> {
fn pow_(self, exponent: ExponentType) -> Self;
}
#[duplicate::duplicate_item(
T;
[f64];
[Complex<f64>];
)]
impl Pow<f64> for T {
fn pow_(self, exponent: f64) -> Self {
self.powf(exponent)
}
}
#[duplicate::duplicate_item(
T exponent_type func_name;
[f64] [i32] [powi];
[Complex<f64>] [i32] [powi];
[Complex<f64>] [u32] [powu];
)]
impl Pow<exponent_type> for T {
fn pow_(self, exponent: exponent_type) -> Self {
self.func_name(exponent)
}
}
#[duplicate::duplicate_item(
T exponent_type func_name;
[f64] [i8] [powi];
[f64] [u8] [powi];
[f64] [i16] [powi];
[f64] [u16] [powi];
[Complex<f64>] [i8] [powi];
[Complex<f64>] [u8] [powu];
[Complex<f64>] [i16] [powi];
[Complex<f64>] [u16] [powu];
)]
impl Pow<exponent_type> for T {
fn pow_(self, exponent: exponent_type) -> Self {
self.func_name(exponent.into())
}
}
#[duplicate::duplicate_item(
T exponent_type func_name;
[f64] [u32] [powi];
[f64] [i64] [powi];
[f64] [u64] [powi];
[f64] [i128] [powi];
[f64] [u128] [powi];
[f64] [usize] [powi];
[Complex<f64>] [i64] [powi];
[Complex<f64>] [i128] [powi];
[Complex<f64>] [u64] [powu];
[Complex<f64>] [u128] [powu];
[Complex<f64>] [usize] [powu];
)]
impl Pow<exponent_type> for T {
fn pow_(self, exponent: exponent_type) -> Self {
self.func_name(exponent.try_into().unwrap())
}
}
pub trait PowTrait<T: NumKernel>:
Pow<T::RealType>
+ Pow<i8>
+ Pow<u8>
+ Pow<i16>
+ Pow<u16>
+ Pow<i32>
+ Pow<u32>
+ Pow<i64>
+ Pow<u64>
+ Pow<i128>
+ Pow<u128>
+ Pow<usize>
{
}
impl PowTrait<Native64> for f64 {}
impl PowTrait<Native64> for Complex<f64> {}
pub trait Arithmetic: Sized
where
Self: Add<Self, Output = Self>
+ for<'a> Add<&'a Self, Output = Self>
+ AddAssign
+ for<'a> AddAssign<&'a Self>
+ Sub<Output = Self>
+ for<'a> Sub<&'a Self, Output = Self>
+ SubAssign
+ for<'a> SubAssign<&'a Self>
+ Mul<Output = Self>
+ for<'a> Mul<&'a Self, Output = Self>
+ MulAssign
+ for<'a> MulAssign<&'a Self>
+ Div<Output = Self>
+ for<'a> Div<&'a Self, Output = Self>
+ DivAssign
+ for<'a> DivAssign<&'a Self>
+ Neg
+ NegAssign
+ LowerExp,
{
}
pub trait MulComplexLeft<T: NumKernel>:
Mul<T::RealType, Output = T::ComplexType>
+ for<'a> Mul<&'a T::RealType, Output = T::ComplexType>
+ MulAssign<T::RealType>
+ for<'a> MulAssign<&'a T::RealType>
{
}
pub trait MulComplexRight<T: NumKernel>: Mul<T::ComplexType, Output = T::ComplexType> {}
impl Arithmetic for f64 {}
impl Arithmetic for Complex<f64> {}
impl MulComplexRight<Native64> for f64 {}
impl MulComplexLeft<Native64> for Complex<f64> {}
#[cfg(feature = "rug")]
impl Arithmetic for rug::Float {}
#[cfg(feature = "rug")]
impl Arithmetic for rug::Complex {}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Native64;
#[cfg(feature = "rug")]
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Rug<const PRECISION: u32>;
pub trait NumKernel: Clone + fmt::Debug + PartialEq + Sync {
type RawRealType: Sized + fmt::Debug + RealValueValidator + PartialOrd<f64>;
type RawComplexType: Sized + fmt::Debug + ComplexValueValidator<RealType = Self::RawRealType>;
type RealType: FunctionsRealType<Self> + Serialize + DeserializeOwned;
type ComplexType: FunctionsComplexType<Self> + Serialize + DeserializeOwned;
}
impl NumKernel for Native64 {
type RawRealType = f64;
type RawComplexType = Complex<f64>;
type RealType = f64;
type ComplexType = Complex<f64>;
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> NumKernel for Rug<PRECISION> {
type RawRealType = rug::Float;
type RawComplexType = rug::Complex;
type RealType = RealRug<PRECISION>;
type ComplexType = ComplexRug<PRECISION>;
}
#[duplicate::duplicate_item(
trait_name func_name trait_comment func_comment;
[ACos] [acos_] ["This trait provides the interface for the *inverse cosine* function."] ["Computes the *inverse cosine* of `self`, rounding to the nearest."];
[ASin] [asin_] ["This trait provides the interface for the *inverse sine* function."] ["Computes the *inverse sine* of `self`, rounding to the nearest."];
[ATan] [atan_] ["This trait provides the interface for the *inverse tangent* function."] ["Computes the *inverse tangent* of `self`, rounding to the nearest."];
[Cos] [cos_] ["This trait provides the interface for the *cosine* function."] ["Computes the *cosine* of `self`, rounding to the nearest."];
[Sin] [sin_] ["This trait provides the interface for the *sine* function."] ["Computes the *sine* of `self`, rounding to the nearest."];
[Tan] [tan_] ["This trait provides the interface for the *tangent* function."] ["Computes the *tangent* of `self`, rounding to the nearest."];
[ACosH] [acosh_] ["This trait provides the interface for the *inverse hyperbolic cosine* function."] ["Computes the *inverse hyperbolic cosine* of `self`, rounding to the nearest."];
[ASinH] [asinh_] ["This trait provides the interface for the *inverse hyperbolic* function."] ["Computes the *inverse hyperbolic sine* of `self`, rounding to the nearest."];
[ATanH] [atanh_] ["This trait provides the interface for the *inverse hyperbolic tangent* function."] ["Computes the *inverse hyperbolic tangent* of `self`, rounding to the nearest."];
[CosH] [cosh_] ["This trait provides the interface for the *hyperbolic cosine* function."] ["Computes the *hyperbolic cosine* of `self`, rounding to the nearest."];
[SinH] [sinh_] ["This trait provides the interface for the *hyperbolic sine* function."] ["Computes the *hyperbolic sine* of `self`, rounding to the nearest."];
[TanH] [tanh_] ["This trait provides the interface for the *hyperbolic tangent* function."] ["Computes the *tangent* of `self`, rounding to the nearest."];
[Exp] [exp_] ["This trait provides the interface for the *exponential* function."] ["Computes `e^(self)`, rounding to the nearest."];
[Ln] [ln_] ["This trait provides the interface for the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) function."] ["Computes the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) of `self`, rounding to the nearest."];
[Log10] [log10_] ["This trait provides the interface for the [*common logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) function."] ["Computes the [*common logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of `self`, rounding to the nearest."];
[Log2] [log2_] ["This trait provides the interface for the *base 2 logarithm* function."] ["Computes the *base 2 logarithm* of `self`, rounding to the nearest."];
)]
#[doc = trait_comment]
pub trait trait_name {
#[doc = func_comment]
fn func_name(self) -> Self;
}
#[duplicate::duplicate_item(
trait_name func_name implementation T func_comment;
duplicate!{
[
T_nested; [f64]; [Complex::<f64>]
]
[ACos] [acos_] [acos(self)] [T_nested] ["Computes the *inverse cosine* of `self`, rounding to the nearest."];
[ASin] [asin_] [asin(self)] [T_nested] ["Computes the *inverse sine* of `self`, rounding to the nearest."];
[ATan] [atan_] [atan(self)] [T_nested] ["Computes the *inverse tangent* of `self`, rounding to the nearest."];
[Cos] [cos_] [cos(self)] [T_nested] ["Computes the *cosine* of `self`, rounding to the nearest."];
[Sin] [sin_] [sin(self)] [T_nested] ["Computes the *sine* of `self`, rounding to the nearest."];
[Tan] [tan_] [tan(self)] [T_nested] ["Computes the *tangent* of `self`, rounding to the nearest."];
[ACosH] [acosh_] [acosh(self)] [T_nested] ["Computes the *inverse hyperbolic cosine* of `self`, rounding to the nearest."];
[ASinH] [asinh_] [asinh(self)] [T_nested] ["Computes the *inverse hyperbolic sine* of `self`, rounding to the nearest."];
[ATanH] [atanh_] [atanh(self)] [T_nested] ["Computes the *inverse hyperbolic tangent* of `self`, rounding to the nearest."];
[CosH] [cosh_] [cosh(self)] [T_nested] ["Computes the *hyperbolic cosine* of `self`, rounding to the nearest."];
[SinH] [sinh_] [sinh(self)] [T_nested] ["Computes the *hyperbolic sine* of `self`, rounding to the nearest."];
[TanH] [tanh_] [tanh(self)] [T_nested] ["Computes the *hyperbolic tangent* of `self`, rounding to the nearest."];
[Exp] [exp_] [exp(self)] [T_nested] ["Computes `e^(self)`, rounding to the nearest."];
[Ln] [ln_] [ln(self)] [T_nested] ["Computes the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) of `self`, rounding to the nearest."];
[Log10] [log10_] [log10(self)] [T_nested] ["Computes the [*common logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of `self`, rounding to the nearest."];
[Log2] [log2_] [log2(self)] [T_nested] ["Computes the *base 2 logarithm* of `self`, rounding to the nearest."];
}
)]
impl trait_name for T {
#[doc = func_comment]
#[inline(always)]
fn func_name(self) -> Self {
T::implementation
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
trait_name func_name implementation T func_comment;
duplicate!{
[
T_nested; [RealRug<PRECISION>]; [ComplexRug<PRECISION>]
]
[ACos] [acos_] [self.0.acos()] [T_nested] ["Computes the *inverse cosine* of `self`, rounding to the nearest."];
[ASin] [asin_] [self.0.asin()] [T_nested] ["Computes the *inverse sine* of `self`, rounding to the nearest."];
[ATan] [atan_] [self.0.atan()] [T_nested] ["Computes the *inverse tangent* of `self`, rounding to the nearest."];
[Cos] [cos_] [self.0.cos()] [T_nested] ["Computes the *cosine* of `self`, rounding to the nearest."];
[Sin] [sin_] [self.0.sin()] [T_nested] ["Computes the *sine* of `self`, rounding to the nearest."];
[Tan] [tan_] [self.0.tan()] [T_nested] ["Computes the *tangent* of `self`, rounding to the nearest."];
[ACosH] [acosh_] [self.0.acosh()] [T_nested] ["Computes the *inverse hyperbolic cosine* of `self`, rounding to the nearest."];
[ASinH] [asinh_] [self.0.asinh()] [T_nested] ["Computes the *inverse hyperbolic sine* of `self`, rounding to the nearest."];
[ATanH] [atanh_] [self.0.atanh()] [T_nested] ["Computes the *inverse hyperbolic tangent* of `self`, rounding to the nearest."];
[CosH] [cosh_] [self.0.cosh()] [T_nested] ["Computes the *hyperbolic cosine* of `self`, rounding to the nearest."];
[SinH] [sinh_] [self.0.sinh()] [T_nested] ["Computes the *hyperbolic sine* of `self`, rounding to the nearest."];
[TanH] [tanh_] [self.0.tanh()] [T_nested] ["Computes the *hyperbolic tangent* of `self`, rounding to the nearest."];
[Exp] [exp_] [self.0.exp()] [T_nested] ["Computes `e^(self)`, rounding to the nearest."];
[Ln] [ln_] [self.0.ln()] [T_nested] ["Computes the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) of `self`, rounding to the nearest."];
[Log10] [log10_] [self.0.log10()] [T_nested] ["Computes the [*common logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of `self`, rounding to the nearest."];
}
)]
impl<const PRECISION: u32> trait_name for T {
#[doc = func_comment]
#[inline(always)]
fn func_name(self) -> Self {
Self(implementation)
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Log2 for RealRug<PRECISION> {
#[inline(always)]
fn log2_(self) -> Self {
Self(self.0.log2())
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Log2 for ComplexRug<PRECISION> {
#[inline(always)]
fn log2_(self) -> Self {
Self(rug::Complex::with_val(
PRECISION,
self.0.log10() / rug::Float::with_val(PRECISION, 2.).log10(),
))
}
}
pub trait TrigonometricFunctions: ACos + ASin + ATan + Sin + Cos + Tan {}
impl TrigonometricFunctions for f64 {}
impl TrigonometricFunctions for Complex<f64> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> TrigonometricFunctions for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> TrigonometricFunctions for ComplexRug<PRECISION> {}
pub trait HyperbolicFunctions: ACosH + ASinH + ATanH + SinH + CosH + TanH {}
impl HyperbolicFunctions for f64 {}
impl HyperbolicFunctions for Complex<f64> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> HyperbolicFunctions for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> HyperbolicFunctions for ComplexRug<PRECISION> {}
#[duplicate::duplicate_item(
trait_name func_name trait_comment func_comment;
[IsFinite] [is_finite_] ["This trait provides the interface for the function used to check if a number is finite (i.e. neither infinite or NaN)."] ["Returns `true` if `self` is neither infinite nor NaN."];
[IsInfinite] [is_infinite_] ["This trait provides the interface for the function used to check if a number is infinite."] ["Returns `true` if `self` is positive infinity or negative infinity."];
[IsNaN] [is_nan_] ["This trait provides the interface for the function used to check if a value is NaN."] ["Returns `true` if `self` is NaN."];
[IsNormal] [is_normal_] ["This trait provides the interface for the function used to check if a number is *normal* (i.e. neither zero, infinite, subnormal, or NaN)."] ["Returns `true` if `self` is *normal* (i.e. neither zero, infinite, subnormal, or NaN)."];
[IsSubnormal] [is_subnormal_] ["This trait provides the interface for the function used to check if a number is *sub-normal*."] ["Returns `true` if `self` is *sub-normal*."];
)]
#[doc = trait_comment]
pub trait trait_name {
#[doc = func_comment]
fn func_name(&self) -> bool;
}
#[duplicate::duplicate_item(
trait_name func_name implementation T func_comment;
duplicate!{
[
T_nested; [f64]; [Complex<f64>]
]
[IsFinite] [is_finite_] [self.is_finite()] [T_nested] ["Returns `true` if `self` is neither infinite nor NaN."];
[IsInfinite] [is_infinite_] [self.is_infinite()] [T_nested] ["Returns `true` if `self` is positive infinity or negative infinity, and `false` otherwise."];
[IsNaN] [is_nan_] [self.is_nan()] [T_nested] ["Returns `true` if `self` is NaN."];
[IsNormal] [is_normal_] [self.is_normal()] [T_nested] ["Returns `true` if `self` is *normal* (i.e. neither zero, infinite, subnormal, or NaN)."];
}
)]
impl trait_name for T {
#[doc = func_comment]
#[inline(always)]
fn func_name(&self) -> bool {
implementation
}
}
impl IsSubnormal for f64 {
#[inline(always)]
fn is_subnormal_(&self) -> bool {
self.classify() == FpCategory::Subnormal
}
}
impl IsSubnormal for Complex<f64> {
#[inline(always)]
fn is_subnormal_(&self) -> bool {
self.re.classify() == FpCategory::Subnormal || self.im.classify() == FpCategory::Subnormal
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
trait_name func_name implementation func_comment;
[IsFinite] [is_finite_] [self.0.is_finite()] ["Returns `true` if `self` is neither infinite nor NaN."];
[IsInfinite] [is_infinite_] [self.0.is_infinite()] ["Returns `true` if `self` is positive infinity or negative infinity, and `false` otherwise."];
[IsNaN] [is_nan_] [self.0.is_nan()] ["Returns `true` if `self` is NaN."];
[IsNormal] [is_normal_] [self.0.is_normal()] ["Returns `true` if `self` is *normal* (i.e. neither zero, infinite, subnormal, or NaN)."];
[IsSubnormal] [is_subnormal_] [self.0.classify() == FpCategory::Subnormal] ["Returns `true` if `self` is *sub-normal*."];
)]
impl<const PRECISION: u32> trait_name for RealRug<PRECISION> {
#[doc = func_comment]
#[inline(always)]
fn func_name(&self) -> bool {
implementation
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> IsFinite for ComplexRug<PRECISION> {
#[inline(always)]
fn is_finite_(&self) -> bool {
self.0.real().is_finite() && self.0.imag().is_finite()
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> IsInfinite for ComplexRug<PRECISION> {
#[inline(always)]
fn is_infinite_(&self) -> bool {
self.0.real().is_infinite() || self.0.imag().is_infinite()
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> IsNaN for ComplexRug<PRECISION> {
#[inline(always)]
fn is_nan_(&self) -> bool {
self.0.real().is_nan() || self.0.imag().is_nan()
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> IsNormal for ComplexRug<PRECISION> {
#[inline(always)]
fn is_normal_(&self) -> bool {
self.0.real().is_normal() && self.0.imag().is_normal()
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> IsSubnormal for ComplexRug<PRECISION> {
#[inline(always)]
fn is_subnormal_(&self) -> bool {
self.0.real().classify() == FpCategory::Subnormal
|| self.0.imag().classify() == FpCategory::Subnormal
}
}
pub trait FpChecks: IsFinite + IsInfinite + IsNaN + IsNormal + IsSubnormal {}
impl FpChecks for f64 {}
impl FpChecks for Complex<f64> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> FpChecks for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> FpChecks for ComplexRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Zero for RealRug<PRECISION> {
fn zero() -> Self {
Self(rug::Float::with_val(PRECISION, 0.))
}
fn is_zero(&self) -> bool {
self.0.is_zero()
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Zero for ComplexRug<PRECISION> {
fn zero() -> Self {
Self(rug::Complex::with_val(PRECISION, (0., 0.)))
}
fn is_zero(&self) -> bool {
self.0.is_zero()
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> One for RealRug<PRECISION> {
fn one() -> Self {
Self(rug::Float::with_val(PRECISION, 1.))
}
}
pub trait MulAdd {
fn mul_add(self, b: &Self, c: &Self) -> Self;
}
#[duplicate::duplicate_item(
T trait_comment;
[f64] ["Implementation of the [`MulAdd`] trait for `f64`."];
[Complex<f64>] ["Implementation of the [`MulAdd`] trait for `Complex<f64>`."];
)]
#[doc = trait_comment]
impl MulAdd for T {
#[inline(always)]
fn mul_add(self, b: &Self, c: &Self) -> Self {
<Self as num::traits::MulAdd>::mul_add(self, *b, *c)
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
T trait_comment;
[RealRug<PRECISION>] ["Implementation of the [`MulAdd`] trait for [`RealRug`]."];
[ComplexRug<PRECISION>] ["Implementation of the [`MulAdd`] trait for [`ComplexRug`]."];
)]
#[doc = trait_comment]
impl<const PRECISION: u32> MulAdd for T {
#[inline(always)]
fn mul_add(self, b: &Self, c: &Self) -> Self {
Self(self.0.mul_add(&b.0, &c.0))
}
}
pub trait FunctionsGeneralType<T: NumKernel>:
Clone
+ fmt::Debug
+ fmt::Display
+ Arithmetic
+ Sqrt
+ PowTrait<T>
+ TrigonometricFunctions
+ HyperbolicFunctions
+ Exp
+ Ln
+ Log10
+ Log2
+ Zero
+ Abs<Output = T::RealType>
+ FpChecks
+ Neg<Output = Self>
+ MulAdd
+ Reciprocal
+ Send
+ Sync
{
}
pub trait TryNew: Sized {
type ValueType;
type Error;
fn try_new(value: Self::ValueType) -> Result<Self, Self::Error>;
fn new(value: Self::ValueType) -> Self;
}
impl TryNew for f64 {
type ValueType = f64;
type Error = RealValueErrors<f64>;
#[inline(always)]
fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
value.validate()
}
#[inline(always)]
fn new(value: Self::ValueType) -> Self {
if cfg!(debug_assertions) {
Self::try_new(value).unwrap()
} else {
value
}
}
}
impl TryNew for Complex<f64> {
type ValueType = Complex<f64>;
type Error = ComplexValueErrors<f64, Complex<f64>>;
#[inline(always)]
fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
value.validate()
}
#[inline(always)]
fn new(value: Self::ValueType) -> Self {
if cfg!(debug_assertions) {
Self::try_new(value).unwrap()
} else {
value
}
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> TryNew for RealRug<PRECISION> {
type ValueType = rug::Float;
type Error = RealValueErrors<rug::Float>;
#[inline(always)]
fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
assert_eq!(value.prec(), PRECISION,
"The precision of the numerical kernel ({PRECISION}) and is different from the precision of the input value ({})!",value.prec());
let value = value.validate()?;
Ok(Self(value))
}
#[inline(always)]
fn new(value: Self::ValueType) -> Self {
if cfg!(debug_assertions) {
Self::try_new(value).unwrap()
} else {
Self(value)
}
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> TryNew for ComplexRug<PRECISION> {
type ValueType = rug::Complex;
type Error = ComplexValueErrors<rug::Float, rug::Complex>;
#[inline(always)]
fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
assert_eq!(value.prec(), (PRECISION, PRECISION),
"The precision of the numerical kernel ({PRECISION}) and is different from the precision of the input value ({:?})!",value.prec());
let value = value.validate()?;
Ok(Self(value))
}
#[inline(always)]
fn new(value: Self::ValueType) -> Self {
if cfg!(debug_assertions) {
Self::try_new(value).unwrap()
} else {
Self(value)
}
}
}
pub trait FunctionsRealType<T: NumKernel>:
FunctionsGeneralType<T>
+ PartialEq
+ PartialEq<f64>
+ PartialOrd
+ PartialOrd<f64>
+ MulComplexRight<T>
+ One
{
fn atan2_(self, other: &Self) -> Self;
fn ceil_(self) -> Self;
fn clamp_(self, min: &Self, max: &Self) -> Self;
fn classify_(&self) -> FpCategory;
fn copysign_(self, sign: &Self) -> Self;
fn epsilon_() -> Self;
fn exp_m1_(self) -> Self;
fn floor_(self) -> Self;
fn fract_(self) -> Self;
fn hypot_(self, other: &Self) -> Self;
fn infinity_() -> Self;
fn is_sign_negative_(&self) -> bool;
fn is_sign_positive_(&self) -> bool;
fn ln_1p_(self) -> Self;
fn neg_infinity_() -> Self;
fn max_(self, other: &Self) -> Self;
fn min_(self, other: &Self) -> Self;
fn mul_add_mul_mut_(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
fn mul_sub_mul_mut_(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
fn negative_one_() -> Self;
fn one_div_2_() -> Self;
fn pi_() -> Self {
Self::negative_one_().acos_()
}
fn pi_div_2_() -> Self {
Self::one().asin_()
}
fn round_(self) -> Self;
fn round_ties_even_(self) -> Self;
fn signum_(self) -> Self;
fn total_cmp_(&self, other: &Self) -> Ordering;
fn try_from_f64_(value: f64) -> Result<Self, TryFromf64Errors>;
fn trunc_(self) -> Self;
fn two_() -> Self;
}
pub trait FunctionsComplexType<T: NumKernel>:
FunctionsGeneralType<T> + PartialEq + MulComplexLeft<T>
{
fn arg_(self) -> T::RealType;
fn new_(real_part: T::RealType, imag_part: T::RealType) -> Self;
fn real_(&self) -> T::RealType;
fn imag_(&self) -> T::RealType;
fn set_real_(&mut self, real_part: T::RealType);
fn set_imag_(&mut self, imag_part: T::RealType);
fn add_real_(&mut self, c: &T::RealType);
fn add_imag_(&mut self, c: &T::RealType);
fn multiply_real_(&mut self, c: &T::RealType);
fn multiply_imag_(&mut self, c: &T::RealType);
fn conj_(self) -> Self;
fn try_from_f64_(real_part: f64, imag_part: f64) -> Result<Self, TryFromf64Errors>;
}
impl FunctionsGeneralType<Native64> for f64 {}
impl FunctionsGeneralType<Native64> for Complex<f64> {}
impl FunctionsRealType<Native64> for f64 {
#[inline(always)]
fn atan2_(self, other: &Self) -> Self {
self.atan2(*other)
}
#[inline(always)]
fn ceil_(self) -> Self {
self.ceil()
}
#[inline(always)]
fn clamp_(self, min: &Self, max: &Self) -> Self {
self.clamp(*min, *max)
}
#[inline(always)]
fn classify_(&self) -> FpCategory {
self.classify()
}
#[inline(always)]
fn copysign_(self, sign: &Self) -> Self {
self.copysign(*sign)
}
#[inline(always)]
fn epsilon_() -> Self {
f64::EPSILON
}
#[inline(always)]
fn exp_m1_(self) -> Self {
self.exp_m1()
}
#[inline(always)]
fn floor_(self) -> Self {
self.floor()
}
#[inline(always)]
fn fract_(self) -> Self {
self.fract()
}
#[inline(always)]
fn hypot_(self, other: &Self) -> Self {
self.hypot(*other)
}
#[inline(always)]
fn infinity_() -> Self {
f64::INFINITY
}
#[inline(always)]
fn is_sign_negative_(&self) -> bool {
self.is_sign_negative()
}
#[inline(always)]
fn is_sign_positive_(&self) -> bool {
self.is_sign_positive()
}
#[inline(always)]
fn ln_1p_(self) -> Self {
self.ln_1p()
}
#[inline(always)]
fn neg_infinity_() -> Self {
f64::NEG_INFINITY
}
#[inline(always)]
fn max_(self, other: &Self) -> Self {
self.max(*other)
}
#[inline(always)]
fn min_(self, other: &Self) -> Self {
self.min(*other)
}
#[inline(always)]
fn mul_add_mul_mut_(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
self.mul_add_assign(*mul, add_mul1 * add_mul2);
}
#[inline(always)]
fn mul_sub_mul_mut_(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
self.mul_add_assign(*mul, -sub_mul1 * sub_mul2);
}
#[inline(always)]
fn negative_one_() -> Self {
-1.
}
#[inline(always)]
fn one_div_2_() -> Self {
0.5
}
#[inline(always)]
fn round_(self) -> Self {
self.round()
}
#[inline(always)]
fn round_ties_even_(self) -> Self {
self.round_ties_even()
}
#[inline(always)]
fn signum_(self) -> Self {
self.signum()
}
#[inline(always)]
fn total_cmp_(&self, other: &Self) -> Ordering {
self.total_cmp(other)
}
#[inline(always)]
fn try_from_f64_(value: f64) -> Result<Self, TryFromf64Errors> {
match value.validate() {
Ok(value) => Ok(value),
Err(e) => Err(TryFromf64Errors::ValidationError { source: e }),
}
}
#[inline(always)]
fn trunc_(self) -> Self {
self.trunc()
}
#[inline(always)]
fn two_() -> Self {
2.
}
}
impl IntoInner for Complex<f64> {
type Target = (f64, f64);
#[inline(always)]
fn into_inner(self) -> Self::Target {
(self.re, self.im)
}
}
impl FunctionsComplexType<Native64> for Complex<f64> {
#[inline(always)]
fn arg_(self) -> f64 {
self.arg()
}
#[inline(always)]
fn new_(real_part: f64, imag_part: f64) -> Self {
debug_assert!(
real_part.is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
debug_assert!(
imag_part.is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
Complex::new(real_part, imag_part)
}
#[inline(always)]
fn real_(&self) -> f64 {
self.re
}
#[inline(always)]
fn imag_(&self) -> f64 {
self.im
}
#[inline(always)]
fn set_real_(&mut self, real_part: f64) {
debug_assert!(
real_part.is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
self.re = real_part;
}
#[inline(always)]
fn set_imag_(&mut self, imag_part: f64) {
debug_assert!(
imag_part.is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
self.im = imag_part;
}
#[inline(always)]
fn add_real_(&mut self, c: &f64) {
self.re += c;
debug_assert!(
self.re.is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn add_imag_(&mut self, c: &f64) {
self.im += c;
debug_assert!(
self.im.is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn multiply_real_(&mut self, c: &f64) {
self.re *= c;
debug_assert!(
self.re.is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn multiply_imag_(&mut self, c: &f64) {
self.im *= c;
debug_assert!(
self.im.is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn conj_(self) -> Self {
self.conj()
}
#[inline(always)]
fn try_from_f64_(real_part: f64, imag_part: f64) -> Result<Self, TryFromf64Errors> {
let real_part = <f64 as FunctionsRealType<Native64>>::try_from_f64_(real_part)?;
let imag_part = <f64 as FunctionsRealType<Native64>>::try_from_f64_(imag_part)?;
Ok(Complex::new(real_part, imag_part))
}
}
#[cfg(feature = "rug")]
#[derive(
Add,
AddAssign,
AsRef,
Clone,
Debug,
Deserialize,
Display,
Div,
DivAssign,
LowerExp,
Mul,
MulAssign,
Neg,
PartialEq,
PartialOrd,
Serialize,
Sub,
SubAssign,
)]
#[mul(forward)]
#[mul_assign(forward)]
#[div(forward)]
#[div_assign(forward)]
pub struct RealRug<const PRECISION: u32>(rug::Float);
#[cfg(feature = "rug")]
impl<const PRECISION: u32> RealRug<PRECISION> {
#[inline(always)]
pub fn new(value: rug::Float) -> Self {
debug_assert!(value.is_finite(), "Not a finite number!");
debug_assert_eq!(
value.prec(),
PRECISION,
"The input value must have a precision = {PRECISION}, but actually has precision = {}",
value.prec()
);
Self(value)
}
}
#[cfg(feature = "rug")]
#[derive(
Add,
AddAssign,
AsRef,
Clone,
Debug,
Deserialize,
Display,
Div,
DivAssign,
LowerExp,
Mul,
MulAssign,
Neg,
PartialEq,
Serialize,
Sub,
SubAssign,
)]
#[mul(forward)]
#[mul_assign(forward)]
#[div(forward)]
#[div_assign(forward)]
pub struct ComplexRug<const PRECISION: u32>(rug::Complex);
#[cfg(feature = "rug")]
impl<const PRECISION: u32> ComplexRug<PRECISION> {
#[inline(always)]
pub fn new(value: rug::Complex) -> Self {
debug_assert!(
value.real().is_finite() && value.imag().is_finite(),
"Not a finite number!"
);
debug_assert_eq!(
value.prec(),
(PRECISION, PRECISION),
"The input value must have a precision = {:?}, but actually has precision = {:?}",
(PRECISION, PRECISION),
value.prec()
);
Self(value)
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> IntoInner for ComplexRug<PRECISION> {
type Target = (RealRug<PRECISION>, RealRug<PRECISION>);
#[inline(always)]
fn into_inner(self) -> Self::Target {
(
RealRug::new(self.0.real().clone()),
RealRug::new(self.0.imag().clone()),
)
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
T;
[RealRug<PRECISION>];
[ComplexRug<PRECISION>];
)]
impl<const PRECISION: u32> NegAssign for T {
#[inline(always)]
fn neg_assign(&mut self) {
rug::ops::NegAssign::neg_assign(&mut self.0);
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
trait_name method T;
duplicate!{
[
rug_type;[RealRug];[ComplexRug]
]
[Add] [add] [rug_type];
[Sub] [sub] [rug_type];
[Mul] [mul] [rug_type];
}
)]
impl<'a, const PRECISION: u32> trait_name<&'a T<PRECISION>> for T<PRECISION> {
type Output = T<PRECISION>;
#[inline(always)]
fn method(self, rhs: &'a T<PRECISION>) -> Self::Output {
T(self.0.method(&rhs.0))
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
trait_name method T;
duplicate!{
[
rug_type;[RealRug];[ComplexRug]
]
[Add] [add] [rug_type];
[Sub] [sub] [rug_type];
[Mul] [mul] [rug_type];
}
)]
impl<'a, const PRECISION: u32> trait_name<T<PRECISION>> for &T<PRECISION> {
type Output = T<PRECISION>;
#[inline(always)]
fn method(self, rhs: T<PRECISION>) -> Self::Output {
let lhs = &self.0;
T(lhs.method(rhs.0))
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
T;
[RealRug];
[ComplexRug];
)]
impl<'a, const PRECISION: u32> Div<&'a T<PRECISION>> for T<PRECISION> {
type Output = T<PRECISION>;
#[inline(always)]
fn div(self, rhs: &'a T<PRECISION>) -> Self::Output {
debug_assert!(!rhs.0.is_zero(), "Division by zero!");
T(self.0.div(&rhs.0))
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
T;
[RealRug];
[ComplexRug];
)]
impl<'a, const PRECISION: u32> Div<T<PRECISION>> for &T<PRECISION> {
type Output = T<PRECISION>;
#[inline(always)]
fn div(self, rhs: T<PRECISION>) -> Self::Output {
debug_assert!(!rhs.0.is_zero(), "Division by zero!");
let lhs = &self.0;
T(lhs.div(rhs.0))
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
trait_name method T;
duplicate!{
[
rug_type;[RealRug];[ComplexRug]
]
[AddAssign] [add_assign] [rug_type];
[SubAssign] [sub_assign] [rug_type];
[MulAssign] [mul_assign] [rug_type];
}
)]
impl<'a, const PRECISION: u32> trait_name<&'a T<PRECISION>> for T<PRECISION> {
#[inline(always)]
fn method(&mut self, rhs: &'a T<PRECISION>) {
self.0.method(&rhs.0);
}
}
#[cfg(feature = "rug")]
impl<'a, const PRECISION: u32> Mul<RealRug<PRECISION>> for ComplexRug<PRECISION> {
type Output = ComplexRug<PRECISION>;
#[inline(always)]
fn mul(self, rhs: RealRug<PRECISION>) -> ComplexRug<PRECISION> {
Self(self.0.mul(rhs.0))
}
}
#[cfg(feature = "rug")]
impl<'a, const PRECISION: u32> Mul<&'a RealRug<PRECISION>> for ComplexRug<PRECISION> {
type Output = ComplexRug<PRECISION>;
#[inline(always)]
fn mul(self, rhs: &'a RealRug<PRECISION>) -> ComplexRug<PRECISION> {
Self(self.0.mul(&rhs.0))
}
}
#[cfg(feature = "rug")]
impl<'a, const PRECISION: u32> MulAssign<RealRug<PRECISION>> for ComplexRug<PRECISION> {
#[inline(always)]
fn mul_assign(&mut self, rhs: RealRug<PRECISION>) {
self.0.mul_assign(rhs.0);
}
}
#[cfg(feature = "rug")]
impl<'a, const PRECISION: u32> MulAssign<&'a RealRug<PRECISION>> for ComplexRug<PRECISION> {
#[inline(always)]
fn mul_assign(&mut self, rhs: &'a RealRug<PRECISION>) {
self.0.mul_assign(&rhs.0);
}
}
#[cfg(feature = "rug")]
#[duplicate_item(
T;
[RealRug<PRECISION>];
[ComplexRug<PRECISION>];
)]
impl<'a, const PRECISION: u32> DivAssign<&'a T> for T {
#[inline(always)]
fn div_assign(&mut self, rhs: &'a T) {
debug_assert!(!rhs.0.is_zero(), "Division by zero!");
self.0.div_assign(&rhs.0);
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Arithmetic for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Arithmetic for ComplexRug<PRECISION> {}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
exponent_type T;
duplicate!{
[
rug_type;[RealRug<PRECISION>];[ComplexRug<PRECISION>]
]
[i8] [rug_type];
[u8] [rug_type];
[i16] [rug_type];
[u16] [rug_type];
[i32] [rug_type];
[u32] [rug_type];
[i64] [rug_type];
[u64] [rug_type];
[i128] [rug_type];
[u128] [rug_type];
[usize] [rug_type];
}
)]
impl<const PRECISION: u32> Pow<exponent_type> for T {
#[inline(always)]
fn pow_(self, exponent: exponent_type) -> Self {
Self(self.0.pow(exponent))
}
}
#[cfg(feature = "rug")]
#[duplicate::duplicate_item(
T;
[RealRug<PRECISION>];
[ComplexRug<PRECISION>];
)]
impl<const PRECISION: u32> Pow<RealRug<PRECISION>> for T {
#[inline(always)]
fn pow_(self, exponent: RealRug<PRECISION>) -> Self {
Self(self.0.pow(exponent.0))
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> PowTrait<Rug<PRECISION>> for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> PowTrait<Rug<PRECISION>> for ComplexRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> PartialEq<f64> for RealRug<PRECISION> {
#[inline(always)]
fn eq(&self, other: &f64) -> bool {
self.0.eq(other)
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> PartialOrd<f64> for RealRug<PRECISION> {
#[inline(always)]
fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
self.0.partial_cmp(other)
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> FunctionsGeneralType<Rug<PRECISION>> for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> FunctionsRealType<Rug<PRECISION>> for RealRug<PRECISION> {
#[inline(always)]
fn atan2_(self, other: &Self) -> Self {
Self(self.0.atan2(&other.0))
}
#[inline(always)]
fn ceil_(self) -> Self {
Self(self.0.ceil())
}
#[inline(always)]
fn clamp_(self, min: &Self, max: &Self) -> Self {
Self(self.0.clamp(&min.0, &max.0))
}
#[inline(always)]
fn classify_(&self) -> FpCategory {
self.0.classify()
}
#[inline(always)]
fn copysign_(self, sign: &Self) -> Self {
Self(self.0.copysign(&sign.0))
}
#[inline(always)]
fn epsilon_() -> Self {
Self(
rug::Float::u_pow_u(2, PRECISION - 1)
.complete(PRECISION.into())
.recip(),
)
}
#[inline(always)]
fn exp_m1_(self) -> Self {
Self(self.0.exp_m1())
}
#[inline(always)]
fn floor_(self) -> Self {
Self(self.0.floor())
}
#[inline(always)]
fn fract_(self) -> Self {
Self(self.0.fract())
}
#[inline(always)]
fn hypot_(self, other: &Self) -> Self {
Self(self.0.hypot(&other.0))
}
#[inline(always)]
fn infinity_() -> Self {
Self(rug::Float::with_val(
PRECISION,
rug::float::Special::Infinity,
))
}
#[inline(always)]
fn is_sign_negative_(&self) -> bool {
self.0.is_sign_negative()
}
#[inline(always)]
fn is_sign_positive_(&self) -> bool {
self.0.is_sign_positive()
}
#[inline(always)]
fn ln_1p_(self) -> Self {
Self(self.0.ln_1p())
}
#[inline(always)]
fn neg_infinity_() -> Self {
Self(rug::Float::with_val(
PRECISION,
rug::float::Special::NegInfinity,
))
}
#[inline(always)]
fn max_(self, other: &Self) -> Self {
Self(self.0.max(&other.0))
}
#[inline(always)]
fn min_(self, other: &Self) -> Self {
Self(self.0.min(&other.0))
}
#[inline(always)]
fn mul_add_mul_mut_(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
self.0.mul_add_mul_mut(&mul.0, &add_mul1.0, &add_mul2.0);
}
#[inline(always)]
fn mul_sub_mul_mut_(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
self.0.mul_sub_mul_mut(&mul.0, &sub_mul1.0, &sub_mul2.0);
}
#[inline(always)]
fn negative_one_() -> Self {
Self(rug::Float::with_val(PRECISION, -1.))
}
#[inline(always)]
fn one_div_2_() -> Self {
Self(rug::Float::with_val(PRECISION, 0.5))
}
#[inline(always)]
fn round_(self) -> Self {
Self(self.0.round())
}
#[inline(always)]
fn round_ties_even_(self) -> Self {
Self(self.0.round_even())
}
#[inline(always)]
fn signum_(self) -> Self {
Self(self.0.signum())
}
#[inline(always)]
fn total_cmp_(&self, other: &Self) -> Ordering {
self.0.total_cmp(&other.0)
}
#[inline(always)]
fn try_from_f64_(value: f64) -> Result<Self, TryFromf64Errors> {
match value.validate() {
Ok(value) => {
let value_rug = rug::Float::with_val(PRECISION, value);
if value_rug == value {
Ok(Self(value_rug))
} else {
Err(TryFromf64Errors::NonRepresentableExactly {
value,
precision: PRECISION,
backtrace: Backtrace::force_capture(),
})
}
}
Err(e) => Err(TryFromf64Errors::ValidationError { source: e }),
}
}
#[inline(always)]
fn trunc_(self) -> Self {
Self(self.0.trunc())
}
#[inline(always)]
fn two_() -> Self {
Self(rug::Float::with_val(PRECISION, 2.))
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Mul<ComplexRug<PRECISION>> for RealRug<PRECISION> {
type Output = ComplexRug<PRECISION>;
#[inline(always)]
fn mul(self, other: ComplexRug<PRECISION>) -> Self::Output {
ComplexRug(self.0 * other.0)
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> MulComplexRight<Rug<PRECISION>> for RealRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> FunctionsGeneralType<Rug<PRECISION>> for ComplexRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> FunctionsComplexType<Rug<PRECISION>> for ComplexRug<PRECISION> {
#[inline(always)]
fn arg_(self) -> RealRug<PRECISION> {
RealRug(self.0.arg().real().clone())
}
#[inline(always)]
fn new_(real_part: RealRug<PRECISION>, imag_part: RealRug<PRECISION>) -> Self {
debug_assert!(
real_part.0.is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
debug_assert!(
imag_part.0.is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
Self(rug::Complex::with_val(
PRECISION,
(real_part.0, imag_part.0),
))
}
#[inline(always)]
fn real_(&self) -> RealRug<PRECISION> {
RealRug(self.0.real().clone())
}
#[inline(always)]
fn imag_(&self) -> RealRug<PRECISION> {
RealRug(self.0.imag().clone())
}
#[inline(always)]
fn set_real_(&mut self, real_part: RealRug<PRECISION>) {
debug_assert!(
real_part.0.is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
*self.0.mut_real() = real_part.0;
}
#[inline(always)]
fn set_imag_(&mut self, imag_part: RealRug<PRECISION>) {
debug_assert!(
imag_part.0.is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
*self.0.mut_imag() = imag_part.0;
}
#[inline(always)]
fn add_real_(&mut self, c: &RealRug<PRECISION>) {
*self.0.mut_real() += c.as_ref();
debug_assert!(
self.0.real().is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn add_imag_(&mut self, c: &RealRug<PRECISION>) {
*self.0.mut_imag() += c.as_ref();
debug_assert!(
self.0.imag().is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn multiply_real_(&mut self, c: &RealRug<PRECISION>) {
*self.0.mut_real() *= c.as_ref();
debug_assert!(
self.0.real().is_finite(),
"The real part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn multiply_imag_(&mut self, c: &RealRug<PRECISION>) {
*self.0.mut_imag() *= c.as_ref();
debug_assert!(
self.0.imag().is_finite(),
"The imaginary part is not finite (i.e. is infinite or NaN)."
);
}
#[inline(always)]
fn conj_(self) -> Self {
Self(self.0.conj())
}
#[inline(always)]
fn try_from_f64_(real_part: f64, imag_part: f64) -> Result<Self, TryFromf64Errors> {
let real_part = RealRug::<PRECISION>::try_from_f64_(real_part)?;
let imag_part = RealRug::<PRECISION>::try_from_f64_(imag_part)?;
Ok(Self(rug::Complex::with_val(
PRECISION,
(real_part.0, imag_part.0),
)))
}
}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> MulComplexLeft<Rug<PRECISION>> for ComplexRug<PRECISION> {}
#[cfg(feature = "rug")]
impl<const PRECISION: u32> Mul<ComplexRug<PRECISION>> for &RealRug<PRECISION> {
type Output = ComplexRug<PRECISION>;
fn mul(self, rhs: ComplexRug<PRECISION>) -> ComplexRug<PRECISION> {
ComplexRug(rhs.0.mul(&self.0))
}
}
#[inline(always)]
pub fn vec_f64_into_vec_float<T: NumKernel>(vec: Vec<f64>) -> Vec<T::RealType> {
vec.into_iter()
.map(|v| T::RealType::try_from_f64_(v).unwrap())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use core::ops::{Add, Div, Mul, Sub};
fn test_add_real<T>()
where
T: NumKernel,
for<'a> &'a T::RealType: Add<T::RealType, Output = T::RealType>,
{
let a = T::RealType::one();
let b = T::RealType::try_from_f64_(2.).unwrap();
let c_expected = T::RealType::try_from_f64_(3.0).unwrap();
let c = a.clone() + &b;
assert_eq!(c, c_expected);
let c = &a + b.clone();
assert_eq!(c, c_expected);
let c = a.clone() + b.clone();
assert_eq!(c, c_expected);
}
fn test_add_complex<T>()
where
T: NumKernel,
for<'a> &'a T::ComplexType: Add<T::ComplexType, Output = T::ComplexType>,
{
let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
let b = T::ComplexType::try_from_f64_(3., 4.).unwrap();
let c_expected = T::ComplexType::try_from_f64_(4., 6.).unwrap();
let c = a.clone() + &b;
assert_eq!(c, c_expected);
let c = &a + b.clone();
assert_eq!(c, c_expected);
let c = a.clone() + b.clone();
assert_eq!(c, c_expected);
}
fn test_sub_real<T>()
where
T: NumKernel,
for<'a> &'a T::RealType: Sub<T::RealType, Output = T::RealType>,
{
let a = T::RealType::one();
let b = T::RealType::try_from_f64_(2.).unwrap();
let c_expected = T::RealType::try_from_f64_(-1.0).unwrap();
let c = a.clone() - &b;
assert_eq!(c, c_expected);
let c = &a - b.clone();
assert_eq!(c, c_expected);
let c = a.clone() - b.clone();
assert_eq!(c, c_expected);
}
fn test_sub_complex<T>()
where
T: NumKernel,
for<'a> &'a T::ComplexType: Sub<T::ComplexType, Output = T::ComplexType>,
{
let a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
let b = T::ComplexType::try_from_f64_(1., 4.).unwrap();
let c_expected = T::ComplexType::try_from_f64_(2., -2.).unwrap();
let c = a.clone() - &b;
assert_eq!(c, c_expected);
let c = &a - b.clone();
assert_eq!(c, c_expected);
let c = a.clone() - b.clone();
assert_eq!(c, c_expected);
}
fn test_mul_real<T>()
where
T: NumKernel,
for<'a> &'a T::RealType: Mul<T::RealType, Output = T::RealType>,
{
let a = T::RealType::try_from_f64_(2.).unwrap();
let b = T::RealType::try_from_f64_(3.).unwrap();
let c_expected = T::RealType::try_from_f64_(6.0).unwrap();
let c = a.clone() * &b;
assert_eq!(c, c_expected);
let c = &a * b.clone();
assert_eq!(c, c_expected);
let c = a.clone() * b.clone();
assert_eq!(c, c_expected);
}
fn test_mul_complex<T>()
where
T: NumKernel,
for<'a> &'a T::ComplexType: Mul<T::ComplexType, Output = T::ComplexType>,
{
let a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
let b = T::ComplexType::try_from_f64_(1., 4.).unwrap();
let c_expected = T::ComplexType::try_from_f64_(-5., 14.).unwrap();
let c = a.clone() * &b;
assert_eq!(c, c_expected);
let c = &a * b.clone();
assert_eq!(c, c_expected);
let c = a.clone() * b.clone();
assert_eq!(c, c_expected);
}
fn test_div_real<T>()
where
T: NumKernel,
for<'a> &'a T::RealType: Div<T::RealType, Output = T::RealType>,
{
let a = T::RealType::try_from_f64_(6.).unwrap();
let b = T::RealType::try_from_f64_(2.).unwrap();
let c_expected = T::RealType::try_from_f64_(3.0).unwrap();
let c = a.clone() / &b;
assert_eq!(c, c_expected);
let c = &a / b.clone();
assert_eq!(c, c_expected);
let c = a.clone() / b.clone();
assert_eq!(c, c_expected);
}
fn test_div_complex<T>()
where
T: NumKernel,
for<'a> &'a T::ComplexType: Div<T::ComplexType, Output = T::ComplexType>,
{
let a = T::ComplexType::try_from_f64_(-5., 14.).unwrap();
let b = T::ComplexType::try_from_f64_(1., 4.).unwrap();
let c_expected = T::ComplexType::try_from_f64_(3., 2.).unwrap();
let c = a.clone() / &b;
assert_eq!(c, c_expected);
let c = &a / b.clone();
assert_eq!(c, c_expected);
let c = a.clone() / b.clone();
assert_eq!(c, c_expected);
}
fn test_neg_assign_real<T: NumKernel>() {
let mut a = T::RealType::try_from_f64_(1.).unwrap();
a.neg_assign();
let a_expected = T::RealType::try_from_f64_(-1.).unwrap();
assert_eq!(a, a_expected);
}
fn test_neg_assign_complex<T: NumKernel>() {
let mut a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
a.neg_assign();
let a_expected = T::ComplexType::try_from_f64_(-1., -2.).unwrap();
assert_eq!(a, a_expected);
}
fn test_add_assign_real<T: NumKernel>() {
let mut a = T::RealType::try_from_f64_(1.0).unwrap();
let b = T::RealType::try_from_f64_(2.0).unwrap();
a += &b;
let a_expected = T::RealType::try_from_f64_(3.0).unwrap();
assert_eq!(a, a_expected);
a += b;
let a_expected = T::RealType::try_from_f64_(5.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_add_assign_complex<T: NumKernel>() {
let mut a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
let b = T::ComplexType::try_from_f64_(3., 4.).unwrap();
a += &b;
let a_expected = T::ComplexType::try_from_f64_(4., 6.).unwrap();
assert_eq!(a, a_expected);
a += b;
let a_expected = T::ComplexType::try_from_f64_(7., 10.).unwrap();
assert_eq!(a, a_expected);
}
fn test_sub_assign_real<T: NumKernel>() {
let mut a = T::RealType::try_from_f64_(1.0).unwrap();
let b = T::RealType::try_from_f64_(2.0).unwrap();
a -= &b;
let a_expected = T::RealType::try_from_f64_(-1.0).unwrap();
assert_eq!(a, a_expected);
a -= b;
let a_expected = T::RealType::try_from_f64_(-3.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_sub_assign_complex<T: NumKernel>() {
let mut a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
let b = T::ComplexType::try_from_f64_(2., 4.).unwrap();
a -= &b;
let a_expected = T::ComplexType::try_from_f64_(1., -2.).unwrap();
assert_eq!(a, a_expected);
a -= b;
let a_expected = T::ComplexType::try_from_f64_(-1., -6.).unwrap();
assert_eq!(a, a_expected);
}
fn test_mul_assign_real<T: NumKernel>() {
let mut a = T::RealType::try_from_f64_(1.0).unwrap();
let b = T::RealType::try_from_f64_(2.0).unwrap();
a *= &b;
let a_expected = T::RealType::try_from_f64_(2.0).unwrap();
assert_eq!(a, a_expected);
a *= b;
let a_expected = T::RealType::try_from_f64_(4.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_mul_assign_complex<T: NumKernel>() {
let mut a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
let b = T::ComplexType::try_from_f64_(2., 4.).unwrap();
a *= &b;
let a_expected = T::ComplexType::try_from_f64_(-2., 16.).unwrap();
assert_eq!(a, a_expected);
a *= b;
let a_expected = T::ComplexType::try_from_f64_(-68., 24.).unwrap();
assert_eq!(a, a_expected);
}
fn test_div_assign_real<T: NumKernel>() {
let mut a = T::RealType::try_from_f64_(4.0).unwrap();
let b = T::RealType::try_from_f64_(2.0).unwrap();
a /= &b;
let a_expected = T::RealType::try_from_f64_(2.0).unwrap();
assert_eq!(a, a_expected);
a /= b;
let a_expected = T::RealType::try_from_f64_(1.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_div_assign_complex<T: NumKernel>() {
let mut a = T::ComplexType::try_from_f64_(-68., 24.).unwrap();
let b = T::ComplexType::try_from_f64_(2., 4.).unwrap();
a /= &b;
let a_expected = T::ComplexType::try_from_f64_(-2., 16.).unwrap();
assert_eq!(a, a_expected);
a /= b;
let a_expected = T::ComplexType::try_from_f64_(3., 2.).unwrap();
assert_eq!(a, a_expected);
}
fn test_abs_real<T: NumKernel>() {
let a = T::RealType::try_from_f64_(-1.).unwrap();
let abs = a.abs();
let expected = T::RealType::try_from_f64_(1.).unwrap();
assert_eq!(abs, expected);
}
fn test_abs_complex<T: NumKernel>() {
let a = T::ComplexType::try_from_f64_(-3., 4.).unwrap();
let abs = a.abs();
let expected = T::RealType::try_from_f64_(5.).unwrap();
assert_eq!(abs, expected);
}
fn test_mul_add_real<T: NumKernel>() {
let a = T::RealType::try_from_f64_(2.0).unwrap();
let b = T::RealType::try_from_f64_(3.0).unwrap();
let c = T::RealType::try_from_f64_(1.0).unwrap();
let d_expected = T::RealType::try_from_f64_(7.0).unwrap();
let d = a.mul_add(&b, &c);
assert_eq!(d, d_expected);
}
fn test_mul_add_complex<T: NumKernel>() {
let a = T::ComplexType::try_from_f64_(2., -3.).unwrap();
let b = T::ComplexType::try_from_f64_(3., 1.).unwrap();
let c = T::ComplexType::try_from_f64_(1., -4.).unwrap();
let d_expected = T::ComplexType::try_from_f64_(10., -11.).unwrap();
let d = a.mul_add(&b, &c);
assert_eq!(d, d_expected);
}
fn test_mul_complex_with_real<T>()
where
T: NumKernel,
for<'a> &'a T::RealType: Mul<T::ComplexType, Output = T::ComplexType>,
{
let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
let b = T::RealType::try_from_f64_(3.).unwrap();
let a_times_b_expected = T::ComplexType::try_from_f64_(3., 6.).unwrap();
let b_times_a_expected = a_times_b_expected.clone();
let a_times_b = a.clone() * &b;
assert_eq!(a_times_b, a_times_b_expected);
let a_times_b = a.clone() * b.clone();
assert_eq!(a_times_b, a_times_b_expected);
let b_times_a = &b * a.clone();
assert_eq!(b_times_a, b_times_a_expected);
let b_times_a = b.clone() * a.clone();
assert_eq!(b_times_a, b_times_a_expected);
}
fn test_mul_assign_complex_with_real<T>()
where
T: NumKernel,
{
let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
let b = T::RealType::try_from_f64_(3.).unwrap();
let a_times_b_expected = T::ComplexType::try_from_f64_(3., 6.).unwrap();
let mut a_times_b = a.clone();
a_times_b *= &b;
assert_eq!(a_times_b, a_times_b_expected);
let mut a_times_b = a.clone();
a_times_b *= b;
assert_eq!(a_times_b, a_times_b_expected);
}
mod native64 {
use super::*;
mod real {
use super::*;
#[test]
fn from_f64() {
let v_native64 =
<f64 as FunctionsRealType<Native64>>::try_from_f64_(16.25).unwrap();
assert_eq!(v_native64, 16.25);
}
#[test]
fn zero() {
test_zero::<Native64>();
}
#[test]
fn one() {
test_one::<Native64>();
}
#[test]
fn add() {
test_add_real::<Native64>();
}
#[test]
fn sub() {
test_sub_real::<Native64>();
}
#[test]
fn mul() {
test_mul_real::<Native64>();
}
#[test]
fn div() {
test_div_real::<Native64>();
}
#[test]
fn neg_assign() {
test_neg_assign_real::<Native64>();
}
#[test]
fn add_assign() {
test_add_assign_real::<Native64>();
}
#[test]
fn sub_assign() {
test_sub_assign_real::<Native64>();
}
#[test]
fn mul_assign() {
test_mul_assign_real::<Native64>();
}
#[test]
fn div_assign() {
test_div_assign_real::<Native64>();
}
#[test]
fn abs() {
test_abs_real::<Native64>();
}
#[test]
fn mul_add() {
test_mul_add_real::<Native64>();
}
#[test]
fn recip() {
test_recip::<Native64>();
}
#[test]
fn acos() {
let a = 0.;
let pi_over_2 = a.acos_();
let expected = 1.5707963267948966;
assert_eq!(pi_over_2, expected);
}
#[test]
fn asin() {
let a = 1.;
let pi_over_2 = a.asin_();
let expected = 1.5707963267948966;
assert_eq!(pi_over_2, expected);
}
#[test]
fn cos() {
test_cos::<Native64>();
}
#[test]
fn sin() {
test_sin::<Native64>();
}
}
mod complex {
use super::*;
use num::Complex;
#[test]
fn from_f64() {
let v = <Complex<f64> as FunctionsComplexType<Native64>>::try_from_f64_(16.25, 2.)
.unwrap();
assert_eq!(v.real_(), 16.25);
assert_eq!(v.imag_(), 2.);
}
#[test]
fn conj() {
let v = <Complex<f64> as FunctionsComplexType<Native64>>::try_from_f64_(16.25, 2.)
.unwrap();
let v_conj = v.conj_();
assert_eq!(v_conj.real_(), 16.25);
assert_eq!(v_conj.imag_(), -2.);
}
#[test]
fn add() {
test_add_complex::<Native64>();
}
#[test]
fn sub() {
test_sub_complex::<Native64>();
}
#[test]
fn mul() {
test_mul_complex::<Native64>();
}
#[test]
fn div() {
test_div_complex::<Native64>();
}
#[test]
fn neg_assign() {
test_neg_assign_complex::<Native64>();
}
#[test]
fn add_assign() {
test_add_assign_complex::<Native64>();
}
#[test]
fn sub_assign() {
test_sub_assign_complex::<Native64>();
}
#[test]
fn mul_assign() {
test_mul_assign_complex::<Native64>();
}
#[test]
fn div_assign() {
test_div_assign_complex::<Native64>();
}
#[test]
fn abs() {
test_abs_complex::<Native64>();
}
#[test]
fn mul_add() {
test_mul_add_complex::<Native64>();
}
#[test]
fn mul_complex_with_real() {
test_mul_complex_with_real::<Native64>();
}
#[test]
fn mul_assign_complex_with_real() {
test_mul_assign_complex_with_real::<Native64>();
}
}
}
#[cfg(feature = "rug")]
mod rug_ {
use super::*;
mod real {
use super::*;
#[test]
fn from_f64() {
let v_100bits = RealRug::<100>::try_from_f64_(16.25).unwrap();
assert_eq!(v_100bits, 16.25);
let v_53bits = RealRug::<53>::try_from_f64_(16.25).unwrap();
assert_eq!(v_53bits, 16.25);
let v_7bits = RealRug::<7>::try_from_f64_(16.25).unwrap();
assert_eq!(v_7bits, 16.25);
}
#[test]
#[should_panic]
fn from_f64_failing() {
let _v_6bits = RealRug::<6>::try_from_f64_(16.25).unwrap();
}
#[test]
fn zero() {
test_zero::<Rug<64>>();
test_zero::<Rug<100>>();
}
#[test]
fn one() {
test_one::<Rug<64>>();
test_one::<Rug<100>>();
}
#[test]
fn add() {
test_add_real::<Rug<100>>();
}
#[test]
fn sub() {
test_sub_real::<Rug<100>>();
}
#[test]
fn mul() {
test_mul_real::<Rug<100>>();
}
#[test]
fn div() {
test_div_real::<Rug<100>>();
}
#[test]
fn neg_assign() {
test_neg_assign_real::<Rug<100>>();
}
#[test]
fn add_assign() {
test_add_assign_real::<Rug<100>>();
}
#[test]
fn sub_assign() {
test_sub_assign_real::<Rug<100>>();
}
#[test]
fn mul_assign() {
test_mul_assign_real::<Rug<100>>();
}
#[test]
fn div_assign() {
test_div_assign_real::<Rug<100>>();
}
#[test]
fn abs() {
test_abs_real::<Rug<100>>();
}
#[test]
fn mul_add() {
test_mul_add_real::<Rug<100>>();
}
#[test]
fn recip() {
test_recip::<Rug<64>>();
test_recip::<Rug<100>>();
}
#[test]
fn acos() {
{
let a = RealRug::<53>::zero();
let pi_over_2 = RealRug::<53>::acos_(a);
let expected = rug::Float::with_val(53, 1.5707963267948966);
assert_eq!(pi_over_2.as_ref(), &expected);
}
{
let a = RealRug::<100>::zero();
let pi_over_2 = RealRug::<100>::acos_(a);
let expected = rug::Float::with_val(
100,
rug::Float::parse("1.5707963267948966192313216916397e0").unwrap(),
);
assert_eq!(pi_over_2.as_ref(), &expected);
}
}
#[test]
fn asin() {
{
let a = RealRug::<53>::one();
let pi_over_2 = RealRug::<53>::asin_(a);
let expected = rug::Float::with_val(53, 1.5707963267948966);
assert_eq!(pi_over_2.as_ref(), &expected);
}
{
let a = RealRug::<100>::one();
let pi_over_2 = RealRug::<100>::asin_(a);
let expected = rug::Float::with_val(
100,
rug::Float::parse("1.5707963267948966192313216916397e0").unwrap(),
);
assert_eq!(pi_over_2.as_ref(), &expected);
}
}
#[test]
fn cos() {
test_cos::<Rug<64>>();
test_cos::<Rug<100>>();
}
#[test]
fn sin() {
test_sin::<Rug<64>>();
test_sin::<Rug<100>>();
}
#[test]
fn dot_product() {
let a = &[
RealRug::<100>::try_from_f64_(1.).unwrap(),
RealRug::<100>::try_from_f64_(2.).unwrap(),
];
let b = &[
RealRug::<100>::try_from_f64_(2.).unwrap(),
RealRug::<100>::try_from_f64_(-1.).unwrap(),
];
let a: Vec<_> = a.iter().map(|a_i| a_i.as_ref()).collect();
let b: Vec<_> = b.iter().map(|b_i| b_i.as_ref()).collect();
let value =
RealRug::<100>(rug::Float::dot(a.into_iter().zip(b.into_iter())).complete(100));
assert_eq!(value.as_ref(), &rug::Float::with_val(100, 0.));
}
}
mod complex {
use super::*;
#[test]
fn from_f64() {
let v_100bits = ComplexRug::<100>::try_from_f64_(16.25, 2.).unwrap();
assert_eq!(ComplexRug::<100>::real_(&v_100bits), 16.25);
assert_eq!(ComplexRug::<100>::imag_(&v_100bits), 2.);
let v_53bits = ComplexRug::<53>::try_from_f64_(16.25, 2.).unwrap();
assert_eq!(ComplexRug::<53>::real_(&v_53bits), 16.25);
assert_eq!(ComplexRug::<53>::imag_(&v_53bits), 2.);
let v_7bits = ComplexRug::<7>::try_from_f64_(16.25, 2.).unwrap();
assert_eq!(ComplexRug::<7>::real_(&v_7bits), 16.25);
assert_eq!(ComplexRug::<7>::imag_(&v_7bits), 2.);
}
#[test]
#[should_panic]
fn from_f64_failing() {
let _v_6bits = ComplexRug::<6>::try_from_f64_(16.25, 2.).unwrap();
}
#[test]
fn conj() {
let v = ComplexRug::<100>::try_from_f64_(16.25, 2.).unwrap();
let v_conj = ComplexRug::<100>::conj_(v);
assert_eq!(ComplexRug::<100>::real_(&v_conj), 16.25);
assert_eq!(ComplexRug::<100>::imag_(&v_conj), -2.);
}
#[test]
fn add() {
test_add_complex::<Rug<100>>();
}
#[test]
fn sub() {
test_sub_complex::<Rug<100>>();
}
#[test]
fn mul() {
test_mul_complex::<Rug<100>>();
}
#[test]
fn div() {
test_div_complex::<Rug<100>>();
}
#[test]
fn neg_assign() {
test_neg_assign_complex::<Rug<100>>();
}
#[test]
fn add_assign() {
test_add_assign_complex::<Rug<100>>();
}
#[test]
fn sub_assign() {
test_sub_assign_complex::<Rug<100>>();
}
#[test]
fn mul_assign() {
test_mul_assign_complex::<Rug<100>>();
}
#[test]
fn div_assign() {
test_div_assign_complex::<Rug<100>>();
}
#[test]
fn abs() {
test_abs_complex::<Rug<100>>();
}
#[test]
fn mul_add() {
test_mul_add_complex::<Rug<100>>();
}
#[test]
fn mul_complex_with_real() {
test_mul_complex_with_real::<Rug<100>>();
}
#[test]
fn mul_assign_complex_with_real() {
test_mul_assign_complex_with_real::<Rug<100>>();
}
#[test]
fn dot_product() {
let a = &[
ComplexRug::<100>::try_from_f64_(1., 3.).unwrap(),
ComplexRug::<100>::try_from_f64_(2., 4.).unwrap(),
];
let b = &[
ComplexRug::<100>::try_from_f64_(-2., -5.).unwrap(),
ComplexRug::<100>::try_from_f64_(-1., 6.).unwrap(),
];
let a: Vec<_> = a.iter().map(|a_i| a_i.as_ref()).collect();
let b: Vec<_> = b.iter().map(|b_i| b_i.as_ref()).collect();
let a_times_a = ComplexRug::<100>(
rug::Complex::dot(a.clone().into_iter().zip(a.clone().into_iter()))
.complete((100, 100)),
);
assert_eq!(
a_times_a.as_ref(),
&rug::Complex::with_val(100, (-20., 22.))
);
let a_times_b = ComplexRug::<100>(
rug::Complex::dot(a.clone().into_iter().zip(b.clone().into_iter()))
.complete((100, 100)),
);
assert_eq!(
a_times_b.as_ref(),
&rug::Complex::with_val(100, (-13., -3.))
);
let b_times_a = ComplexRug::<100>(
rug::Complex::dot(b.into_iter().zip(a.into_iter())).complete((100, 100)),
);
assert_eq!(
b_times_a.as_ref(),
&rug::Complex::with_val(100, (-13., -3.))
);
}
}
}
fn test_sin<T: NumKernel>() {
let a = T::RealType::zero();
let a = a.sin_();
let expected = T::RealType::zero();
assert_eq!(a, expected);
}
fn test_cos<T: NumKernel>() {
let a = T::RealType::zero();
let a = a.cos_();
let expected = T::RealType::one();
assert_eq!(a, expected);
}
fn test_recip<T: NumKernel>() {
let a = T::RealType::two_();
let a = a.try_reciprocal().unwrap();
let expected = T::RealType::one_div_2_();
assert_eq!(a, expected);
}
fn test_zero<T: NumKernel>() {
let a = T::RealType::zero();
assert_eq!(a, 0.0);
}
fn test_one<T: NumKernel>() {
let a = T::RealType::one();
assert_eq!(a, 1.0);
}
}
#[cfg(test)]
mod tests_new {
use super::*;
mod functions_general_type {
use super::*;
mod native64 {
use super::*;
mod real {
use super::*;
#[test]
fn test_acos_() {
let value: f64 = 0.5;
let result = value.acos_();
assert_eq!(result, value.acos());
}
#[test]
fn test_acosh_() {
let value: f64 = 1.5;
let result = value.acosh_();
assert_eq!(result, value.acosh());
}
#[test]
fn test_asin_() {
let value: f64 = 0.5;
let result = value.asin_();
assert_eq!(result, value.asin());
}
#[test]
fn test_asinh_() {
let value: f64 = 0.5;
let result = value.asinh_();
assert_eq!(result, value.asinh());
}
#[test]
fn test_atan_() {
let value: f64 = 0.5;
let result = value.atan_();
assert_eq!(result, value.atan());
}
#[test]
fn test_atanh_() {
let value: f64 = 0.5;
let result = value.atanh_();
assert_eq!(result, value.atanh());
}
#[test]
fn test_cos_() {
let value: f64 = 0.5;
let result = value.cos_();
assert_eq!(result, value.cos());
}
#[test]
fn test_cosh_() {
let value: f64 = 0.5;
let result = value.cosh_();
assert_eq!(result, value.cosh());
}
#[test]
fn test_exp_() {
let value: f64 = 0.5;
let result = value.exp_();
print!("result = {:?}", result);
assert_eq!(result, value.exp());
}
#[test]
fn test_is_finite_() {
let value: f64 = 0.5;
assert!(value.is_finite_());
let value: f64 = f64::INFINITY;
assert!(!value.is_finite_());
}
#[test]
fn test_is_infinite_() {
let value: f64 = f64::INFINITY;
assert!(value.is_infinite_());
let value: f64 = 0.5;
assert!(!value.is_infinite_());
}
#[test]
fn test_ln_() {
let value: f64 = 2.718281828459045;
let result = value.ln_();
println!("result = {:?}", result);
assert_eq!(result, value.ln());
}
#[test]
fn test_log10_() {
let value: f64 = 10.0;
let result = value.log10_();
println!("result = {:?}", result);
assert_eq!(result, value.log10());
}
#[test]
fn test_log2_() {
let value: f64 = 8.0;
let result = value.log2_();
println!("result = {:?}", result);
assert_eq!(result, value.log2());
}
#[test]
fn test_recip_() {
let value: f64 = 2.0;
let result = value.try_reciprocal().unwrap();
assert_eq!(result, value.recip());
}
#[test]
fn test_sin_() {
let value: f64 = 0.5;
let result = value.sin_();
assert_eq!(result, value.sin());
}
#[test]
fn test_sinh_() {
let value: f64 = 0.5;
let result = value.sinh_();
assert_eq!(result, value.sinh());
}
#[test]
fn sqrt() {
let value: f64 = 4.0;
let result = value.sqrt();
assert_eq!(result, value.sqrt());
}
#[test]
fn try_sqrt() {
let value: f64 = 4.0;
let result = value.try_sqrt().unwrap();
assert_eq!(result, value.sqrt());
assert!((-1.0).try_sqrt().is_err());
}
#[test]
fn test_tan_() {
let value: f64 = 0.5;
let result = value.tan_();
assert_eq!(result, value.tan());
}
#[test]
fn test_tanh_() {
let value: f64 = 0.5;
let result = value.tanh_();
assert_eq!(result, value.tanh());
}
}
mod complex {
use super::*;
#[test]
fn test_acos_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.acos_();
assert_eq!(result, value.acos());
}
#[test]
fn test_acosh_() {
let value: Complex<f64> = Complex::new(1.5, 0.5);
let result = value.acosh_();
assert_eq!(result, value.acosh());
}
#[test]
fn test_asin_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.asin_();
assert_eq!(result, value.asin());
}
#[test]
fn test_asinh_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.asinh_();
assert_eq!(result, value.asinh());
}
#[test]
fn test_atan_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.atan_();
assert_eq!(result, value.atan());
}
#[test]
fn test_atanh_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.atanh_();
assert_eq!(result, value.atanh());
}
#[test]
fn test_cos_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.cos_();
assert_eq!(result, value.cos());
}
#[test]
fn test_cosh_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.cosh_();
assert_eq!(result, value.cosh());
}
#[test]
fn test_exp_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.exp_();
print!("result = {:?}", result);
assert_eq!(result, value.exp());
}
#[test]
fn test_is_finite_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
assert!(value.is_finite_());
let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
assert!(!value.is_finite_());
}
#[test]
fn test_is_infinite_() {
let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
assert!(value.is_infinite_());
let value: Complex<f64> = Complex::new(0.5, 0.5);
assert!(!value.is_infinite_());
}
#[test]
fn test_ln_() {
let value: Complex<f64> = Complex::new(2.718281828459045, 1.0);
let result = value.ln_();
println!("result = {:?}", result);
assert_eq!(result, value.ln());
}
#[test]
fn test_log10_() {
let value: Complex<f64> = Complex::new(10.0, 1.0);
let result = value.log10_();
println!("result = {:?}", result);
assert_eq!(result, value.log10());
}
#[test]
fn test_log2_() {
let value: Complex<f64> = Complex::new(8.0, 1.0);
let result = value.log2_();
println!("result = {:?}", result);
assert_eq!(result, value.log2());
}
#[test]
fn test_recip_() {
let value: Complex<f64> = Complex::new(2.0, 0.0);
let result = value.try_reciprocal().unwrap();
assert_eq!(result, value.finv());
}
#[test]
fn test_sin_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.sin_();
assert_eq!(result, value.sin());
}
#[test]
fn test_sinh_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.sinh_();
assert_eq!(result, value.sinh());
}
#[test]
fn sqrt() {
let value: Complex<f64> = Complex::new(4.0, 1.0);
let result = value.sqrt();
assert_eq!(result, value.sqrt());
}
#[test]
fn try_sqrt() {
let value: Complex<f64> = Complex::new(4.0, 1.0);
let result = value.try_sqrt().unwrap();
assert_eq!(result, value.sqrt());
}
#[test]
fn test_tan_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.tan_();
assert_eq!(result, value.tan());
}
#[test]
fn test_tanh_() {
let value: Complex<f64> = Complex::new(0.5, 0.5);
let result = value.tanh_();
assert_eq!(result, value.tanh());
}
}
}
#[cfg(feature = "rug")]
mod rug100 {
use super::*;
const PRECISION: u32 = 100;
mod real {
use super::*;
use rug::Float;
#[test]
fn test_acos_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().acos_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.acos()))
);
}
#[test]
fn test_acosh_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 1.5));
let result = value.clone().acosh_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.acosh()))
);
}
#[test]
fn test_asin_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().asin_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.asin()))
);
}
#[test]
fn test_asinh_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().asinh_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.asinh()))
);
}
#[test]
fn test_atan_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().atan_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.atan()))
);
}
#[test]
fn test_atanh_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().atanh_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.atanh()))
);
}
#[test]
fn test_cos_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().cos_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.cos()))
);
}
#[test]
fn test_cosh_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().cosh_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.cosh()))
);
}
#[test]
fn test_exp_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().exp_();
print!("result = {:?}", result);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.exp()))
);
}
#[test]
fn test_is_finite_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
assert!(value.is_finite_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, f64::INFINITY));
assert!(!value.is_finite_());
}
#[test]
fn test_is_infinite_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, f64::INFINITY));
assert!(value.is_infinite_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
assert!(!value.is_infinite_());
}
#[test]
fn test_ln_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.718281828459045));
let result = value.clone().ln_();
println!("result = {:?}", result);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.ln()))
);
}
#[test]
fn test_log10_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 10.0));
let result = value.clone().log10_();
println!("result = {:?}", result);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.log10()))
);
}
#[test]
fn test_log2_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 8.0));
let result = value.clone().log2_();
println!("result = {:?}", result);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.log2()))
);
}
#[test]
fn test_recip_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
let result = value.clone().try_reciprocal().unwrap();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.recip()))
);
}
#[test]
fn test_sin_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().sin_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sin()))
);
}
#[test]
fn test_sinh_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().sinh_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sinh()))
);
}
#[test]
fn sqrt() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = value.clone().sqrt();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sqrt()))
);
}
#[test]
fn try_sqrt() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = value.clone().try_sqrt().unwrap();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sqrt()))
);
assert!(RealRug::<PRECISION>(Float::with_val(PRECISION, -4.0))
.try_sqrt()
.is_err())
}
#[test]
fn test_tan_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().tan_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.tan()))
);
}
#[test]
fn test_tanh_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().tanh_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.tanh()))
);
}
#[test]
fn test_mul_add_() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let c = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = a.clone().mul_add(&b, &c);
assert_eq!(result, RealRug::<PRECISION>(a.0.clone() * b.0 + c.0));
}
}
mod complex {
use super::*;
use rug::Complex;
use rug::Float;
#[test]
fn test_acos_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().acos_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.acos()))
);
}
#[test]
fn test_acosh_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (1.5, 0.5)));
let result = value.clone().acosh_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.acosh()))
);
}
#[test]
fn test_asin_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().asin_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.asin()))
);
}
#[test]
fn test_asinh_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().asinh_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.asinh()))
);
}
#[test]
fn test_atan_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().atan_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.atan()))
);
}
#[test]
fn test_atanh_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().atanh_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.atanh()))
);
}
#[test]
fn test_cos_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().cos_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.cos()))
);
}
#[test]
fn test_cosh_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().cosh_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.cosh()))
);
}
#[test]
fn test_exp_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().exp_();
print!("result = {:?}", result);
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.exp()))
);
}
#[test]
fn test_is_finite_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
assert!(value.is_finite_());
let value = ComplexRug::<PRECISION>(Complex::with_val(
100,
(Float::with_val(PRECISION, f64::INFINITY), 0.5),
));
assert!(!value.is_finite_());
}
#[test]
fn test_is_infinite_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(
100,
(Float::with_val(PRECISION, f64::INFINITY), 0.5),
));
assert!(value.is_infinite_());
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
assert!(!value.is_infinite_());
}
#[test]
fn test_ln_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(
PRECISION,
(2.718281828459045, 1.0),
));
let result = value.clone().ln_();
println!("result = {:?}", result);
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.ln()))
);
}
#[test]
fn test_log10_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (10.0, 1.0)));
let result = value.clone().log10_();
println!("result = {:?}", result);
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.log10()))
);
}
#[test]
fn test_log2_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (8.0, 1.0)));
let result = value.clone().log2_();
println!("result = {:?}", result);
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(
PRECISION,
value.0.log10() / rug::Float::with_val(PRECISION, 2.).log10()
))
);
}
#[test]
fn test_recip_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (2.0, 0.0)));
let result = value.clone().try_reciprocal().unwrap();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.recip()))
);
}
#[test]
fn test_sin_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().sin_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sin()))
);
}
#[test]
fn test_sinh_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().sinh_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sinh()))
);
}
#[test]
fn sqrt() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (4.0, 1.0)));
let result = value.clone().sqrt();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sqrt()))
);
}
#[test]
fn try_sqrt() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (4.0, 1.0)));
let result = value.clone().try_sqrt().unwrap();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sqrt()))
);
}
#[test]
fn test_tan_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().tan_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.tan()))
);
}
#[test]
fn test_tanh_() {
let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
let result = value.clone().tanh_();
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.tanh()))
);
}
#[test]
fn test_mul_add_() {
let a = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (2.0, 1.0)));
let b = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (3.0, 1.0)));
let c = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (4.0, 1.0)));
let result = a.clone().mul_add(&b, &c);
assert_eq!(
result,
ComplexRug::<PRECISION>(Complex::with_val(PRECISION, a.0 * b.0 + c.0))
);
}
}
}
}
mod functions_real_type {
use super::*;
mod native64 {
use super::*;
#[test]
fn test_atan2_() {
let a: f64 = 27.0;
let b: f64 = 13.0;
let result = a.atan2_(&b);
assert_eq!(result, a.atan2(b));
}
#[test]
fn test_ceil_() {
let value: f64 = 3.7;
let result = value.ceil_();
assert_eq!(result, value.ceil());
}
#[test]
fn test_clamp_() {
let value: f64 = 5.0;
let min: f64 = 3.0;
let max: f64 = 7.0;
let result = value.clamp_(&min, &max);
assert_eq!(result, value.clamp(min, max));
}
#[test]
fn test_classify_() {
let value: f64 = 3.7;
let result = value.classify_();
assert_eq!(result, value.classify());
}
#[test]
fn test_copysign_() {
let value: f64 = 3.5;
let sign: f64 = -1.0;
let result = value.copysign_(&sign);
assert_eq!(result, value.copysign(sign));
}
#[test]
fn test_epsilon_() {
let eps = f64::epsilon_();
assert_eq!(eps, f64::EPSILON);
}
#[test]
fn test_exp_m1_() {
let value: f64 = 0.5;
let result = value.exp_m1_();
assert_eq!(result, value.exp_m1());
}
#[test]
fn test_floor_() {
let value: f64 = 3.7;
let result = value.floor_();
assert_eq!(result, value.floor());
}
#[test]
fn test_fract_() {
let value: f64 = 3.7;
let result = value.fract_();
assert_eq!(result, value.fract());
}
#[test]
fn test_hypot_() {
let a: f64 = 3.0;
let b: f64 = 4.0;
let result = a.hypot_(&b);
assert_eq!(result, a.hypot(b));
}
#[test]
fn test_infinity_() {
let inf = f64::infinity_();
assert_eq!(inf, f64::INFINITY);
}
#[test]
fn test_is_sign_negative_() {
let value: f64 = -1.0;
assert!(value.is_sign_negative_());
let value: f64 = -0.0;
assert!(value.is_sign_negative_());
let value: f64 = 0.0;
assert!(!value.is_sign_negative_());
let value: f64 = 1.0;
assert!(!value.is_sign_negative_());
}
#[test]
fn test_is_sign_positive_() {
let value: f64 = -1.0;
assert!(!value.is_sign_positive_());
let value: f64 = -0.0;
assert!(!value.is_sign_positive_());
let value: f64 = 0.0;
assert!(value.is_sign_positive_());
let value: f64 = 1.0;
assert!(value.is_sign_positive_());
}
#[test]
fn test_ln_1p_() {
let value: f64 = 0.5;
let result = value.ln_1p_();
assert_eq!(result, value.ln_1p());
}
#[test]
fn test_neg_infinity_() {
let inf = f64::neg_infinity_();
assert_eq!(inf, f64::NEG_INFINITY);
}
#[test]
fn test_max_() {
let a: f64 = 3.0;
let b: f64 = 4.0;
let result = a.max_(&b);
assert_eq!(result, a.max(b));
}
#[test]
fn test_min_() {
let a: f64 = 3.0;
let b: f64 = 4.0;
let result = a.min_(&b);
assert_eq!(result, a.min(b));
}
#[test]
fn test_mul_add_mul_mut() {
let mut a: f64 = 2.0;
let b: f64 = 3.0;
let c: f64 = 4.0;
let d: f64 = -1.0;
let result = a.mul_add_mul_mut_(&b, &c, &d);
assert_eq!(result, a.mul_add_assign(b, c * d));
}
#[test]
fn test_mul_sub_mul_mut() {
let mut a: f64 = 2.0;
let b: f64 = 3.0;
let c: f64 = 4.0;
let d: f64 = -1.0;
let result = a.mul_sub_mul_mut_(&b, &c, &d);
assert_eq!(result, a.mul_add_assign(b, -c * d));
}
#[test]
fn test_negative_one_() {
let value = f64::negative_one_();
assert_eq!(value, -1.0);
}
#[test]
fn test_one_() {
let value = f64::one();
assert_eq!(value, 1.0);
}
#[test]
fn test_round_() {
let value: f64 = 3.5;
let result = value.round_();
assert_eq!(result, value.round());
}
#[test]
fn test_round_ties_even_() {
let value: f64 = 3.5;
let result = value.round_ties_even_();
assert_eq!(result, value.round_ties_even());
}
#[test]
fn test_signum_() {
let value: f64 = -3.5;
let result = value.signum_();
assert_eq!(result, value.signum());
}
#[test]
fn test_total_cmp_() {
let a: f64 = 3.0;
let b: f64 = 4.0;
let result = a.total_cmp_(&b);
assert_eq!(result, a.total_cmp(&b));
}
#[test]
fn test_try_from_64_() {
let result = f64::try_from_f64_(3.7);
assert!(result.is_ok());
}
#[test]
fn test_try_from_64_error_infinite() {
let result = f64::try_from_f64_(f64::INFINITY);
assert!(result.is_err());
}
#[test]
fn test_try_from_64_error_nan() {
let result = f64::try_from_f64_(f64::NAN);
assert!(result.is_err());
}
#[test]
fn test_trunc_() {
let value: f64 = 3.7;
let result = value.trunc_();
assert_eq!(result, value.trunc());
}
#[test]
fn test_two_() {
let value = f64::two_();
assert_eq!(value, 2.0);
}
}
#[cfg(feature = "rug")]
mod rug100 {
use super::*;
use rug::{float, Float};
const PRECISION: u32 = 100;
#[test]
fn test_atan2_() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 27.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 13.0));
let result = a.clone().atan2_(&b);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.atan2(&b.0)))
);
}
#[test]
fn test_ceil_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
let result = value.clone().ceil_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.ceil()))
);
}
#[test]
fn test_clamp_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 5.0));
let min = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let max = RealRug::<PRECISION>(Float::with_val(PRECISION, 7.0));
let result = value.clone().clamp_(&min, &max);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.clamp(&min.0, &max.0)))
);
}
#[test]
fn test_classify_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
let result = value.classify_();
assert_eq!(result, value.0.classify());
}
#[test]
fn test_copysign_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.5));
let sign = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
let result = value.clone().copysign_(&sign);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.copysign(&sign.0)))
);
}
#[test]
fn test_epsilon_() {
let rug_eps = rug::Float::u_pow_u(2, PRECISION - 1)
.complete(PRECISION.into())
.recip();
println!("eps: {}", rug_eps);
let eps = RealRug::<PRECISION>::epsilon_();
assert_eq!(eps, RealRug::<PRECISION>(rug_eps.clone()));
let mut new_eps = Float::with_val(PRECISION, 1.);
new_eps.next_up();
new_eps -= Float::with_val(PRECISION, 1.);
assert_eq!(new_eps, rug_eps.clone());
println!("new_eps: {}", new_eps);
let one = RealRug::<PRECISION>::one();
let result = RealRug::<PRECISION>(new_eps / Float::with_val(PRECISION, 2.)) + &one;
assert_eq!(result, one);
}
#[test]
fn test_exp_m1_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().exp_m1_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.exp_m1()))
);
}
#[test]
fn test_floor_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
let result = value.clone().floor_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.floor()))
);
}
#[test]
fn test_fract_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
let result = value.clone().fract_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.fract()))
);
}
#[test]
fn test_hypot_() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = a.clone().hypot_(&b);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.hypot(&b.0)))
);
}
#[test]
fn test_infinity_() {
let inf = RealRug::<PRECISION>::infinity_();
assert_eq!(
inf,
RealRug::<PRECISION>(Float::with_val(PRECISION, float::Special::Infinity))
);
}
#[test]
fn test_is_sign_negative_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
assert!(value.is_sign_negative_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -0.0));
assert!(value.is_sign_negative_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.0));
assert!(!value.is_sign_negative_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 1.0));
assert!(!value.is_sign_negative_());
}
#[test]
fn test_is_sign_positive_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
assert!(!value.is_sign_positive_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -0.0));
assert!(!value.is_sign_positive_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.0));
assert!(value.is_sign_positive_());
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 1.0));
assert!(value.is_sign_positive_());
}
#[test]
fn test_ln_1p_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
let result = value.clone().ln_1p_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.ln_1p()))
);
}
#[test]
fn test_neg_infinity_() {
let inf = RealRug::<PRECISION>::neg_infinity_();
assert_eq!(
inf,
RealRug::<PRECISION>(Float::with_val(PRECISION, float::Special::NegInfinity))
);
}
#[test]
fn test_max_() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = a.clone().max_(&b);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.max(&b.0)))
);
}
#[test]
fn test_min_() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = a.clone().min_(&b);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.min(&b.0)))
);
}
#[test]
fn test_mul_add_mul_mut() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let c = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let d = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
let mut result = a.clone();
result.mul_add_mul_mut_(&b, &c, &d);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(
PRECISION,
a.0.mul_add(&b.0, &(c.0 * &d.0))
))
);
}
#[test]
fn test_mul_sub_mul_mut() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let c = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let d = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
let mut result = a.clone();
result.mul_sub_mul_mut_(&b, &c, &d);
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(
PRECISION,
a.0.mul_add(&b.0, &(-c.0 * &d.0))
))
);
}
#[test]
fn test_negative_one_() {
let value = RealRug::<PRECISION>::negative_one_();
assert_eq!(
value,
RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0))
);
}
#[test]
fn test_one_() {
let value = RealRug::<PRECISION>::one();
assert_eq!(value, RealRug::<PRECISION>(Float::with_val(PRECISION, 1.0)));
}
#[test]
fn test_round_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.5));
let result = value.clone().round_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.round()))
);
}
#[test]
fn test_round_ties_even_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.5));
let result = value.clone().round_ties_even_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.round_even()))
);
}
#[test]
fn test_signum_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -3.5));
let result = value.clone().signum_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.signum()))
);
}
#[test]
fn test_total_cmp_() {
let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
let result = a.total_cmp_(&b);
assert_eq!(result, a.0.total_cmp(&b.0));
}
#[test]
fn test_try_from_64_() {
let result = RealRug::<PRECISION>::try_from_f64_(3.7);
assert!(result.is_ok());
}
#[test]
fn test_try_from_64_error_infinite() {
let result = RealRug::<PRECISION>::try_from_f64_(f64::INFINITY);
assert!(result.is_err());
}
#[test]
fn test_try_from_64_error_nan() {
let result = RealRug::<PRECISION>::try_from_f64_(f64::NAN);
assert!(result.is_err());
}
#[test]
fn test_trunc_() {
let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
let result = value.clone().trunc_();
assert_eq!(
result,
RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.trunc()))
);
}
#[test]
fn test_two_() {
let value = RealRug::<PRECISION>::two_();
assert_eq!(value, RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0)));
}
}
}
}