#![deny(rustdoc::broken_intra_doc_links)]
#![feature(box_patterns)]
#![feature(error_generic_member_access)]
#![feature(trait_alias)]
pub mod algorithms;
pub mod backends;
pub mod core;
pub mod functions;
pub mod kernels;
pub mod prelude;
pub mod scalars;
mod macros;
use crate::{
algorithms::neumaier_sum::NeumaierAddable,
core::{
errors::{ErrorsRawRealToInteger, ErrorsTryFromf64},
traits::{NumKernel, validation::FpChecks},
},
functions::{
ACos, ACosH, ASin, ASinH, ATan, ATan2, ATanH, Abs, Arg, Arithmetic, Clamp, Classify,
ComplexScalarConstructors, ComplexScalarGetParts, ComplexScalarMutateParts,
ComplexScalarSetParts, Conjugate, Cos, CosH, Exp, ExpM1, HyperbolicFunctions, Hypot, Ln,
Ln1p, Log2, Log10, LogarithmFunctions, Max, Min, MulAddRef, Pow,
PowComplexBaseRealExponentErrors, PowIntExponent, PowRealBaseRealExponentErrors,
Reciprocal, Rounding, Sign, Sin, SinH, Sqrt, Tan, TanH, TotalCmp, TrigonometricFunctions,
},
kernels::{ComplexValidated, RawRealTrait, RawScalarTrait, RealValidated},
};
use num::{Complex, One, Zero};
use rand::{Rng, distr::Distribution};
use serde::{Deserialize, Serialize};
use std::{
fmt::{Debug, Display},
ops::{Mul, MulAssign, Neg},
};
use try_create::IntoInner;
pub use crate::backends::native64::validated::{
ComplexNative64StrictFinite, ComplexNative64StrictFiniteInDebug, Native64StrictFinite,
Native64StrictFiniteInDebug, RealNative64StrictFinite, RealNative64StrictFiniteInDebug,
};
#[cfg(feature = "rug")]
pub use crate::backends::rug::validated::{
ComplexRugStrictFinite, RealRugStrictFinite, RugStrictFinite,
};
pub use approx;
pub(crate) mod scalar_kind {
pub trait Sealed {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Real;
impl Sealed for Real {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Complex;
impl Sealed for Complex {}
}
pub trait ScalarCore = Sized
+ Clone
+ Debug
+ Display
+ PartialEq
+ Send
+ Sync
+ Serialize
+ for<'a> Deserialize<'a>
+ 'static;
pub trait FpScalar:
ScalarCore
+ Zero
+ One
+ IntoInner<InnerType: RawScalarTrait>
+ Arithmetic
+ Abs<Output = Self::RealType>
+ Sqrt
+ PowIntExponent<RawType = Self::InnerType>
+ TrigonometricFunctions
+ HyperbolicFunctions
+ LogarithmFunctions
+ Exp
+ FpChecks
+ Neg<Output = Self>
+ MulAddRef
+ Reciprocal
+ NeumaierAddable
+ RandomSampleFromF64
{
type Kind: scalar_kind::Sealed;
type RealType: RealScalar<RealType = Self::RealType>;
fn as_raw_ref(&self) -> &Self::InnerType;
}
pub trait Constants: Sized {
fn epsilon() -> Self;
fn negative_one() -> Self;
fn one_div_2() -> Self;
fn pi() -> Self;
fn two_pi() -> Self;
fn pi_div_2() -> Self;
fn two() -> Self;
fn max_finite() -> Self;
fn min_finite() -> Self;
fn ln_2() -> Self;
fn ln_10() -> Self;
fn log10_2() -> Self;
fn log2_10() -> Self;
fn log2_e() -> Self;
fn log10_e() -> Self;
fn e() -> Self;
}
pub trait RealScalar:
FpScalar<RealType = Self, InnerType = Self::RawReal>
+ Sign
+ Rounding
+ Constants
+ PartialEq<f64>
+ PartialOrd
+ PartialOrd<f64>
+ Max
+ Min
+ ATan2
+ for<'a> Pow<&'a Self, Error = PowRealBaseRealExponentErrors<Self::RawReal>>
+ Clamp
+ Classify
+ ExpM1
+ Hypot
+ Ln1p
+ TotalCmp
+ TryFrom<f64>
{
type RawReal: RawRealTrait;
fn kernel_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
fn kernel_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
#[must_use = "this `Result` may contain an error that should be handled"]
fn try_from_f64(value: f64) -> Result<Self, ErrorsTryFromf64<Self::RawReal>>;
fn from_f64(value: f64) -> Self {
Self::try_from_f64(value).expect("RealScalar::from_f64() failed: invalid f64 value")
}
fn truncate_to_usize(self) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>> {
let raw: Self::RawReal = self.into_inner();
raw.truncate_to_usize()
}
}
pub trait ComplexScalar:
ComplexScalarMutateParts
+ Conjugate
+ Arg<Output = Self::RealType>
+ for<'a> Mul<&'a Self::RealType, Output = Self>
+ for<'a> MulAssign<&'a Self::RealType>
+ for<'a> Pow<&'a Self::RealType, Error = PowComplexBaseRealExponentErrors<Self::RawComplex>>
{
#[inline(always)]
fn scale(self, c: &Self::RealType) -> Self {
self * c
}
#[inline(always)]
fn scale_mut(&mut self, c: &Self::RealType) {
*self *= c;
}
fn into_parts(self) -> (Self::RealType, Self::RealType);
}
#[inline(always)]
pub fn try_vec_f64_into_vec_real<RealType: RealScalar>(
vec: Vec<f64>,
) -> Result<Vec<RealType>, ErrorsTryFromf64<RealType::RawReal>> {
vec.into_iter().map(|v| RealType::try_from_f64(v)).collect()
}
#[inline(always)]
pub fn vec_f64_into_vec_real<RealType: RealScalar>(vec: Vec<f64>) -> Vec<RealType> {
try_vec_f64_into_vec_real(vec).expect(
"The conversion from f64 to RealType failed, which should not happen in a well-defined numerical kernel."
)
}
pub trait RandomSampleFromF64: Sized + Clone {
fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
where
D: Distribution<f64>,
R: Rng + ?Sized;
fn sample_iter_from<D, R>(dist: &D, rng: &mut R, n: usize) -> impl Iterator<Item = Self>
where
D: Distribution<f64>,
R: Rng + ?Sized,
{
(0..n).map(move |_| Self::sample_from(dist, rng))
}
}
impl RandomSampleFromF64 for f64 {
#[inline]
fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
where
D: Distribution<f64>,
R: Rng + ?Sized,
{
dist.sample(rng)
}
}
impl RandomSampleFromF64 for Complex<f64> {
#[inline]
fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
where
D: Distribution<f64>,
R: Rng + ?Sized,
{
let re = dist.sample(rng);
let im = dist.sample(rng);
Complex::new(re, im)
}
}
impl<K> RandomSampleFromF64 for RealValidated<K>
where
K: NumKernel,
{
#[inline]
fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
where
D: Distribution<f64>,
R: Rng + ?Sized,
{
loop {
let value_f64 = dist.sample(rng);
let value = RealValidated::try_from_f64(value_f64);
if let Ok(validated_value) = value {
return validated_value;
}
}
}
}
impl<K> RandomSampleFromF64 for ComplexValidated<K>
where
K: NumKernel,
{
#[inline]
fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
where
D: Distribution<f64>,
R: Rng + ?Sized,
{
let re = RealValidated::<K>::sample_from(dist, rng);
let im = RealValidated::<K>::sample_from(dist, rng);
ComplexValidated::new_complex(re, im)
}
}
pub fn new_random_vec<T, D, R>(n: usize, distribution: &D, rng: &mut R) -> Vec<T>
where
T: RandomSampleFromF64,
D: Distribution<f64>,
R: Rng + ?Sized,
{
T::sample_iter_from(distribution, rng, n).collect()
}
#[cfg(test)]
mod tests {
use super::*;
use num::Complex;
use num_traits::MulAddAssign;
use std::ops::{Add, Div, Sub};
mod functions_general_type {
use super::*;
fn test_recip<RealType: RealScalar>() {
let a = RealType::two();
let a = a.try_reciprocal().unwrap();
let expected = RealType::one_div_2();
assert_eq!(a, expected);
}
fn test_zero<RealType: RealScalar>() {
let a = RealType::zero();
assert_eq!(a, 0.0);
}
fn test_one<RealType: RealScalar>() {
let a = RealType::one();
assert_eq!(a, 1.0);
}
fn test_add<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
where
for<'a> &'a ScalarType:
Add<ScalarType, Output = ScalarType> + Add<&'a ScalarType, Output = ScalarType>,
{
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);
let c = &a + &b;
assert_eq!(c, c_expected);
}
fn test_sub<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
where
for<'a> &'a ScalarType:
Sub<ScalarType, Output = ScalarType> + Sub<&'a ScalarType, Output = ScalarType>,
{
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);
let c = &a - &b;
assert_eq!(c, c_expected);
}
fn test_mul<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
where
for<'a> &'a ScalarType:
Mul<ScalarType, Output = ScalarType> + Mul<&'a ScalarType, Output = ScalarType>,
{
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);
let c = &a * &b;
assert_eq!(c, c_expected);
}
fn test_div<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
where
for<'a> &'a ScalarType:
Div<ScalarType, Output = ScalarType> + Div<&'a ScalarType, Output = ScalarType>,
{
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);
let c = &a / &b;
assert_eq!(c, c_expected);
}
fn test_mul_complex_with_real<ComplexType: ComplexScalar>(
a: ComplexType,
b: ComplexType::RealType,
a_times_b_expected: ComplexType,
) {
let a_times_b = a.clone().scale(&b);
assert_eq!(a_times_b, a_times_b_expected);
let a_times_b = a.clone() * &b;
assert_eq!(a_times_b, a_times_b_expected);
}
fn test_mul_assign_complex_with_real<ComplexType: ComplexScalar>(
a: ComplexType,
b: ComplexType::RealType,
a_times_b_expected: ComplexType,
) {
let mut a_times_b = a.clone();
a_times_b.scale_mut(&b);
assert_eq!(a_times_b, a_times_b_expected);
}
fn test_neg_assign_real<RealType: RealScalar>() {
let mut a = RealType::one();
a.neg_assign();
let a_expected = RealType::try_from_f64(-1.).unwrap();
assert_eq!(a, a_expected);
}
fn test_add_assign_real<RealType: RealScalar>() {
let mut a = RealType::try_from_f64(1.0).unwrap();
let b = RealType::try_from_f64(2.0).unwrap();
a += &b;
let a_expected = RealType::try_from_f64(3.0).unwrap();
assert_eq!(a, a_expected);
a += b;
let a_expected = RealType::try_from_f64(5.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_sub_assign_real<RealType: RealScalar>() {
let mut a = RealType::try_from_f64(1.0).unwrap();
let b = RealType::try_from_f64(2.0).unwrap();
a -= &b;
let a_expected = RealType::try_from_f64(-1.0).unwrap();
assert_eq!(a, a_expected);
a -= b;
let a_expected = RealType::try_from_f64(-3.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_mul_assign_real<RealType: RealScalar>() {
let mut a = RealType::try_from_f64(1.0).unwrap();
let b = RealType::try_from_f64(2.0).unwrap();
a *= &b;
let a_expected = RealType::try_from_f64(2.0).unwrap();
assert_eq!(a, a_expected);
a *= b;
let a_expected = RealType::try_from_f64(4.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_div_assign_real<RealType: RealScalar>() {
let mut a = RealType::try_from_f64(4.0).unwrap();
let b = RealType::try_from_f64(2.0).unwrap();
a /= &b;
let a_expected = RealType::try_from_f64(2.0).unwrap();
assert_eq!(a, a_expected);
a /= b;
let a_expected = RealType::try_from_f64(1.0).unwrap();
assert_eq!(a, a_expected);
}
fn test_mul_add_ref_real<RealType: RealScalar>() {
let a = RealType::try_from_f64(2.0).unwrap();
let b = RealType::try_from_f64(3.0).unwrap();
let c = RealType::try_from_f64(1.0).unwrap();
let d_expected = RealType::try_from_f64(7.0).unwrap();
let d = a.mul_add_ref(&b, &c);
assert_eq!(d, d_expected);
}
fn test_sin_real<RealType: RealScalar>() {
let a = RealType::zero();
let a = a.sin();
let expected = RealType::zero();
assert_eq!(a, expected);
}
fn test_cos_real<RealType: RealScalar>() {
let a = RealType::zero();
let a = a.cos();
let expected = RealType::one();
assert_eq!(a, expected);
}
fn test_abs_real<RealType: RealScalar>() {
let a = RealType::try_from_f64(-1.).unwrap();
let abs: RealType = a.abs();
let expected = RealType::one();
assert_eq!(abs, expected);
}
mod native64 {
use super::*;
mod real {
use super::*;
#[test]
fn zero() {
test_zero::<f64>();
}
#[test]
fn one() {
test_one::<f64>();
}
#[test]
fn recip() {
test_recip::<f64>();
}
#[test]
fn add() {
let a = 1.0;
let b = 2.0;
let c_expected = 3.0;
test_add(a, b, c_expected);
}
#[test]
fn sub() {
let a = 1.0;
let b = 2.0;
let c_expected = -1.0;
test_sub(a, b, c_expected);
}
#[test]
fn mul() {
let a = 2.0;
let b = 3.0;
let c_expected = 6.0;
test_mul(a, b, c_expected);
}
#[test]
fn div() {
let a = 6.;
let b = 2.;
let c_expected = 3.;
test_div(a, b, c_expected);
}
#[test]
fn neg_assign() {
test_neg_assign_real::<f64>();
}
#[test]
fn add_assign() {
test_add_assign_real::<f64>();
}
#[test]
fn sub_assign() {
test_sub_assign_real::<f64>();
}
#[test]
fn mul_assign() {
test_mul_assign_real::<f64>();
}
#[test]
fn div_assign() {
test_div_assign_real::<f64>();
}
#[test]
fn mul_add_ref() {
test_mul_add_ref_real::<f64>();
}
#[test]
fn from_f64() {
let v_native64 = f64::try_from_f64(16.25).unwrap();
assert_eq!(v_native64, 16.25);
}
#[test]
fn abs() {
test_abs_real::<f64>();
}
#[test]
fn acos() {
let a = 0.;
let pi_over_2 = a.acos();
let expected = std::f64::consts::FRAC_PI_2;
assert_eq!(pi_over_2, expected);
}
#[test]
fn asin() {
let a = 1.;
let pi_over_2 = a.asin();
let expected = std::f64::consts::FRAC_PI_2;
assert_eq!(pi_over_2, expected);
}
#[test]
fn cos() {
test_cos_real::<f64>();
}
#[test]
fn sin() {
test_sin_real::<f64>();
}
#[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_02() {
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();
println!("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 = std::f64::consts::E;
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_02() {
let value: f64 = 2.0;
let result = value.try_reciprocal().unwrap();
assert_eq!(result, value.recip());
}
#[test]
fn test_sin_02() {
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 add() {
let a = Complex::new(1., 2.);
let b = Complex::new(3., 4.);
let c_expected = Complex::new(4., 6.);
test_add(a, b, c_expected);
}
#[test]
fn sub() {
let a = Complex::new(3., 2.);
let b = Complex::new(1., 4.);
let c_expected = Complex::new(2., -2.);
test_sub(a, b, c_expected);
}
#[test]
fn mul() {
let a = Complex::new(3., 2.);
let b = Complex::new(1., 4.);
let c_expected = Complex::new(-5., 14.);
test_mul(a, b, c_expected);
}
#[test]
fn div() {
let a = Complex::new(-5., 14.);
let b = Complex::new(1., 4.);
let c_expected = Complex::new(3., 2.);
test_div(a, b, c_expected);
}
#[test]
fn add_assign() {
let mut a = Complex::new(1., 2.);
let b = Complex::new(3., 4.);
a += &b;
let a_expected = Complex::new(4., 6.);
assert_eq!(a, a_expected);
a += b;
let a_expected = Complex::new(7., 10.);
assert_eq!(a, a_expected);
}
#[test]
fn sub_assign() {
let mut a = Complex::new(3., 2.);
let b = Complex::new(2., 4.);
a -= &b;
let a_expected = Complex::new(1., -2.);
assert_eq!(a, a_expected);
a -= b;
let a_expected = Complex::new(-1., -6.);
assert_eq!(a, a_expected);
}
#[test]
fn mul_assign() {
let mut a = Complex::new(3., 2.);
let b = Complex::new(2., 4.);
a *= &b;
let a_expected = Complex::new(-2., 16.);
assert_eq!(a, a_expected);
a *= b;
let a_expected = Complex::new(-68., 24.);
assert_eq!(a, a_expected);
}
#[test]
fn div_assign() {
let mut a = Complex::new(-68., 24.);
let b = Complex::new(2., 4.);
a /= &b;
let a_expected = Complex::new(-2., 16.);
assert_eq!(a, a_expected);
a /= b;
let a_expected = Complex::new(3., 2.);
assert_eq!(a, a_expected);
}
#[test]
fn from_f64() {
let v = Complex::new(16.25, 2.);
assert_eq!(v.real_part(), 16.25);
assert_eq!(v.imag_part(), 2.);
}
#[test]
fn conj() {
let v = Complex::new(16.25, 2.);
let v_conj = v.conjugate();
assert_eq!(v_conj.real_part(), 16.25);
assert_eq!(v_conj.imag_part(), -2.);
}
#[test]
fn neg_assign() {
let mut a = Complex::new(1., 2.);
a.neg_assign();
let a_expected = Complex::new(-1., -2.);
assert_eq!(a, a_expected);
}
#[test]
fn abs() {
let a = Complex::new(-3., 4.);
let abs = a.abs();
let expected = 5.;
assert_eq!(abs, expected);
}
#[test]
fn mul_add_ref() {
let a = Complex::new(2., -3.);
let b = Complex::new(3., 1.);
let c = Complex::new(1., -4.);
let d_expected = Complex::new(10., -11.);
let d = a.mul_add_ref(&b, &c);
assert_eq!(d, d_expected);
}
#[test]
fn mul_complex_with_real() {
let a = Complex::new(1., 2.);
let b = 3.;
let a_times_b_expected = Complex::new(3., 6.);
test_mul_complex_with_real(a, b, a_times_b_expected);
}
#[test]
fn mul_assign_complex_with_real() {
let a = Complex::new(1., 2.);
let b = 3.;
let a_times_b_expected = Complex::new(3., 6.);
test_mul_assign_complex_with_real(a, b, a_times_b_expected);
}
#[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_01() {
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();
println!("result = {result:?}");
assert_eq!(result, value.exp());
}
#[test]
fn test_ln() {
let value: Complex<f64> = Complex::new(std::f64::consts::E, 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_01() {
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 rug_ {
use super::*;
use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
use rug::ops::CompleteRound;
use try_create::{IntoInner, TryNew};
const PRECISION: u32 = 100;
mod real {
use super::*;
use rug::Float;
#[test]
fn zero() {
test_zero::<RealRugStrictFinite<64>>();
test_zero::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn one() {
test_one::<RealRugStrictFinite<64>>();
test_one::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn recip() {
test_recip::<RealRugStrictFinite<64>>();
test_recip::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn add() {
let a = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
test_add(a, b, c_expected);
}
#[test]
fn sub() {
let a = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.0).unwrap();
test_sub(a, b, c_expected);
}
#[test]
fn mul() {
let a = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(6.0).unwrap();
test_mul(a, b, c_expected);
}
#[test]
fn div() {
let a = RealRugStrictFinite::<PRECISION>::try_from_f64(6.).unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.).unwrap();
let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(3.).unwrap();
test_div(a, b, c_expected);
}
#[test]
fn neg_assign() {
test_neg_assign_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn add_assign() {
test_add_assign_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn sub_assign() {
test_sub_assign_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn mul_assign() {
test_mul_assign_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn div_assign() {
test_div_assign_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn mul_add_ref() {
test_mul_add_ref_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn abs() {
test_abs_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn acos() {
{
let a = RealRugStrictFinite::<53>::zero();
let pi_over_2 = RealRugStrictFinite::<53>::acos(a);
let expected = rug::Float::with_val(53, std::f64::consts::FRAC_PI_2);
assert_eq!(pi_over_2.as_ref(), &expected);
}
{
let a = RealRugStrictFinite::<100>::zero();
let pi_over_2 = RealRugStrictFinite::<100>::acos(a);
let expected = rug::Float::with_val(
100,
rug::Float::parse("1.5707963267948966192313216916397").unwrap(),
);
assert_eq!(pi_over_2.as_ref(), &expected);
}
}
#[test]
fn asin() {
{
let a = RealRugStrictFinite::<53>::one();
let pi_over_2 = RealRugStrictFinite::<53>::asin(a);
let expected = rug::Float::with_val(53, std::f64::consts::FRAC_PI_2);
assert_eq!(pi_over_2.as_ref(), &expected);
}
{
let a = RealRugStrictFinite::<100>::one();
let pi_over_2 = RealRugStrictFinite::<100>::asin(a);
let expected = rug::Float::with_val(
100,
rug::Float::parse("1.5707963267948966192313216916397").unwrap(),
);
assert_eq!(pi_over_2.as_ref(), &expected);
}
}
#[test]
fn cos() {
test_cos_real::<RealRugStrictFinite<64>>();
test_cos_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn sin() {
test_sin_real::<RealRugStrictFinite<64>>();
test_sin_real::<RealRugStrictFinite<PRECISION>>();
}
#[test]
fn dot_product() {
let a = &[
RealRugStrictFinite::<100>::one(),
RealRugStrictFinite::<100>::try_from_f64(2.).unwrap(),
];
let b = &[
RealRugStrictFinite::<100>::try_from_f64(2.).unwrap(),
RealRugStrictFinite::<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 = RealRugStrictFinite::<100>::try_new(
rug::Float::dot(a.into_iter().zip(b)).complete(100),
)
.unwrap();
assert_eq!(value.as_ref(), &rug::Float::with_val(100, 0.));
}
#[test]
fn test_acos() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().acos();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().acos()
))
.unwrap()
);
}
#[test]
fn test_acosh() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.5))
.unwrap();
let result = value.clone().acosh();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().acosh()
))
.unwrap()
);
}
#[test]
fn test_asin() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().asin();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().asin()
))
.unwrap()
);
}
#[test]
fn test_asinh() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().asinh();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().asinh()
))
.unwrap()
);
}
#[test]
fn test_atan() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().atan();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().atan()
))
.unwrap()
);
}
#[test]
fn test_atanh() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().atanh();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().atanh()
))
.unwrap()
);
}
#[test]
fn test_cos_02() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().cos();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().cos()
))
.unwrap()
);
}
#[test]
fn test_cosh() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().cosh();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().cosh()
))
.unwrap()
);
}
#[test]
fn test_exp() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().exp();
println!("result = {result:?}");
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().exp()
))
.unwrap()
);
}
#[test]
fn test_is_finite() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
assert!(value.is_finite());
let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
f64::INFINITY,
));
assert!(value.is_err());
}
#[test]
fn test_is_infinite() {
let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
f64::INFINITY,
));
assert!(value.is_err());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
assert!(!value.is_infinite());
}
#[test]
fn test_ln() {
let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
std::f64::consts::E,
))
.unwrap();
let result = value.clone().ln();
println!("result = {result:?}");
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().ln()
))
.unwrap()
);
}
#[test]
fn test_log10() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 10.0))
.unwrap();
let result = value.clone().log10();
println!("result = {result:?}");
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().log10()
))
.unwrap()
);
}
#[test]
fn test_log2() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 8.0))
.unwrap();
let result = value.clone().log2();
println!("result = {result:?}");
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().log2()
))
.unwrap()
);
}
#[test]
fn test_recip_02() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
.unwrap();
let result = value.clone().try_reciprocal().unwrap();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().recip()
))
.unwrap()
);
}
#[test]
fn test_sin_02() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().sin();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().sin()
))
.unwrap()
);
}
#[test]
fn test_sinh() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().sinh();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().sinh()
))
.unwrap()
);
}
#[test]
fn sqrt() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = value.clone().sqrt();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().sqrt()
))
.unwrap()
);
}
#[test]
fn try_sqrt() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = value.clone().try_sqrt().unwrap();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().sqrt()
))
.unwrap()
);
assert!(
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -4.0))
.unwrap()
.try_sqrt()
.is_err()
)
}
#[test]
fn test_tan() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().tan();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().tan()
))
.unwrap()
);
}
#[test]
fn test_tanh() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().tanh();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().tanh()
))
.unwrap()
);
}
#[test]
fn test_mul_add() {
let a =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
.unwrap();
let b =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let c =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = a.clone().mul_add_ref(&b, &c);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(
a.into_inner() * b.as_ref() + c.as_ref()
)
.unwrap()
);
}
}
mod complex {
use super::*;
use rug::Float;
#[test]
fn add() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 4.))
.unwrap();
let c_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(4., 6.))
.unwrap();
test_add(a, b, c_expected);
}
#[test]
fn sub() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
.unwrap();
let c_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., -2.))
.unwrap();
test_sub(a, b, c_expected);
}
#[test]
fn mul() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
.unwrap();
let c_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-5., 14.))
.unwrap();
test_mul(a, b, c_expected);
}
#[test]
fn div() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-5., 14.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
.unwrap();
let c_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
.unwrap();
test_div(a, b, c_expected);
}
#[test]
fn add_assign() {
let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 4.))
.unwrap();
a += &b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(4., 6.))
.unwrap();
assert_eq!(a, a_expected);
a += b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(7., 10.))
.unwrap();
assert_eq!(a, a_expected);
}
#[test]
fn sub_assign() {
let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
.unwrap();
a -= &b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., -2.))
.unwrap();
assert_eq!(a, a_expected);
a -= b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., -6.))
.unwrap();
assert_eq!(a, a_expected);
}
#[test]
fn mul_assign() {
let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
.unwrap();
a *= &b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., 16.))
.unwrap();
assert_eq!(a, a_expected);
a *= b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-68., 24.))
.unwrap();
assert_eq!(a, a_expected);
}
#[test]
fn div_assign() {
let mut a =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-68., 24.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
.unwrap();
a /= &b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., 16.))
.unwrap();
assert_eq!(a, a_expected);
a /= b;
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
.unwrap();
assert_eq!(a, a_expected);
}
#[test]
fn from_f64() {
let v_100bits =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(16.25, 2.))
.unwrap();
assert_eq!(
ComplexRugStrictFinite::<PRECISION>::real_part(&v_100bits),
16.25
);
assert_eq!(
ComplexRugStrictFinite::<PRECISION>::imag_part(&v_100bits),
2.
);
let v_53bits =
ComplexRugStrictFinite::<53>::try_from(Complex::new(16.25, 2.)).unwrap();
assert_eq!(ComplexRugStrictFinite::<53>::real_part(&v_53bits), 16.25);
assert_eq!(ComplexRugStrictFinite::<53>::imag_part(&v_53bits), 2.);
let v_53bits_2 =
ComplexRugStrictFinite::<53>::try_from(Complex::new(16.25, 2.)).unwrap();
assert_eq!(ComplexRugStrictFinite::<53>::real_part(&v_53bits_2), 16.25);
assert_eq!(ComplexRugStrictFinite::<53>::imag_part(&v_53bits_2), 2.);
}
#[test]
#[should_panic]
fn from_f64_failing() {
let _v_52bits =
ComplexRugStrictFinite::<52>::try_from(Complex::new(16.25, 2.)).unwrap();
}
#[test]
fn conj() {
let v = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(16.25, 2.))
.unwrap();
let v_conj = ComplexRugStrictFinite::<PRECISION>::conjugate(v);
assert_eq!(
ComplexRugStrictFinite::<PRECISION>::real_part(&v_conj),
16.25
);
assert_eq!(ComplexRugStrictFinite::<PRECISION>::imag_part(&v_conj), -2.);
}
#[test]
fn neg_assign() {
let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
.unwrap();
a.neg_assign();
let a_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., -2.))
.unwrap();
assert_eq!(a, a_expected);
}
#[test]
fn abs() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-3., 4.))
.unwrap();
let abs = a.abs();
let abs_expected = RealRugStrictFinite::<100>::try_from_f64(5.).unwrap();
assert_eq!(abs, abs_expected);
}
#[test]
fn mul_add_ref() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., -3.))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 1.))
.unwrap();
let c = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., -4.))
.unwrap();
let d_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(10., -11.))
.unwrap();
let d = a.mul_add_ref(&b, &c);
assert_eq!(d, d_expected);
}
#[test]
fn mul_complex_with_real() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
.unwrap();
let b = RealRugStrictFinite::<100>::try_from_f64(3.).unwrap();
let a_times_b_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 6.))
.unwrap();
test_mul_complex_with_real(a, b, a_times_b_expected);
}
#[test]
fn mul_assign_complex_with_real() {
let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
.unwrap();
let b = RealRugStrictFinite::<100>::try_from_f64(3.).unwrap();
let a_times_b_expected =
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 6.))
.unwrap();
test_mul_assign_complex_with_real(a, b, a_times_b_expected);
}
#[test]
fn dot_product() {
let a = &[
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 3.))
.unwrap(),
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
.unwrap(),
];
let b = &[
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., -5.))
.unwrap(),
ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-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 = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::dot(a.clone().into_iter().zip(a.clone()))
.complete((100, 100)),
)
.unwrap();
assert_eq!(
a_times_a.as_ref(),
&rug::Complex::with_val(100, (-20., 22.))
);
let a_times_b = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::dot(a.clone().into_iter().zip(b.clone()))
.complete((100, 100)),
)
.unwrap();
assert_eq!(
a_times_b.as_ref(),
&rug::Complex::with_val(100, (-13., -3.))
);
let b_times_a = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::dot(b.into_iter().zip(a)).complete((100, 100)),
)
.unwrap();
assert_eq!(
b_times_a.as_ref(),
&rug::Complex::with_val(100, (-13., -3.))
);
}
#[test]
fn test_acos() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().acos();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().acos()
))
.unwrap()
);
}
#[test]
fn test_acosh() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (1.5, 0.5)),
)
.unwrap();
let result = value.clone().acosh();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().acosh()
))
.unwrap()
);
}
#[test]
fn test_asin() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().asin();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().asin()
))
.unwrap()
);
}
#[test]
fn test_asinh() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().asinh();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().asinh()
))
.unwrap()
);
}
#[test]
fn test_atan() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().atan();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().atan()
))
.unwrap()
);
}
#[test]
fn test_atanh() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().atanh();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().atanh()
))
.unwrap()
);
}
#[test]
fn test_cos_01() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().cos();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().cos()
))
.unwrap()
);
}
#[test]
fn test_cosh() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().cosh();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().cosh()
))
.unwrap()
);
}
#[test]
fn test_exp() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().exp();
println!("result = {result:?}");
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().exp()
))
.unwrap()
);
}
#[test]
fn test_is_finite() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
assert!(value.is_finite());
let value =
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
100,
(Float::with_val(PRECISION, f64::INFINITY), 0.5),
));
assert!(value.is_err());
}
#[test]
fn test_is_infinite() {
let value =
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
100,
(Float::with_val(PRECISION, f64::INFINITY), 0.5),
));
assert!(value.is_err());
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
assert!(!value.is_infinite());
}
#[test]
fn test_ln() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (std::f64::consts::E, 1.0)),
)
.unwrap();
let result = value.clone().ln();
println!("result = {result:?}");
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().ln()
))
.unwrap()
);
}
#[test]
fn test_log10() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (10.0, 1.0)),
)
.unwrap();
let result = value.clone().log10();
println!("result = {result:?}");
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().log10()
))
.unwrap()
);
}
#[test]
fn test_log2() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (8.0, 1.0)),
)
.unwrap();
let result = value.clone().log2();
println!("result = {result:?}");
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().ln() / rug::Float::with_val(PRECISION, 2.).ln()
))
.unwrap()
);
}
#[test]
fn test_recip() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (2.0, 0.0)),
)
.unwrap();
let result = value.clone().try_reciprocal().unwrap();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().recip()
))
.unwrap()
);
}
#[test]
fn test_sin_01() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().sin();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().sin()
))
.unwrap()
);
}
#[test]
fn test_sinh() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().sinh();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().sinh()
))
.unwrap()
);
}
#[test]
fn sqrt() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (4.0, 1.0)),
)
.unwrap();
let result = value.clone().sqrt();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().sqrt()
))
.unwrap()
);
}
#[test]
fn try_sqrt() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (4.0, 1.0)),
)
.unwrap();
let result = value.clone().try_sqrt().unwrap();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().sqrt()
))
.unwrap()
);
}
#[test]
fn test_tan() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().tan();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().tan()
))
.unwrap()
);
}
#[test]
fn test_tanh() {
let value = ComplexRugStrictFinite::<PRECISION>::try_new(
rug::Complex::with_val(PRECISION, (0.5, 0.5)),
)
.unwrap();
let result = value.clone().tanh();
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
value.into_inner().tanh()
))
.unwrap()
);
}
#[test]
fn test_mul_add() {
let a = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
(2.0, 1.0),
))
.unwrap();
let b = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
(3.0, 1.0),
))
.unwrap();
let c = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
(4.0, 1.0),
))
.unwrap();
let result = a.clone().mul_add_ref(&b, &c);
assert_eq!(
result,
ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
PRECISION,
a.as_ref() * b.as_ref() + c.as_ref()
))
.unwrap()
);
}
}
}
}
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.kernel_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 = Clamp::clamp_ref(value, &min, &max);
assert_eq!(result, f64::clamp(value, min, max));
}
#[test]
fn test_classify() {
let value: f64 = 3.7;
let result = Classify::classify(&value);
assert_eq!(result, f64::classify(value));
}
#[test]
fn test_copysign() {
let value: f64 = 3.5;
let sign: f64 = -1.0;
let result = value.kernel_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 = ExpM1::exp_m1(value);
assert_eq!(result, f64::exp_m1(value));
}
#[test]
fn test_floor() {
let value: f64 = 3.7;
let result = value.kernel_floor();
assert_eq!(result, value.floor());
}
#[test]
fn test_fract() {
let value: f64 = 3.7;
let result = value.kernel_fract();
assert_eq!(result, value.fract());
}
#[test]
fn test_hypot() {
let a: f64 = 3.0;
let b: f64 = 4.0;
let result = Hypot::hypot(a, &b);
assert_eq!(result, f64::hypot(a, b));
}
#[test]
fn test_is_sign_negative() {
let value: f64 = -1.0;
assert!(value.kernel_is_sign_negative());
let value: f64 = -0.0;
assert!(value.kernel_is_sign_negative());
let value: f64 = 0.0;
assert!(!value.kernel_is_sign_negative());
let value: f64 = 1.0;
assert!(!value.kernel_is_sign_negative());
}
#[test]
fn test_is_sign_positive() {
let value: f64 = -1.0;
assert!(!value.kernel_is_sign_positive());
let value: f64 = -0.0;
assert!(!value.kernel_is_sign_positive());
let value: f64 = 0.0;
assert!(value.kernel_is_sign_positive());
let value: f64 = 1.0;
assert!(value.kernel_is_sign_positive());
}
#[test]
fn test_ln_1p() {
let value: f64 = 0.5;
let result = Ln1p::ln_1p(value);
assert_eq!(result, f64::ln_1p(value));
}
#[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 max_finite() {
let max = f64::max_finite();
assert_eq!(max, f64::MAX);
}
#[test]
fn min_finite() {
let min = f64::min_finite();
assert_eq!(min, f64::MIN);
}
#[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 mut result = a;
result.kernel_mul_add_mul_mut(&b, &c, &d);
a.mul_add_assign(b, c * d);
assert_eq!(result, a);
}
#[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 mut result = a;
result.kernel_mul_sub_mul_mut(&b, &c, &d);
a.mul_add_assign(b, -c * d);
assert_eq!(result, a);
}
#[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.kernel_round();
assert_eq!(result, value.round());
}
#[test]
fn test_round_ties_even() {
let value: f64 = 3.5;
let result = value.kernel_round_ties_even();
assert_eq!(result, value.round_ties_even());
}
#[test]
fn test_signum() {
let value: f64 = -3.5;
let result = value.kernel_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.kernel_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 crate::backends::rug::validated::RealRugStrictFinite;
use rug::{Float, ops::CompleteRound};
use try_create::{IntoInner, TryNew};
const PRECISION: u32 = 100;
#[test]
fn from_f64() {
let v_100bits = RealRugStrictFinite::<100>::try_from_f64(16.25).unwrap();
assert_eq!(v_100bits, 16.25);
let v_53bits = RealRugStrictFinite::<53>::try_from_f64(16.25).unwrap();
assert_eq!(v_53bits, 16.25);
let v_53bits_2 = RealRugStrictFinite::<53>::try_from_f64(16.25).unwrap();
assert_eq!(v_53bits_2, 16.25);
}
#[test]
#[should_panic]
fn from_f64_failing() {
let _v_52bits = RealRugStrictFinite::<52>::try_from_f64(16.25).unwrap();
}
#[test]
fn max_finite() {
let max = RealRugStrictFinite::<53>::max_finite();
assert_eq!(
max.as_ref(),
&rug::Float::with_val(
53,
rug::Float::parse("1.0492893582336937e323228496").unwrap()
)
);
}
#[test]
fn min_finite() {
let min = RealRugStrictFinite::<53>::min_finite();
assert_eq!(
min.as_ref(),
&rug::Float::with_val(
53,
rug::Float::parse("-1.0492893582336937e323228496").unwrap()
)
);
}
#[test]
fn test_atan2() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 27.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 13.0))
.unwrap();
let result = a.clone().atan2(&b);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
a.into_inner().atan2(b.as_ref())
))
.unwrap()
);
}
#[test]
fn test_ceil() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
.unwrap();
let result = value.clone().kernel_ceil();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().ceil()
))
.unwrap()
);
}
#[test]
fn test_clamp() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0))
.unwrap();
let min =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let max =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 7.0))
.unwrap();
let result = value.clone().clamp_ref(&min, &max);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().clamp_ref(min.as_ref(), max.as_ref())
))
.unwrap()
);
}
#[test]
fn test_classify() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
.unwrap();
let result = value.classify();
assert_eq!(result, value.into_inner().classify());
}
#[test]
fn test_copysign() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
.unwrap();
let sign =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
.unwrap();
let result = value.clone().kernel_copysign(&sign);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().copysign(sign.as_ref())
))
.unwrap()
);
}
#[test]
fn test_epsilon() {
let rug_eps = rug::Float::u_pow_u(2, PRECISION - 1)
.complete(PRECISION)
.recip();
let eps = RealRugStrictFinite::<PRECISION>::epsilon();
assert_eq!(
eps,
RealRugStrictFinite::<PRECISION>::try_new(rug_eps.clone()).unwrap()
);
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());
let one = RealRugStrictFinite::<PRECISION>::one();
let result = RealRugStrictFinite::<PRECISION>::try_new(
new_eps / Float::with_val(PRECISION, 2.),
)
.unwrap()
+ &one;
assert_eq!(result, one);
}
#[test]
fn test_exp_m1() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().exp_m1();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().exp_m1()
))
.unwrap()
);
}
#[test]
fn test_floor() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
.unwrap();
let result = value.clone().kernel_floor();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().floor()
))
.unwrap()
);
}
#[test]
fn test_fract() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
.unwrap();
let result = value.clone().kernel_fract();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().fract()
))
.unwrap()
);
}
#[test]
fn test_hypot() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = a.clone().hypot(&b);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
a.into_inner().hypot(b.as_ref())
))
.unwrap()
);
}
#[test]
fn test_is_sign_negative() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
.unwrap();
assert!(value.kernel_is_sign_negative());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -0.0))
.unwrap();
assert!(value.kernel_is_sign_negative());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0))
.unwrap();
assert!(!value.kernel_is_sign_negative());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
.unwrap();
assert!(!value.kernel_is_sign_negative());
}
#[test]
fn test_is_sign_positive() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
.unwrap();
assert!(!value.kernel_is_sign_positive());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -0.0))
.unwrap();
assert!(!value.kernel_is_sign_positive());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0))
.unwrap();
assert!(value.kernel_is_sign_positive());
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
.unwrap();
assert!(value.kernel_is_sign_positive());
}
#[test]
fn test_ln_1p() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
.unwrap();
let result = value.clone().ln_1p();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().ln_1p()
))
.unwrap()
);
}
#[test]
fn test_max() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = a.max_by_ref(&b);
assert_eq!(
result,
&RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
a.clone().into_inner().max(b.as_ref())
))
.unwrap()
);
}
#[test]
fn test_min() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = a.min_by_ref(&b);
assert_eq!(
result,
&RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
a.clone().into_inner().min(b.as_ref())
))
.unwrap()
);
}
#[test]
fn test_mul_add_mul_mut() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let c = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let d = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
.unwrap();
let mut result = a.clone();
result.kernel_mul_add_mul_mut(&b, &c, &d);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
a.into_inner()
.mul_add_ref(b.as_ref(), &(c.into_inner() * d.as_ref()))
))
.unwrap()
);
}
#[test]
fn test_mul_sub_mul_mut() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let c = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let d = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
.unwrap();
let mut result = a.clone();
result.kernel_mul_sub_mul_mut(&b, &c, &d);
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
a.into_inner()
.mul_add_ref(b.as_ref(), &(-c.into_inner() * d.as_ref()))
))
.unwrap()
);
}
#[test]
fn test_negative_one() {
let value = RealRugStrictFinite::<PRECISION>::negative_one();
assert_eq!(
value,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
.unwrap()
);
}
#[test]
fn test_one() {
let value = RealRugStrictFinite::<PRECISION>::one();
assert_eq!(
value,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
.unwrap()
);
}
#[test]
fn test_round() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
.unwrap();
let result = value.clone().kernel_round();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().round()
))
.unwrap()
);
}
#[test]
fn test_round_ties_even() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
.unwrap();
let result = value.clone().kernel_round_ties_even();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().round_even()
))
.unwrap()
);
}
#[test]
fn test_signum() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.5))
.unwrap();
let result = value.clone().kernel_signum();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().signum()
))
.unwrap()
);
}
#[test]
fn test_total_cmp() {
let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
.unwrap();
let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
.unwrap();
let result = a.total_cmp(&b);
assert_eq!(result, a.into_inner().total_cmp(b.as_ref()));
}
#[test]
fn test_try_from_64() {
let result = RealRugStrictFinite::<PRECISION>::try_from_f64(3.7);
assert!(result.is_ok());
}
#[test]
fn test_try_from_64_error_infinite() {
let result = RealRugStrictFinite::<PRECISION>::try_from_f64(f64::INFINITY);
assert!(result.is_err());
}
#[test]
fn test_try_from_64_error_nan() {
let result = RealRugStrictFinite::<PRECISION>::try_from_f64(f64::NAN);
assert!(result.is_err());
}
#[test]
fn test_trunc() {
let value =
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
.unwrap();
let result = value.clone().kernel_trunc();
assert_eq!(
result,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
PRECISION,
value.into_inner().trunc()
))
.unwrap()
);
}
#[test]
fn test_two() {
let value = RealRugStrictFinite::<PRECISION>::two();
assert_eq!(
value,
RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
.unwrap()
);
}
}
}
mod util_funcs {
use crate::{
backends::native64::validated::RealNative64StrictFinite, new_random_vec,
try_vec_f64_into_vec_real,
};
use rand::{SeedableRng, distr::Uniform, rngs::StdRng};
#[test]
fn test_new_random_vec_deterministic() {
let seed = [42; 32];
let mut rng1 = StdRng::from_seed(seed);
let mut rng2 = StdRng::from_seed(seed);
let uniform = Uniform::new(-1.0, 1.0).unwrap();
let vec1: Vec<f64> = new_random_vec(10, &uniform, &mut rng1);
let vec2: Vec<RealNative64StrictFinite> = new_random_vec(10, &uniform, &mut rng2);
assert_eq!(vec1.len(), 10);
assert_eq!(vec2.len(), 10);
for i in 0..10 {
assert_eq!(&vec1[i], vec2[i].as_ref());
}
}
#[test]
fn test_try_vec_f64_into_vec_real_success() {
let input = vec![1.0, -2.5, 1e10];
let result = try_vec_f64_into_vec_real::<RealNative64StrictFinite>(input);
assert!(result.is_ok());
let output = result.unwrap();
assert_eq!(output[0].as_ref(), &1.0);
assert_eq!(output[1].as_ref(), &-2.5);
}
#[test]
fn test_try_vec_f64_into_vec_real_fail() {
let input = vec![1.0, f64::NAN, 3.0];
let result = try_vec_f64_into_vec_real::<RealNative64StrictFinite>(input);
assert!(result.is_err());
}
}
}