ftl_numkernel/
lib.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2#![feature(error_generic_member_access)]
3
4//! This library contains the structures and traits that define which ***numerical kernel*** (i.e. the representation/manipulation of floating point numbers) must be used.
5//!
6//! At the time of writing, you can use 2 numerical kernels:
7//! - [`Native64`], is the numerical kernel in which the floating point numbers are
8//!   described by the Rust's native (64bit) representation, as described by the ANSI/IEEE Std 754-1985;
9//! - `Rug`, is the numerical kernel in which the floating point numbers are described with **arbitrary precision**.
10//!   The precision of the number is described by the generic parameter `PRECISION`.
11//!   This numerical kernel is available if the library is compiled with the optional flag `--features=rug` and uses the Rust library [`rug`](https://crates.io/crates/rug).
12
13pub mod errors;
14pub mod functions;
15pub mod neumaier_compensated_sum;
16
17use crate::{
18    errors::{
19        ComplexValueErrors, ComplexValueValidator, RealValueErrors, RealValueValidator,
20        TryFromf64Errors,
21    },
22    functions::{Abs, Reciprocal, Sqrt},
23};
24use num::{Complex, One, Zero};
25use num_traits::ops::mul_add::MulAddAssign;
26use serde::{de::DeserializeOwned, Serialize};
27use std::{
28    backtrace::Backtrace,
29    cmp::Ordering,
30    fmt::{self},
31    num::FpCategory,
32};
33use thiserror::Error;
34
35// Conditional compilation for the `rug` feature
36#[cfg(feature = "rug")]
37use derive_more::{
38    Add, AddAssign, AsRef, Display, Div, DivAssign, LowerExp, Mul, MulAssign, Neg, Sub, SubAssign,
39};
40
41// Conditional compilation for when the `rug` feature is not enabled
42#[cfg(not(feature = "rug"))]
43use std::{
44    fmt::LowerExp,
45    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
46};
47
48// Conditional compilation for the `rug` feature
49#[cfg(feature = "rug")]
50use duplicate::duplicate_item;
51
52// Conditional compilation for the `rug` feature
53#[cfg(feature = "rug")]
54use rug::ops::{CompleteRound, Pow as RugPow};
55
56// Conditional compilation for the `rug` feature
57#[cfg(feature = "rug")]
58use serde::Deserialize;
59
60//-------------------------------------------------------------
61/// Trait representing the conversion of a type into its inner type.
62pub trait IntoInner {
63    /// The inner type.
64    type Target;
65
66    /// Returns the inner type consuming the original value.
67    fn into_inner(self) -> Self::Target;
68}
69//-------------------------------------------------------------
70
71//-------------------------------------------------------------
72#[derive(Debug, Error)]
73pub enum RecipErrors<ValueType: Sized> {
74    /// The input value is NaN.
75    #[error("the input value is NaN!")]
76    NanInput { backtrace: Backtrace },
77
78    /// The output value is NaN.
79    #[error("the output value is NaN!")]
80    NanOutput { backtrace: Backtrace },
81
82    /// The input value is zero.
83    #[error("the input value is zero!")]
84    DivisionByZero { backtrace: Backtrace },
85
86    /// The output value is [subnormal](https://en.wikipedia.org/wiki/Subnormal_number).
87    #[error("the output value ({value:?}) is subnormal!")]
88    Underflow {
89        value: ValueType,
90        backtrace: Backtrace,
91    },
92
93    /// The output value cannot be represented becaus an overflow has occourred.
94    #[error("The output value cannot be represented becaus an overflow has occourred")]
95    Overflow { backtrace: Backtrace },
96}
97//-------------------------------------------------------------
98
99//-------------------------------------------------------------
100
101/// Compound negation and assignment.
102pub trait NegAssign {
103    /// Performs the negation.
104    fn neg_assign(&mut self);
105}
106
107#[duplicate::duplicate_item(
108    T;
109    [f64];
110    [Complex<f64>];
111)]
112/// Compound negation and assignment.
113impl NegAssign for T {
114    /// Performs the negation of `self`.
115    fn neg_assign(&mut self) {
116        *self = -*self;
117    }
118}
119
120// Conditional compilation for the `rug` feature
121#[cfg(feature = "rug")]
122#[duplicate::duplicate_item(
123    T;
124    [rug::Float];
125    [rug::Complex];
126)]
127/// Compound negation and assignment.
128impl NegAssign for T {
129    /// Performs the negation of `self`.
130    fn neg_assign(&mut self) {
131        <T as rug::ops::NegAssign>::neg_assign(self);
132    }
133}
134//-------------------------------------------------------------
135
136//------------------------------------------------------------------
137pub trait Pow<ExponentType> {
138    /// Raises th number `self` to the power `exponent`.
139    fn pow_(self, exponent: ExponentType) -> Self;
140}
141
142#[duplicate::duplicate_item(
143    T;
144    [f64];
145    [Complex<f64>];
146)]
147impl Pow<f64> for T {
148    /// Raises th number `self` to the power `exponent`.
149    fn pow_(self, exponent: f64) -> Self {
150        self.powf(exponent)
151    }
152}
153
154#[duplicate::duplicate_item(
155    T exponent_type func_name;
156    [f64] [i32] [powi];
157    [Complex<f64>] [i32] [powi];
158    [Complex<f64>] [u32] [powu];
159)]
160impl Pow<exponent_type> for T {
161    /// Raises th number `self` to the power `exponent`.
162    fn pow_(self, exponent: exponent_type) -> Self {
163        self.func_name(exponent)
164    }
165}
166
167#[duplicate::duplicate_item(
168    T exponent_type func_name;
169    [f64] [i8]  [powi];
170    [f64] [u8]  [powi];
171    [f64] [i16] [powi];
172    [f64] [u16] [powi];
173    [Complex<f64>] [i8]  [powi];
174    [Complex<f64>] [u8]  [powu];
175    [Complex<f64>] [i16] [powi];
176    [Complex<f64>] [u16] [powu];
177)]
178impl Pow<exponent_type> for T {
179    /// Raises th number `self` to the power `exponent`.
180    fn pow_(self, exponent: exponent_type) -> Self {
181        self.func_name(exponent.into())
182    }
183}
184
185#[duplicate::duplicate_item(
186    T exponent_type func_name;
187    [f64] [u32]   [powi];
188    [f64] [i64]   [powi];
189    [f64] [u64]   [powi];
190    [f64] [i128]  [powi];
191    [f64] [u128]  [powi];
192    [f64] [usize] [powi];
193    [Complex<f64>] [i64]   [powi];
194    [Complex<f64>] [i128]  [powi];
195    [Complex<f64>] [u64]   [powu];
196    [Complex<f64>] [u128]  [powu];
197    [Complex<f64>] [usize] [powu];
198)]
199impl Pow<exponent_type> for T {
200    /// Raises th number `self` to the power `exponent`.
201    fn pow_(self, exponent: exponent_type) -> Self {
202        self.func_name(exponent.try_into().unwrap())
203    }
204}
205
206pub trait PowTrait<T: NumKernel>:
207    Pow<T::RealType>
208    + Pow<i8>
209    + Pow<u8>
210    + Pow<i16>
211    + Pow<u16>
212    + Pow<i32>
213    + Pow<u32>
214    + Pow<i64>
215    + Pow<u64>
216    + Pow<i128>
217    + Pow<u128>
218    + Pow<usize>
219{
220}
221
222impl PowTrait<Native64> for f64 {}
223impl PowTrait<Native64> for Complex<f64> {}
224//------------------------------------------------------------------------------------------------
225
226//-------------------------------------------------------------
227/// Trait representing the arithmetic operations (e.g. addition, subtraction, multiplication division, negation).
228pub trait Arithmetic: Sized
229where
230    Self: Add<Self, Output = Self>
231        + for<'a> Add<&'a Self, Output = Self>
232        + AddAssign
233        + for<'a> AddAssign<&'a Self>
234        + Sub<Output = Self>
235        + for<'a> Sub<&'a Self, Output = Self>
236        + SubAssign
237        + for<'a> SubAssign<&'a Self>
238        + Mul<Output = Self>
239        + for<'a> Mul<&'a Self, Output = Self>
240        + MulAssign
241        + for<'a> MulAssign<&'a Self>
242        + Div<Output = Self>
243        + for<'a> Div<&'a Self, Output = Self>
244        + DivAssign
245        + for<'a> DivAssign<&'a Self>
246        + Neg
247        + NegAssign
248        + LowerExp,
249{
250}
251
252/// Trait for the multiplication between a complex number (on the left hand side) and a real number (on the right hand side).
253/// The result of these binary operation will be always a complex number.
254///
255/// # Note
256///
257/// We only permit multiplication between complex and real numbers.
258/// Addition and subtraction of a complex number with a real number is not allowed for safety reasons.
259pub trait MulComplexLeft<T: NumKernel>:
260    Mul<T::RealType, Output = T::ComplexType>
261    + for<'a> Mul<&'a T::RealType, Output = T::ComplexType>
262    + MulAssign<T::RealType>
263    + for<'a> MulAssign<&'a T::RealType>
264{
265}
266
267/// Trait for the multiplication between a real number (on the left hand side) and a complex number (on the right hand side).
268/// The result of these binary operation will be always a complex number.
269///
270/// # Note
271///
272/// We only permit multiplication between  real and complex numbers.
273/// Addition and subtraction of a real number with a complex number is not allowed for safety reasons.
274pub trait MulComplexRight<T: NumKernel>: Mul<T::ComplexType, Output = T::ComplexType> {}
275
276impl Arithmetic for f64 {}
277impl Arithmetic for Complex<f64> {}
278impl MulComplexRight<Native64> for f64 {}
279impl MulComplexLeft<Native64> for Complex<f64> {}
280
281// Conditional compilation for the `rug` feature
282#[cfg(feature = "rug")]
283impl Arithmetic for rug::Float {}
284
285// Conditional compilation for the `rug` feature
286#[cfg(feature = "rug")]
287impl Arithmetic for rug::Complex {}
288
289//------------------------------------------------------------------------------------------------------------
290
291//------------------------------------------------------------------------------------------------------------
292
293/// Numerical kernel specifier to be used as generic argument (or associated type) in order to indicate
294/// that the floating point values that must be used are the Rust's native `f64` and/or `Complex<f64>`.
295#[derive(Debug, Clone, PartialEq, PartialOrd)]
296pub struct Native64;
297
298// Conditional compilation for the `rug` feature
299#[cfg(feature = "rug")]
300/// Numerical kernel specifier to be used as generic argument (or associated type) in order to indicate
301/// that the floating point values that must be used are [`rug::Float`] and/or [`rug::Complex`].
302///
303/// # Generic argument
304/// `PRECISION` - value used to specify the precision (in bit) used in the construction of the various [`rug::Float`]/[`rug::Complex`] objects.
305#[derive(Debug, Clone, PartialEq, PartialOrd)]
306pub struct Rug<const PRECISION: u32>;
307
308/// Trait used to indicate the type of floating point number that is used.
309pub trait NumKernel: Clone + fmt::Debug + PartialEq + Sync {
310    type RawRealType: Sized + fmt::Debug + RealValueValidator + PartialOrd<f64>;
311    type RawComplexType: Sized + fmt::Debug + ComplexValueValidator<RealType = Self::RawRealType>;
312
313    /// The type for a real scalar value in this numerical kernel.
314    type RealType: FunctionsRealType<Self> + Serialize + DeserializeOwned;
315
316    /// The type for a complex scalar value in this numerical kernel.
317    type ComplexType: FunctionsComplexType<Self> + Serialize + DeserializeOwned;
318}
319
320/// Implement the [`NumKernel`] trait for [`Native64`]
321impl NumKernel for Native64 {
322    type RawRealType = f64;
323    type RawComplexType = Complex<f64>;
324
325    /// The type for a real scalar value in this numerical kernel.
326    type RealType = f64;
327
328    /// The type for a complex scalar value in this numerical kernel.
329    type ComplexType = Complex<f64>;
330}
331
332/// Implement the [`NumKernel`] trait for Rug with arbitrary precision
333#[cfg(feature = "rug")]
334impl<const PRECISION: u32> NumKernel for Rug<PRECISION> {
335    type RawRealType = rug::Float;
336    type RawComplexType = rug::Complex;
337
338    /// The type for a real scalar value in this numerical kernel.
339    type RealType = RealRug<PRECISION>;
340
341    /// The type for a complex scalar value in this numerical kernel.
342    type ComplexType = ComplexRug<PRECISION>;
343}
344
345//------------------------------------------------------------------------------------------------
346
347//------------------------------------------------------------------------------------------------
348#[duplicate::duplicate_item(
349    trait_name func_name trait_comment func_comment;
350    [ACos] [acos_] ["This trait provides the interface for the *inverse cosine* function."] ["Computes the *inverse cosine* of `self`, rounding to the nearest."];
351    [ASin] [asin_] ["This trait provides the interface for the *inverse sine* function."] ["Computes the *inverse sine* of `self`, rounding to the nearest."];
352    [ATan] [atan_] ["This trait provides the interface for the *inverse tangent* function."] ["Computes the *inverse tangent* of `self`, rounding to the nearest."];
353    [Cos] [cos_] ["This trait provides the interface for the *cosine* function."] ["Computes the *cosine* of `self`, rounding to the nearest."];
354    [Sin] [sin_] ["This trait provides the interface for the *sine* function."] ["Computes the *sine* of `self`, rounding to the nearest."];
355    [Tan] [tan_] ["This trait provides the interface for the *tangent* function."] ["Computes the *tangent* of `self`, rounding to the nearest."];
356    [ACosH] [acosh_] ["This trait provides the interface for the *inverse hyperbolic cosine* function."] ["Computes the *inverse hyperbolic cosine* of `self`, rounding to the nearest."];
357    [ASinH] [asinh_] ["This trait provides the interface for the *inverse hyperbolic* function."] ["Computes the *inverse hyperbolic sine* of `self`, rounding to the nearest."];
358    [ATanH] [atanh_] ["This trait provides the interface for the *inverse hyperbolic tangent* function."] ["Computes the *inverse hyperbolic tangent* of `self`, rounding to the nearest."];
359    [CosH] [cosh_] ["This trait provides the interface for the *hyperbolic cosine* function."] ["Computes the *hyperbolic cosine* of `self`, rounding to the nearest."];
360    [SinH] [sinh_] ["This trait provides the interface for the *hyperbolic sine* function."] ["Computes the *hyperbolic sine* of `self`, rounding to the nearest."];
361    [TanH] [tanh_] ["This trait provides the interface for the *hyperbolic tangent* function."] ["Computes the *tangent* of `self`, rounding to the nearest."];
362    [Exp] [exp_] ["This trait provides the interface for the *exponential* function."] ["Computes `e^(self)`, rounding to the nearest."];
363    [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."];
364    [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."];
365    [Log2] [log2_] ["This trait provides the interface for the *base 2 logarithm* function."] ["Computes the *base 2 logarithm* of `self`, rounding to the nearest."];
366)]
367#[doc = trait_comment]
368pub trait trait_name {
369    #[doc = func_comment]
370    fn func_name(self) -> Self;
371}
372
373#[duplicate::duplicate_item(
374    trait_name func_name implementation T func_comment;
375    duplicate!{
376        [
377            T_nested; [f64]; [Complex::<f64>]
378        ]
379        [ACos] [acos_] [acos(self)] [T_nested] ["Computes the *inverse cosine* of `self`, rounding to the nearest."];
380        [ASin] [asin_] [asin(self)] [T_nested] ["Computes the *inverse sine* of `self`, rounding to the nearest."];
381        [ATan] [atan_] [atan(self)] [T_nested] ["Computes the *inverse tangent* of `self`, rounding to the nearest."];
382        [Cos] [cos_] [cos(self)] [T_nested] ["Computes the *cosine* of `self`, rounding to the nearest."];
383        [Sin] [sin_] [sin(self)] [T_nested] ["Computes the *sine* of `self`, rounding to the nearest."];
384        [Tan] [tan_] [tan(self)] [T_nested] ["Computes the *tangent* of `self`, rounding to the nearest."];
385        [ACosH] [acosh_] [acosh(self)] [T_nested] ["Computes the *inverse hyperbolic cosine* of `self`, rounding to the nearest."];
386        [ASinH] [asinh_] [asinh(self)] [T_nested] ["Computes the *inverse hyperbolic sine* of `self`, rounding to the nearest."];
387        [ATanH] [atanh_] [atanh(self)] [T_nested] ["Computes the *inverse hyperbolic tangent* of `self`, rounding to the nearest."];
388        [CosH] [cosh_] [cosh(self)] [T_nested] ["Computes the *hyperbolic cosine* of `self`, rounding to the nearest."];
389        [SinH] [sinh_] [sinh(self)] [T_nested] ["Computes the *hyperbolic sine* of `self`, rounding to the nearest."];
390        [TanH] [tanh_] [tanh(self)] [T_nested] ["Computes the *hyperbolic tangent* of `self`, rounding to the nearest."];
391        [Exp] [exp_] [exp(self)] [T_nested] ["Computes `e^(self)`, rounding to the nearest."];
392        [Ln] [ln_] [ln(self)] [T_nested] ["Computes the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) of `self`, rounding to the nearest."];
393        [Log10] [log10_] [log10(self)] [T_nested] ["Computes the [*common logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of `self`, rounding to the nearest."];
394        [Log2] [log2_] [log2(self)] [T_nested] ["Computes the *base 2 logarithm* of `self`, rounding to the nearest."];
395    }
396)]
397impl trait_name for T {
398    #[doc = func_comment]
399    #[inline(always)]
400    fn func_name(self) -> Self {
401        T::implementation
402    }
403}
404
405#[cfg(feature = "rug")]
406#[duplicate_item(
407    trait_name func_name implementation T func_comment;
408    duplicate!{
409        [
410            T_nested; [RealRug<PRECISION>]; [ComplexRug<PRECISION>]
411        ]
412        [ACos] [acos_] [self.0.acos()] [T_nested] ["Computes the *inverse cosine* of `self`, rounding to the nearest."];
413        [ASin] [asin_] [self.0.asin()] [T_nested] ["Computes the *inverse sine* of `self`, rounding to the nearest."];
414        [ATan] [atan_] [self.0.atan()] [T_nested] ["Computes the *inverse tangent* of `self`, rounding to the nearest."];
415        [Cos] [cos_] [self.0.cos()] [T_nested] ["Computes the *cosine* of `self`, rounding to the nearest."];
416        [Sin] [sin_] [self.0.sin()] [T_nested] ["Computes the *sine* of `self`, rounding to the nearest."];
417        [Tan] [tan_] [self.0.tan()] [T_nested] ["Computes the *tangent* of `self`, rounding to the nearest."];
418        [ACosH] [acosh_] [self.0.acosh()] [T_nested] ["Computes the *inverse hyperbolic cosine* of `self`, rounding to the nearest."];
419        [ASinH] [asinh_] [self.0.asinh()] [T_nested] ["Computes the *inverse hyperbolic sine* of `self`, rounding to the nearest."];
420        [ATanH] [atanh_] [self.0.atanh()] [T_nested] ["Computes the *inverse hyperbolic tangent* of `self`, rounding to the nearest."];
421        [CosH] [cosh_] [self.0.cosh()] [T_nested] ["Computes the *hyperbolic cosine* of `self`, rounding to the nearest."];
422        [SinH] [sinh_] [self.0.sinh()] [T_nested] ["Computes the *hyperbolic sine* of `self`, rounding to the nearest."];
423        [TanH] [tanh_] [self.0.tanh()] [T_nested] ["Computes the *hyperbolic tangent* of `self`, rounding to the nearest."];
424        [Exp] [exp_] [self.0.exp()] [T_nested] ["Computes `e^(self)`, rounding to the nearest."];
425        [Ln] [ln_] [self.0.ln()]  [T_nested] ["Computes the [*natural logarithm*](https://en.wikipedia.org/wiki/Natural_logarithm) of `self`, rounding to the nearest."];
426        [Log10] [log10_] [self.0.log10()] [T_nested] ["Computes the [*common logarithm*](https://en.wikipedia.org/wiki/Common_logarithm) of `self`, rounding to the nearest."];
427    }
428)]
429impl<const PRECISION: u32> trait_name for T {
430    #[doc = func_comment]
431    #[inline(always)]
432    fn func_name(self) -> Self {
433        Self(implementation)
434    }
435}
436
437#[cfg(feature = "rug")]
438impl<const PRECISION: u32> Log2 for RealRug<PRECISION> {
439    /// Computes the *base 2 logarithm* of `self`, rounding to the nearest.
440    #[inline(always)]
441    fn log2_(self) -> Self {
442        Self(self.0.log2())
443    }
444}
445
446#[cfg(feature = "rug")]
447impl<const PRECISION: u32> Log2 for ComplexRug<PRECISION> {
448    /// Computes the *base 2 logarithm* of `self`, rounding to the nearest.
449    #[inline(always)]
450    fn log2_(self) -> Self {
451        Self(rug::Complex::with_val(
452            PRECISION,
453            self.0.log10() / rug::Float::with_val(PRECISION, 2.).log10(),
454        ))
455    }
456}
457//------------------------------------------------------------------------------------------------
458
459//------------------------------------------------------------------------------------------------
460pub trait TrigonometricFunctions: ACos + ASin + ATan + Sin + Cos + Tan {}
461impl TrigonometricFunctions for f64 {}
462impl TrigonometricFunctions for Complex<f64> {}
463
464#[cfg(feature = "rug")]
465impl<const PRECISION: u32> TrigonometricFunctions for RealRug<PRECISION> {}
466
467#[cfg(feature = "rug")]
468impl<const PRECISION: u32> TrigonometricFunctions for ComplexRug<PRECISION> {}
469//------------------------------------------------------------------------------------------------
470
471//------------------------------------------------------------------------------------------------
472pub trait HyperbolicFunctions: ACosH + ASinH + ATanH + SinH + CosH + TanH {}
473impl HyperbolicFunctions for f64 {}
474impl HyperbolicFunctions for Complex<f64> {}
475
476#[cfg(feature = "rug")]
477impl<const PRECISION: u32> HyperbolicFunctions for RealRug<PRECISION> {}
478
479#[cfg(feature = "rug")]
480impl<const PRECISION: u32> HyperbolicFunctions for ComplexRug<PRECISION> {}
481//------------------------------------------------------------------------------------------------
482
483//------------------------------------------------------------------------------------------------
484#[duplicate::duplicate_item(
485    trait_name func_name trait_comment func_comment;
486    [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."];
487    [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."];
488    [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."];
489    [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)."];
490    [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*."];
491)]
492#[doc = trait_comment]
493pub trait trait_name {
494    #[doc = func_comment]
495    fn func_name(&self) -> bool;
496}
497
498#[duplicate::duplicate_item(
499    trait_name func_name implementation T func_comment;
500    duplicate!{
501        [
502            T_nested; [f64]; [Complex<f64>]
503        ]
504        [IsFinite] [is_finite_] [self.is_finite()] [T_nested] ["Returns `true` if `self` is neither infinite nor NaN."];
505        [IsInfinite] [is_infinite_] [self.is_infinite()] [T_nested] ["Returns `true` if `self` is positive infinity or negative infinity, and `false` otherwise."];
506        [IsNaN] [is_nan_] [self.is_nan()] [T_nested] ["Returns `true` if `self` is NaN."];
507        [IsNormal] [is_normal_] [self.is_normal()] [T_nested] ["Returns `true` if `self` is *normal* (i.e. neither zero, infinite, subnormal, or NaN)."];
508    }
509)]
510impl trait_name for T {
511    #[doc = func_comment]
512    #[inline(always)]
513    fn func_name(&self) -> bool {
514        implementation
515    }
516}
517
518impl IsSubnormal for f64 {
519    /// Returns `true` if `self` is *sub-normal*
520    #[inline(always)]
521    fn is_subnormal_(&self) -> bool {
522        self.classify() == FpCategory::Subnormal
523    }
524}
525
526impl IsSubnormal for Complex<f64> {
527    /// Returns `true` if `self` is *sub-normal*
528    #[inline(always)]
529    fn is_subnormal_(&self) -> bool {
530        self.re.classify() == FpCategory::Subnormal || self.im.classify() == FpCategory::Subnormal
531    }
532}
533
534#[cfg(feature = "rug")]
535#[duplicate::duplicate_item(
536    trait_name func_name implementation func_comment;
537    [IsFinite] [is_finite_] [self.0.is_finite()] ["Returns `true` if `self` is neither infinite nor NaN."];
538    [IsInfinite] [is_infinite_] [self.0.is_infinite()] ["Returns `true` if `self` is positive infinity or negative infinity, and `false` otherwise."];
539    [IsNaN] [is_nan_] [self.0.is_nan()] ["Returns `true` if `self` is NaN."];
540    [IsNormal] [is_normal_] [self.0.is_normal()] ["Returns `true` if `self` is *normal* (i.e. neither zero, infinite, subnormal, or NaN)."];
541    [IsSubnormal] [is_subnormal_] [self.0.classify() == FpCategory::Subnormal] ["Returns `true` if `self` is *sub-normal*."];
542)]
543impl<const PRECISION: u32> trait_name for RealRug<PRECISION> {
544    #[doc = func_comment]
545    #[inline(always)]
546    fn func_name(&self) -> bool {
547        implementation
548    }
549}
550
551#[cfg(feature = "rug")]
552impl<const PRECISION: u32> IsFinite for ComplexRug<PRECISION> {
553    /// Returns `true` if the real and imaginary parts of `self` are neither infinite nor NaN.
554    #[inline(always)]
555    fn is_finite_(&self) -> bool {
556        self.0.real().is_finite() && self.0.imag().is_finite()
557    }
558}
559
560#[cfg(feature = "rug")]
561impl<const PRECISION: u32> IsInfinite for ComplexRug<PRECISION> {
562    /// Returns `true` if the real or the imaginary part of `self` are positive infinity or negative infinity.
563    #[inline(always)]
564    fn is_infinite_(&self) -> bool {
565        self.0.real().is_infinite() || self.0.imag().is_infinite()
566    }
567}
568
569#[cfg(feature = "rug")]
570impl<const PRECISION: u32> IsNaN for ComplexRug<PRECISION> {
571    /// Returns `true` if the real or the imaginary part of `self` are NaN.
572    #[inline(always)]
573    fn is_nan_(&self) -> bool {
574        self.0.real().is_nan() || self.0.imag().is_nan()
575    }
576}
577
578#[cfg(feature = "rug")]
579impl<const PRECISION: u32> IsNormal for ComplexRug<PRECISION> {
580    /// Returns `true` if the real and the imaginary part of `self` are *normal* (i.e. neither zero, infinite, subnormal, or NaN).
581    #[inline(always)]
582    fn is_normal_(&self) -> bool {
583        self.0.real().is_normal() && self.0.imag().is_normal()
584    }
585}
586
587#[cfg(feature = "rug")]
588impl<const PRECISION: u32> IsSubnormal for ComplexRug<PRECISION> {
589    /// Returns `true` if the real and the imaginary part of `self` are *normal* (i.e. neither zero, infinite, subnormal, or NaN).
590    #[inline(always)]
591    fn is_subnormal_(&self) -> bool {
592        self.0.real().classify() == FpCategory::Subnormal
593            || self.0.imag().classify() == FpCategory::Subnormal
594    }
595}
596//------------------------------------------------------------------------------------------------
597
598//------------------------------------------------------------------------------------------------
599pub trait FpChecks: IsFinite + IsInfinite + IsNaN + IsNormal + IsSubnormal {}
600impl FpChecks for f64 {}
601impl FpChecks for Complex<f64> {}
602
603#[cfg(feature = "rug")]
604impl<const PRECISION: u32> FpChecks for RealRug<PRECISION> {}
605
606#[cfg(feature = "rug")]
607impl<const PRECISION: u32> FpChecks for ComplexRug<PRECISION> {}
608//------------------------------------------------------------------------------------------------
609
610//------------------------------------------------------------------------------------------------
611#[cfg(feature = "rug")]
612impl<const PRECISION: u32> Zero for RealRug<PRECISION> {
613    /// Returns the value `zero`.
614    fn zero() -> Self {
615        Self(rug::Float::with_val(PRECISION, 0.))
616    }
617
618    /// Returns `true` if `self` is `+0.0` or `-0.0`.
619    fn is_zero(&self) -> bool {
620        self.0.is_zero()
621    }
622}
623
624#[cfg(feature = "rug")]
625impl<const PRECISION: u32> Zero for ComplexRug<PRECISION> {
626    /// Returns the value `zero`.
627    fn zero() -> Self {
628        Self(rug::Complex::with_val(PRECISION, (0., 0.)))
629    }
630
631    /// Returns `true` if `self` is zero.
632    fn is_zero(&self) -> bool {
633        self.0.is_zero()
634    }
635}
636//------------------------------------------------------------------------------------------------
637
638//------------------------------------------------------------------------------------------------
639#[cfg(feature = "rug")]
640impl<const PRECISION: u32> One for RealRug<PRECISION> {
641    /// Returns the value `1`.
642    fn one() -> Self {
643        Self(rug::Float::with_val(PRECISION, 1.))
644    }
645}
646//------------------------------------------------------------------------------------------------
647
648//------------------------------------------------------------------------------------------------
649/// This trait provide the interface of the function for performing a multiplication and an addition in one fused operation.
650///
651/// # Note
652/// The difference between this trait and [`num::traits::MulAdd`] is that this trait uses references as input arguments
653/// instead of values as used by the function [`num::traits::MulAdd::mul_add()`].
654pub trait MulAdd {
655    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
656    ///
657    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
658    fn mul_add(self, b: &Self, c: &Self) -> Self;
659}
660
661#[duplicate::duplicate_item(
662    T trait_comment;
663    [f64] ["Implementation of the [`MulAdd`] trait for `f64`."];
664    [Complex<f64>] ["Implementation of the [`MulAdd`] trait for `Complex<f64>`."];
665)]
666#[doc = trait_comment]
667impl MulAdd for T {
668    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
669    ///
670    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
671    #[inline(always)]
672    fn mul_add(self, b: &Self, c: &Self) -> Self {
673        <Self as num::traits::MulAdd>::mul_add(self, *b, *c)
674    }
675}
676
677#[cfg(feature = "rug")]
678#[duplicate::duplicate_item(
679    T trait_comment;
680    [RealRug<PRECISION>] ["Implementation of the [`MulAdd`] trait for [`RealRug`]."];
681    [ComplexRug<PRECISION>] ["Implementation of the [`MulAdd`] trait for [`ComplexRug`]."];
682)]
683#[doc = trait_comment]
684impl<const PRECISION: u32> MulAdd for T {
685    /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
686    ///
687    /// `a.mul_add(b, c)` produces a result like `a * &b + &c`.
688    #[inline(always)]
689    fn mul_add(self, b: &Self, c: &Self) -> Self {
690        Self(self.0.mul_add(&b.0, &c.0))
691    }
692}
693//------------------------------------------------------------------------------------------------
694
695//------------------------------------------------------------------------------------------------
696/// This trait represents the functions that can be applied on real and complex numbers.
697pub trait FunctionsGeneralType<T: NumKernel>:
698    Clone
699    + fmt::Debug
700    + fmt::Display
701    + Arithmetic
702    + Sqrt
703    + PowTrait<T>
704    + TrigonometricFunctions
705    + HyperbolicFunctions
706    + Exp
707    + Ln
708    + Log10
709    + Log2
710    + Zero
711    + Abs<Output = T::RealType>
712    + FpChecks
713    + Neg<Output = Self>
714    + MulAdd
715    + Reciprocal
716    + Send
717    + Sync
718{
719}
720//-------------------------------------------------------------------------------------------------------------
721
722//-------------------------------------------------------------------------------------------------------------
723pub trait TryNew: Sized {
724    type ValueType;
725    type Error;
726
727    fn try_new(value: Self::ValueType) -> Result<Self, Self::Error>;
728
729    fn new(value: Self::ValueType) -> Self;
730}
731
732impl TryNew for f64 {
733    type ValueType = f64;
734    type Error = RealValueErrors<f64>;
735
736    #[inline(always)]
737    fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
738        value.validate()
739    }
740
741    #[inline(always)]
742    fn new(value: Self::ValueType) -> Self {
743        if cfg!(debug_assertions) {
744            Self::try_new(value).unwrap()
745        } else {
746            value
747        }
748    }
749}
750
751impl TryNew for Complex<f64> {
752    type ValueType = Complex<f64>;
753    type Error = ComplexValueErrors<f64, Complex<f64>>;
754
755    #[inline(always)]
756    fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
757        value.validate()
758    }
759
760    #[inline(always)]
761    fn new(value: Self::ValueType) -> Self {
762        if cfg!(debug_assertions) {
763            Self::try_new(value).unwrap()
764        } else {
765            value
766        }
767    }
768}
769
770#[cfg(feature = "rug")]
771impl<const PRECISION: u32> TryNew for RealRug<PRECISION> {
772    type ValueType = rug::Float;
773    type Error = RealValueErrors<rug::Float>;
774
775    #[inline(always)]
776    fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
777        assert_eq!(value.prec(), PRECISION,
778            "The precision of the numerical kernel ({PRECISION}) and is different from the precision of the input value ({})!",value.prec());
779
780        let value = value.validate()?;
781        Ok(Self(value))
782    }
783
784    #[inline(always)]
785    fn new(value: Self::ValueType) -> Self {
786        if cfg!(debug_assertions) {
787            Self::try_new(value).unwrap()
788        } else {
789            Self(value)
790        }
791    }
792}
793
794#[cfg(feature = "rug")]
795impl<const PRECISION: u32> TryNew for ComplexRug<PRECISION> {
796    type ValueType = rug::Complex;
797    type Error = ComplexValueErrors<rug::Float, rug::Complex>;
798
799    #[inline(always)]
800    fn try_new(value: Self::ValueType) -> Result<Self, Self::Error> {
801        assert_eq!(value.prec(), (PRECISION, PRECISION),
802            "The precision of the numerical kernel ({PRECISION}) and is different from the precision of the input value ({:?})!",value.prec());
803
804        let value = value.validate()?;
805        Ok(Self(value))
806    }
807
808    #[inline(always)]
809    fn new(value: Self::ValueType) -> Self {
810        if cfg!(debug_assertions) {
811            Self::try_new(value).unwrap()
812        } else {
813            Self(value)
814        }
815    }
816}
817
818//-------------------------------------------------------------------------------------------------------------
819
820//-------------------------------------------------------------------------------------------------------------
821/// This trait represents the functions that can be applied on real numbers.
822pub trait FunctionsRealType<T: NumKernel>:
823    FunctionsGeneralType<T>
824    + PartialEq
825    + PartialEq<f64>
826    + PartialOrd
827    + PartialOrd<f64>
828    + MulComplexRight<T>
829    + One
830{
831    /// Computes the four quadrant arctangent of `self` (y) and `other` (x) in radians.
832    /// - `x = 0`, `y = 0`: `0`
833    /// - `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
834    /// - `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
835    /// - `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
836    fn atan2_(self, other: &Self) -> Self;
837
838    /// Returns the smallest integer greater than or equal to `self`.
839    fn ceil_(self) -> Self;
840
841    /// Clamp the value within the specified bounds.
842    ///
843    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is less than `min`.
844    /// Otherwise this returns `self`.
845    ///
846    /// Note that this function returns `NaN` if the initial value was `NaN` as well.
847    ///
848    /// # Panics
849    /// Panics if `min` > `max`, `min` is `NaN`, or `max` is `NaN`.
850    /// ```
851    /// use ftl_numkernel::{FunctionsGeneralType, FunctionsRealType, IsNaN};
852    ///
853    /// assert!((-3.0f64).clamp_(&-2.0, &1.0) == -2.0);
854    /// assert!((0.0f64).clamp_(&-2.0, &1.0) == 0.0);
855    /// assert!((2.0f64).clamp_(&-2.0, &1.0) == 1.0);
856    /// assert!((f64::NAN).clamp_(&-2.0, &1.0).is_nan_());
857    /// ```
858    fn clamp_(self, min: &Self, max: &Self) -> Self;
859
860    /// Returns the floating point category of the number. If only one property is going to be tested,
861    /// it is generally faster to use the specific predicate instead.
862    /// ```
863    /// use ftl_numkernel::FunctionsRealType;
864    /// use std::num::FpCategory;
865    ///
866    /// let num = 12.4_f64;
867    /// let inf = f64::INFINITY;
868    ///
869    /// assert_eq!(num.classify_(), FpCategory::Normal);
870    /// assert_eq!(inf.classify_(), FpCategory::Infinite);
871    /// ```
872    fn classify_(&self) -> FpCategory;
873
874    /// Returns a number with the magnitude of `self` and the sign of `sign`.
875    fn copysign_(self, sign: &Self) -> Self;
876
877    /// [Machine epsilon] value for `Self`.
878    ///
879    /// This is the difference between `1.0` and the next larger representable number.
880    ///
881    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
882    fn epsilon_() -> Self;
883
884    /// Returns `e^(self) - 1`` in a way that is accurate even if the number is close to zero.
885    fn exp_m1_(self) -> Self;
886
887    /// Returns the largest integer smaller than or equal to `self`.
888    fn floor_(self) -> Self;
889
890    /// Returns the fractional part of `self`.
891    fn fract_(self) -> Self;
892
893    /// Compute the distance between the origin and a point (`self`, `other`) on the Euclidean plane.
894    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `self.abs()` and `other.abs()`.
895    fn hypot_(self, other: &Self) -> Self;
896
897    /// Returns the special value representing the *positive infinity*.
898    fn infinity_() -> Self;
899
900    /// Returns `true` if the value is negative, −0 or NaN with a negative sign.
901    fn is_sign_negative_(&self) -> bool;
902
903    /// Returns `true` if the value is positive, +0 or NaN with a positive sign.
904    fn is_sign_positive_(&self) -> bool;
905
906    /// Returns `ln(1. + self)` (natural logarithm) more accurately than if the operations were performed separately.
907    fn ln_1p_(self) -> Self;
908
909    /// Returns the special value representing the *negative infinity*.
910    fn neg_infinity_() -> Self;
911
912    /// Computes the maximum between `self` and `other`.
913    fn max_(self, other: &Self) -> Self;
914
915    /// Computes the minimum between `self` and `other`.
916    fn min_(self, other: &Self) -> Self;
917
918    /// Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
919    /// `a.mul_add_mul_mut_(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
920    fn mul_add_mul_mut_(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
921
922    /// Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
923    /// `a.mul_sub_mul_mut_(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
924    fn mul_sub_mul_mut_(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
925
926    /// Build and return the (floating point) value -1. represented by the proper type.
927    fn negative_one_() -> Self;
928
929    /// Build and return the (floating point) value 0.5 represented by the proper type.
930    fn one_div_2_() -> Self;
931
932    /// Build and return the (floating point) value π represented by the proper type.
933    fn pi_() -> Self {
934        Self::negative_one_().acos_()
935    }
936
937    /// Build and return the (floating point) value π/2 represented by the proper type.
938    fn pi_div_2_() -> Self {
939        Self::one().asin_()
940    }
941
942    /// Rounds `self` to the nearest integer, rounding half-way cases away from zero.
943    fn round_(self) -> Self;
944
945    /// Returns the nearest integer to a number. Rounds half-way cases to the number with an even least significant digit.
946    ///
947    /// This function always returns the precise result.
948    ///
949    /// # Examples
950    /// ```
951    /// use ftl_numkernel::FunctionsRealType;
952    ///
953    /// let f = 3.3_f64;
954    /// let g = -3.3_f64;
955    /// let h = 3.5_f64;
956    /// let i = 4.5_f64;
957    ///
958    /// assert_eq!(f.round_ties_even_(), 3.0);
959    /// assert_eq!(g.round_ties_even_(), -3.0);
960    /// assert_eq!(h.round_ties_even_(), 4.0);
961    /// assert_eq!(i.round_ties_even_(), 4.0);
962    /// ```
963    fn round_ties_even_(self) -> Self;
964
965    /// Computes the signum.
966    ///
967    /// The returned value is:
968    /// - `1.0` if the value is positive, +0.0 or +∞
969    /// - `−1.0` if the value is negative, −0.0 or −∞
970    /// - `NaN` if the value is NaN
971    fn signum_(self) -> Self;
972
973    fn total_cmp_(&self, other: &Self) -> Ordering;
974
975    /// Try to build a `Self` from a [`f64`].
976    /// The returned value is `Ok` if the input `value` is finite and can be exactly represented by `T::RealType`,
977    /// otherwise the returned value is `TryFromf64Errors`.
978    fn try_from_f64_(value: f64) -> Result<Self, TryFromf64Errors>;
979
980    /// Returns the integer part of `self`. This means that non-integer numbers are always truncated towards zero.
981    ///    
982    /// # Examples
983    /// ```
984    /// use ftl_numkernel::FunctionsRealType;
985    ///
986    /// let f = 3.7_f64;
987    /// let g = 3.0_f64;
988    /// let h = -3.7_f64;
989    ///
990    /// assert_eq!(f.trunc_(), 3.0);
991    /// assert_eq!(g.trunc_(), 3.0);
992    /// assert_eq!(h.trunc_(), -3.0);
993    /// ```
994    fn trunc_(self) -> Self;
995
996    /// Build and return the (floating point) value 1. represented by the proper type.
997    fn two_() -> Self;
998}
999
1000/// This trait represents the functions that can be applied on complex numbers.
1001pub trait FunctionsComplexType<T: NumKernel>:
1002    FunctionsGeneralType<T> + PartialEq + MulComplexLeft<T>
1003{
1004    /// Computes the principal Arg of `self`.
1005    fn arg_(self) -> T::RealType;
1006
1007    /// Creates a complex number of type `T::ComplexType` from its real and imaginary parts.
1008    fn new_(real_part: T::RealType, imag_part: T::RealType) -> Self;
1009
1010    /// Get the real part of the complex number.
1011    fn real_(&self) -> T::RealType;
1012
1013    /// Get the imaginary part of the complex number.
1014    fn imag_(&self) -> T::RealType;
1015
1016    /// Set the value of the real part.
1017    fn set_real_(&mut self, real_part: T::RealType);
1018
1019    /// Set the value of the imaginary part.
1020    fn set_imag_(&mut self, imag_part: T::RealType);
1021
1022    /// Add the value of the the real coefficient `c` to real part of `self`.
1023    fn add_real_(&mut self, c: &T::RealType);
1024
1025    /// Add the value of the the real coefficient `c` to imaginary part of `self`.
1026    fn add_imag_(&mut self, c: &T::RealType);
1027
1028    /// Multiply the value of the real part by the real coefficient `c`.
1029    fn multiply_real_(&mut self, c: &T::RealType);
1030
1031    /// Multiply the value of the imaginary part by the real coefficient `c`.
1032    fn multiply_imag_(&mut self, c: &T::RealType);
1033
1034    /// Computes the complex conjugate.
1035    fn conj_(self) -> Self;
1036
1037    /// Try to build a `Self` from real and imaginary parts as [`f64`] values.
1038    /// The returned value is `Ok` if the input `real_part` and `imag_part` are finite and can be exactly represented by `T::RealType`,
1039    /// otherwise the returned value is `TryFromf64Errors`.
1040    fn try_from_f64_(real_part: f64, imag_part: f64) -> Result<Self, TryFromf64Errors>;
1041}
1042
1043impl FunctionsGeneralType<Native64> for f64 {}
1044
1045impl FunctionsGeneralType<Native64> for Complex<f64> {}
1046
1047impl FunctionsRealType<Native64> for f64 {
1048    /// Computes the four quadrant arctangent of `self` (y) and `other` (x) in radians.
1049    /// - `x = 0`, `y = 0`: `0`
1050    /// - `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
1051    /// - `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
1052    /// - `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
1053    /// ```
1054    /// use ftl_numkernel::{FunctionsGeneralType, FunctionsRealType};
1055    ///
1056    /// let y = 3.0_f64;
1057    /// let x = -4.0_f64;
1058    /// let atan2 = y.atan2_(&x);
1059    /// let expected = 2.4981_f64;
1060    /// assert!((atan2 - expected).abs() < 0.0001);
1061    /// ```
1062    #[inline(always)]
1063    fn atan2_(self, other: &Self) -> Self {
1064        self.atan2(*other)
1065    }
1066
1067    /// Returns the smallest integer greater than or equal to `self`.
1068    #[inline(always)]
1069    fn ceil_(self) -> Self {
1070        self.ceil()
1071    }
1072
1073    /// Clamp the value within the specified bounds.
1074    ///
1075    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is less than `min`.
1076    /// Otherwise this returns `self`.
1077    ///
1078    /// Note that this function returns `NaN` if the initial value was `NaN` as well.
1079    ///
1080    /// # Panics
1081    /// Panics if `min` > `max`, `min` is `NaN`, or `max` is `NaN`.
1082    /// ```
1083    /// use ftl_numkernel::{FunctionsRealType, IsNaN};
1084    ///
1085    /// assert!((-3.0f64).clamp_(&-2.0, &1.0) == -2.0);
1086    /// assert!((0.0f64).clamp_(&-2.0, &1.0) == 0.0);
1087    /// assert!((2.0f64).clamp_(&-2.0, &1.0) == 1.0);
1088    /// assert!((f64::NAN).clamp_(&-2.0, &1.0).is_nan_());
1089    /// ```
1090    #[inline(always)]
1091    fn clamp_(self, min: &Self, max: &Self) -> Self {
1092        self.clamp(*min, *max)
1093    }
1094
1095    /// Returns the floating point category of the number. If only one property is going to be tested,
1096    /// it is generally faster to use the specific predicate instead.
1097    /// ```
1098    /// use ftl_numkernel::FunctionsRealType;
1099    /// use std::num::FpCategory;
1100    ///
1101    /// let num = 12.4_f64;
1102    /// let inf = f64::INFINITY;
1103    ///
1104    /// assert_eq!(num.classify_(), FpCategory::Normal);
1105    /// assert_eq!(inf.classify_(), FpCategory::Infinite);
1106    /// ```
1107    #[inline(always)]
1108    fn classify_(&self) -> FpCategory {
1109        self.classify()
1110    }
1111
1112    /// Returns a number with the magnitude of `self` and the sign of `sign`.
1113    #[inline(always)]
1114    fn copysign_(self, sign: &Self) -> Self {
1115        self.copysign(*sign)
1116    }
1117
1118    /// [Machine epsilon] value for `f64`.
1119    ///
1120    /// This is the difference between `1.0` and the next larger representable number.
1121    ///
1122    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
1123    #[inline(always)]
1124    fn epsilon_() -> Self {
1125        f64::EPSILON
1126    }
1127
1128    /// Returns `e^(self) - 1`` in a way that is accurate even if the number is close to zero.
1129    #[inline(always)]
1130    fn exp_m1_(self) -> Self {
1131        self.exp_m1()
1132    }
1133
1134    /// Returns the largest integer smaller than or equal to `self`.
1135    #[inline(always)]
1136    fn floor_(self) -> Self {
1137        self.floor()
1138    }
1139
1140    /// Returns the fractional part of `self`.
1141    #[inline(always)]
1142    fn fract_(self) -> Self {
1143        self.fract()
1144    }
1145
1146    /// Compute the distance between the origin and a point (`self`, `other`) on the Euclidean plane.
1147    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `self.abs()` and `other.abs()`.
1148    #[inline(always)]
1149    fn hypot_(self, other: &Self) -> Self {
1150        self.hypot(*other)
1151    }
1152
1153    /// Returns the special value representing the *positive infinity*.
1154    #[inline(always)]
1155    fn infinity_() -> Self {
1156        f64::INFINITY
1157    }
1158
1159    /// Returns `true` if the value is negative, −0 or NaN with a negative sign.
1160    #[inline(always)]
1161    fn is_sign_negative_(&self) -> bool {
1162        self.is_sign_negative()
1163    }
1164
1165    /// Returns `true` if the value is positive, +0 or NaN with a positive sign.
1166    #[inline(always)]
1167    fn is_sign_positive_(&self) -> bool {
1168        self.is_sign_positive()
1169    }
1170
1171    /// Returns `ln(1. + self)` (natural logarithm) more accurately than if the operations were performed separately.
1172    #[inline(always)]
1173    fn ln_1p_(self) -> Self {
1174        self.ln_1p()
1175    }
1176
1177    /// Returns the special value representing the *negative infinity*.
1178    #[inline(always)]
1179    fn neg_infinity_() -> Self {
1180        f64::NEG_INFINITY
1181    }
1182
1183    /// Computes the maximum between `self` and `other`.
1184    #[inline(always)]
1185    fn max_(self, other: &Self) -> Self {
1186        self.max(*other)
1187    }
1188
1189    /// Computes the minimum between `self` and `other`.
1190    #[inline(always)]
1191    fn min_(self, other: &Self) -> Self {
1192        self.min(*other)
1193    }
1194
1195    /// Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
1196    /// `a.mul_add_mul_mut_(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
1197    #[inline(always)]
1198    fn mul_add_mul_mut_(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
1199        self.mul_add_assign(*mul, add_mul1 * add_mul2);
1200    }
1201
1202    /// Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
1203    /// `a.mul_sub_mul_mut_(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
1204    #[inline(always)]
1205    fn mul_sub_mul_mut_(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
1206        self.mul_add_assign(*mul, -sub_mul1 * sub_mul2);
1207    }
1208
1209    /// Build and return the (floating point) value -1. represented by a `f64`.
1210    #[inline(always)]
1211    fn negative_one_() -> Self {
1212        -1.
1213    }
1214
1215    /// Build and return the (floating point) value 0.5 represented by the proper type.
1216    #[inline(always)]
1217    fn one_div_2_() -> Self {
1218        0.5
1219    }
1220
1221    /// Rounds `self` to the nearest integer, rounding half-way cases away from zero.
1222    #[inline(always)]
1223    fn round_(self) -> Self {
1224        self.round()
1225    }
1226
1227    /// Returns the nearest integer to a number. Rounds half-way cases to the number with an even least significant digit.
1228    ///
1229    /// This function always returns the precise result.
1230    ///
1231    /// # Examples
1232    /// ```
1233    /// use ftl_numkernel::FunctionsRealType;
1234    ///
1235    /// let f = 3.3_f64;
1236    /// let g = -3.3_f64;
1237    /// let h = 3.5_f64;
1238    /// let i = 4.5_f64;
1239    ///
1240    /// assert_eq!(f.round_ties_even_(), 3.0);
1241    /// assert_eq!(g.round_ties_even_(), -3.0);
1242    /// assert_eq!(h.round_ties_even_(), 4.0);
1243    /// assert_eq!(i.round_ties_even_(), 4.0);
1244    /// ```
1245    #[inline(always)]
1246    fn round_ties_even_(self) -> Self {
1247        self.round_ties_even()
1248    }
1249
1250    /// Computes the signum.
1251    ///
1252    /// The returned value is:
1253    /// - `1.0` if the value is positive, +0.0 or +∞
1254    /// - `−1.0` if the value is negative, −0.0 or −∞
1255    /// - `NaN` if the value is NaN
1256    #[inline(always)]
1257    fn signum_(self) -> Self {
1258        self.signum()
1259    }
1260
1261    #[inline(always)]
1262    fn total_cmp_(&self, other: &Self) -> Ordering {
1263        self.total_cmp(other)
1264    }
1265
1266    /// Try to build a [`f64`] instance from a [`f64`].
1267    /// The returned value is `Ok` if the input `value` is finite,
1268    /// otherwise the returned value is `TryFromf64Errors`.
1269    #[inline(always)]
1270    fn try_from_f64_(value: f64) -> Result<Self, TryFromf64Errors> {
1271        match value.validate() {
1272            Ok(value) => Ok(value),
1273            Err(e) => Err(TryFromf64Errors::ValidationError { source: e }),
1274        }
1275    }
1276
1277    /// Returns the integer part of `self`. This means that non-integer numbers are always truncated towards zero.
1278    ///    
1279    /// # Examples
1280    /// ```
1281    /// use ftl_numkernel::FunctionsRealType;
1282    ///
1283    /// let f = 3.7_f64;
1284    /// let g = 3.0_f64;
1285    /// let h = -3.7_f64;
1286    ///
1287    /// assert_eq!(f.trunc_(), 3.0);
1288    /// assert_eq!(g.trunc_(), 3.0);
1289    /// assert_eq!(h.trunc_(), -3.0);
1290    /// ```
1291    #[inline(always)]
1292    fn trunc_(self) -> Self {
1293        self.trunc()
1294    }
1295
1296    /// Build and return the (floating point) value 2. represented by a `f64`.
1297    #[inline(always)]
1298    fn two_() -> Self {
1299        2.
1300    }
1301}
1302
1303/// Implement the `IntoInner` trait for the `Complex<f64>` type.
1304impl IntoInner for Complex<f64> {
1305    /// The inner type of the `Complex<f64>` type.
1306    type Target = (f64, f64);
1307
1308    /// Convert the `Complex<f64>` type into its inner type `(f64, f64)` corresponding to the real and imaginary part.
1309    #[inline(always)]
1310    fn into_inner(self) -> Self::Target {
1311        (self.re, self.im)
1312    }
1313}
1314
1315/// Implement the `FunctionsComplexType` trait for the `Complex<f64>` type.
1316impl FunctionsComplexType<Native64> for Complex<f64> {
1317    /// Computes the principal Arg of `self`.
1318    #[inline(always)]
1319    fn arg_(self) -> f64 {
1320        self.arg()
1321    }
1322
1323    /// Creates a complex number of type `T::ComplexType` from its real and imaginary parts.
1324    ///
1325    /// # Panics
1326    /// In debug mode a `panic!` will be emitted if the `real_part` or the `imag_part` is not finite.
1327    #[inline(always)]
1328    fn new_(real_part: f64, imag_part: f64) -> Self {
1329        debug_assert!(
1330            real_part.is_finite(),
1331            "The real part is not finite (i.e. is infinite or NaN)."
1332        );
1333        debug_assert!(
1334            imag_part.is_finite(),
1335            "The imaginary part is not finite (i.e. is infinite or NaN)."
1336        );
1337        Complex::new(real_part, imag_part)
1338    }
1339
1340    /// Get the real part of the complex number.
1341    #[inline(always)]
1342    fn real_(&self) -> f64 {
1343        self.re
1344    }
1345
1346    /// Get the imaginary part of the complex number.
1347    #[inline(always)]
1348    fn imag_(&self) -> f64 {
1349        self.im
1350    }
1351
1352    /// Set the value of the real part.
1353    ///
1354    /// # Panics
1355    /// In debug mode a `panic!` will be emitted if `real_part` is not finite.
1356    #[inline(always)]
1357    fn set_real_(&mut self, real_part: f64) {
1358        debug_assert!(
1359            real_part.is_finite(),
1360            "The real part is not finite (i.e. is infinite or NaN)."
1361        );
1362        self.re = real_part;
1363    }
1364
1365    /// Set the value of the imaginary part.
1366    ///
1367    /// # Panics
1368    /// In debug mode a `panic!` will be emitted if `imaginary_part` is not finite.
1369    #[inline(always)]
1370    fn set_imag_(&mut self, imag_part: f64) {
1371        debug_assert!(
1372            imag_part.is_finite(),
1373            "The imaginary part is not finite (i.e. is infinite or NaN)."
1374        );
1375        self.im = imag_part;
1376    }
1377
1378    /// Add the value of the the real coefficient `c` to real part of `self`.
1379    #[inline(always)]
1380    fn add_real_(&mut self, c: &f64) {
1381        self.re += c;
1382
1383        debug_assert!(
1384            self.re.is_finite(),
1385            "The real part is not finite (i.e. is infinite or NaN)."
1386        );
1387    }
1388
1389    /// Add the value of the the real coefficient `c` to imaginary part of `self`.
1390    #[inline(always)]
1391    fn add_imag_(&mut self, c: &f64) {
1392        self.im += c;
1393
1394        debug_assert!(
1395            self.im.is_finite(),
1396            "The imaginary part is not finite (i.e. is infinite or NaN)."
1397        );
1398    }
1399
1400    /// Multiply the value of the real part by the real coefficient `c`.
1401    #[inline(always)]
1402    fn multiply_real_(&mut self, c: &f64) {
1403        self.re *= c;
1404
1405        debug_assert!(
1406            self.re.is_finite(),
1407            "The real part is not finite (i.e. is infinite or NaN)."
1408        );
1409    }
1410
1411    /// Multiply the value of the imaginary part by the real coefficient `c`.
1412    #[inline(always)]
1413    fn multiply_imag_(&mut self, c: &f64) {
1414        self.im *= c;
1415
1416        debug_assert!(
1417            self.im.is_finite(),
1418            "The imaginary part is not finite (i.e. is infinite or NaN)."
1419        );
1420    }
1421
1422    /// Computes the complex conjugate.
1423    #[inline(always)]
1424    fn conj_(self) -> Self {
1425        self.conj()
1426    }
1427
1428    /// Try to build a `Self` from real and imaginary parts as [`f64`] values.
1429    /// The returned value is `Ok` if the input `real_part` and `imag_part` are finite and can be exactly represented by `T::RealType`,
1430    /// otherwise the returned value is `TryFromf64Errors`.
1431    #[inline(always)]
1432    fn try_from_f64_(real_part: f64, imag_part: f64) -> Result<Self, TryFromf64Errors> {
1433        let real_part = <f64 as FunctionsRealType<Native64>>::try_from_f64_(real_part)?;
1434        let imag_part = <f64 as FunctionsRealType<Native64>>::try_from_f64_(imag_part)?;
1435
1436        Ok(Complex::new(real_part, imag_part))
1437    }
1438}
1439
1440//------------------------------------------------------------------------------------------------------------
1441
1442//------------------------------------------------------------------------------------------------------------
1443// Conditional compilation for the `rug` feature
1444#[cfg(feature = "rug")]
1445#[derive(
1446    Add,
1447    AddAssign,
1448    AsRef,
1449    Clone,
1450    Debug,
1451    Deserialize,
1452    Display,
1453    Div,
1454    DivAssign,
1455    LowerExp,
1456    Mul,
1457    MulAssign,
1458    Neg,
1459    PartialEq,
1460    PartialOrd,
1461    Serialize,
1462    Sub,
1463    SubAssign,
1464)]
1465#[mul(forward)]
1466#[mul_assign(forward)]
1467#[div(forward)]
1468#[div_assign(forward)]
1469pub struct RealRug<const PRECISION: u32>(rug::Float);
1470
1471// Conditional compilation for the `rug` feature
1472#[cfg(feature = "rug")]
1473impl<const PRECISION: u32> RealRug<PRECISION> {
1474    #[inline(always)]
1475    pub fn new(value: rug::Float) -> Self {
1476        debug_assert!(value.is_finite(), "Not a finite number!");
1477        debug_assert_eq!(
1478            value.prec(),
1479            PRECISION,
1480            "The input value must have a precision = {PRECISION}, but actually has precision = {}",
1481            value.prec()
1482        );
1483        Self(value)
1484    }
1485}
1486
1487// Conditional compilation for the `rug` feature
1488#[cfg(feature = "rug")]
1489#[derive(
1490    Add,
1491    AddAssign,
1492    AsRef,
1493    Clone,
1494    Debug,
1495    Deserialize,
1496    Display,
1497    Div,
1498    DivAssign,
1499    LowerExp,
1500    Mul,
1501    MulAssign,
1502    Neg,
1503    PartialEq,
1504    Serialize,
1505    Sub,
1506    SubAssign,
1507)]
1508#[mul(forward)]
1509#[mul_assign(forward)]
1510#[div(forward)]
1511#[div_assign(forward)]
1512pub struct ComplexRug<const PRECISION: u32>(rug::Complex);
1513
1514// Conditional compilation for the `rug` feature
1515#[cfg(feature = "rug")]
1516impl<const PRECISION: u32> ComplexRug<PRECISION> {
1517    #[inline(always)]
1518    pub fn new(value: rug::Complex) -> Self {
1519        debug_assert!(
1520            value.real().is_finite() && value.imag().is_finite(),
1521            "Not a finite number!"
1522        );
1523        debug_assert_eq!(
1524            value.prec(),
1525            (PRECISION, PRECISION),
1526            "The input value must have a precision = {:?}, but actually has precision = {:?}",
1527            (PRECISION, PRECISION),
1528            value.prec()
1529        );
1530        Self(value)
1531    }
1532}
1533
1534#[cfg(feature = "rug")]
1535impl<const PRECISION: u32> IntoInner for ComplexRug<PRECISION> {
1536    type Target = (RealRug<PRECISION>, RealRug<PRECISION>);
1537
1538    #[inline(always)]
1539    fn into_inner(self) -> Self::Target {
1540        (
1541            RealRug::new(self.0.real().clone()),
1542            RealRug::new(self.0.imag().clone()),
1543        )
1544    }
1545}
1546
1547// Conditional compilation for the `rug` feature
1548#[cfg(feature = "rug")]
1549#[duplicate_item(
1550    T;
1551    [RealRug<PRECISION>];
1552    [ComplexRug<PRECISION>];
1553)]
1554impl<const PRECISION: u32> NegAssign for T {
1555    /// Performs the negation of `self`.
1556    #[inline(always)]
1557    fn neg_assign(&mut self) {
1558        rug::ops::NegAssign::neg_assign(&mut self.0);
1559    }
1560}
1561
1562// Conditional compilation for the `rug` feature
1563#[cfg(feature = "rug")]
1564#[duplicate_item(
1565    trait_name method T;
1566    duplicate!{
1567        [
1568            rug_type;[RealRug];[ComplexRug]
1569        ]
1570        [Add] [add] [rug_type];
1571        [Sub] [sub] [rug_type];
1572        [Mul] [mul] [rug_type];
1573    }
1574)]
1575impl<'a, const PRECISION: u32> trait_name<&'a T<PRECISION>> for T<PRECISION> {
1576    type Output = T<PRECISION>;
1577
1578    #[inline(always)]
1579    fn method(self, rhs: &'a T<PRECISION>) -> Self::Output {
1580        T(self.0.method(&rhs.0))
1581    }
1582}
1583
1584// Conditional compilation for the `rug` feature
1585#[cfg(feature = "rug")]
1586#[duplicate_item(
1587    trait_name method T;
1588    duplicate!{
1589        [
1590            rug_type;[RealRug];[ComplexRug]
1591        ]
1592        [Add] [add] [rug_type];
1593        [Sub] [sub] [rug_type];
1594        [Mul] [mul] [rug_type];
1595    }
1596)]
1597impl<'a, const PRECISION: u32> trait_name<T<PRECISION>> for &T<PRECISION> {
1598    type Output = T<PRECISION>;
1599
1600    #[inline(always)]
1601    fn method(self, rhs: T<PRECISION>) -> Self::Output {
1602        let lhs = &self.0;
1603        T(lhs.method(rhs.0))
1604    }
1605}
1606
1607// Conditional compilation for the `rug` feature
1608#[cfg(feature = "rug")]
1609#[duplicate_item(
1610    T;
1611    [RealRug];
1612    [ComplexRug];
1613)]
1614impl<'a, const PRECISION: u32> Div<&'a T<PRECISION>> for T<PRECISION> {
1615    type Output = T<PRECISION>;
1616
1617    #[inline(always)]
1618    fn div(self, rhs: &'a T<PRECISION>) -> Self::Output {
1619        debug_assert!(!rhs.0.is_zero(), "Division by zero!");
1620        T(self.0.div(&rhs.0))
1621    }
1622}
1623
1624// Conditional compilation for the `rug` feature
1625#[cfg(feature = "rug")]
1626#[duplicate_item(
1627    T;
1628    [RealRug];
1629    [ComplexRug];
1630)]
1631impl<'a, const PRECISION: u32> Div<T<PRECISION>> for &T<PRECISION> {
1632    type Output = T<PRECISION>;
1633
1634    #[inline(always)]
1635    fn div(self, rhs: T<PRECISION>) -> Self::Output {
1636        debug_assert!(!rhs.0.is_zero(), "Division by zero!");
1637        let lhs = &self.0;
1638        T(lhs.div(rhs.0))
1639    }
1640}
1641
1642// Conditional compilation for the `rug` feature
1643#[cfg(feature = "rug")]
1644#[duplicate_item(
1645    trait_name method T;
1646    duplicate!{
1647        [
1648            rug_type;[RealRug];[ComplexRug]
1649        ]
1650        [AddAssign] [add_assign] [rug_type];
1651        [SubAssign] [sub_assign] [rug_type];
1652        [MulAssign] [mul_assign] [rug_type];
1653    }
1654)]
1655impl<'a, const PRECISION: u32> trait_name<&'a T<PRECISION>> for T<PRECISION> {
1656    #[inline(always)]
1657    fn method(&mut self, rhs: &'a T<PRECISION>) {
1658        self.0.method(&rhs.0);
1659    }
1660}
1661
1662// Conditional compilation for the `rug` feature
1663#[cfg(feature = "rug")]
1664impl<'a, const PRECISION: u32> Mul<RealRug<PRECISION>> for ComplexRug<PRECISION> {
1665    type Output = ComplexRug<PRECISION>;
1666
1667    #[inline(always)]
1668    fn mul(self, rhs: RealRug<PRECISION>) -> ComplexRug<PRECISION> {
1669        Self(self.0.mul(rhs.0))
1670    }
1671}
1672
1673// Conditional compilation for the `rug` feature
1674#[cfg(feature = "rug")]
1675impl<'a, const PRECISION: u32> Mul<&'a RealRug<PRECISION>> for ComplexRug<PRECISION> {
1676    type Output = ComplexRug<PRECISION>;
1677
1678    #[inline(always)]
1679    fn mul(self, rhs: &'a RealRug<PRECISION>) -> ComplexRug<PRECISION> {
1680        Self(self.0.mul(&rhs.0))
1681    }
1682}
1683
1684// Conditional compilation for the `rug` feature
1685#[cfg(feature = "rug")]
1686impl<'a, const PRECISION: u32> MulAssign<RealRug<PRECISION>> for ComplexRug<PRECISION> {
1687    #[inline(always)]
1688    fn mul_assign(&mut self, rhs: RealRug<PRECISION>) {
1689        self.0.mul_assign(rhs.0);
1690    }
1691}
1692
1693// Conditional compilation for the `rug` feature
1694#[cfg(feature = "rug")]
1695impl<'a, const PRECISION: u32> MulAssign<&'a RealRug<PRECISION>> for ComplexRug<PRECISION> {
1696    #[inline(always)]
1697    fn mul_assign(&mut self, rhs: &'a RealRug<PRECISION>) {
1698        self.0.mul_assign(&rhs.0);
1699    }
1700}
1701
1702// Conditional compilation for the `rug` feature
1703#[cfg(feature = "rug")]
1704#[duplicate_item(
1705    T;
1706    [RealRug<PRECISION>];
1707    [ComplexRug<PRECISION>];
1708)]
1709impl<'a, const PRECISION: u32> DivAssign<&'a T> for T {
1710    #[inline(always)]
1711    fn div_assign(&mut self, rhs: &'a T) {
1712        debug_assert!(!rhs.0.is_zero(), "Division by zero!");
1713        self.0.div_assign(&rhs.0);
1714    }
1715}
1716
1717// Conditional compilation for the `rug` feature
1718#[cfg(feature = "rug")]
1719impl<const PRECISION: u32> Arithmetic for RealRug<PRECISION> {}
1720
1721// Conditional compilation for the `rug` feature
1722#[cfg(feature = "rug")]
1723impl<const PRECISION: u32> Arithmetic for ComplexRug<PRECISION> {}
1724
1725// Conditional compilation for the `rug` feature
1726#[cfg(feature = "rug")]
1727#[duplicate::duplicate_item(
1728    exponent_type T;
1729    duplicate!{
1730        [
1731            rug_type;[RealRug<PRECISION>];[ComplexRug<PRECISION>]
1732        ]
1733    [i8]          [rug_type];
1734    [u8]          [rug_type];
1735    [i16]         [rug_type];
1736    [u16]         [rug_type];
1737    [i32]         [rug_type];
1738    [u32]         [rug_type];
1739    [i64]         [rug_type];
1740    [u64]         [rug_type];
1741    [i128]        [rug_type];
1742    [u128]        [rug_type];
1743    [usize]       [rug_type];
1744    }
1745)]
1746impl<const PRECISION: u32> Pow<exponent_type> for T {
1747    /// Raises th number `self` to the power `exponent`.
1748    #[inline(always)]
1749    fn pow_(self, exponent: exponent_type) -> Self {
1750        Self(self.0.pow(exponent))
1751    }
1752}
1753
1754// Conditional compilation for the `rug` feature
1755#[cfg(feature = "rug")]
1756#[duplicate::duplicate_item(
1757    T;
1758    [RealRug<PRECISION>];
1759    [ComplexRug<PRECISION>];
1760)]
1761impl<const PRECISION: u32> Pow<RealRug<PRECISION>> for T {
1762    /// Raises th number `self` to the power `exponent`.
1763    #[inline(always)]
1764    fn pow_(self, exponent: RealRug<PRECISION>) -> Self {
1765        Self(self.0.pow(exponent.0))
1766    }
1767}
1768
1769// Conditional compilation for the `rug` feature
1770#[cfg(feature = "rug")]
1771impl<const PRECISION: u32> PowTrait<Rug<PRECISION>> for RealRug<PRECISION> {}
1772
1773// Conditional compilation for the `rug` feature
1774#[cfg(feature = "rug")]
1775impl<const PRECISION: u32> PowTrait<Rug<PRECISION>> for ComplexRug<PRECISION> {}
1776
1777// Conditional compilation for the `rug` feature
1778#[cfg(feature = "rug")]
1779impl<const PRECISION: u32> PartialEq<f64> for RealRug<PRECISION> {
1780    #[inline(always)]
1781    fn eq(&self, other: &f64) -> bool {
1782        self.0.eq(other)
1783    }
1784}
1785
1786// Conditional compilation for the `rug` feature
1787#[cfg(feature = "rug")]
1788impl<const PRECISION: u32> PartialOrd<f64> for RealRug<PRECISION> {
1789    #[inline(always)]
1790    fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
1791        self.0.partial_cmp(other)
1792    }
1793}
1794
1795// Conditional compilation for the `rug` feature
1796#[cfg(feature = "rug")]
1797impl<const PRECISION: u32> FunctionsGeneralType<Rug<PRECISION>> for RealRug<PRECISION> {}
1798
1799// Conditional compilation for the `rug` feature
1800#[cfg(feature = "rug")]
1801impl<const PRECISION: u32> FunctionsRealType<Rug<PRECISION>> for RealRug<PRECISION> {
1802    /// Computes the four quadrant arctangent of `self` (y) and `other` (x) in radians.
1803    /// - `x = 0`, `y = 0`: `0`
1804    /// - `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
1805    /// - `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
1806    /// - `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
1807    /// ```
1808    /// use ftl_numkernel::{
1809    ///     FunctionsRealType, RealRug,
1810    ///     functions::Abs,
1811    /// };
1812    ///
1813    /// const PRECISION: u32 = 100;
1814    ///
1815    /// let y = RealRug::<PRECISION>::try_from_f64_(3.).unwrap();
1816    /// let x = RealRug::<PRECISION>::try_from_f64_(-4.).unwrap();
1817    /// let atan2 = y.clone().atan2_(&x);
1818    /// let expected = RealRug::<PRECISION>::try_from_f64_(2.4981).unwrap();
1819    /// assert!((atan2 - expected).abs() < 0.0001);
1820    /// ```
1821    #[inline(always)]
1822    fn atan2_(self, other: &Self) -> Self {
1823        Self(self.0.atan2(&other.0))
1824    }
1825
1826    /// Returns the smallest integer greater than or equal to `self`.
1827    #[inline(always)]
1828    fn ceil_(self) -> Self {
1829        Self(self.0.ceil())
1830    }
1831
1832    /// Clamps the value within the specified bounds.
1833    #[inline(always)]
1834    fn clamp_(self, min: &Self, max: &Self) -> Self {
1835        Self(self.0.clamp(&min.0, &max.0))
1836    }
1837
1838    /// Returns the floating point category of the number. If only one property is going to be tested,
1839    /// it is generally faster to use the specific predicate instead.
1840    /// ```
1841    /// use ftl_numkernel::{FunctionsRealType, RealRug};
1842    /// use std::num::FpCategory;
1843    ///
1844    /// const PRECISION: u32 = 100;
1845    ///
1846    /// let num = RealRug::<PRECISION>::try_from_f64_(12.4).unwrap();
1847    /// let inf = RealRug::<PRECISION>::infinity_();
1848    ///
1849    /// assert_eq!(num.classify_(), FpCategory::Normal);
1850    /// assert_eq!(inf.classify_(), FpCategory::Infinite);
1851    /// ```
1852    #[inline(always)]
1853    fn classify_(&self) -> FpCategory {
1854        self.0.classify()
1855    }
1856
1857    /// Returns a number with the magnitude of `self` and the sign of `sign`.
1858    #[inline(always)]
1859    fn copysign_(self, sign: &Self) -> Self {
1860        Self(self.0.copysign(&sign.0))
1861    }
1862
1863    /// [Machine epsilon] value for `rug::Float` with the given `PRECISION` (in bits).
1864    ///
1865    /// It is equal to `2^(1-PRECISION)` and it is the difference between `1.0` and the next larger representable number.
1866    ///
1867    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
1868    #[inline(always)]
1869    fn epsilon_() -> Self {
1870        Self(
1871            rug::Float::u_pow_u(2, PRECISION - 1)
1872                .complete(PRECISION.into())
1873                .recip(),
1874        )
1875    }
1876
1877    /// Returns `e^(self) - 1`` in a way that is accurate even if the number is close to zero.
1878    #[inline(always)]
1879    fn exp_m1_(self) -> Self {
1880        Self(self.0.exp_m1())
1881    }
1882
1883    /// Returns the largest integer smaller than or equal to `self`.
1884    #[inline(always)]
1885    fn floor_(self) -> Self {
1886        Self(self.0.floor())
1887    }
1888
1889    /// Returns the fractional part of `self`.
1890    #[inline(always)]
1891    fn fract_(self) -> Self {
1892        Self(self.0.fract())
1893    }
1894
1895    /// Compute the distance between the origin and a point (`self`, `other`) on the Euclidean plane.
1896    /// Equivalently, compute the length of the hypotenuse of a right-angle triangle with other sides having length `self.abs()` and `other.abs()`.
1897    #[inline(always)]
1898    fn hypot_(self, other: &Self) -> Self {
1899        Self(self.0.hypot(&other.0))
1900    }
1901
1902    /// Returns the special value representing the *positive infinity*.
1903    #[inline(always)]
1904    fn infinity_() -> Self {
1905        Self(rug::Float::with_val(
1906            PRECISION,
1907            rug::float::Special::Infinity,
1908        ))
1909    }
1910
1911    /// Returns `true` if the value is negative, −0 or NaN with a negative sign.
1912    #[inline(always)]
1913    fn is_sign_negative_(&self) -> bool {
1914        self.0.is_sign_negative()
1915    }
1916
1917    /// Returns `true` if the value is positive, +0 or NaN with a positive sign.
1918    #[inline(always)]
1919    fn is_sign_positive_(&self) -> bool {
1920        self.0.is_sign_positive()
1921    }
1922
1923    /// Returns `ln(1. + self)` (natural logarithm) more accurately than if the operations were performed separately.
1924    #[inline(always)]
1925    fn ln_1p_(self) -> Self {
1926        Self(self.0.ln_1p())
1927    }
1928
1929    /// Returns the special value representing the *negative infinity*.
1930    #[inline(always)]
1931    fn neg_infinity_() -> Self {
1932        Self(rug::Float::with_val(
1933            PRECISION,
1934            rug::float::Special::NegInfinity,
1935        ))
1936    }
1937
1938    /// Computes the maximum between `self` and `other`.
1939    #[inline(always)]
1940    fn max_(self, other: &Self) -> Self {
1941        Self(self.0.max(&other.0))
1942    }
1943
1944    /// Computes the minimum between `self` and `other`.
1945    #[inline(always)]
1946    fn min_(self, other: &Self) -> Self {
1947        Self(self.0.min(&other.0))
1948    }
1949
1950    /// Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
1951    /// `a.mul_add_mul_mut_(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
1952    #[inline(always)]
1953    fn mul_add_mul_mut_(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self) {
1954        self.0.mul_add_mul_mut(&mul.0, &add_mul1.0, &add_mul2.0);
1955    }
1956
1957    /// Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
1958    /// `a.mul_sub_mul_mut_(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
1959    #[inline(always)]
1960    fn mul_sub_mul_mut_(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self) {
1961        self.0.mul_sub_mul_mut(&mul.0, &sub_mul1.0, &sub_mul2.0);
1962    }
1963
1964    /// Build and return the (floating point) value -1. represented by a `rug::Float` with the given `PRECISION`.
1965    #[inline(always)]
1966    fn negative_one_() -> Self {
1967        Self(rug::Float::with_val(PRECISION, -1.))
1968    }
1969
1970    /// Build and return the (floating point) value 0.5 represented by the proper type.
1971    #[inline(always)]
1972    fn one_div_2_() -> Self {
1973        Self(rug::Float::with_val(PRECISION, 0.5))
1974    }
1975
1976    /// Rounds `self` to the nearest integer, rounding half-way cases away from zero.
1977    #[inline(always)]
1978    fn round_(self) -> Self {
1979        Self(self.0.round())
1980    }
1981
1982    /// Returns the nearest integer to a number. Rounds half-way cases to the number with an even least significant digit.
1983    ///
1984    /// This function always returns the precise result.
1985    ///
1986    /// # Examples
1987    /// ```
1988    /// use ftl_numkernel::{FunctionsRealType, NumKernel, RealRug};
1989    ///
1990    /// const PRECISION: u32 = 100;
1991    ///
1992    /// let f = RealRug::<PRECISION>::try_from_f64_(3.3).unwrap();
1993    /// let g = RealRug::<PRECISION>::try_from_f64_(-3.3).unwrap();
1994    /// let h = RealRug::<PRECISION>::try_from_f64_(3.5).unwrap();
1995    /// let i = RealRug::<PRECISION>::try_from_f64_(-4.5).unwrap();
1996    ///
1997    /// assert_eq!(f.round_ties_even_(), RealRug::<PRECISION>::try_from_f64_(3.).unwrap());
1998    /// assert_eq!(g.round_ties_even_(), RealRug::<PRECISION>::try_from_f64_(-3.).unwrap());
1999    /// assert_eq!(h.round_ties_even_(), RealRug::<PRECISION>::try_from_f64_(4.).unwrap());
2000    /// assert_eq!(i.round_ties_even_(), RealRug::<PRECISION>::try_from_f64_(-4.).unwrap());
2001    /// ```
2002    #[inline(always)]
2003    fn round_ties_even_(self) -> Self {
2004        Self(self.0.round_even())
2005    }
2006
2007    /// Computes the signum.
2008    ///
2009    /// The returned value is:
2010    /// - `1.0` if the value is positive, +0.0 or +∞
2011    /// - `−1.0` if the value is negative, −0.0 or −∞
2012    /// - `NaN` if the value is NaN
2013    #[inline(always)]
2014    fn signum_(self) -> Self {
2015        Self(self.0.signum())
2016    }
2017
2018    #[inline(always)]
2019    fn total_cmp_(&self, other: &Self) -> Ordering {
2020        self.0.total_cmp(&other.0)
2021    }
2022
2023    /// Try to build a [`rug::Float`] instance (with the given `PRECISION`) from a [`f64`].
2024    /// The returned value is `Ok` if the input `value` is finite and can be exactly represented with the given `PRECISION`,
2025    /// otherwise the returned value is `TryFromf64Errors`.
2026    #[inline(always)]
2027    fn try_from_f64_(value: f64) -> Result<Self, TryFromf64Errors> {
2028        match value.validate() {
2029            Ok(value) => {
2030                let value_rug = rug::Float::with_val(PRECISION, value);
2031                if value_rug == value {
2032                    Ok(Self(value_rug))
2033                } else {
2034                    Err(TryFromf64Errors::NonRepresentableExactly {
2035                        value,
2036                        precision: PRECISION,
2037                        backtrace: Backtrace::force_capture(),
2038                    })
2039                }
2040            }
2041            Err(e) => Err(TryFromf64Errors::ValidationError { source: e }),
2042        }
2043    }
2044
2045    /// Returns the integer part of `self`. This means that non-integer numbers are always truncated towards zero.
2046    ///    
2047    /// # Examples
2048    /// ```
2049    /// use ftl_numkernel::{FunctionsRealType, NumKernel, RealRug};
2050    ///
2051    /// const PRECISION: u32 = 100;
2052    ///
2053    /// let f = RealRug::<PRECISION>::try_from_f64_(3.7).unwrap();
2054    /// let g = RealRug::<PRECISION>::try_from_f64_(3.).unwrap();
2055    /// let h = RealRug::<PRECISION>::try_from_f64_(-3.7).unwrap();
2056    ///
2057    /// assert_eq!(f.trunc_(), RealRug::<PRECISION>::try_from_f64_(3.).unwrap());
2058    /// assert_eq!(g.trunc_(), RealRug::<PRECISION>::try_from_f64_(3.).unwrap());
2059    /// assert_eq!(h.trunc_(), RealRug::<PRECISION>::try_from_f64_(-3.).unwrap());
2060    /// ```
2061    #[inline(always)]
2062    fn trunc_(self) -> Self {
2063        Self(self.0.trunc())
2064    }
2065
2066    /// Build and return the (floating point) value 2. represented by a `rug::Float` with the given `PRECISION`.
2067    #[inline(always)]
2068    fn two_() -> Self {
2069        Self(rug::Float::with_val(PRECISION, 2.))
2070    }
2071}
2072
2073// Conditional compilation for the `rug` feature
2074#[cfg(feature = "rug")]
2075impl<const PRECISION: u32> Mul<ComplexRug<PRECISION>> for RealRug<PRECISION> {
2076    type Output = ComplexRug<PRECISION>;
2077
2078    #[inline(always)]
2079    fn mul(self, other: ComplexRug<PRECISION>) -> Self::Output {
2080        ComplexRug(self.0 * other.0)
2081    }
2082}
2083
2084// Conditional compilation for the `rug` feature
2085#[cfg(feature = "rug")]
2086impl<const PRECISION: u32> MulComplexRight<Rug<PRECISION>> for RealRug<PRECISION> {}
2087
2088// Conditional compilation for the `rug` feature
2089#[cfg(feature = "rug")]
2090impl<const PRECISION: u32> FunctionsGeneralType<Rug<PRECISION>> for ComplexRug<PRECISION> {}
2091
2092// Conditional compilation for the `rug` feature
2093#[cfg(feature = "rug")]
2094impl<const PRECISION: u32> FunctionsComplexType<Rug<PRECISION>> for ComplexRug<PRECISION> {
2095    /// Computes the principal Arg of `self`.
2096    #[inline(always)]
2097    fn arg_(self) -> RealRug<PRECISION> {
2098        RealRug(self.0.arg().real().clone())
2099    }
2100
2101    /// Creates a complex number of type `T::ComplexType` from its real and imaginary parts.
2102    ///
2103    /// # Panics
2104    /// In debug mode a `panic!` will be emitted if:
2105    /// - the `real_part` or the `imag_part` is not finite.
2106    /// - the precision of `real part` or of `imag_part` is not equal to `PRECISION`;
2107    #[inline(always)]
2108    fn new_(real_part: RealRug<PRECISION>, imag_part: RealRug<PRECISION>) -> Self {
2109        debug_assert!(
2110            real_part.0.is_finite(),
2111            "The real part is not finite (i.e. is infinite or NaN)."
2112        );
2113        debug_assert!(
2114            imag_part.0.is_finite(),
2115            "The imaginary part is not finite (i.e. is infinite or NaN)."
2116        );
2117
2118        Self(rug::Complex::with_val(
2119            PRECISION,
2120            (real_part.0, imag_part.0),
2121        ))
2122    }
2123
2124    /// Get the real part of the complex number.
2125    #[inline(always)]
2126    fn real_(&self) -> RealRug<PRECISION> {
2127        RealRug(self.0.real().clone())
2128    }
2129
2130    /// Get the imaginary part of the complex number.
2131    #[inline(always)]
2132    fn imag_(&self) -> RealRug<PRECISION> {
2133        RealRug(self.0.imag().clone())
2134    }
2135
2136    /// Set the value of the real part.
2137    ///
2138    /// # Panics
2139    /// In debug mode a `panic!` will be emitted if `real_part` is not finite
2140    /// or if the precision of `real_part` is different from `PRECISION`.
2141    #[inline(always)]
2142    fn set_real_(&mut self, real_part: RealRug<PRECISION>) {
2143        debug_assert!(
2144            real_part.0.is_finite(),
2145            "The real part is not finite (i.e. is infinite or NaN)."
2146        );
2147
2148        *self.0.mut_real() = real_part.0;
2149    }
2150
2151    /// Set the value of the imaginary part.
2152    ///
2153    /// # Panics
2154    /// In debug mode a `panic!` will be emitted if `imaginary_part` is not finite.
2155    /// or if the precision of `imaginary_part` is different from `PRECISION`.
2156    #[inline(always)]
2157    fn set_imag_(&mut self, imag_part: RealRug<PRECISION>) {
2158        debug_assert!(
2159            imag_part.0.is_finite(),
2160            "The imaginary part is not finite (i.e. is infinite or NaN)."
2161        );
2162        //        debug_assert_eq!(imag_part.prec(), PRECISION, "Different precisions!");
2163
2164        *self.0.mut_imag() = imag_part.0;
2165    }
2166
2167    /// Add the value of the the real coefficient `c` to real part of `self`.
2168    #[inline(always)]
2169    fn add_real_(&mut self, c: &RealRug<PRECISION>) {
2170        *self.0.mut_real() += c.as_ref();
2171
2172        debug_assert!(
2173            self.0.real().is_finite(),
2174            "The real part is not finite (i.e. is infinite or NaN)."
2175        );
2176    }
2177
2178    /// Add the value of the the real coefficient `c` to imaginary part of `self`.
2179    #[inline(always)]
2180    fn add_imag_(&mut self, c: &RealRug<PRECISION>) {
2181        *self.0.mut_imag() += c.as_ref();
2182
2183        debug_assert!(
2184            self.0.imag().is_finite(),
2185            "The imaginary part is not finite (i.e. is infinite or NaN)."
2186        );
2187    }
2188
2189    /// Multiply the value of the real part by the real coefficient `c`.
2190    #[inline(always)]
2191    fn multiply_real_(&mut self, c: &RealRug<PRECISION>) {
2192        *self.0.mut_real() *= c.as_ref();
2193
2194        debug_assert!(
2195            self.0.real().is_finite(),
2196            "The real part is not finite (i.e. is infinite or NaN)."
2197        );
2198    }
2199
2200    /// Multiply the value of the imaginary part by the real coefficient `c`.
2201    #[inline(always)]
2202    fn multiply_imag_(&mut self, c: &RealRug<PRECISION>) {
2203        *self.0.mut_imag() *= c.as_ref();
2204
2205        debug_assert!(
2206            self.0.imag().is_finite(),
2207            "The imaginary part is not finite (i.e. is infinite or NaN)."
2208        );
2209    }
2210
2211    /// Computes the complex conjugate.
2212    #[inline(always)]
2213    fn conj_(self) -> Self {
2214        Self(self.0.conj())
2215    }
2216
2217    /// Try to build a `Self` from real and imaginary parts as [`rug::Float`] values.
2218    /// The returned value is `Ok` if the input `real_part` and `imag_part` are finite and can be exactly represented by `T::RealType`,
2219    /// otherwise the returned value is `TryFromf64Errors`.
2220    #[inline(always)]
2221    fn try_from_f64_(real_part: f64, imag_part: f64) -> Result<Self, TryFromf64Errors> {
2222        let real_part = RealRug::<PRECISION>::try_from_f64_(real_part)?;
2223        let imag_part = RealRug::<PRECISION>::try_from_f64_(imag_part)?;
2224
2225        Ok(Self(rug::Complex::with_val(
2226            PRECISION,
2227            (real_part.0, imag_part.0),
2228        )))
2229    }
2230}
2231
2232// Conditional compilation for the `rug` feature
2233#[cfg(feature = "rug")]
2234impl<const PRECISION: u32> MulComplexLeft<Rug<PRECISION>> for ComplexRug<PRECISION> {}
2235//------------------------------------------------------------------------------------------------------------
2236
2237//------------------------------------------------------------------------------------------------------------
2238// Conditional compilation for the `rug` feature
2239#[cfg(feature = "rug")]
2240impl<const PRECISION: u32> Mul<ComplexRug<PRECISION>> for &RealRug<PRECISION> {
2241    type Output = ComplexRug<PRECISION>;
2242
2243    fn mul(self, rhs: ComplexRug<PRECISION>) -> ComplexRug<PRECISION> {
2244        ComplexRug(rhs.0.mul(&self.0))
2245    }
2246}
2247//------------------------------------------------------------------------------------------------------------
2248
2249//------------------------------------------------------------------------------------------------------------
2250/// Converts the input `vec` of [`f64`] values into a vector of floating point number, as described by the generic numerical kernel `T`.
2251///
2252/// # Panics
2253/// In debug and release mode a `panic!` will be emitted if the conversion from `f64` to `T::RealType` causes
2254/// some loss of information (e.g. if the type `T` has less precision of `f64` then there is the possbility
2255/// that some `f64` values cannot be exactly represented by a `T::RealType`).
2256/// # Example
2257/// ```
2258/// use ftl_numkernel::{Native64, vec_f64_into_vec_float};
2259///
2260/// // Conditional compilation for the `rug` feature
2261/// #[cfg(feature = "rug")]
2262/// use ftl_numkernel::Rug;
2263///
2264/// // vector of f64 values
2265/// let a = vec![0., 1.];
2266///
2267/// let b = vec_f64_into_vec_float::<Native64>(a.clone());
2268/// assert_eq!(b[0], 0.);
2269/// assert_eq!(b[1], 1.);
2270///
2271///
2272/// // Conditional compilation for the `rug` feature
2273/// #[cfg(feature = "rug")]
2274/// {
2275///     const PRECISION: u32 = 100;
2276///
2277///      // vector of rug::Float values with PRECISION = 100
2278///     let b = vec_f64_into_vec_float::<Rug<PRECISION>>(a);
2279///     assert_eq!(b[0].as_ref(), &rug::Float::with_val(PRECISION, 0.));
2280///     assert_eq!(b[1].as_ref(), &rug::Float::with_val(PRECISION, 1.));
2281/// }
2282/// ```
2283#[inline(always)]
2284pub fn vec_f64_into_vec_float<T: NumKernel>(vec: Vec<f64>) -> Vec<T::RealType> {
2285    vec.into_iter()
2286        .map(|v| T::RealType::try_from_f64_(v).unwrap())
2287        .collect()
2288}
2289//------------------------------------------------------------------------------------------------------------
2290
2291//------------------------------------------------------------------------------------------------------------
2292#[cfg(test)]
2293mod tests {
2294    use super::*;
2295    use core::ops::{Add, Div, Mul, Sub};
2296
2297    fn test_add_real<T>()
2298    where
2299        T: NumKernel,
2300        for<'a> &'a T::RealType: Add<T::RealType, Output = T::RealType>,
2301    {
2302        let a = T::RealType::one();
2303        let b = T::RealType::try_from_f64_(2.).unwrap();
2304
2305        let c_expected = T::RealType::try_from_f64_(3.0).unwrap();
2306
2307        let c = a.clone() + &b;
2308        assert_eq!(c, c_expected);
2309
2310        let c = &a + b.clone();
2311        assert_eq!(c, c_expected);
2312
2313        let c = a.clone() + b.clone();
2314        assert_eq!(c, c_expected);
2315    }
2316
2317    fn test_add_complex<T>()
2318    where
2319        T: NumKernel,
2320        for<'a> &'a T::ComplexType: Add<T::ComplexType, Output = T::ComplexType>,
2321    {
2322        let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2323        let b = T::ComplexType::try_from_f64_(3., 4.).unwrap();
2324
2325        let c_expected = T::ComplexType::try_from_f64_(4., 6.).unwrap();
2326
2327        let c = a.clone() + &b;
2328        assert_eq!(c, c_expected);
2329
2330        let c = &a + b.clone();
2331        assert_eq!(c, c_expected);
2332
2333        let c = a.clone() + b.clone();
2334        assert_eq!(c, c_expected);
2335    }
2336
2337    fn test_sub_real<T>()
2338    where
2339        T: NumKernel,
2340        for<'a> &'a T::RealType: Sub<T::RealType, Output = T::RealType>,
2341    {
2342        let a = T::RealType::one();
2343        let b = T::RealType::try_from_f64_(2.).unwrap();
2344
2345        let c_expected = T::RealType::try_from_f64_(-1.0).unwrap();
2346
2347        let c = a.clone() - &b;
2348        assert_eq!(c, c_expected);
2349
2350        let c = &a - b.clone();
2351        assert_eq!(c, c_expected);
2352
2353        let c = a.clone() - b.clone();
2354        assert_eq!(c, c_expected);
2355    }
2356
2357    fn test_sub_complex<T>()
2358    where
2359        T: NumKernel,
2360        for<'a> &'a T::ComplexType: Sub<T::ComplexType, Output = T::ComplexType>,
2361    {
2362        let a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
2363        let b = T::ComplexType::try_from_f64_(1., 4.).unwrap();
2364
2365        let c_expected = T::ComplexType::try_from_f64_(2., -2.).unwrap();
2366
2367        let c = a.clone() - &b;
2368        assert_eq!(c, c_expected);
2369
2370        let c = &a - b.clone();
2371        assert_eq!(c, c_expected);
2372
2373        let c = a.clone() - b.clone();
2374        assert_eq!(c, c_expected);
2375    }
2376
2377    fn test_mul_real<T>()
2378    where
2379        T: NumKernel,
2380        for<'a> &'a T::RealType: Mul<T::RealType, Output = T::RealType>,
2381    {
2382        let a = T::RealType::try_from_f64_(2.).unwrap();
2383        let b = T::RealType::try_from_f64_(3.).unwrap();
2384
2385        let c_expected = T::RealType::try_from_f64_(6.0).unwrap();
2386
2387        let c = a.clone() * &b;
2388        assert_eq!(c, c_expected);
2389
2390        let c = &a * b.clone();
2391        assert_eq!(c, c_expected);
2392
2393        let c = a.clone() * b.clone();
2394        assert_eq!(c, c_expected);
2395    }
2396
2397    fn test_mul_complex<T>()
2398    where
2399        T: NumKernel,
2400        for<'a> &'a T::ComplexType: Mul<T::ComplexType, Output = T::ComplexType>,
2401    {
2402        let a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
2403        let b = T::ComplexType::try_from_f64_(1., 4.).unwrap();
2404
2405        let c_expected = T::ComplexType::try_from_f64_(-5., 14.).unwrap();
2406
2407        let c = a.clone() * &b;
2408        assert_eq!(c, c_expected);
2409
2410        let c = &a * b.clone();
2411        assert_eq!(c, c_expected);
2412
2413        let c = a.clone() * b.clone();
2414        assert_eq!(c, c_expected);
2415    }
2416
2417    fn test_div_real<T>()
2418    where
2419        T: NumKernel,
2420        for<'a> &'a T::RealType: Div<T::RealType, Output = T::RealType>,
2421    {
2422        let a = T::RealType::try_from_f64_(6.).unwrap();
2423        let b = T::RealType::try_from_f64_(2.).unwrap();
2424
2425        let c_expected = T::RealType::try_from_f64_(3.0).unwrap();
2426
2427        let c = a.clone() / &b;
2428        assert_eq!(c, c_expected);
2429
2430        let c = &a / b.clone();
2431        assert_eq!(c, c_expected);
2432
2433        let c = a.clone() / b.clone();
2434        assert_eq!(c, c_expected);
2435    }
2436
2437    fn test_div_complex<T>()
2438    where
2439        T: NumKernel,
2440        for<'a> &'a T::ComplexType: Div<T::ComplexType, Output = T::ComplexType>,
2441    {
2442        let a = T::ComplexType::try_from_f64_(-5., 14.).unwrap();
2443        let b = T::ComplexType::try_from_f64_(1., 4.).unwrap();
2444
2445        let c_expected = T::ComplexType::try_from_f64_(3., 2.).unwrap();
2446
2447        let c = a.clone() / &b;
2448        assert_eq!(c, c_expected);
2449
2450        let c = &a / b.clone();
2451        assert_eq!(c, c_expected);
2452
2453        let c = a.clone() / b.clone();
2454        assert_eq!(c, c_expected);
2455    }
2456
2457    fn test_neg_assign_real<T: NumKernel>() {
2458        let mut a = T::RealType::try_from_f64_(1.).unwrap();
2459        a.neg_assign();
2460
2461        let a_expected = T::RealType::try_from_f64_(-1.).unwrap();
2462        assert_eq!(a, a_expected);
2463    }
2464
2465    fn test_neg_assign_complex<T: NumKernel>() {
2466        let mut a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2467        a.neg_assign();
2468
2469        let a_expected = T::ComplexType::try_from_f64_(-1., -2.).unwrap();
2470        assert_eq!(a, a_expected);
2471    }
2472
2473    fn test_add_assign_real<T: NumKernel>() {
2474        let mut a = T::RealType::try_from_f64_(1.0).unwrap();
2475        let b = T::RealType::try_from_f64_(2.0).unwrap();
2476
2477        a += &b;
2478        let a_expected = T::RealType::try_from_f64_(3.0).unwrap();
2479        assert_eq!(a, a_expected);
2480
2481        a += b;
2482        let a_expected = T::RealType::try_from_f64_(5.0).unwrap();
2483        assert_eq!(a, a_expected);
2484    }
2485
2486    fn test_add_assign_complex<T: NumKernel>() {
2487        let mut a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2488        let b = T::ComplexType::try_from_f64_(3., 4.).unwrap();
2489
2490        a += &b;
2491        let a_expected = T::ComplexType::try_from_f64_(4., 6.).unwrap();
2492        assert_eq!(a, a_expected);
2493
2494        a += b;
2495        let a_expected = T::ComplexType::try_from_f64_(7., 10.).unwrap();
2496        assert_eq!(a, a_expected);
2497    }
2498
2499    fn test_sub_assign_real<T: NumKernel>() {
2500        let mut a = T::RealType::try_from_f64_(1.0).unwrap();
2501        let b = T::RealType::try_from_f64_(2.0).unwrap();
2502
2503        a -= &b;
2504        let a_expected = T::RealType::try_from_f64_(-1.0).unwrap();
2505        assert_eq!(a, a_expected);
2506
2507        a -= b;
2508        let a_expected = T::RealType::try_from_f64_(-3.0).unwrap();
2509        assert_eq!(a, a_expected);
2510    }
2511
2512    fn test_sub_assign_complex<T: NumKernel>() {
2513        let mut a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
2514        let b = T::ComplexType::try_from_f64_(2., 4.).unwrap();
2515
2516        a -= &b;
2517        let a_expected = T::ComplexType::try_from_f64_(1., -2.).unwrap();
2518        assert_eq!(a, a_expected);
2519
2520        a -= b;
2521        let a_expected = T::ComplexType::try_from_f64_(-1., -6.).unwrap();
2522        assert_eq!(a, a_expected);
2523    }
2524
2525    fn test_mul_assign_real<T: NumKernel>() {
2526        let mut a = T::RealType::try_from_f64_(1.0).unwrap();
2527        let b = T::RealType::try_from_f64_(2.0).unwrap();
2528
2529        a *= &b;
2530        let a_expected = T::RealType::try_from_f64_(2.0).unwrap();
2531        assert_eq!(a, a_expected);
2532
2533        a *= b;
2534        let a_expected = T::RealType::try_from_f64_(4.0).unwrap();
2535        assert_eq!(a, a_expected);
2536    }
2537
2538    fn test_mul_assign_complex<T: NumKernel>() {
2539        let mut a = T::ComplexType::try_from_f64_(3., 2.).unwrap();
2540        let b = T::ComplexType::try_from_f64_(2., 4.).unwrap();
2541
2542        a *= &b;
2543        let a_expected = T::ComplexType::try_from_f64_(-2., 16.).unwrap();
2544        assert_eq!(a, a_expected);
2545
2546        a *= b;
2547        let a_expected = T::ComplexType::try_from_f64_(-68., 24.).unwrap();
2548        assert_eq!(a, a_expected);
2549    }
2550
2551    fn test_div_assign_real<T: NumKernel>() {
2552        let mut a = T::RealType::try_from_f64_(4.0).unwrap();
2553        let b = T::RealType::try_from_f64_(2.0).unwrap();
2554
2555        a /= &b;
2556        let a_expected = T::RealType::try_from_f64_(2.0).unwrap();
2557        assert_eq!(a, a_expected);
2558
2559        a /= b;
2560        let a_expected = T::RealType::try_from_f64_(1.0).unwrap();
2561        assert_eq!(a, a_expected);
2562    }
2563
2564    fn test_div_assign_complex<T: NumKernel>() {
2565        let mut a = T::ComplexType::try_from_f64_(-68., 24.).unwrap();
2566        let b = T::ComplexType::try_from_f64_(2., 4.).unwrap();
2567
2568        a /= &b;
2569        let a_expected = T::ComplexType::try_from_f64_(-2., 16.).unwrap();
2570        assert_eq!(a, a_expected);
2571
2572        a /= b;
2573        let a_expected = T::ComplexType::try_from_f64_(3., 2.).unwrap();
2574        assert_eq!(a, a_expected);
2575    }
2576
2577    fn test_abs_real<T: NumKernel>() {
2578        let a = T::RealType::try_from_f64_(-1.).unwrap();
2579
2580        let abs = a.abs();
2581        let expected = T::RealType::try_from_f64_(1.).unwrap();
2582        assert_eq!(abs, expected);
2583    }
2584
2585    fn test_abs_complex<T: NumKernel>() {
2586        let a = T::ComplexType::try_from_f64_(-3., 4.).unwrap();
2587
2588        let abs = a.abs();
2589        let expected = T::RealType::try_from_f64_(5.).unwrap();
2590        assert_eq!(abs, expected);
2591    }
2592
2593    fn test_mul_add_real<T: NumKernel>() {
2594        let a = T::RealType::try_from_f64_(2.0).unwrap();
2595        let b = T::RealType::try_from_f64_(3.0).unwrap();
2596        let c = T::RealType::try_from_f64_(1.0).unwrap();
2597
2598        let d_expected = T::RealType::try_from_f64_(7.0).unwrap();
2599
2600        let d = a.mul_add(&b, &c);
2601        assert_eq!(d, d_expected);
2602    }
2603
2604    fn test_mul_add_complex<T: NumKernel>() {
2605        let a = T::ComplexType::try_from_f64_(2., -3.).unwrap();
2606        let b = T::ComplexType::try_from_f64_(3., 1.).unwrap();
2607        let c = T::ComplexType::try_from_f64_(1., -4.).unwrap();
2608
2609        let d_expected = T::ComplexType::try_from_f64_(10., -11.).unwrap();
2610
2611        let d = a.mul_add(&b, &c);
2612        assert_eq!(d, d_expected);
2613    }
2614
2615    /*
2616    fn test_add_complex_with_real<T>()
2617    where
2618        T: NumKernel,
2619        for<'a> &'a T::RealType: Add<T::ComplexType, Output = T::ComplexType>,
2620    {
2621        let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2622        let b = T::RealType::try_from_f64_(3.).unwrap();
2623
2624        let c_expected = T::ComplexType::try_from_f64_(4., 2.).unwrap();
2625
2626        let c = a.clone() + &b;
2627        assert_eq!(c, c_expected);
2628
2629        //        let c = &a + b.clone();
2630        //        assert_eq!(c, c_expected);
2631
2632        let c = a.clone() + b.clone();
2633        assert_eq!(c, c_expected);
2634
2635        //        let c = b.clone() + &a;
2636        //        assert_eq!(c, c_expected);
2637
2638        let c = &b + a.clone();
2639        assert_eq!(c, c_expected);
2640
2641        let c = b.clone() + a.clone();
2642        assert_eq!(c, c_expected);
2643    }
2644
2645    fn test_sub_complex_with_real<T>()
2646    where
2647        T: NumKernel,
2648        for<'a> &'a T::RealType: Sub<T::ComplexType, Output = T::ComplexType>,
2649    {
2650        let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2651        let b = T::RealType::try_from_f64_(3.).unwrap();
2652
2653        let a_minus_b_expected = T::ComplexType::try_from_f64_(-2., 2.).unwrap();
2654        let b_minus_a_expected = T::ComplexType::try_from_f64_(2., -2.).unwrap();
2655
2656        let a_minus_b = a.clone() - &b;
2657        assert_eq!(a_minus_b, a_minus_b_expected);
2658
2659        //        let a_minus_b = &a_minus_b - b.clone();
2660        //        assert_eq!(a_minus_b, a_minus_b_expected);
2661
2662        let a_minus_b = a.clone() - b.clone();
2663        assert_eq!(a_minus_b, a_minus_b_expected);
2664
2665        //        let c = b.clone() - &a;
2666        //        assert_eq!(c, b_minus_a_expected);
2667
2668        let b_minus_a = &b - a.clone();
2669        assert_eq!(b_minus_a, b_minus_a_expected);
2670
2671        let b_minus_a = b.clone() - a.clone();
2672        assert_eq!(b_minus_a, b_minus_a_expected);
2673    }
2674    */
2675
2676    fn test_mul_complex_with_real<T>()
2677    where
2678        T: NumKernel,
2679        for<'a> &'a T::RealType: Mul<T::ComplexType, Output = T::ComplexType>,
2680    {
2681        let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2682        let b = T::RealType::try_from_f64_(3.).unwrap();
2683
2684        let a_times_b_expected = T::ComplexType::try_from_f64_(3., 6.).unwrap();
2685        let b_times_a_expected = a_times_b_expected.clone();
2686
2687        let a_times_b = a.clone() * &b;
2688        assert_eq!(a_times_b, a_times_b_expected);
2689
2690        //        let a_times_b = &a_minus_b * b.clone();
2691        //        assert_eq!(a_times_b, a_times_b_expected);
2692
2693        let a_times_b = a.clone() * b.clone();
2694        assert_eq!(a_times_b, a_times_b_expected);
2695
2696        //        let c = b.clone() - &a;
2697        //        assert_eq!(c, b_minus_a_expected);
2698
2699        let b_times_a = &b * a.clone();
2700        assert_eq!(b_times_a, b_times_a_expected);
2701
2702        let b_times_a = b.clone() * a.clone();
2703        assert_eq!(b_times_a, b_times_a_expected);
2704    }
2705
2706    fn test_mul_assign_complex_with_real<T>()
2707    where
2708        T: NumKernel,
2709    {
2710        let a = T::ComplexType::try_from_f64_(1., 2.).unwrap();
2711        let b = T::RealType::try_from_f64_(3.).unwrap();
2712
2713        let a_times_b_expected = T::ComplexType::try_from_f64_(3., 6.).unwrap();
2714
2715        let mut a_times_b = a.clone();
2716        a_times_b *= &b;
2717        assert_eq!(a_times_b, a_times_b_expected);
2718
2719        let mut a_times_b = a.clone();
2720        a_times_b *= b;
2721        assert_eq!(a_times_b, a_times_b_expected);
2722    }
2723
2724    mod native64 {
2725        use super::*;
2726
2727        mod real {
2728            use super::*;
2729
2730            #[test]
2731            fn from_f64() {
2732                let v_native64 =
2733                    <f64 as FunctionsRealType<Native64>>::try_from_f64_(16.25).unwrap();
2734                assert_eq!(v_native64, 16.25);
2735            }
2736
2737            #[test]
2738            fn zero() {
2739                test_zero::<Native64>();
2740            }
2741
2742            #[test]
2743            fn one() {
2744                test_one::<Native64>();
2745            }
2746
2747            #[test]
2748            fn add() {
2749                test_add_real::<Native64>();
2750            }
2751
2752            #[test]
2753            fn sub() {
2754                test_sub_real::<Native64>();
2755            }
2756
2757            #[test]
2758            fn mul() {
2759                test_mul_real::<Native64>();
2760            }
2761
2762            #[test]
2763            fn div() {
2764                test_div_real::<Native64>();
2765            }
2766
2767            #[test]
2768            fn neg_assign() {
2769                test_neg_assign_real::<Native64>();
2770            }
2771
2772            #[test]
2773            fn add_assign() {
2774                test_add_assign_real::<Native64>();
2775            }
2776
2777            #[test]
2778            fn sub_assign() {
2779                test_sub_assign_real::<Native64>();
2780            }
2781
2782            #[test]
2783            fn mul_assign() {
2784                test_mul_assign_real::<Native64>();
2785            }
2786
2787            #[test]
2788            fn div_assign() {
2789                test_div_assign_real::<Native64>();
2790            }
2791
2792            #[test]
2793            fn abs() {
2794                test_abs_real::<Native64>();
2795            }
2796
2797            #[test]
2798            fn mul_add() {
2799                test_mul_add_real::<Native64>();
2800            }
2801
2802            #[test]
2803            fn recip() {
2804                test_recip::<Native64>();
2805            }
2806
2807            #[test]
2808            fn acos() {
2809                let a = 0.;
2810
2811                let pi_over_2 = a.acos_();
2812                let expected = 1.5707963267948966;
2813                assert_eq!(pi_over_2, expected);
2814            }
2815
2816            #[test]
2817            fn asin() {
2818                let a = 1.;
2819
2820                let pi_over_2 = a.asin_();
2821                let expected = 1.5707963267948966;
2822                assert_eq!(pi_over_2, expected);
2823            }
2824
2825            #[test]
2826            fn cos() {
2827                test_cos::<Native64>();
2828            }
2829
2830            #[test]
2831            fn sin() {
2832                test_sin::<Native64>();
2833            }
2834        }
2835
2836        mod complex {
2837            use super::*;
2838            use num::Complex;
2839
2840            #[test]
2841            fn from_f64() {
2842                let v = <Complex<f64> as FunctionsComplexType<Native64>>::try_from_f64_(16.25, 2.)
2843                    .unwrap();
2844                assert_eq!(v.real_(), 16.25);
2845                assert_eq!(v.imag_(), 2.);
2846            }
2847
2848            #[test]
2849            fn conj() {
2850                let v = <Complex<f64> as FunctionsComplexType<Native64>>::try_from_f64_(16.25, 2.)
2851                    .unwrap();
2852
2853                let v_conj = v.conj_();
2854                assert_eq!(v_conj.real_(), 16.25);
2855                assert_eq!(v_conj.imag_(), -2.);
2856            }
2857
2858            #[test]
2859            fn add() {
2860                test_add_complex::<Native64>();
2861            }
2862
2863            #[test]
2864            fn sub() {
2865                test_sub_complex::<Native64>();
2866            }
2867
2868            #[test]
2869            fn mul() {
2870                test_mul_complex::<Native64>();
2871            }
2872
2873            #[test]
2874            fn div() {
2875                test_div_complex::<Native64>();
2876            }
2877
2878            #[test]
2879            fn neg_assign() {
2880                test_neg_assign_complex::<Native64>();
2881            }
2882
2883            #[test]
2884            fn add_assign() {
2885                test_add_assign_complex::<Native64>();
2886            }
2887
2888            #[test]
2889            fn sub_assign() {
2890                test_sub_assign_complex::<Native64>();
2891            }
2892
2893            #[test]
2894            fn mul_assign() {
2895                test_mul_assign_complex::<Native64>();
2896            }
2897
2898            #[test]
2899            fn div_assign() {
2900                test_div_assign_complex::<Native64>();
2901            }
2902
2903            #[test]
2904            fn abs() {
2905                test_abs_complex::<Native64>();
2906            }
2907
2908            #[test]
2909            fn mul_add() {
2910                test_mul_add_complex::<Native64>();
2911            }
2912
2913            /*
2914                        #[test]
2915                        fn add_complex_with_real() {
2916                            test_add_complex_with_real::<Native64>();
2917                        }
2918
2919                        #[test]
2920                        fn sub_complex_with_real() {
2921                            test_sub_complex_with_real::<Native64>();
2922                        }
2923            */
2924
2925            #[test]
2926            fn mul_complex_with_real() {
2927                test_mul_complex_with_real::<Native64>();
2928            }
2929
2930            #[test]
2931            fn mul_assign_complex_with_real() {
2932                test_mul_assign_complex_with_real::<Native64>();
2933            }
2934        }
2935    }
2936
2937    // Conditional compilation for the `rug` feature
2938    #[cfg(feature = "rug")]
2939    mod rug_ {
2940        use super::*;
2941
2942        mod real {
2943            use super::*;
2944
2945            #[test]
2946            fn from_f64() {
2947                let v_100bits = RealRug::<100>::try_from_f64_(16.25).unwrap();
2948
2949                assert_eq!(v_100bits, 16.25);
2950
2951                let v_53bits = RealRug::<53>::try_from_f64_(16.25).unwrap();
2952                assert_eq!(v_53bits, 16.25);
2953
2954                // 16.25 has seven significant bits (binary 10000.01)
2955                let v_7bits = RealRug::<7>::try_from_f64_(16.25).unwrap();
2956                assert_eq!(v_7bits, 16.25);
2957            }
2958
2959            #[test]
2960            #[should_panic]
2961            fn from_f64_failing() {
2962                // this should fail because 16.25 has seven significant bits (binary 10000.01) and we ask a float with 6 significant bits
2963                let _v_6bits = RealRug::<6>::try_from_f64_(16.25).unwrap();
2964            }
2965
2966            #[test]
2967            fn zero() {
2968                test_zero::<Rug<64>>();
2969                test_zero::<Rug<100>>();
2970            }
2971
2972            #[test]
2973            fn one() {
2974                test_one::<Rug<64>>();
2975                test_one::<Rug<100>>();
2976            }
2977
2978            #[test]
2979            fn add() {
2980                test_add_real::<Rug<100>>();
2981            }
2982
2983            #[test]
2984            fn sub() {
2985                test_sub_real::<Rug<100>>();
2986            }
2987
2988            #[test]
2989            fn mul() {
2990                test_mul_real::<Rug<100>>();
2991            }
2992
2993            #[test]
2994            fn div() {
2995                test_div_real::<Rug<100>>();
2996            }
2997
2998            #[test]
2999            fn neg_assign() {
3000                test_neg_assign_real::<Rug<100>>();
3001            }
3002
3003            #[test]
3004            fn add_assign() {
3005                test_add_assign_real::<Rug<100>>();
3006            }
3007
3008            #[test]
3009            fn sub_assign() {
3010                test_sub_assign_real::<Rug<100>>();
3011            }
3012
3013            #[test]
3014            fn mul_assign() {
3015                test_mul_assign_real::<Rug<100>>();
3016            }
3017
3018            #[test]
3019            fn div_assign() {
3020                test_div_assign_real::<Rug<100>>();
3021            }
3022
3023            #[test]
3024            fn abs() {
3025                test_abs_real::<Rug<100>>();
3026            }
3027
3028            #[test]
3029            fn mul_add() {
3030                test_mul_add_real::<Rug<100>>();
3031            }
3032
3033            #[test]
3034            fn recip() {
3035                test_recip::<Rug<64>>();
3036                test_recip::<Rug<100>>();
3037            }
3038
3039            #[test]
3040            fn acos() {
3041                {
3042                    let a = RealRug::<53>::zero();
3043                    let pi_over_2 = RealRug::<53>::acos_(a);
3044                    let expected = rug::Float::with_val(53, 1.5707963267948966);
3045                    assert_eq!(pi_over_2.as_ref(), &expected);
3046                }
3047                {
3048                    let a = RealRug::<100>::zero();
3049                    let pi_over_2 = RealRug::<100>::acos_(a);
3050                    let expected = rug::Float::with_val(
3051                        100,
3052                        rug::Float::parse("1.5707963267948966192313216916397e0").unwrap(),
3053                    );
3054                    assert_eq!(pi_over_2.as_ref(), &expected);
3055                }
3056            }
3057
3058            #[test]
3059            fn asin() {
3060                {
3061                    let a = RealRug::<53>::one();
3062                    let pi_over_2 = RealRug::<53>::asin_(a);
3063                    let expected = rug::Float::with_val(53, 1.5707963267948966);
3064                    assert_eq!(pi_over_2.as_ref(), &expected);
3065                }
3066                {
3067                    let a = RealRug::<100>::one();
3068                    let pi_over_2 = RealRug::<100>::asin_(a);
3069                    let expected = rug::Float::with_val(
3070                        100,
3071                        rug::Float::parse("1.5707963267948966192313216916397e0").unwrap(),
3072                    );
3073                    assert_eq!(pi_over_2.as_ref(), &expected);
3074                }
3075            }
3076
3077            #[test]
3078            fn cos() {
3079                test_cos::<Rug<64>>();
3080                test_cos::<Rug<100>>();
3081            }
3082
3083            #[test]
3084            fn sin() {
3085                test_sin::<Rug<64>>();
3086                test_sin::<Rug<100>>();
3087            }
3088
3089            #[test]
3090            fn dot_product() {
3091                let a = &[
3092                    RealRug::<100>::try_from_f64_(1.).unwrap(),
3093                    RealRug::<100>::try_from_f64_(2.).unwrap(),
3094                ];
3095
3096                let b = &[
3097                    RealRug::<100>::try_from_f64_(2.).unwrap(),
3098                    RealRug::<100>::try_from_f64_(-1.).unwrap(),
3099                ];
3100
3101                let a: Vec<_> = a.iter().map(|a_i| a_i.as_ref()).collect();
3102                let b: Vec<_> = b.iter().map(|b_i| b_i.as_ref()).collect();
3103
3104                let value =
3105                    RealRug::<100>(rug::Float::dot(a.into_iter().zip(b.into_iter())).complete(100));
3106
3107                assert_eq!(value.as_ref(), &rug::Float::with_val(100, 0.));
3108            }
3109        }
3110
3111        mod complex {
3112            use super::*;
3113
3114            #[test]
3115            fn from_f64() {
3116                let v_100bits = ComplexRug::<100>::try_from_f64_(16.25, 2.).unwrap();
3117                assert_eq!(ComplexRug::<100>::real_(&v_100bits), 16.25);
3118                assert_eq!(ComplexRug::<100>::imag_(&v_100bits), 2.);
3119
3120                let v_53bits = ComplexRug::<53>::try_from_f64_(16.25, 2.).unwrap();
3121                assert_eq!(ComplexRug::<53>::real_(&v_53bits), 16.25);
3122                assert_eq!(ComplexRug::<53>::imag_(&v_53bits), 2.);
3123
3124                // 16.25 has seven significant bits (binary 10000.01)
3125                let v_7bits = ComplexRug::<7>::try_from_f64_(16.25, 2.).unwrap();
3126                assert_eq!(ComplexRug::<7>::real_(&v_7bits), 16.25);
3127                assert_eq!(ComplexRug::<7>::imag_(&v_7bits), 2.);
3128            }
3129
3130            #[test]
3131            #[should_panic]
3132            fn from_f64_failing() {
3133                // this should fail because 16.25 has seven significant bits (binary 10000.01) and we ask a float with 6 significant bits
3134                let _v_6bits = ComplexRug::<6>::try_from_f64_(16.25, 2.).unwrap();
3135            }
3136
3137            #[test]
3138            fn conj() {
3139                let v = ComplexRug::<100>::try_from_f64_(16.25, 2.).unwrap();
3140
3141                let v_conj = ComplexRug::<100>::conj_(v);
3142                assert_eq!(ComplexRug::<100>::real_(&v_conj), 16.25);
3143                assert_eq!(ComplexRug::<100>::imag_(&v_conj), -2.);
3144            }
3145
3146            #[test]
3147            fn add() {
3148                test_add_complex::<Rug<100>>();
3149            }
3150
3151            #[test]
3152            fn sub() {
3153                test_sub_complex::<Rug<100>>();
3154            }
3155
3156            #[test]
3157            fn mul() {
3158                test_mul_complex::<Rug<100>>();
3159            }
3160
3161            #[test]
3162            fn div() {
3163                test_div_complex::<Rug<100>>();
3164            }
3165
3166            #[test]
3167            fn neg_assign() {
3168                test_neg_assign_complex::<Rug<100>>();
3169            }
3170
3171            #[test]
3172            fn add_assign() {
3173                test_add_assign_complex::<Rug<100>>();
3174            }
3175
3176            #[test]
3177            fn sub_assign() {
3178                test_sub_assign_complex::<Rug<100>>();
3179            }
3180
3181            #[test]
3182            fn mul_assign() {
3183                test_mul_assign_complex::<Rug<100>>();
3184            }
3185
3186            #[test]
3187            fn div_assign() {
3188                test_div_assign_complex::<Rug<100>>();
3189            }
3190
3191            #[test]
3192            fn abs() {
3193                test_abs_complex::<Rug<100>>();
3194            }
3195
3196            #[test]
3197            fn mul_add() {
3198                test_mul_add_complex::<Rug<100>>();
3199            }
3200            /*
3201                        #[test]
3202                        fn add_complex_with_real() {
3203                            test_add_complex_with_real::<Rug<100>>();
3204                        }
3205
3206                        #[test]
3207                        fn sub_complex_with_real() {
3208                            test_sub_complex_with_real::<Rug<100>>();
3209                        }
3210            */
3211            #[test]
3212            fn mul_complex_with_real() {
3213                test_mul_complex_with_real::<Rug<100>>();
3214            }
3215
3216            #[test]
3217            fn mul_assign_complex_with_real() {
3218                test_mul_assign_complex_with_real::<Rug<100>>();
3219            }
3220
3221            #[test]
3222            fn dot_product() {
3223                let a = &[
3224                    ComplexRug::<100>::try_from_f64_(1., 3.).unwrap(),
3225                    ComplexRug::<100>::try_from_f64_(2., 4.).unwrap(),
3226                ];
3227
3228                let b = &[
3229                    ComplexRug::<100>::try_from_f64_(-2., -5.).unwrap(),
3230                    ComplexRug::<100>::try_from_f64_(-1., 6.).unwrap(),
3231                ];
3232
3233                let a: Vec<_> = a.iter().map(|a_i| a_i.as_ref()).collect();
3234                let b: Vec<_> = b.iter().map(|b_i| b_i.as_ref()).collect();
3235
3236                // computes a * a^T
3237                let a_times_a = ComplexRug::<100>(
3238                    rug::Complex::dot(a.clone().into_iter().zip(a.clone().into_iter()))
3239                        .complete((100, 100)),
3240                );
3241                assert_eq!(
3242                    a_times_a.as_ref(),
3243                    &rug::Complex::with_val(100, (-20., 22.))
3244                );
3245
3246                // computes a * b^T
3247                let a_times_b = ComplexRug::<100>(
3248                    rug::Complex::dot(a.clone().into_iter().zip(b.clone().into_iter()))
3249                        .complete((100, 100)),
3250                );
3251                assert_eq!(
3252                    a_times_b.as_ref(),
3253                    &rug::Complex::with_val(100, (-13., -3.))
3254                );
3255
3256                // computes b * a^T
3257                let b_times_a = ComplexRug::<100>(
3258                    rug::Complex::dot(b.into_iter().zip(a.into_iter())).complete((100, 100)),
3259                );
3260                assert_eq!(
3261                    b_times_a.as_ref(),
3262                    &rug::Complex::with_val(100, (-13., -3.))
3263                );
3264            }
3265        }
3266    }
3267
3268    fn test_sin<T: NumKernel>() {
3269        let a = T::RealType::zero();
3270
3271        let a = a.sin_();
3272        let expected = T::RealType::zero();
3273        assert_eq!(a, expected);
3274    }
3275
3276    fn test_cos<T: NumKernel>() {
3277        let a = T::RealType::zero();
3278
3279        let a = a.cos_();
3280        let expected = T::RealType::one();
3281        assert_eq!(a, expected);
3282    }
3283
3284    fn test_recip<T: NumKernel>() {
3285        let a = T::RealType::two_();
3286
3287        let a = a.try_reciprocal().unwrap();
3288        let expected = T::RealType::one_div_2_();
3289        assert_eq!(a, expected);
3290    }
3291
3292    fn test_zero<T: NumKernel>() {
3293        let a = T::RealType::zero();
3294
3295        assert_eq!(a, 0.0);
3296    }
3297
3298    fn test_one<T: NumKernel>() {
3299        let a = T::RealType::one();
3300
3301        assert_eq!(a, 1.0);
3302    }
3303}
3304
3305#[cfg(test)]
3306mod tests_new {
3307    use super::*;
3308
3309    mod functions_general_type {
3310        use super::*;
3311
3312        mod native64 {
3313            use super::*;
3314
3315            mod real {
3316                use super::*;
3317
3318                #[test]
3319                fn test_acos_() {
3320                    let value: f64 = 0.5;
3321                    let result = value.acos_();
3322                    assert_eq!(result, value.acos());
3323                }
3324
3325                #[test]
3326                fn test_acosh_() {
3327                    let value: f64 = 1.5;
3328                    let result = value.acosh_();
3329                    assert_eq!(result, value.acosh());
3330                }
3331
3332                #[test]
3333                fn test_asin_() {
3334                    let value: f64 = 0.5;
3335                    let result = value.asin_();
3336                    assert_eq!(result, value.asin());
3337                }
3338
3339                #[test]
3340                fn test_asinh_() {
3341                    let value: f64 = 0.5;
3342                    let result = value.asinh_();
3343                    assert_eq!(result, value.asinh());
3344                }
3345
3346                #[test]
3347                fn test_atan_() {
3348                    let value: f64 = 0.5;
3349                    let result = value.atan_();
3350                    assert_eq!(result, value.atan());
3351                }
3352
3353                #[test]
3354                fn test_atanh_() {
3355                    let value: f64 = 0.5;
3356                    let result = value.atanh_();
3357                    assert_eq!(result, value.atanh());
3358                }
3359
3360                #[test]
3361                fn test_cos_() {
3362                    let value: f64 = 0.5;
3363                    let result = value.cos_();
3364                    assert_eq!(result, value.cos());
3365                }
3366
3367                #[test]
3368                fn test_cosh_() {
3369                    let value: f64 = 0.5;
3370                    let result = value.cosh_();
3371                    assert_eq!(result, value.cosh());
3372                }
3373
3374                #[test]
3375                fn test_exp_() {
3376                    let value: f64 = 0.5;
3377                    let result = value.exp_();
3378                    print!("result = {:?}", result);
3379
3380                    assert_eq!(result, value.exp());
3381                }
3382
3383                #[test]
3384                fn test_is_finite_() {
3385                    let value: f64 = 0.5;
3386                    assert!(value.is_finite_());
3387
3388                    let value: f64 = f64::INFINITY;
3389                    assert!(!value.is_finite_());
3390                }
3391
3392                #[test]
3393                fn test_is_infinite_() {
3394                    let value: f64 = f64::INFINITY;
3395                    assert!(value.is_infinite_());
3396
3397                    let value: f64 = 0.5;
3398                    assert!(!value.is_infinite_());
3399                }
3400
3401                #[test]
3402                fn test_ln_() {
3403                    let value: f64 = 2.718281828459045;
3404                    let result = value.ln_();
3405                    println!("result = {:?}", result);
3406                    assert_eq!(result, value.ln());
3407                }
3408
3409                #[test]
3410                fn test_log10_() {
3411                    let value: f64 = 10.0;
3412                    let result = value.log10_();
3413                    println!("result = {:?}", result);
3414                    assert_eq!(result, value.log10());
3415                }
3416
3417                #[test]
3418                fn test_log2_() {
3419                    let value: f64 = 8.0;
3420                    let result = value.log2_();
3421                    println!("result = {:?}", result);
3422                    assert_eq!(result, value.log2());
3423                }
3424
3425                #[test]
3426                fn test_recip_() {
3427                    let value: f64 = 2.0;
3428                    let result = value.try_reciprocal().unwrap();
3429                    assert_eq!(result, value.recip());
3430                }
3431
3432                #[test]
3433                fn test_sin_() {
3434                    let value: f64 = 0.5;
3435                    let result = value.sin_();
3436                    assert_eq!(result, value.sin());
3437                }
3438
3439                #[test]
3440                fn test_sinh_() {
3441                    let value: f64 = 0.5;
3442                    let result = value.sinh_();
3443                    assert_eq!(result, value.sinh());
3444                }
3445
3446                #[test]
3447                fn sqrt() {
3448                    let value: f64 = 4.0;
3449                    let result = value.sqrt();
3450                    assert_eq!(result, value.sqrt());
3451                }
3452
3453                #[test]
3454                fn try_sqrt() {
3455                    let value: f64 = 4.0;
3456                    let result = value.try_sqrt().unwrap();
3457                    assert_eq!(result, value.sqrt());
3458
3459                    assert!((-1.0).try_sqrt().is_err());
3460                }
3461
3462                #[test]
3463                fn test_tan_() {
3464                    let value: f64 = 0.5;
3465                    let result = value.tan_();
3466                    assert_eq!(result, value.tan());
3467                }
3468
3469                #[test]
3470                fn test_tanh_() {
3471                    let value: f64 = 0.5;
3472                    let result = value.tanh_();
3473                    assert_eq!(result, value.tanh());
3474                }
3475            }
3476
3477            mod complex {
3478                use super::*;
3479
3480                #[test]
3481                fn test_acos_() {
3482                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3483                    let result = value.acos_();
3484                    assert_eq!(result, value.acos());
3485                }
3486
3487                #[test]
3488                fn test_acosh_() {
3489                    let value: Complex<f64> = Complex::new(1.5, 0.5);
3490                    let result = value.acosh_();
3491                    assert_eq!(result, value.acosh());
3492                }
3493
3494                #[test]
3495                fn test_asin_() {
3496                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3497                    let result = value.asin_();
3498                    assert_eq!(result, value.asin());
3499                }
3500
3501                #[test]
3502                fn test_asinh_() {
3503                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3504                    let result = value.asinh_();
3505                    assert_eq!(result, value.asinh());
3506                }
3507
3508                #[test]
3509                fn test_atan_() {
3510                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3511                    let result = value.atan_();
3512                    assert_eq!(result, value.atan());
3513                }
3514
3515                #[test]
3516                fn test_atanh_() {
3517                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3518                    let result = value.atanh_();
3519                    assert_eq!(result, value.atanh());
3520                }
3521
3522                #[test]
3523                fn test_cos_() {
3524                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3525                    let result = value.cos_();
3526                    assert_eq!(result, value.cos());
3527                }
3528
3529                #[test]
3530                fn test_cosh_() {
3531                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3532                    let result = value.cosh_();
3533                    assert_eq!(result, value.cosh());
3534                }
3535
3536                #[test]
3537                fn test_exp_() {
3538                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3539                    let result = value.exp_();
3540                    print!("result = {:?}", result);
3541                    assert_eq!(result, value.exp());
3542                }
3543
3544                #[test]
3545                fn test_is_finite_() {
3546                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3547                    assert!(value.is_finite_());
3548
3549                    let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
3550                    assert!(!value.is_finite_());
3551                }
3552
3553                #[test]
3554                fn test_is_infinite_() {
3555                    let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
3556                    assert!(value.is_infinite_());
3557
3558                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3559                    assert!(!value.is_infinite_());
3560                }
3561
3562                #[test]
3563                fn test_ln_() {
3564                    let value: Complex<f64> = Complex::new(2.718281828459045, 1.0);
3565                    let result = value.ln_();
3566                    println!("result = {:?}", result);
3567                    assert_eq!(result, value.ln());
3568                }
3569
3570                #[test]
3571                fn test_log10_() {
3572                    let value: Complex<f64> = Complex::new(10.0, 1.0);
3573                    let result = value.log10_();
3574                    println!("result = {:?}", result);
3575                    assert_eq!(result, value.log10());
3576                }
3577
3578                #[test]
3579                fn test_log2_() {
3580                    let value: Complex<f64> = Complex::new(8.0, 1.0);
3581                    let result = value.log2_();
3582                    println!("result = {:?}", result);
3583                    assert_eq!(result, value.log2());
3584                }
3585
3586                #[test]
3587                fn test_recip_() {
3588                    let value: Complex<f64> = Complex::new(2.0, 0.0);
3589                    let result = value.try_reciprocal().unwrap();
3590                    assert_eq!(result, value.finv());
3591                }
3592
3593                #[test]
3594                fn test_sin_() {
3595                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3596                    let result = value.sin_();
3597                    assert_eq!(result, value.sin());
3598                }
3599
3600                #[test]
3601                fn test_sinh_() {
3602                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3603                    let result = value.sinh_();
3604                    assert_eq!(result, value.sinh());
3605                }
3606
3607                #[test]
3608                fn sqrt() {
3609                    let value: Complex<f64> = Complex::new(4.0, 1.0);
3610                    let result = value.sqrt();
3611                    assert_eq!(result, value.sqrt());
3612                }
3613
3614                #[test]
3615                fn try_sqrt() {
3616                    let value: Complex<f64> = Complex::new(4.0, 1.0);
3617                    let result = value.try_sqrt().unwrap();
3618                    assert_eq!(result, value.sqrt());
3619                }
3620
3621                #[test]
3622                fn test_tan_() {
3623                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3624                    let result = value.tan_();
3625                    assert_eq!(result, value.tan());
3626                }
3627
3628                #[test]
3629                fn test_tanh_() {
3630                    let value: Complex<f64> = Complex::new(0.5, 0.5);
3631                    let result = value.tanh_();
3632                    assert_eq!(result, value.tanh());
3633                }
3634            }
3635        }
3636
3637        #[cfg(feature = "rug")]
3638        mod rug100 {
3639            use super::*;
3640
3641            const PRECISION: u32 = 100;
3642
3643            mod real {
3644                use super::*;
3645                use rug::Float;
3646
3647                #[test]
3648                fn test_acos_() {
3649                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3650                    let result = value.clone().acos_();
3651                    assert_eq!(
3652                        result,
3653                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.acos()))
3654                    );
3655                }
3656
3657                #[test]
3658                fn test_acosh_() {
3659                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 1.5));
3660                    let result = value.clone().acosh_();
3661                    assert_eq!(
3662                        result,
3663                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.acosh()))
3664                    );
3665                }
3666
3667                #[test]
3668                fn test_asin_() {
3669                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3670                    let result = value.clone().asin_();
3671                    assert_eq!(
3672                        result,
3673                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.asin()))
3674                    );
3675                }
3676
3677                #[test]
3678                fn test_asinh_() {
3679                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3680                    let result = value.clone().asinh_();
3681                    assert_eq!(
3682                        result,
3683                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.asinh()))
3684                    );
3685                }
3686
3687                #[test]
3688                fn test_atan_() {
3689                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3690                    let result = value.clone().atan_();
3691                    assert_eq!(
3692                        result,
3693                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.atan()))
3694                    );
3695                }
3696
3697                #[test]
3698                fn test_atanh_() {
3699                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3700                    let result = value.clone().atanh_();
3701                    assert_eq!(
3702                        result,
3703                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.atanh()))
3704                    );
3705                }
3706
3707                #[test]
3708                fn test_cos_() {
3709                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3710                    let result = value.clone().cos_();
3711                    assert_eq!(
3712                        result,
3713                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.cos()))
3714                    );
3715                }
3716
3717                #[test]
3718                fn test_cosh_() {
3719                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3720                    let result = value.clone().cosh_();
3721                    assert_eq!(
3722                        result,
3723                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.cosh()))
3724                    );
3725                }
3726
3727                #[test]
3728                fn test_exp_() {
3729                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3730                    let result = value.clone().exp_();
3731                    print!("result = {:?}", result);
3732                    assert_eq!(
3733                        result,
3734                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.exp()))
3735                    );
3736                }
3737
3738                #[test]
3739                fn test_is_finite_() {
3740                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3741                    assert!(value.is_finite_());
3742
3743                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, f64::INFINITY));
3744                    assert!(!value.is_finite_());
3745                }
3746
3747                #[test]
3748                fn test_is_infinite_() {
3749                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, f64::INFINITY));
3750                    assert!(value.is_infinite_());
3751
3752                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3753                    assert!(!value.is_infinite_());
3754                }
3755
3756                #[test]
3757                fn test_ln_() {
3758                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.718281828459045));
3759                    let result = value.clone().ln_();
3760                    println!("result = {:?}", result);
3761                    assert_eq!(
3762                        result,
3763                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.ln()))
3764                    );
3765                }
3766
3767                #[test]
3768                fn test_log10_() {
3769                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 10.0));
3770                    let result = value.clone().log10_();
3771                    println!("result = {:?}", result);
3772                    assert_eq!(
3773                        result,
3774                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.log10()))
3775                    );
3776                }
3777
3778                #[test]
3779                fn test_log2_() {
3780                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 8.0));
3781                    let result = value.clone().log2_();
3782                    println!("result = {:?}", result);
3783                    assert_eq!(
3784                        result,
3785                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.log2()))
3786                    );
3787                }
3788
3789                #[test]
3790                fn test_recip_() {
3791                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
3792                    let result = value.clone().try_reciprocal().unwrap();
3793                    assert_eq!(
3794                        result,
3795                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.recip()))
3796                    );
3797                }
3798
3799                #[test]
3800                fn test_sin_() {
3801                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3802                    let result = value.clone().sin_();
3803                    assert_eq!(
3804                        result,
3805                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sin()))
3806                    );
3807                }
3808
3809                #[test]
3810                fn test_sinh_() {
3811                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3812                    let result = value.clone().sinh_();
3813                    assert_eq!(
3814                        result,
3815                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sinh()))
3816                    );
3817                }
3818
3819                #[test]
3820                fn sqrt() {
3821                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
3822                    let result = value.clone().sqrt();
3823                    assert_eq!(
3824                        result,
3825                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sqrt()))
3826                    );
3827                }
3828
3829                #[test]
3830                fn try_sqrt() {
3831                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
3832                    let result = value.clone().try_sqrt().unwrap();
3833                    assert_eq!(
3834                        result,
3835                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.sqrt()))
3836                    );
3837
3838                    assert!(RealRug::<PRECISION>(Float::with_val(PRECISION, -4.0))
3839                        .try_sqrt()
3840                        .is_err())
3841                }
3842
3843                #[test]
3844                fn test_tan_() {
3845                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3846                    let result = value.clone().tan_();
3847                    assert_eq!(
3848                        result,
3849                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.tan()))
3850                    );
3851                }
3852
3853                #[test]
3854                fn test_tanh_() {
3855                    let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
3856                    let result = value.clone().tanh_();
3857                    assert_eq!(
3858                        result,
3859                        RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.tanh()))
3860                    );
3861                }
3862
3863                #[test]
3864                fn test_mul_add_() {
3865                    let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
3866                    let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
3867                    let c = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
3868                    let result = a.clone().mul_add(&b, &c);
3869                    assert_eq!(result, RealRug::<PRECISION>(a.0.clone() * b.0 + c.0));
3870                }
3871            }
3872
3873            mod complex {
3874                use super::*;
3875                use rug::Complex;
3876                use rug::Float;
3877
3878                #[test]
3879                fn test_acos_() {
3880                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3881                    let result = value.clone().acos_();
3882                    assert_eq!(
3883                        result,
3884                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.acos()))
3885                    );
3886                }
3887
3888                #[test]
3889                fn test_acosh_() {
3890                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (1.5, 0.5)));
3891                    let result = value.clone().acosh_();
3892                    assert_eq!(
3893                        result,
3894                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.acosh()))
3895                    );
3896                }
3897
3898                #[test]
3899                fn test_asin_() {
3900                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3901                    let result = value.clone().asin_();
3902                    assert_eq!(
3903                        result,
3904                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.asin()))
3905                    );
3906                }
3907
3908                #[test]
3909                fn test_asinh_() {
3910                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3911                    let result = value.clone().asinh_();
3912                    assert_eq!(
3913                        result,
3914                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.asinh()))
3915                    );
3916                }
3917
3918                #[test]
3919                fn test_atan_() {
3920                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3921                    let result = value.clone().atan_();
3922                    assert_eq!(
3923                        result,
3924                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.atan()))
3925                    );
3926                }
3927
3928                #[test]
3929                fn test_atanh_() {
3930                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3931                    let result = value.clone().atanh_();
3932                    assert_eq!(
3933                        result,
3934                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.atanh()))
3935                    );
3936                }
3937
3938                #[test]
3939                fn test_cos_() {
3940                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3941                    let result = value.clone().cos_();
3942                    assert_eq!(
3943                        result,
3944                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.cos()))
3945                    );
3946                }
3947
3948                #[test]
3949                fn test_cosh_() {
3950                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3951                    let result = value.clone().cosh_();
3952                    assert_eq!(
3953                        result,
3954                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.cosh()))
3955                    );
3956                }
3957
3958                #[test]
3959                fn test_exp_() {
3960                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3961                    let result = value.clone().exp_();
3962                    print!("result = {:?}", result);
3963                    assert_eq!(
3964                        result,
3965                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.exp()))
3966                    );
3967                }
3968
3969                #[test]
3970                fn test_is_finite_() {
3971                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3972                    assert!(value.is_finite_());
3973
3974                    let value = ComplexRug::<PRECISION>(Complex::with_val(
3975                        100,
3976                        (Float::with_val(PRECISION, f64::INFINITY), 0.5),
3977                    ));
3978                    assert!(!value.is_finite_());
3979                }
3980
3981                #[test]
3982                fn test_is_infinite_() {
3983                    let value = ComplexRug::<PRECISION>(Complex::with_val(
3984                        100,
3985                        (Float::with_val(PRECISION, f64::INFINITY), 0.5),
3986                    ));
3987                    assert!(value.is_infinite_());
3988
3989                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
3990                    assert!(!value.is_infinite_());
3991                }
3992
3993                #[test]
3994                fn test_ln_() {
3995                    let value = ComplexRug::<PRECISION>(Complex::with_val(
3996                        PRECISION,
3997                        (2.718281828459045, 1.0),
3998                    ));
3999                    let result = value.clone().ln_();
4000                    println!("result = {:?}", result);
4001                    assert_eq!(
4002                        result,
4003                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.ln()))
4004                    );
4005                }
4006
4007                #[test]
4008                fn test_log10_() {
4009                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (10.0, 1.0)));
4010                    let result = value.clone().log10_();
4011                    println!("result = {:?}", result);
4012                    assert_eq!(
4013                        result,
4014                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.log10()))
4015                    );
4016                }
4017
4018                #[test]
4019                fn test_log2_() {
4020                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (8.0, 1.0)));
4021                    let result = value.clone().log2_();
4022                    println!("result = {:?}", result);
4023                    assert_eq!(
4024                        result,
4025                        ComplexRug::<PRECISION>(Complex::with_val(
4026                            PRECISION,
4027                            value.0.log10() / rug::Float::with_val(PRECISION, 2.).log10()
4028                        ))
4029                    );
4030                }
4031
4032                #[test]
4033                fn test_recip_() {
4034                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (2.0, 0.0)));
4035                    let result = value.clone().try_reciprocal().unwrap();
4036                    assert_eq!(
4037                        result,
4038                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.recip()))
4039                    );
4040                }
4041
4042                #[test]
4043                fn test_sin_() {
4044                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
4045                    let result = value.clone().sin_();
4046                    assert_eq!(
4047                        result,
4048                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sin()))
4049                    );
4050                }
4051
4052                #[test]
4053                fn test_sinh_() {
4054                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
4055                    let result = value.clone().sinh_();
4056                    assert_eq!(
4057                        result,
4058                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sinh()))
4059                    );
4060                }
4061
4062                #[test]
4063                fn sqrt() {
4064                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (4.0, 1.0)));
4065                    let result = value.clone().sqrt();
4066                    assert_eq!(
4067                        result,
4068                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sqrt()))
4069                    );
4070                }
4071
4072                #[test]
4073                fn try_sqrt() {
4074                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (4.0, 1.0)));
4075                    let result = value.clone().try_sqrt().unwrap();
4076                    assert_eq!(
4077                        result,
4078                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.sqrt()))
4079                    );
4080                }
4081
4082                #[test]
4083                fn test_tan_() {
4084                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
4085                    let result = value.clone().tan_();
4086                    assert_eq!(
4087                        result,
4088                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.tan()))
4089                    );
4090                }
4091
4092                #[test]
4093                fn test_tanh_() {
4094                    let value = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (0.5, 0.5)));
4095                    let result = value.clone().tanh_();
4096                    assert_eq!(
4097                        result,
4098                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, value.0.tanh()))
4099                    );
4100                }
4101
4102                #[test]
4103                fn test_mul_add_() {
4104                    let a = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (2.0, 1.0)));
4105                    let b = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (3.0, 1.0)));
4106                    let c = ComplexRug::<PRECISION>(Complex::with_val(PRECISION, (4.0, 1.0)));
4107                    let result = a.clone().mul_add(&b, &c);
4108                    assert_eq!(
4109                        result,
4110                        ComplexRug::<PRECISION>(Complex::with_val(PRECISION, a.0 * b.0 + c.0))
4111                    );
4112                }
4113            }
4114        }
4115    }
4116
4117    mod functions_real_type {
4118        use super::*;
4119
4120        mod native64 {
4121            use super::*;
4122
4123            #[test]
4124            fn test_atan2_() {
4125                let a: f64 = 27.0;
4126                let b: f64 = 13.0;
4127
4128                let result = a.atan2_(&b);
4129                assert_eq!(result, a.atan2(b));
4130            }
4131
4132            #[test]
4133            fn test_ceil_() {
4134                let value: f64 = 3.7;
4135                let result = value.ceil_();
4136                assert_eq!(result, value.ceil());
4137            }
4138
4139            #[test]
4140            fn test_clamp_() {
4141                let value: f64 = 5.0;
4142                let min: f64 = 3.0;
4143                let max: f64 = 7.0;
4144                let result = value.clamp_(&min, &max);
4145                assert_eq!(result, value.clamp(min, max));
4146            }
4147
4148            #[test]
4149            fn test_classify_() {
4150                let value: f64 = 3.7;
4151                let result = value.classify_();
4152                assert_eq!(result, value.classify());
4153            }
4154
4155            #[test]
4156            fn test_copysign_() {
4157                let value: f64 = 3.5;
4158                let sign: f64 = -1.0;
4159                let result = value.copysign_(&sign);
4160                assert_eq!(result, value.copysign(sign));
4161            }
4162
4163            #[test]
4164            fn test_epsilon_() {
4165                let eps = f64::epsilon_();
4166                assert_eq!(eps, f64::EPSILON);
4167            }
4168
4169            #[test]
4170            fn test_exp_m1_() {
4171                let value: f64 = 0.5;
4172                let result = value.exp_m1_();
4173                assert_eq!(result, value.exp_m1());
4174            }
4175
4176            #[test]
4177            fn test_floor_() {
4178                let value: f64 = 3.7;
4179                let result = value.floor_();
4180                assert_eq!(result, value.floor());
4181            }
4182
4183            #[test]
4184            fn test_fract_() {
4185                let value: f64 = 3.7;
4186                let result = value.fract_();
4187                assert_eq!(result, value.fract());
4188            }
4189
4190            #[test]
4191            fn test_hypot_() {
4192                let a: f64 = 3.0;
4193                let b: f64 = 4.0;
4194                let result = a.hypot_(&b);
4195                assert_eq!(result, a.hypot(b));
4196            }
4197
4198            #[test]
4199            fn test_infinity_() {
4200                let inf = f64::infinity_();
4201                assert_eq!(inf, f64::INFINITY);
4202            }
4203
4204            #[test]
4205            fn test_is_sign_negative_() {
4206                let value: f64 = -1.0;
4207                assert!(value.is_sign_negative_());
4208
4209                let value: f64 = -0.0;
4210                assert!(value.is_sign_negative_());
4211
4212                let value: f64 = 0.0;
4213                assert!(!value.is_sign_negative_());
4214
4215                let value: f64 = 1.0;
4216                assert!(!value.is_sign_negative_());
4217            }
4218
4219            #[test]
4220            fn test_is_sign_positive_() {
4221                let value: f64 = -1.0;
4222                assert!(!value.is_sign_positive_());
4223
4224                let value: f64 = -0.0;
4225                assert!(!value.is_sign_positive_());
4226
4227                let value: f64 = 0.0;
4228                assert!(value.is_sign_positive_());
4229
4230                let value: f64 = 1.0;
4231                assert!(value.is_sign_positive_());
4232            }
4233
4234            #[test]
4235            fn test_ln_1p_() {
4236                let value: f64 = 0.5;
4237                let result = value.ln_1p_();
4238                assert_eq!(result, value.ln_1p());
4239            }
4240
4241            #[test]
4242            fn test_neg_infinity_() {
4243                let inf = f64::neg_infinity_();
4244                assert_eq!(inf, f64::NEG_INFINITY);
4245            }
4246
4247            #[test]
4248            fn test_max_() {
4249                let a: f64 = 3.0;
4250                let b: f64 = 4.0;
4251                let result = a.max_(&b);
4252                assert_eq!(result, a.max(b));
4253            }
4254
4255            #[test]
4256            fn test_min_() {
4257                let a: f64 = 3.0;
4258                let b: f64 = 4.0;
4259                let result = a.min_(&b);
4260                assert_eq!(result, a.min(b));
4261            }
4262
4263            #[test]
4264            fn test_mul_add_mul_mut() {
4265                let mut a: f64 = 2.0;
4266                let b: f64 = 3.0;
4267                let c: f64 = 4.0;
4268                let d: f64 = -1.0;
4269                let result = a.mul_add_mul_mut_(&b, &c, &d);
4270                assert_eq!(result, a.mul_add_assign(b, c * d));
4271            }
4272
4273            #[test]
4274            fn test_mul_sub_mul_mut() {
4275                let mut a: f64 = 2.0;
4276                let b: f64 = 3.0;
4277                let c: f64 = 4.0;
4278                let d: f64 = -1.0;
4279                let result = a.mul_sub_mul_mut_(&b, &c, &d);
4280                assert_eq!(result, a.mul_add_assign(b, -c * d));
4281            }
4282
4283            #[test]
4284            fn test_negative_one_() {
4285                let value = f64::negative_one_();
4286                assert_eq!(value, -1.0);
4287            }
4288
4289            #[test]
4290            fn test_one_() {
4291                let value = f64::one();
4292                assert_eq!(value, 1.0);
4293            }
4294
4295            #[test]
4296            fn test_round_() {
4297                let value: f64 = 3.5;
4298                let result = value.round_();
4299                assert_eq!(result, value.round());
4300            }
4301
4302            #[test]
4303            fn test_round_ties_even_() {
4304                let value: f64 = 3.5;
4305                let result = value.round_ties_even_();
4306                assert_eq!(result, value.round_ties_even());
4307            }
4308
4309            #[test]
4310            fn test_signum_() {
4311                let value: f64 = -3.5;
4312                let result = value.signum_();
4313                assert_eq!(result, value.signum());
4314            }
4315
4316            #[test]
4317            fn test_total_cmp_() {
4318                let a: f64 = 3.0;
4319                let b: f64 = 4.0;
4320                let result = a.total_cmp_(&b);
4321                assert_eq!(result, a.total_cmp(&b));
4322            }
4323
4324            #[test]
4325            fn test_try_from_64_() {
4326                let result = f64::try_from_f64_(3.7);
4327                assert!(result.is_ok());
4328            }
4329
4330            #[test]
4331            fn test_try_from_64_error_infinite() {
4332                let result = f64::try_from_f64_(f64::INFINITY);
4333                assert!(result.is_err());
4334            }
4335
4336            #[test]
4337            fn test_try_from_64_error_nan() {
4338                let result = f64::try_from_f64_(f64::NAN);
4339                assert!(result.is_err());
4340            }
4341
4342            #[test]
4343            fn test_trunc_() {
4344                let value: f64 = 3.7;
4345                let result = value.trunc_();
4346                assert_eq!(result, value.trunc());
4347            }
4348
4349            #[test]
4350            fn test_two_() {
4351                let value = f64::two_();
4352                assert_eq!(value, 2.0);
4353            }
4354        }
4355
4356        #[cfg(feature = "rug")]
4357        mod rug100 {
4358            use super::*;
4359            use rug::{float, Float};
4360
4361            const PRECISION: u32 = 100;
4362
4363            #[test]
4364            fn test_atan2_() {
4365                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 27.0));
4366                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 13.0));
4367                let result = a.clone().atan2_(&b);
4368                assert_eq!(
4369                    result,
4370                    RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.atan2(&b.0)))
4371                );
4372            }
4373
4374            #[test]
4375            fn test_ceil_() {
4376                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
4377                let result = value.clone().ceil_();
4378                assert_eq!(
4379                    result,
4380                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.ceil()))
4381                );
4382            }
4383
4384            #[test]
4385            fn test_clamp_() {
4386                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 5.0));
4387                let min = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4388                let max = RealRug::<PRECISION>(Float::with_val(PRECISION, 7.0));
4389                let result = value.clone().clamp_(&min, &max);
4390                assert_eq!(
4391                    result,
4392                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.clamp(&min.0, &max.0)))
4393                );
4394            }
4395
4396            #[test]
4397            fn test_classify_() {
4398                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
4399                let result = value.classify_();
4400                assert_eq!(result, value.0.classify());
4401            }
4402
4403            #[test]
4404            fn test_copysign_() {
4405                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.5));
4406                let sign = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
4407                let result = value.clone().copysign_(&sign);
4408                assert_eq!(
4409                    result,
4410                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.copysign(&sign.0)))
4411                );
4412            }
4413
4414            #[test]
4415            fn test_epsilon_() {
4416                let rug_eps = rug::Float::u_pow_u(2, PRECISION - 1)
4417                    .complete(PRECISION.into())
4418                    .recip();
4419                println!("eps: {}", rug_eps);
4420
4421                let eps = RealRug::<PRECISION>::epsilon_();
4422                assert_eq!(eps, RealRug::<PRECISION>(rug_eps.clone()));
4423
4424                // here we compute new_eps as the difference between 1 and the next larger floating point number
4425                let mut new_eps = Float::with_val(PRECISION, 1.);
4426                new_eps.next_up();
4427                new_eps -= Float::with_val(PRECISION, 1.);
4428                assert_eq!(new_eps, rug_eps.clone());
4429
4430                println!("new_eps: {}", new_eps);
4431
4432                let one = RealRug::<PRECISION>::one();
4433                let result = RealRug::<PRECISION>(new_eps / Float::with_val(PRECISION, 2.)) + &one;
4434                assert_eq!(result, one);
4435            }
4436
4437            #[test]
4438            fn test_exp_m1_() {
4439                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
4440                let result = value.clone().exp_m1_();
4441                assert_eq!(
4442                    result,
4443                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.exp_m1()))
4444                );
4445            }
4446
4447            #[test]
4448            fn test_floor_() {
4449                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
4450                let result = value.clone().floor_();
4451                assert_eq!(
4452                    result,
4453                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.floor()))
4454                );
4455            }
4456
4457            #[test]
4458            fn test_fract_() {
4459                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
4460                let result = value.clone().fract_();
4461                assert_eq!(
4462                    result,
4463                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.fract()))
4464                );
4465            }
4466
4467            #[test]
4468            fn test_hypot_() {
4469                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4470                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
4471                let result = a.clone().hypot_(&b);
4472                assert_eq!(
4473                    result,
4474                    RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.hypot(&b.0)))
4475                );
4476            }
4477
4478            #[test]
4479            fn test_infinity_() {
4480                let inf = RealRug::<PRECISION>::infinity_();
4481                assert_eq!(
4482                    inf,
4483                    RealRug::<PRECISION>(Float::with_val(PRECISION, float::Special::Infinity))
4484                );
4485            }
4486
4487            #[test]
4488            fn test_is_sign_negative_() {
4489                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
4490                assert!(value.is_sign_negative_());
4491
4492                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -0.0));
4493                assert!(value.is_sign_negative_());
4494
4495                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.0));
4496                assert!(!value.is_sign_negative_());
4497
4498                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 1.0));
4499                assert!(!value.is_sign_negative_());
4500            }
4501
4502            #[test]
4503            fn test_is_sign_positive_() {
4504                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
4505                assert!(!value.is_sign_positive_());
4506
4507                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -0.0));
4508                assert!(!value.is_sign_positive_());
4509
4510                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.0));
4511                assert!(value.is_sign_positive_());
4512
4513                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 1.0));
4514                assert!(value.is_sign_positive_());
4515            }
4516
4517            #[test]
4518            fn test_ln_1p_() {
4519                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 0.5));
4520                let result = value.clone().ln_1p_();
4521                assert_eq!(
4522                    result,
4523                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.ln_1p()))
4524                );
4525            }
4526
4527            #[test]
4528            fn test_neg_infinity_() {
4529                let inf = RealRug::<PRECISION>::neg_infinity_();
4530                assert_eq!(
4531                    inf,
4532                    RealRug::<PRECISION>(Float::with_val(PRECISION, float::Special::NegInfinity))
4533                );
4534            }
4535
4536            #[test]
4537            fn test_max_() {
4538                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4539                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
4540                let result = a.clone().max_(&b);
4541                assert_eq!(
4542                    result,
4543                    RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.max(&b.0)))
4544                );
4545            }
4546
4547            #[test]
4548            fn test_min_() {
4549                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4550                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
4551                let result = a.clone().min_(&b);
4552                assert_eq!(
4553                    result,
4554                    RealRug::<PRECISION>(Float::with_val(PRECISION, a.0.min(&b.0)))
4555                );
4556            }
4557
4558            #[test]
4559            fn test_mul_add_mul_mut() {
4560                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
4561                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4562                let c = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
4563                let d = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
4564                let mut result = a.clone();
4565                result.mul_add_mul_mut_(&b, &c, &d);
4566                assert_eq!(
4567                    result,
4568                    RealRug::<PRECISION>(Float::with_val(
4569                        PRECISION,
4570                        a.0.mul_add(&b.0, &(c.0 * &d.0))
4571                    ))
4572                );
4573            }
4574
4575            #[test]
4576            fn test_mul_sub_mul_mut() {
4577                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0));
4578                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4579                let c = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
4580                let d = RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0));
4581                let mut result = a.clone();
4582                result.mul_sub_mul_mut_(&b, &c, &d);
4583                assert_eq!(
4584                    result,
4585                    RealRug::<PRECISION>(Float::with_val(
4586                        PRECISION,
4587                        a.0.mul_add(&b.0, &(-c.0 * &d.0))
4588                    ))
4589                );
4590            }
4591
4592            #[test]
4593            fn test_negative_one_() {
4594                let value = RealRug::<PRECISION>::negative_one_();
4595                assert_eq!(
4596                    value,
4597                    RealRug::<PRECISION>(Float::with_val(PRECISION, -1.0))
4598                );
4599            }
4600
4601            #[test]
4602            fn test_one_() {
4603                let value = RealRug::<PRECISION>::one();
4604                assert_eq!(value, RealRug::<PRECISION>(Float::with_val(PRECISION, 1.0)));
4605            }
4606
4607            #[test]
4608            fn test_round_() {
4609                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.5));
4610                let result = value.clone().round_();
4611                assert_eq!(
4612                    result,
4613                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.round()))
4614                );
4615            }
4616
4617            #[test]
4618            fn test_round_ties_even_() {
4619                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.5));
4620                let result = value.clone().round_ties_even_();
4621                assert_eq!(
4622                    result,
4623                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.round_even()))
4624                );
4625            }
4626
4627            #[test]
4628            fn test_signum_() {
4629                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, -3.5));
4630                let result = value.clone().signum_();
4631                assert_eq!(
4632                    result,
4633                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.signum()))
4634                );
4635            }
4636
4637            #[test]
4638            fn test_total_cmp_() {
4639                let a = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.0));
4640                let b = RealRug::<PRECISION>(Float::with_val(PRECISION, 4.0));
4641                let result = a.total_cmp_(&b);
4642                assert_eq!(result, a.0.total_cmp(&b.0));
4643            }
4644
4645            #[test]
4646            fn test_try_from_64_() {
4647                let result = RealRug::<PRECISION>::try_from_f64_(3.7);
4648                assert!(result.is_ok());
4649            }
4650
4651            #[test]
4652            fn test_try_from_64_error_infinite() {
4653                let result = RealRug::<PRECISION>::try_from_f64_(f64::INFINITY);
4654                assert!(result.is_err());
4655            }
4656
4657            #[test]
4658            fn test_try_from_64_error_nan() {
4659                let result = RealRug::<PRECISION>::try_from_f64_(f64::NAN);
4660                assert!(result.is_err());
4661            }
4662
4663            #[test]
4664            fn test_trunc_() {
4665                let value = RealRug::<PRECISION>(Float::with_val(PRECISION, 3.7));
4666                let result = value.clone().trunc_();
4667                assert_eq!(
4668                    result,
4669                    RealRug::<PRECISION>(Float::with_val(PRECISION, value.0.trunc()))
4670                );
4671            }
4672
4673            #[test]
4674            fn test_two_() {
4675                let value = RealRug::<PRECISION>::two_();
4676                assert_eq!(value, RealRug::<PRECISION>(Float::with_val(PRECISION, 2.0)));
4677            }
4678        }
4679    }
4680}