num_valid/
lib.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2#![feature(error_generic_member_access)]
3//#![feature(const_trait_impl)]
4#![feature(associated_const_equality)]
5#![feature(trait_alias)]
6//#![feature(generic_const_exprs)]
7//#![feature(associated_type_defaults)]
8//#![feature(non_lifetime_binders)]
9//#![feature(negative_impls)]
10
11//! [`num-valid`](crate) is a Rust library designed for robust, generic, and high-performance numerical computation.
12//! It provides a safe and extensible framework for working with both real and complex numbers, addressing the challenges
13//! of floating-point arithmetic by ensuring correctness and preventing common errors like `NaN` propagation.
14//!
15//!
16//! # Key Features \& Architecture
17//!
18//! - **Safety by Construction with Validated Types:** Instead of using raw primitives like [`f64`] or [`num::complex<f64>`]
19//!   directly, [`num-valid`](crate) encourages the use of validated wrappers like [`RealValidated`]
20//!   and [`ComplexValidated`]. These types guarantee that the value they hold is always valid (e.g.,
21//!   finite) according to a specific policy, eliminating entire classes of numerical bugs.
22//!
23//! - **Support for Real and Complex Numbers:** The library supports for both real and complex numbers,
24//!   with specific validation policy for each type.
25//!
26//! - **Layered and Extensible Design:** The library has a well-defined, layered, and highly generic architecture. It abstracts the concept of a "numerical kernel" (the underlying number representation and its operations) from the high-level mathematical traits.
27//!
28//!   The architecture can be understood in four main layers:
29//!   - **Layer 1: Raw Trait Contracts** (in the [`kernels`] module):
30//!     - The [`RawScalarTrait`], [`RawRealTrait`], and [`RawComplexTrait`](crate::kernels::RawComplexTrait) define the low-level, "unchecked" contract
31//!       for any number type.
32//!     - These traits are the foundation, providing a standard set of `unchecked_*` methods.
33//!     - The contract is that the caller must guarantee the validity of inputs. This is a strong design choice, separating the raw, potentially unsafe operations from the validated, safe API.
34//!     - **Why?** This design separates the pure, high-performance computational logic from the safety and validation logic.
35//!       It creates a clear, minimal contract for backend implementors and allows the validated wrappers in Layer 3
36//!       to be built on a foundation of trusted, high-speed operations.
37//!   - **Layer 2: Validation Policies**:
38//!     - The [`NumKernel`] trait is the bridge between the raw types and the validated wrappers.
39//!     - It bundles together the raw real/complex types and their corresponding validation policies
40//!       (e.g., [`StrictFinitePolicy`](crate::validation::StrictFinitePolicy), [`DebugValidationPolicy`](crate::validation::DebugValidationPolicy),
41//!       etc.). This allows the entire behavior of the validated types to be configured with a single generic parameter.
42//!     - **Why?** It acts as the central policy configuration point. By choosing a [`NumKernel`], a user selects both a
43//!       numerical backend (e.g., `f64` vs. `rug`) and a set of safety rules (e.g., [`StrictFinitePolicy`](crate::validation::StrictFinitePolicy)
44//!       vs. [`DebugValidationPolicy<StrictFinitePolicy>`](crate::validation::DebugValidationPolicy))
45//!       with a single generic parameter. This dramatically simplifies writing generic code that can be configured for
46//!       different safety and performance trade-offs.
47//!   - **Layer 3: Validated Wrappers**:
48//!     - [`RealValidated<K>`](crate::kernels::RealValidated) and [`ComplexValidated<K>`](crate::kernels::ComplexValidated)
49//!       are the primary user-facing types.
50//!     - These are newtype wrappers that are guaranteed to hold a value that conforms to the [`NumKernel`] `K` (and to the validation policies therein).
51//!     - They use extensive macros to implement high-level traits. The logic is clean: perform a check (if necessary) on the input value,
52//!       then call the corresponding `unchecked_*` method from the raw trait, and then perform a check on the output value before returning it.
53//!       This ensures safety and correctness.
54//!     - **Why?** These wrappers use the newtype pattern to enforce correctness at the type level. By construction, an instance
55//!       of [`RealValidated`] is guaranteed to contain a value that has passed the validation policy, eliminating entire
56//!       classes of errors (like `NaN` propagation) in user code.
57//!   - **Layer 4: High-Level Abstraction Traits**:
58//!     - The [`FpScalar`] trait is the central abstraction, defining a common interface for all scalar types. It uses an associated type sealed type (`Kind`),
59//!       to enforce that a scalar is either real or complex, but not both.
60//!     - [`RealScalar`] and [`ComplexScalar`] are specialized sub-traits of [`FpScalar`] that serve as markers for real and complex numbers, respectively.
61//!     - Generic code in a consumer crate is written against these high-level traits.
62//!     - The [`RealValidated`] and [`ComplexValidated`] structs from Layer 3 are the concrete implementors of these traits.
63//!     - **Why?** These traits provide the final, safe, and generic public API. Library consumers write their algorithms
64//!       against these traits, making their code independent of the specific numerical kernel being used.
65//!
66//!   This layered approach is powerful, providing both high performance (by using unchecked methods internally) and safety
67//!   (through the validated wrappers). The use of generics and traits makes it extensible to new numerical backends (as demonstrated by the rug implementation).
68//!
69//! - **Multiple Numerical Backends**. At the time of writing, 2 numerical backends can be used:
70//!   - the standard (high-performance) numerical backend is the one in which the raw floating point and complex numbers are
71//!     described by the Rust's native [`f64`] and [`num::complex<f64>`] types, as described by the ANSI/IEEE Std 754-1985;
72//!   - an optional (high-precision) numerical backend is available if the library is compiled with the optional flag `--features=rug`,
73//!     and uses the arbitrary precision raw types `rug::Float` and `rug::Complex` from the Rust library [`rug`](https://crates.io/crates/rug).
74//! - **Comprehensive Mathematical Library**. It includes a wide range of mathematical functions for
75//!   trigonometry, logarithms, exponentials, and more, all implemented as traits (e.g., Sin, Cos, Sqrt) and available on the validated types.
76//! - **Numerically Robust Implementations**. The library commits to numerical accuracy. As an example,
77//!   by using `NeumaierSum` for its default [`std::iter::Sum`] implementation to minimize precision loss.
78//! - **Robust Error Handling:** The library defines detailed error types for various numerical operations,
79//!   ensuring that invalid inputs and outputs are properly handled and reported.
80//!   Errors are categorized into input and output errors, with specific variants for different types of numerical
81//!   issues such as division by zero, invalid values, and subnormal numbers.
82//! - **Comprehensive Documentation:** The library includes detailed documentation for each struct, trait, method,
83//!   and error type, making it easy for users to understand and utilize the provided functionality.
84//!   Examples are provided for key functions to demonstrate their usage and expected behavior.
85//!
86//! # Compiler Requirement: Rust Nightly
87//! This library currently requires the **nightly** toolchain because it uses some unstable Rust features which,
88//! at the time of writing (July 2025), are not yet available in stable or beta releases.
89//!
90//! If these feature are stabilized in a future Rust release, the library will be updated to support the stable compiler.
91//!
92//! To use the nightly toolchain, please run:
93//!
94//! ```bash,ignore
95//! rustup install nightly
96//! rustup override set nightly
97//! ```
98//!
99//! This will set your environment to use the nightly compiler, enabling compatibility with the current version of the
100//! library.
101//!
102//! # Getting Started
103//!
104//! This guide will walk you through the basics of using [`num-valid`](crate).
105//!
106//! ## 1. Add [`num-valid`](crate)to your Project
107//!
108//! Add the following to your `Cargo.toml` (change the versions to the latest ones):
109//!
110//! ```toml
111//! [dependencies]
112//! num-valid = "0.1.1" # Change to the latest vesion
113//! try_create = "0.1.2" # Needed for the TryNew trait
114//! ```
115//!
116//! To enable the arbitrary-precision backend, use the `rug` feature:
117//!
118//! ```toml
119//! [dependencies]
120//! num-valid = { version = "0.1.1", features = ["rug"] }
121//! try_create = "0.1.2"
122//! ```
123//!
124//! ## 2. Core Concept: Validated Types
125//!
126//! The central idea in [`num-valid`](crate)is to use **validated types** instead of raw primitives like [`f64`].
127//! These are wrappers that guarantee their inner value is always valid (e.g., not `NaN` or `Infinity`) according to
128//! a specific policy.
129//!
130//! The most common type you'll use is [`RealNative64StrictFinite`], which wraps an [`f64`] and ensures it's always finite,
131//! both in Debug and Release mode. For a similar type wrapping an [`f64`] that ensures it's always finite, but with the
132//! validity checks executed only in Debug mode (providing a performance equal to the raw [`f64`] type), you can use
133//! [`RealNative64StrictFiniteInDebug`].
134//!
135//! ## 3. Your First Calculation
136//!
137//! Let's perform a square root calculation. You'll need to bring the necessary traits into scope.
138//!
139//! ```rust
140//! // Import traits for the constructor, the sqrt function and the sqrt errors.
141//! use num_valid::{
142//!     RealNative64StrictFinite,
143//!     functions::{Sqrt, SqrtRealInputErrors, SqrtRealErrors},
144//! };
145//! use try_create::TryNew;
146//!
147//! // 1. Create a validated number. try_new() returns a Result.
148//! let x = RealNative64StrictFinite::try_new(4.0).unwrap();
149//!
150//! // 2. Use the direct method for operations.
151//! // This will panic if the operation is invalid (e.g., sqrt of a negative).
152//! let sqrt_x = x.sqrt();
153//! assert_eq!(sqrt_x, 2.0);
154//!
155//! // 3. Use the `try_*` methods for error handling.
156//! // This is the safe way to handle inputs that might be out of the function's domain.
157//! let neg_x = RealNative64StrictFinite::try_new(-4.0).unwrap();
158//! let sqrt_neg_x_result = neg_x.try_sqrt();
159//!
160//! // The operation fails gracefully, returning an Err.
161//! assert!(sqrt_neg_x_result.is_err());
162//!
163//! // The error gives informations about the problem occurred
164//! assert!(matches!(sqrt_neg_x_result.unwrap_err(),
165//!     SqrtRealErrors::Input{ source: SqrtRealInputErrors::NegativeValue{ value: -4., .. }}));
166//! ```
167//!
168//! ## 4. Writing Generic Functions
169//!
170//! The real power of [`num-valid`](crate) comes from writing generic functions that work with any
171//! supported numerical type. You can do this by using the [`FpScalar`] and [`RealScalar`] traits as bounds.
172//!
173//! ```rust
174//! use num_valid::{
175//!     RealScalar, RealNative64StrictFinite, FpScalar,
176//!     functions::{Abs, Sin, Cos},
177//! };
178//! use num::One;
179//! use try_create::TryNew;
180//!
181//! // This function works for any type that implements RealScalar,
182//! // including f64, RealNative64StrictFinite, and RealRugStrictFinite.
183//! fn verify_trig_identity<T: RealScalar>(angle: T) -> T {
184//!     // We can use .sin(), .cos(), and arithmetic ops because they are
185//!     // required by the RealScalar trait.
186//!     let sin_x = angle.clone().sin();
187//!     let cos_x = angle.cos();
188//!     (sin_x.clone() * sin_x) + (cos_x.clone() * cos_x)
189//! }
190//!
191//! // Define a type alias for convenience
192//! type MyReal = RealNative64StrictFinite;
193//!
194//! // Call it with a validated f64 type.
195//! let angle = MyReal::try_from_f64(0.5).unwrap();
196//! let identity = verify_trig_identity(angle);
197//!
198//! // The result should be very close to 1.0.
199//! let one = MyReal::one();
200//! assert!((identity - one).abs() < 1e-15);
201//! ```
202//!
203//! If the `rug` feature is enabled, you could call the exact same
204//! function with a high-precision number changing only the defintionion
205//! of the alias type `MyReal`. For example, for real numbers with precision of 100 bits:
206//! ```rust,ignore
207//! // we need to add the proper module
208//! use num_valid::RealRugStrictFinite;
209//! // ... same modules as above
210//!
211//! // ... same verify_trig_identity() function as above
212//!
213//! // Define a type alias for convenience
214//! type MyReal = RealRugStrictFinite<100>; // real number with precision of 100 bits
215//!
216//! // Initialize it with an f64 value.
217//! let angle = MyReal::try_from_f64(0.5).unwrap();
218//! let identity = verify_trig_identity(angle);
219//!
220//! // The result should be very close to 1.0.
221//! let one = MyReal::one();
222//! assert!((identity - one).abs() < 1e-15);
223//! ```
224//!
225//! # License
226//! Copyright 2023-2025, C.N.R. - Consiglio Nazionale delle Ricerche
227//!
228//! Licensed under either of
229//! - Apache License, Version 2.0
230//! - MIT license
231//!
232//! at your option.
233//!
234//! Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you,
235//! as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
236//!
237//! ## License Notice for Optional Feature Dependencies (LGPL-3.0 Compliance)
238//! If you enable the `rug` feature, this project will depend on the [`rug`](https://crates.io/crates/rug) library,
239//! which is licensed under the LGPL-3.0 license. Activating this feature may introduce LGPL-3.0 requirements to your
240//! project. Please review the terms of the LGPL-3.0 license to ensure compliance.
241
242pub mod functions;
243pub mod kernels;
244pub mod neumaier_compensated_sum;
245pub mod validation;
246
247use crate::{
248    functions::{
249        ACos, ACosH, ASin, ASinH, ATan, ATan2, ATanH, Abs, Arg, Arithmetic, Clamp, Classify,
250        ComplexScalarConstructors, ComplexScalarGetParts, ComplexScalarMutateParts,
251        ComplexScalarSetParts, Conjugate, Cos, CosH, Exp, ExpM1, HyperbolicFunctions, Hypot, Ln,
252        Ln1p, Log2, Log10, LogarithmFunctions, Max, Min, MulAddRef, NegAssign, Pow,
253        PowComplexBaseRealExponentErrors, PowIntExponent, PowRealBaseRealExponentErrors,
254        Reciprocal, Rounding, Sign, Sin, SinH, Sqrt, Tan, TanH, TotalCmp, TrigonometricFunctions,
255    },
256    kernels::{RawRealTrait, RawScalarTrait},
257    neumaier_compensated_sum::NeumaierAddable,
258    validation::{ErrorsTryFromf64, FpChecks},
259};
260use num::{Complex, One, Zero};
261use rand::{Rng, distr::Distribution};
262use std::{
263    fmt::{Debug, Display},
264    ops::{Mul, MulAssign, Neg},
265};
266use try_create::IntoInner;
267
268pub use crate::kernels::{
269    ComplexValidated, NumKernel, RawKernel, RealValidated,
270    native64::Native64,
271    native64_validated::{
272        ComplexNative64StrictFinite, ComplexNative64StrictFiniteInDebug, Native64StrictFinite,
273        Native64StrictFiniteInDebug, RealNative64StrictFinite, RealNative64StrictFiniteInDebug,
274    },
275};
276
277#[cfg(feature = "rug")]
278pub use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite, RugStrictFinite};
279
280//------------------------------------------------------------------------------------------------
281// Private module to encapsulate implementation details of the scalar kind for the mutual exclusion.
282pub(crate) mod scalar_kind {
283    /// A sealed trait to mark the "kind" of a scalar.
284    /// External users cannot implement this trait.
285    pub trait Sealed {}
286
287    /// A marker for real scalar types.
288    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
289    pub struct Real;
290    impl Sealed for Real {}
291
292    /// A marker for complex scalar types.
293    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
294    pub struct Complex;
295    impl Sealed for Complex {}
296}
297//------------------------------------------------------------------------------------------------
298
299//------------------------------------------------------------------------------------------------
300
301/// # Core trait for a floating-point scalar number (real or complex)
302///
303/// [`FpScalar`] is a fundamental trait in [`num-valid`](crate) that provides a common interface
304/// for all floating-point scalar types, whether they are real or complex, and regardless
305/// of their underlying numerical kernel (e.g., native [`f64`] or arbitrary-precision [`rug`](https://docs.rs/rug/latest/rug/index.html) types).
306///
307/// This trait serves as a primary bound for generic functions and structures that need to
308/// operate on scalar values capable of floating-point arithmetic. It aggregates a large
309/// number of mathematical function traits (e.g., [`Sin`], [`Cos`], [`Exp`], [`Sqrt`]) and
310/// core properties.
311///
312/// ## Key Responsibilities and Associated Types:
313///
314/// - **Scalar Kind (`FpScalar::Kind`):**
315///   This associated type specifies the fundamental nature of the scalar, which can be
316///   either `scalar_kind::Real` or `scalar_kind::Complex`. It is bound by the private,
317///   sealed trait `scalar_kind::Sealed`. This design enforces **mutual exclusion**:
318///   since a type can only implement [`FpScalar`] once, it can only have one `Kind`,
319///   making it impossible for a type to be both a `RealScalar` and a `ComplexScalar` simultaneously.
320///
321/// - **Real Type Component ([`FpScalar::RealType`]):**
322///   Specifies the real number type corresponding to this scalar via [`RealType`](FpScalar::RealType).
323///   - For real scalars (e.g., [`f64`], [`RealNative64StrictFinite`], [`RealNative64StrictFiniteInDebug`],
324///     `RealRugStrictFinite`, etc.), [`FpScalar::RealType`] is `Self`.
325///   - For complex scalars (e.g., [`num::Complex<f64>`], [`ComplexNative64StrictFinite`], [`ComplexNative64StrictFiniteInDebug`],
326///     `ComplexRugStrictFinite`, etc.), [`FpScalar::RealType`] is their underlying real component type
327///     (e.g., [`f64`], [`RealNative64StrictFinite`], [`RealNative64StrictFiniteInDebug`], `RealRugStrictFinite`, etc.).
328///  
329///   Crucially, this [`FpScalar::RealType`] is constrained to implement [`RealScalar`], ensuring consistency.
330///
331/// - **Core Floating-Point Properties:**
332///   [`FpScalar`] requires implementations of the trait [`FpChecks`], which provides fundamental floating-point checks:
333///   - [`is_finite()`](FpChecks::is_finite): Checks if the number is finite.
334///   - [`is_infinite()`](FpChecks::is_infinite): Checks if the number is positive or negative infinity.
335///   - [`is_nan()`](FpChecks::is_nan): Checks if the number is "Not a Number".
336///   - [`is_normal()`](FpChecks::is_normal): Checks if the number is a normal (not zero, subnormal, infinite, or NaN).
337///
338/// ## Trait Bounds:
339///
340/// [`FpScalar`] itself has several important trait bounds:
341/// - `Sized + Clone + Debug + Display + PartialEq`: Standard utility traits. Note that scalar
342///   types are [`Clone`] but not necessarily [`Copy`].
343/// - [`Zero`] + [`One`]: From `num_traits`, ensuring the type has additive and multiplicative identities.
344/// - [`Neg<Output = Self>`](Neg): Ensures the type can be negated.
345/// - [`Arithmetic`]: A custom aggregate trait in [`num-valid`](crate)that bundles standard
346///   arithmetic operator traits (like [`Add`](std::ops::Add), [`Sub`](std::ops::Sub), [`Mul`], [`Div`](std::ops::Div)).
347/// - [`RandomSampleFromF64`]: Allows the type to be randomly generated from any distribution
348///   that produces `f64`, integrating with the [`rand`] crate.
349/// - `Send + Sync + 'static`: Makes the scalar types suitable for use in concurrent contexts.
350/// - A comprehensive suite of mathematical function traits like [`Sin`], [`Cos`], [`Exp`], [`Ln`], [`Sqrt`], etc.
351///
352/// ## Relationship to Other Traits:
353///
354/// - [`RealScalar`]: A sub-trait of [`FpScalar`] for real numbers, defined by the constraint `FpScalar<Kind = scalar_kind::Real>`.
355/// - [`ComplexScalar`]: A sub-trait of [`FpScalar`] for complex numbers, defined by the constraint `FpScalar<Kind = scalar_kind::Complex>`.
356/// - [`NumKernel`]: Policies like [`StrictFinitePolicy`](crate::validation::StrictFinitePolicy)
357///   are used to validate the raw values that are wrapped inside types implementing `FpScalar`.
358///
359/// ## Example: Generic Function
360///
361/// Here is how you can write a generic function that works with any scalar type
362/// implementing `FpScalar`.
363///
364/// ```
365/// use num_valid::{FpScalar, functions::{MulAddRef, Sqrt}};
366/// use num::Zero;
367///
368/// // This function works with any FpScalar type.
369/// fn norm_and_sqrt<T: FpScalar>(a: T, b: T) -> T {
370///     let val = a.clone().mul_add_ref(&a, &b.pow(2)); // a*a + b*b
371///     val.sqrt()
372/// }
373///
374/// // Also this function works with any FpScalar type.
375/// fn multiply_if_not_zero<T: FpScalar>(a: T, b: T) -> T {
376///     if !a.is_zero() && !b.is_zero() {
377///         a * b
378///     } else {
379///         T::zero()
380///     }
381/// }
382/// ```
383pub trait FpScalar:
384    Sized
385    + Clone
386    + Send
387    + Sync
388    + Debug
389    + Display
390    + IntoInner<InnerType: RawScalarTrait>
391    + PartialEq
392    + Arithmetic
393    + Abs<Output = Self::RealType>
394    + Sqrt
395    + PowIntExponent<RawType = Self::InnerType>
396    + TrigonometricFunctions
397    + HyperbolicFunctions
398    + LogarithmFunctions
399    + Exp
400    + Zero
401    + One
402    + FpChecks
403    + Neg<Output = Self>
404    + MulAddRef
405    + Reciprocal
406    + NeumaierAddable
407    + RandomSampleFromF64
408    + 'static
409{
410    /// The kind of scalar this is, e.g., `Real` or `Complex`.
411    /// This is a sealed trait to prevent external implementations.
412    type Kind: scalar_kind::Sealed;
413
414    /// The real number type corresponding to this scalar.
415    ///
416    /// - For real scalars (e.g., `f64`), `RealType` is `Self`.
417    /// - For complex scalars (e.g., `Complex<f64>`), `RealType` is their underlying
418    ///   real component type (e.g., `f64`).
419    ///
420    /// This `RealType` is guaranteed to implement [`RealScalar`] and belong to the
421    /// same numerical kernel as `Self`.
422    type RealType: RealScalar<RealType = Self::RealType>;
423}
424//-------------------------------------------------------------------------------------------------------------
425
426//-------------------------------------------------------------------------------------------------------------
427
428/// Provides fundamental mathematical constants.
429pub trait Constants: Sized {
430    /// [Machine epsilon] value for `Self`.
431    ///
432    /// This is the difference between `1.0` and the next larger representable number.
433    ///
434    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
435    fn epsilon() -> Self;
436
437    /// Build and return the (floating point) value -1. represented by the proper type.
438    fn negative_one() -> Self;
439
440    /// Build and return the (floating point) value 0.5 represented by the proper type.
441    fn one_div_2() -> Self;
442
443    /// Build and return the (floating point) value `π` represented by the proper type.
444    fn pi() -> Self;
445
446    /// Build and return the (floating point) value `2 π` represented by the proper type.
447    fn two_pi() -> Self;
448
449    /// Build and return the (floating point) value `π/2` represented by the proper type.
450    fn pi_div_2() -> Self;
451
452    /// Build and return the (floating point) value 2. represented by the proper type.
453    fn two() -> Self;
454
455    /// Build and return the maximum finite value allowed by the current floating point representation.
456    fn max_finite() -> Self;
457
458    /// Build and return the minimum finite (i.e., the most negative) value allowed by the current floating point representation.
459    fn min_finite() -> Self;
460
461    /// Build and return the natural logarithm of 2, i.e. the (floating point) value `ln(2)`, represented by the proper type.
462    fn ln_2() -> Self;
463
464    /// Build and return the natural logarithm of 10, i.e. the (floating point) value `ln(10)`, represented by the proper type.
465    fn ln_10() -> Self;
466
467    /// Build and return the base-10 logarithm of 2, i.e. the (floating point) value `Log_10(2)`, represented by the proper type.
468    fn log10_2() -> Self;
469
470    /// Build and return the base-2 logarithm of 10, i.e. the (floating point) value `Log_2(10)`, represented by the proper type.
471    fn log2_10() -> Self;
472
473    /// Build and return the base-2 logarithm of `e`, i.e. the (floating point) value `Log_2(e)`, represented by the proper type.
474    fn log2_e() -> Self;
475
476    /// Build and return the base-10 logarithm of `e`, i.e. the (floating point) value `Log_10(e)`, represented by the proper type.
477    fn log10_e() -> Self;
478
479    /// Build and return the (floating point) value `e` represented by the proper type.
480    fn e() -> Self;
481}
482
483/// # Trait for scalar real numbers
484///
485/// [`RealScalar`] extends the fundamental [`FpScalar`] trait, providing an interface
486/// specifically for real (non-complex) floating-point numbers. It introduces
487/// operations and properties that are unique to real numbers, such as ordering,
488/// rounding, and clamping.
489///
490/// This trait is implemented by real scalar types within each numerical kernel,
491/// for example, [`f64`] for the native kernel,
492/// and `RealRugStrictFinite` for the `rug` kernel (when the `rug` feature is enabled).
493///
494/// ## Key Concepts
495///
496/// - **Inheritance from [`FpScalar`]:** As a sub-trait of [`FpScalar`], any `RealScalar`
497///   type automatically gains all the capabilities of a general floating-point number,
498///   including basic arithmetic and standard mathematical functions (e.g., `sin`, `exp`, `sqrt`).
499///
500/// - **Raw Underlying Type ([`RawReal`](Self::RawReal)):**
501///   This associated type specifies the most fundamental, "raw" representation of the real number,
502///   which implements the [`RawRealTrait`]. This is the type used for low-level, unchecked
503///   operations within the library's internal implementation.
504///   - For [`f64`], [`RealNative64StrictFinite`] and [`RealNative64StrictFiniteInDebug`], `RawReal` is [`f64`].
505///   - For `RealRugStrictFinite<P>`, `RawReal` is `rug::Float`.
506///
507/// ## Provided Operations
508///
509/// In addition to the functions from [`FpScalar`], `RealScalar` provides a suite of methods common in real number arithmetic,
510/// sourced from its super-traits:
511///
512/// - **Rounding ([`Rounding`]):**
513///   [`kernel_ceil()`](Rounding::kernel_ceil), [`kernel_floor()`](Rounding::kernel_floor),
514///   [`kernel_round()`](Rounding::kernel_round), [`kernel_round_ties_even()`](Rounding::kernel_round_ties_even),
515///   [`kernel_trunc()`](Rounding::kernel_trunc), and [`kernel_fract()`](Rounding::kernel_fract).
516///
517/// - **Sign Manipulation ([`Sign`]):**
518///   [`kernel_copysign()`](Sign::kernel_copysign), [`kernel_signum()`](Sign::kernel_signum),
519///   [`kernel_is_sign_positive()`](Sign::kernel_is_sign_positive), and [`kernel_is_sign_negative()`](Sign::kernel_is_sign_negative).
520///
521/// - **Comparison and Ordering:**
522///   - From [`Max`]/[`Min`]: [`max()`](Max::max) and [`min()`](Min::min).
523///   - From [`TotalCmp`]: [`total_cmp()`](TotalCmp::total_cmp) for a total ordering compliant with IEEE 754.
524///   - From [`Clamp`]: [`kernel_clamp()`](Clamp::kernel_clamp).
525///
526/// - **Specialized Functions:**
527///   - From [`ATan2`]: [`atan2()`](ATan2::atan2).
528///   - From [`ExpM1`]/[`Ln1p`]: [`kernel_exp_m1()`](ExpM1::kernel_exp_m1) and [`kernel_ln_1p()`](Ln1p::kernel_ln_1p).
529///   - From [`Hypot`]: [`kernel_hypot()`](Hypot::kernel_hypot); // sqrt(a*a + b*b)
530///   - From [`Classify`]: [`kernel_classify()`](Classify::kernel_classify).
531///
532/// - **Fused Multiply-Add Variants:**
533///   [`kernel_mul_add_mul_mut()`](Self::kernel_mul_add_mul_mut) and
534///   [`kernel_mul_sub_mul_mut()`](Self::kernel_mul_sub_mul_mut).
535///
536/// - **Constants and Constructors:**
537///   - From [`Constants`]: [`epsilon()`](Constants::epsilon), [`pi()`](Constants::pi), [`max_finite()`](Constants::max_finite), etc.
538///   - Fallible constructor from `f64`: [`try_from_f64()`](Self::try_from_f64), which
539///     validates the input for finiteness and, for arbitrary-precision types, exact representability.
540///
541/// ## Naming Convention for `kernel_*` Methods
542///
543/// Methods prefixed with `kernel_` (e.g., `kernel_ceil`, `kernel_copysign`) are
544/// part of the low-level kernel interface. They typically delegate directly to the
545/// most efficient implementation for the underlying type (like `f64::ceil`) without
546/// adding extra validation layers. They are intended to be fast primitives upon which
547/// safer, higher-level abstractions can be built.
548///
549/// ## Critical Trait Bounds
550///
551/// - `Self: FpScalar<RealType = Self>`: This is the defining constraint. It ensures that the type
552///   has all basic floating-point capabilities and confirms that its associated real type is itself.
553/// - `Self: PartialOrd + PartialOrd<f64>`: These bounds are essential for comparison operations,
554///   allowing instances to be compared both with themselves and with native `f64` constants.
555pub trait RealScalar:
556    FpScalar<RealType = Self, InnerType = Self::RawReal>
557    + Sign
558    + Rounding
559    + Constants
560    + PartialEq<f64>
561    + PartialOrd
562    + PartialOrd<f64>
563    + Max
564    + Min
565    + ATan2
566    + for<'a> Pow<&'a Self, Error = PowRealBaseRealExponentErrors<Self::RawReal>>
567    + Clamp
568    + Classify
569    + ExpM1
570    + Hypot
571    + Ln1p
572    + TotalCmp
573{
574    /// The most fundamental, "raw" representation of this real number.
575    ///
576    /// For example:
577    /// - For `f64`, this is `f64`.
578    /// - For `RealRugStrictFinite<P>`, this is `rug::Float` (with precision `P`).
579    ///
580    /// This type is used to parameterize [`ErrorsValidationRawReal`](crate::validation::ErrorsValidationRawReal)
581    /// for this scalar's raw validation errors.
582    type RawReal: RawRealTrait;
583
584    /// Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
585    /// `a.kernel_mul_add_mul_mut(&b, &c, &d)` produces a result like `&a * &b + &c * &d`, but stores the result in `a` using its precision.
586    fn kernel_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
587
588    /// Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
589    /// `a.kernel_mul_sub_mul_mut(&b, &c, &d)` produces a result like `&a * &b - &c * &d`, but stores the result in `a` using its precision.
590    fn kernel_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
591
592    /// Tries to create an instance of `Self` from a [`f64`].
593    ///
594    /// This conversion is fallible and validates the input `value`. For `rug`-based types,
595    /// it also ensures that the `f64` can be represented exactly at the target precision.
596    ///
597    /// # Errors
598    /// Returns [`ErrorsTryFromf64`] if the `value` is not finite or cannot be
599    /// represented exactly by `Self`.
600    fn try_from_f64(value: f64) -> Result<Self, ErrorsTryFromf64<Self::RawReal>>;
601}
602
603/// # Trait for scalar complex numbers
604pub trait ComplexScalar:
605    ComplexScalarMutateParts
606    + Conjugate
607    + Arg<Output = Self::RealType>
608    + for<'a> Mul<&'a Self::RealType, Output = Self>
609    + for<'a> MulAssign<&'a Self::RealType>
610    + for<'a> Pow<&'a Self::RealType, Error = PowComplexBaseRealExponentErrors<Self::RawComplex>>
611{
612    /// Scale the complex number `self` by the real coefficient `c`.
613    #[inline(always)]
614    fn scale(self, c: &Self::RealType) -> Self {
615        self * c
616    }
617
618    /// Scale (in-place) the complex number `self` by the real coefficient `c`.
619    #[inline(always)]
620    fn scale_mut(&mut self, c: &Self::RealType) {
621        *self *= c;
622    }
623}
624
625//------------------------------------------------------------------------------------------------------------
626
627//------------------------------------------------------------------------------------------------------------
628#[inline(always)]
629pub fn try_vec_f64_into_vec_real<RealType: RealScalar>(
630    vec: Vec<f64>,
631) -> Result<Vec<RealType>, ErrorsTryFromf64<RealType::RawReal>> {
632    vec.into_iter().map(|v| RealType::try_from_f64(v)).collect()
633}
634
635/// Converts the input `vec` of [`f64`] values into a vector of floating point number, as described by the generic numerical kernel `T`.
636///
637/// # Panics
638/// In debug and release mode a `panic!` will be emitted if the conversion from `f64` to `T::RealType` causes
639/// some loss of information (e.g. if the type `T` has less precision of `f64` then there is the possbility
640/// that some `f64` values cannot be exactly represented by a `T::RealType`).
641/// # Example
642/// ```
643/// use num_valid::{Native64, vec_f64_into_vec_real};
644///
645/// // Conditional compilation for the `rug` feature
646/// #[cfg(feature = "rug")]
647/// use num_valid::RealRugStrictFinite;
648///
649/// // vector of f64 values
650/// let a = vec![0., 1.];
651///
652/// let b: Vec<f64> = vec_f64_into_vec_real(a.clone());
653/// assert_eq!(b[0], 0.);
654/// assert_eq!(b[1], 1.);
655///
656///
657/// // Conditional compilation for the `rug` feature
658/// #[cfg(feature = "rug")]
659/// {
660///     const PRECISION: u32 = 100;
661///     let b: Vec<RealRugStrictFinite<PRECISION>> = vec_f64_into_vec_real(a);
662///     assert_eq!(b[0].as_ref(), &rug::Float::with_val(PRECISION, 0.));
663///     assert_eq!(b[1].as_ref(), &rug::Float::with_val(PRECISION, 1.));
664/// }
665/// ```
666#[inline(always)]
667pub fn vec_f64_into_vec_real<RealType: RealScalar>(vec: Vec<f64>) -> Vec<RealType> {
668    try_vec_f64_into_vec_real(vec).expect(
669        "The conversion from f64 to RealType failed, which should not happen in a well-defined numerical kernel."
670    )
671}
672//------------------------------------------------------------------------------------------------------------
673
674//------------------------------------------------------------------------------------------------------------
675/// A trait for types that can be randomly generated from a distribution over `f64`.
676///
677/// This trait provides a universal dispatch mechanism for generating random scalar values,
678/// allowing a single generic API to work for primitive types like [`f64`] and
679/// [`Complex<f64>`], as well as custom validated types like [`RealValidated`] and
680/// [`ComplexValidated`].
681///
682/// ## Purpose
683///
684/// The primary goal of [`RandomSampleFromF64`] is to abstract the process of creating a random
685/// scalar. Many random number distributions in the [`rand`] crate are defined to produce
686/// primitive types like `f64`. This trait acts as a bridge, allowing those same
687/// distributions to be used to generate more complex or validated types.
688///
689/// ## How It Works
690///
691/// The trait defines a single required method, [`RandomSampleFromF64::sample_from()`], which takes a reference
692/// to any distribution that implements [`rand::distr::Distribution<f64>`] and a
693/// random number generator (RNG). Each implementing type provides its own logic for
694/// this method:
695///
696/// - For `f64`, it simply samples directly from the distribution.
697/// - For `Complex<f64>`, it samples twice to create the real and imaginary parts.
698/// - For [`RealValidated<K>`], it samples an `f64` and then passes it through the
699///   validation and conversion logic of [`RealValidated::try_from_f64`].
700/// - For [`ComplexValidated<K>`], it reuses the logic for `RealValidated<K>` to sample
701///   the real and imaginary components.
702///
703/// # Example
704///
705/// Here is how you can write a generic function that creates a vector of random numbers
706/// for any type that implements [`RandomSampleFromF64`].
707///
708/// ```
709/// use num_valid::{RealNative64StrictFinite, RealScalar, new_random_vec};
710/// use rand::{distr::Uniform, rngs::StdRng, Rng, SeedableRng};
711///
712/// let seed = [42 ; 32]; // Example seed for reproducibility
713/// let mut rng = StdRng::from_seed(seed);
714/// let uniform = Uniform::new(-10.0, 10.0).unwrap();
715///
716/// // Create a vector of random f64 values.
717/// let f64_vec: Vec<f64> = new_random_vec(3, &uniform, &mut rng);
718/// assert_eq!(&f64_vec, &[-5.257306234905137, 7.212119776268775, -4.666248990558111]);
719///
720/// // Create a vector of random validated real numbers using the same function.
721/// let validated_vec: Vec<RealNative64StrictFinite> = new_random_vec(3, &uniform, &mut rng);
722/// assert_eq!(validated_vec,
723///     [9.66047141517383, -9.04279551029691, -1.026624649331671]
724///         .into_iter()
725///         .map(|v| RealNative64StrictFinite::try_from_f64(v).unwrap())
726///         .collect::<Vec<_>>());
727/// ```
728pub trait RandomSampleFromF64: Sized + Clone {
729    /// Samples a single value of `Self` using the given `f64` distribution.
730    fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
731    where
732        D: Distribution<f64>,
733        R: Rng + ?Sized;
734
735    fn sample_iter_from<D, R>(dist: &D, rng: &mut R, n: usize) -> impl Iterator<Item = Self>
736    where
737        D: Distribution<f64>,
738        R: Rng + ?Sized,
739    {
740        // Create an iterator that samples `n` values from the distribution.
741        (0..n).map(move |_| Self::sample_from(dist, rng))
742    }
743}
744
745impl RandomSampleFromF64 for f64 {
746    #[inline]
747    fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
748    where
749        D: Distribution<f64>,
750        R: Rng + ?Sized,
751    {
752        // Straightforward implementation: sample a f64.
753        dist.sample(rng)
754    }
755}
756impl RandomSampleFromF64 for Complex<f64> {
757    #[inline]
758    fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
759    where
760        D: Distribution<f64>,
761        R: Rng + ?Sized,
762    {
763        // Sample two f64 for the real and imaginary parts.
764        let re = dist.sample(rng);
765        let im = dist.sample(rng);
766        Complex::new(re, im)
767    }
768}
769
770impl<K> RandomSampleFromF64 for RealValidated<K>
771where
772    K: NumKernel,
773{
774    #[inline]
775    fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
776    where
777        D: Distribution<f64>,
778        R: Rng + ?Sized,
779    {
780        loop {
781            // Sample a f64 and then convert/validate it.
782            // The loop ensures that a valid value is returned
783            let value_f64 = dist.sample(rng);
784            let value = RealValidated::try_from_f64(value_f64);
785            if let Ok(validated_value) = value {
786                return validated_value;
787            }
788        }
789    }
790}
791
792impl<K> RandomSampleFromF64 for ComplexValidated<K>
793where
794    K: NumKernel,
795{
796    #[inline]
797    fn sample_from<D, R>(dist: &D, rng: &mut R) -> Self
798    where
799        D: Distribution<f64>,
800        R: Rng + ?Sized,
801    {
802        // Reuse the RealValidated sampling logic for both parts.
803        let re = RealValidated::<K>::sample_from(dist, rng);
804        let im = RealValidated::<K>::sample_from(dist, rng);
805        ComplexValidated::new_complex(re, im)
806    }
807}
808
809//------------------------------------------------------------------------------------------------------------
810
811//------------------------------------------------------------------------------------------------------------
812/// Generates a `Vec<T>` of a specified length with random values.
813///
814/// This function leverages the [`RandomSampleFromF64`] trait to provide a universal way
815/// to create a vector of random numbers for any supported scalar type, including
816/// primitive types like `f64` and `Complex<f64>`, as well as validated types
817/// like [`RealValidated`] and [`ComplexValidated`].
818///
819/// # Parameters
820///
821/// * `n`: The number of random values to generate in the vector.
822/// * `distribution`: A reference to any distribution from the `rand` crate that
823///   implements `Distribution<f64>` (e.g., `Uniform`, `StandardNormal`).
824/// * `rng`: A mutable reference to a random number generator that implements `Rng`.
825///
826/// # Type Parameters
827///
828/// * `T`: The scalar type of the elements in the returned vector. Must implement [`RandomSampleFromF64`].
829/// * `D`: The type of the distribution.
830/// * `R`: The type of the random number generator.
831///
832/// # Example
833///
834/// ```
835/// use num_valid::{new_random_vec, RealNative64StrictFinite};
836/// use rand::{distr::Uniform, rngs::StdRng, SeedableRng};
837/// use try_create::IntoInner;
838///
839/// let seed = [42; 32]; // Use a fixed seed for a reproducible example
840///
841/// // Generate a vector of random f64 values.
842/// let mut rng_f64 = StdRng::from_seed(seed);
843/// let uniform = Uniform::new(-10.0, 10.0).unwrap();
844/// let f64_vec: Vec<f64> = new_random_vec(3, &uniform, &mut rng_f64);
845///
846/// // Generate a vector of random validated real numbers using the same seed.
847/// let mut rng_validated = StdRng::from_seed(seed);
848/// let validated_vec: Vec<RealNative64StrictFinite> = new_random_vec(3, &uniform, &mut rng_validated);
849///
850/// assert_eq!(f64_vec.len(), 3);
851/// assert_eq!(validated_vec.len(), 3);
852///
853/// // The underlying numerical values should be identical because the RNG was seeded the same.
854/// assert_eq!(&f64_vec[0], validated_vec[0].as_ref());
855/// assert_eq!(&f64_vec[1], validated_vec[1].as_ref());
856/// assert_eq!(&f64_vec[2], validated_vec[2].as_ref());
857/// ```
858pub fn new_random_vec<T, D, R>(n: usize, distribution: &D, rng: &mut R) -> Vec<T>
859where
860    T: RandomSampleFromF64,
861    D: Distribution<f64>,
862    R: Rng + ?Sized,
863{
864    T::sample_iter_from(distribution, rng, n).collect()
865}
866//------------------------------------------------------------------------------------------------------------
867
868//------------------------------------------------------------------------------------------------------------
869#[cfg(test)]
870mod tests {
871    use super::*;
872    use num::Complex;
873    use num_traits::MulAddAssign;
874    use std::ops::{Add, Div, Sub};
875
876    mod functions_general_type {
877        use super::*;
878
879        fn test_recip<RealType: RealScalar>() {
880            let a = RealType::two();
881
882            let a = a.try_reciprocal().unwrap();
883            let expected = RealType::one_div_2();
884            assert_eq!(a, expected);
885        }
886
887        fn test_zero<RealType: RealScalar>() {
888            let a = RealType::zero();
889
890            assert_eq!(a, 0.0);
891        }
892
893        fn test_one<RealType: RealScalar>() {
894            let a = RealType::one();
895
896            assert_eq!(a, 1.0);
897        }
898
899        fn test_add<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
900        where
901            for<'a> &'a ScalarType:
902                Add<ScalarType, Output = ScalarType> + Add<&'a ScalarType, Output = ScalarType>,
903        {
904            let c = a.clone() + &b;
905            assert_eq!(c, c_expected);
906
907            let c = &a + b.clone();
908            assert_eq!(c, c_expected);
909
910            let c = a.clone() + b.clone();
911            assert_eq!(c, c_expected);
912
913            let c = &a + &b;
914            assert_eq!(c, c_expected);
915        }
916
917        fn test_sub<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
918        where
919            for<'a> &'a ScalarType:
920                Sub<ScalarType, Output = ScalarType> + Sub<&'a ScalarType, Output = ScalarType>,
921        {
922            let c = a.clone() - &b;
923            assert_eq!(c, c_expected);
924
925            let c = &a - b.clone();
926            assert_eq!(c, c_expected);
927
928            let c = a.clone() - b.clone();
929            assert_eq!(c, c_expected);
930
931            let c = &a - &b;
932            assert_eq!(c, c_expected);
933        }
934
935        fn test_mul<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
936        where
937            for<'a> &'a ScalarType:
938                Mul<ScalarType, Output = ScalarType> + Mul<&'a ScalarType, Output = ScalarType>,
939        {
940            let c = a.clone() * &b;
941            assert_eq!(c, c_expected);
942
943            let c = &a * b.clone();
944            assert_eq!(c, c_expected);
945
946            let c = a.clone() * b.clone();
947            assert_eq!(c, c_expected);
948
949            let c = &a * &b;
950            assert_eq!(c, c_expected);
951        }
952
953        fn test_div<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
954        where
955            for<'a> &'a ScalarType:
956                Div<ScalarType, Output = ScalarType> + Div<&'a ScalarType, Output = ScalarType>,
957        {
958            let c = a.clone() / &b;
959            assert_eq!(c, c_expected);
960
961            let c = &a / b.clone();
962            assert_eq!(c, c_expected);
963
964            let c = a.clone() / b.clone();
965            assert_eq!(c, c_expected);
966
967            let c = &a / &b;
968            assert_eq!(c, c_expected);
969        }
970
971        fn test_mul_complex_with_real<ComplexType: ComplexScalar>(
972            a: ComplexType,
973            b: ComplexType::RealType,
974            a_times_b_expected: ComplexType,
975        ) {
976            let a_times_b = a.clone().scale(&b);
977            assert_eq!(a_times_b, a_times_b_expected);
978
979            let a_times_b = a.clone() * &b;
980            assert_eq!(a_times_b, a_times_b_expected);
981
982            /*
983            let b_times_a_expected = a_times_b_expected.clone();
984
985            let b_times_a = &b * a.clone();
986            assert_eq!(b_times_a, b_times_a_expected);
987
988            let b_times_a = b.clone() * a.clone();
989            assert_eq!(b_times_a, b_times_a_expected);
990            */
991        }
992
993        fn test_mul_assign_complex_with_real<ComplexType: ComplexScalar>(
994            a: ComplexType,
995            b: ComplexType::RealType,
996            a_times_b_expected: ComplexType,
997        ) {
998            let mut a_times_b = a.clone();
999            a_times_b.scale_mut(&b);
1000            assert_eq!(a_times_b, a_times_b_expected);
1001
1002            //        let mut a_times_b = a.clone();
1003            //        a_times_b *= b;
1004            //        assert_eq!(a_times_b, a_times_b_expected);
1005        }
1006
1007        fn test_neg_assign_real<RealType: RealScalar>() {
1008            let mut a = RealType::one();
1009            a.neg_assign();
1010
1011            let a_expected = RealType::try_from_f64(-1.).unwrap();
1012            assert_eq!(a, a_expected);
1013        }
1014
1015        fn test_add_assign_real<RealType: RealScalar>() {
1016            let mut a = RealType::try_from_f64(1.0).unwrap();
1017            let b = RealType::try_from_f64(2.0).unwrap();
1018
1019            a += &b;
1020            let a_expected = RealType::try_from_f64(3.0).unwrap();
1021            assert_eq!(a, a_expected);
1022
1023            a += b;
1024            let a_expected = RealType::try_from_f64(5.0).unwrap();
1025            assert_eq!(a, a_expected);
1026        }
1027
1028        fn test_sub_assign_real<RealType: RealScalar>() {
1029            let mut a = RealType::try_from_f64(1.0).unwrap();
1030            let b = RealType::try_from_f64(2.0).unwrap();
1031
1032            a -= &b;
1033            let a_expected = RealType::try_from_f64(-1.0).unwrap();
1034            assert_eq!(a, a_expected);
1035
1036            a -= b;
1037            let a_expected = RealType::try_from_f64(-3.0).unwrap();
1038            assert_eq!(a, a_expected);
1039        }
1040
1041        fn test_mul_assign_real<RealType: RealScalar>() {
1042            let mut a = RealType::try_from_f64(1.0).unwrap();
1043            let b = RealType::try_from_f64(2.0).unwrap();
1044
1045            a *= &b;
1046            let a_expected = RealType::try_from_f64(2.0).unwrap();
1047            assert_eq!(a, a_expected);
1048
1049            a *= b;
1050            let a_expected = RealType::try_from_f64(4.0).unwrap();
1051            assert_eq!(a, a_expected);
1052        }
1053
1054        fn test_div_assign_real<RealType: RealScalar>() {
1055            let mut a = RealType::try_from_f64(4.0).unwrap();
1056            let b = RealType::try_from_f64(2.0).unwrap();
1057
1058            a /= &b;
1059            let a_expected = RealType::try_from_f64(2.0).unwrap();
1060            assert_eq!(a, a_expected);
1061
1062            a /= b;
1063            let a_expected = RealType::try_from_f64(1.0).unwrap();
1064            assert_eq!(a, a_expected);
1065        }
1066
1067        fn test_mul_add_ref_real<RealType: RealScalar>() {
1068            let a = RealType::try_from_f64(2.0).unwrap();
1069            let b = RealType::try_from_f64(3.0).unwrap();
1070            let c = RealType::try_from_f64(1.0).unwrap();
1071
1072            let d_expected = RealType::try_from_f64(7.0).unwrap();
1073
1074            let d = a.mul_add_ref(&b, &c);
1075            assert_eq!(d, d_expected);
1076        }
1077
1078        fn test_sin_real<RealType: RealScalar>() {
1079            let a = RealType::zero();
1080
1081            let a = a.sin();
1082            let expected = RealType::zero();
1083            assert_eq!(a, expected);
1084        }
1085
1086        fn test_cos_real<RealType: RealScalar>() {
1087            let a = RealType::zero();
1088
1089            let a = a.cos();
1090            let expected = RealType::one();
1091            assert_eq!(a, expected);
1092        }
1093
1094        fn test_abs_real<RealType: RealScalar>() {
1095            let a = RealType::try_from_f64(-1.).unwrap();
1096
1097            let abs: RealType = a.abs();
1098            let expected = RealType::one();
1099            assert_eq!(abs, expected);
1100        }
1101
1102        mod native64 {
1103            use super::*;
1104
1105            mod real {
1106                use super::*;
1107
1108                #[test]
1109                fn zero() {
1110                    test_zero::<f64>();
1111                }
1112
1113                #[test]
1114                fn one() {
1115                    test_one::<f64>();
1116                }
1117
1118                #[test]
1119                fn recip() {
1120                    test_recip::<f64>();
1121                }
1122
1123                #[test]
1124                fn add() {
1125                    let a = 1.0;
1126                    let b = 2.0;
1127                    let c_expected = 3.0;
1128                    test_add(a, b, c_expected);
1129                }
1130
1131                #[test]
1132                fn sub() {
1133                    let a = 1.0;
1134                    let b = 2.0;
1135                    let c_expected = -1.0;
1136                    test_sub(a, b, c_expected);
1137                }
1138
1139                #[test]
1140                fn mul() {
1141                    let a = 2.0;
1142                    let b = 3.0;
1143                    let c_expected = 6.0;
1144                    test_mul(a, b, c_expected);
1145                }
1146
1147                #[test]
1148                fn div() {
1149                    let a = 6.;
1150                    let b = 2.;
1151                    let c_expected = 3.;
1152                    test_div(a, b, c_expected);
1153                }
1154
1155                #[test]
1156                fn neg_assign() {
1157                    test_neg_assign_real::<f64>();
1158                }
1159
1160                #[test]
1161                fn add_assign() {
1162                    test_add_assign_real::<f64>();
1163                }
1164
1165                #[test]
1166                fn sub_assign() {
1167                    test_sub_assign_real::<f64>();
1168                }
1169
1170                #[test]
1171                fn mul_assign() {
1172                    test_mul_assign_real::<f64>();
1173                }
1174
1175                #[test]
1176                fn div_assign() {
1177                    test_div_assign_real::<f64>();
1178                }
1179                #[test]
1180                fn mul_add_ref() {
1181                    test_mul_add_ref_real::<f64>();
1182                }
1183
1184                #[test]
1185                fn from_f64() {
1186                    let v_native64 = f64::try_from_f64(16.25).unwrap();
1187                    assert_eq!(v_native64, 16.25);
1188                }
1189
1190                #[test]
1191                fn abs() {
1192                    test_abs_real::<f64>();
1193                }
1194
1195                #[test]
1196                fn acos() {
1197                    let a = 0.;
1198
1199                    let pi_over_2 = a.acos();
1200                    let expected = std::f64::consts::FRAC_PI_2;
1201                    assert_eq!(pi_over_2, expected);
1202                }
1203
1204                #[test]
1205                fn asin() {
1206                    let a = 1.;
1207
1208                    let pi_over_2 = a.asin();
1209                    let expected = std::f64::consts::FRAC_PI_2;
1210                    assert_eq!(pi_over_2, expected);
1211                }
1212
1213                #[test]
1214                fn cos() {
1215                    test_cos_real::<f64>();
1216                }
1217
1218                #[test]
1219                fn sin() {
1220                    test_sin_real::<f64>();
1221                }
1222
1223                #[test]
1224                fn test_acos() {
1225                    let value: f64 = 0.5;
1226                    let result = value.acos();
1227                    assert_eq!(result, value.acos());
1228                }
1229
1230                #[test]
1231                fn test_acosh() {
1232                    let value: f64 = 1.5;
1233                    let result = value.acosh();
1234                    assert_eq!(result, value.acosh());
1235                }
1236
1237                #[test]
1238                fn test_asin() {
1239                    let value: f64 = 0.5;
1240                    let result = value.asin();
1241                    assert_eq!(result, value.asin());
1242                }
1243
1244                #[test]
1245                fn test_asinh() {
1246                    let value: f64 = 0.5;
1247                    let result = value.asinh();
1248                    assert_eq!(result, value.asinh());
1249                }
1250
1251                #[test]
1252                fn test_atan() {
1253                    let value: f64 = 0.5;
1254                    let result = value.atan();
1255                    assert_eq!(result, value.atan());
1256                }
1257
1258                #[test]
1259                fn test_atanh() {
1260                    let value: f64 = 0.5;
1261                    let result = value.atanh();
1262                    assert_eq!(result, value.atanh());
1263                }
1264
1265                #[test]
1266                fn test_cos_02() {
1267                    let value: f64 = 0.5;
1268                    let result = value.cos();
1269                    assert_eq!(result, value.cos());
1270                }
1271
1272                #[test]
1273                fn test_cosh() {
1274                    let value: f64 = 0.5;
1275                    let result = value.cosh();
1276                    assert_eq!(result, value.cosh());
1277                }
1278
1279                #[test]
1280                fn test_exp() {
1281                    let value: f64 = 0.5;
1282                    let result = value.exp();
1283                    println!("result = {result:?}");
1284
1285                    assert_eq!(result, value.exp());
1286                }
1287
1288                #[test]
1289                fn test_is_finite() {
1290                    let value: f64 = 0.5;
1291                    assert!(value.is_finite());
1292
1293                    let value: f64 = f64::INFINITY;
1294                    assert!(!value.is_finite());
1295                }
1296
1297                #[test]
1298                fn test_is_infinite() {
1299                    let value: f64 = f64::INFINITY;
1300                    assert!(value.is_infinite());
1301
1302                    let value: f64 = 0.5;
1303                    assert!(!value.is_infinite());
1304                }
1305
1306                #[test]
1307                fn test_ln() {
1308                    let value: f64 = std::f64::consts::E;
1309                    let result = value.ln();
1310                    println!("result = {result:?}");
1311                    assert_eq!(result, value.ln());
1312                }
1313
1314                #[test]
1315                fn test_log10() {
1316                    let value: f64 = 10.0;
1317                    let result = value.log10();
1318                    println!("result = {result:?}");
1319                    assert_eq!(result, value.log10());
1320                }
1321
1322                #[test]
1323                fn test_log2() {
1324                    let value: f64 = 8.0;
1325                    let result = value.log2();
1326                    println!("result = {result:?}");
1327                    assert_eq!(result, value.log2());
1328                }
1329
1330                #[test]
1331                fn test_recip_02() {
1332                    let value: f64 = 2.0;
1333                    let result = value.try_reciprocal().unwrap();
1334                    assert_eq!(result, value.recip());
1335                }
1336
1337                #[test]
1338                fn test_sin_02() {
1339                    let value: f64 = 0.5;
1340                    let result = value.sin();
1341                    assert_eq!(result, value.sin());
1342                }
1343
1344                #[test]
1345                fn test_sinh() {
1346                    let value: f64 = 0.5;
1347                    let result = value.sinh();
1348                    assert_eq!(result, value.sinh());
1349                }
1350
1351                #[test]
1352                fn sqrt() {
1353                    let value: f64 = 4.0;
1354                    let result = value.sqrt();
1355                    assert_eq!(result, value.sqrt());
1356                }
1357
1358                #[test]
1359                fn try_sqrt() {
1360                    let value: f64 = 4.0;
1361                    let result = value.try_sqrt().unwrap();
1362                    assert_eq!(result, value.sqrt());
1363
1364                    assert!((-1.0).try_sqrt().is_err());
1365                }
1366
1367                #[test]
1368                fn test_tan() {
1369                    let value: f64 = 0.5;
1370                    let result = value.tan();
1371                    assert_eq!(result, value.tan());
1372                }
1373
1374                #[test]
1375                fn test_tanh() {
1376                    let value: f64 = 0.5;
1377                    let result = value.tanh();
1378                    assert_eq!(result, value.tanh());
1379                }
1380            }
1381
1382            mod complex {
1383                use super::*;
1384
1385                #[test]
1386                fn add() {
1387                    let a = Complex::new(1., 2.);
1388                    let b = Complex::new(3., 4.);
1389
1390                    let c_expected = Complex::new(4., 6.);
1391
1392                    test_add(a, b, c_expected);
1393                }
1394
1395                #[test]
1396                fn sub() {
1397                    let a = Complex::new(3., 2.);
1398                    let b = Complex::new(1., 4.);
1399
1400                    let c_expected = Complex::new(2., -2.);
1401
1402                    test_sub(a, b, c_expected);
1403                }
1404
1405                #[test]
1406                fn mul() {
1407                    let a = Complex::new(3., 2.);
1408                    let b = Complex::new(1., 4.);
1409                    let c_expected = Complex::new(-5., 14.);
1410                    test_mul(a, b, c_expected);
1411                }
1412
1413                #[test]
1414                fn div() {
1415                    let a = Complex::new(-5., 14.);
1416                    let b = Complex::new(1., 4.);
1417
1418                    let c_expected = Complex::new(3., 2.);
1419
1420                    test_div(a, b, c_expected);
1421                }
1422
1423                #[test]
1424                fn add_assign() {
1425                    let mut a = Complex::new(1., 2.);
1426                    let b = Complex::new(3., 4.);
1427
1428                    a += &b;
1429                    let a_expected = Complex::new(4., 6.);
1430                    assert_eq!(a, a_expected);
1431
1432                    a += b;
1433                    let a_expected = Complex::new(7., 10.);
1434                    assert_eq!(a, a_expected);
1435                }
1436
1437                #[test]
1438                fn sub_assign() {
1439                    let mut a = Complex::new(3., 2.);
1440                    let b = Complex::new(2., 4.);
1441
1442                    a -= &b;
1443                    let a_expected = Complex::new(1., -2.);
1444                    assert_eq!(a, a_expected);
1445
1446                    a -= b;
1447                    let a_expected = Complex::new(-1., -6.);
1448                    assert_eq!(a, a_expected);
1449                }
1450
1451                #[test]
1452                fn mul_assign() {
1453                    let mut a = Complex::new(3., 2.);
1454                    let b = Complex::new(2., 4.);
1455
1456                    a *= &b;
1457                    let a_expected = Complex::new(-2., 16.);
1458                    assert_eq!(a, a_expected);
1459
1460                    a *= b;
1461                    let a_expected = Complex::new(-68., 24.);
1462                    assert_eq!(a, a_expected);
1463                }
1464
1465                #[test]
1466                fn div_assign() {
1467                    let mut a = Complex::new(-68., 24.);
1468                    let b = Complex::new(2., 4.);
1469
1470                    a /= &b;
1471                    let a_expected = Complex::new(-2., 16.);
1472                    assert_eq!(a, a_expected);
1473
1474                    a /= b;
1475                    let a_expected = Complex::new(3., 2.);
1476                    assert_eq!(a, a_expected);
1477                }
1478
1479                #[test]
1480                fn from_f64() {
1481                    let v = Complex::new(16.25, 2.);
1482                    assert_eq!(v.real_part(), 16.25);
1483                    assert_eq!(v.imag_part(), 2.);
1484                }
1485
1486                #[test]
1487                fn conj() {
1488                    let v = Complex::new(16.25, 2.);
1489
1490                    let v_conj = v.conjugate();
1491                    assert_eq!(v_conj.real_part(), 16.25);
1492                    assert_eq!(v_conj.imag_part(), -2.);
1493                }
1494
1495                #[test]
1496                fn neg_assign() {
1497                    let mut a = Complex::new(1., 2.);
1498                    a.neg_assign();
1499
1500                    let a_expected = Complex::new(-1., -2.);
1501                    assert_eq!(a, a_expected);
1502                }
1503
1504                #[test]
1505                fn abs() {
1506                    let a = Complex::new(-3., 4.);
1507
1508                    let abs = a.abs();
1509                    let expected = 5.;
1510                    assert_eq!(abs, expected);
1511                }
1512
1513                #[test]
1514                fn mul_add_ref() {
1515                    let a = Complex::new(2., -3.);
1516                    let b = Complex::new(3., 1.);
1517                    let c = Complex::new(1., -4.);
1518
1519                    let d_expected = Complex::new(10., -11.);
1520
1521                    let d = a.mul_add_ref(&b, &c);
1522                    assert_eq!(d, d_expected);
1523                }
1524
1525                #[test]
1526                fn mul_complex_with_real() {
1527                    let a = Complex::new(1., 2.);
1528                    let b = 3.;
1529
1530                    let a_times_b_expected = Complex::new(3., 6.);
1531
1532                    test_mul_complex_with_real(a, b, a_times_b_expected);
1533                }
1534
1535                #[test]
1536                fn mul_assign_complex_with_real() {
1537                    let a = Complex::new(1., 2.);
1538                    let b = 3.;
1539
1540                    let a_times_b_expected = Complex::new(3., 6.);
1541
1542                    test_mul_assign_complex_with_real(a, b, a_times_b_expected);
1543                }
1544
1545                #[test]
1546                fn test_acos() {
1547                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1548                    let result = value.acos();
1549                    assert_eq!(result, value.acos());
1550                }
1551
1552                #[test]
1553                fn test_acosh() {
1554                    let value: Complex<f64> = Complex::new(1.5, 0.5);
1555                    let result = value.acosh();
1556                    assert_eq!(result, value.acosh());
1557                }
1558
1559                #[test]
1560                fn test_asin() {
1561                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1562                    let result = value.asin();
1563                    assert_eq!(result, value.asin());
1564                }
1565
1566                #[test]
1567                fn test_asinh() {
1568                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1569                    let result = value.asinh();
1570                    assert_eq!(result, value.asinh());
1571                }
1572
1573                #[test]
1574                fn test_atan() {
1575                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1576                    let result = value.atan();
1577                    assert_eq!(result, value.atan());
1578                }
1579
1580                #[test]
1581                fn test_atanh() {
1582                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1583                    let result = value.atanh();
1584                    assert_eq!(result, value.atanh());
1585                }
1586
1587                #[test]
1588                fn test_cos_01() {
1589                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1590                    let result = value.cos();
1591                    assert_eq!(result, value.cos());
1592                }
1593
1594                #[test]
1595                fn test_cosh() {
1596                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1597                    let result = value.cosh();
1598                    assert_eq!(result, value.cosh());
1599                }
1600
1601                #[test]
1602                fn test_exp() {
1603                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1604                    let result = value.exp();
1605                    println!("result = {result:?}");
1606                    assert_eq!(result, value.exp());
1607                }
1608
1609                /*
1610                #[test]
1611                fn test_is_finite() {
1612                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1613                    assert!(value.is_finite());
1614
1615                    let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
1616                    assert!(!value.is_finite());
1617                }
1618
1619                #[test]
1620                fn test_is_infinite() {
1621                    let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
1622                    assert!(value.is_infinite());
1623
1624                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1625                    assert!(!value.is_infinite());
1626                }
1627                */
1628
1629                #[test]
1630                fn test_ln() {
1631                    let value: Complex<f64> = Complex::new(std::f64::consts::E, 1.0);
1632                    let result = value.ln();
1633                    println!("result = {result:?}");
1634                    assert_eq!(result, value.ln());
1635                }
1636
1637                #[test]
1638                fn test_log10() {
1639                    let value: Complex<f64> = Complex::new(10.0, 1.0);
1640                    let result = value.log10();
1641                    println!("result = {result:?}");
1642                    assert_eq!(result, value.log10());
1643                }
1644
1645                #[test]
1646                fn test_log2() {
1647                    let value: Complex<f64> = Complex::new(8.0, 1.0);
1648                    let result = value.log2();
1649                    println!("result = {result:?}");
1650                    assert_eq!(result, value.log2());
1651                }
1652
1653                #[test]
1654                fn test_recip() {
1655                    let value: Complex<f64> = Complex::new(2.0, 0.0);
1656                    let result = value.try_reciprocal().unwrap();
1657                    assert_eq!(result, value.finv());
1658                }
1659
1660                #[test]
1661                fn test_sin_01() {
1662                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1663                    let result = value.sin();
1664                    assert_eq!(result, value.sin());
1665                }
1666
1667                #[test]
1668                fn test_sinh() {
1669                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1670                    let result = value.sinh();
1671                    assert_eq!(result, value.sinh());
1672                }
1673
1674                #[test]
1675                fn sqrt() {
1676                    let value: Complex<f64> = Complex::new(4.0, 1.0);
1677                    let result = value.sqrt();
1678                    assert_eq!(result, value.sqrt());
1679                }
1680
1681                #[test]
1682                fn try_sqrt() {
1683                    let value: Complex<f64> = Complex::new(4.0, 1.0);
1684                    let result = value.try_sqrt().unwrap();
1685                    assert_eq!(result, value.sqrt());
1686                }
1687
1688                #[test]
1689                fn test_tan() {
1690                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1691                    let result = value.tan();
1692                    assert_eq!(result, value.tan());
1693                }
1694
1695                #[test]
1696                fn test_tanh() {
1697                    let value: Complex<f64> = Complex::new(0.5, 0.5);
1698                    let result = value.tanh();
1699                    assert_eq!(result, value.tanh());
1700                }
1701            }
1702        }
1703
1704        #[cfg(feature = "rug")]
1705        mod rug_ {
1706            use super::*;
1707            use crate::kernels::rug::{ComplexRugStrictFinite, RealRugStrictFinite};
1708            use rug::ops::CompleteRound;
1709            use try_create::{IntoInner, TryNew};
1710
1711            const PRECISION: u32 = 100;
1712
1713            mod real {
1714                use super::*;
1715                use rug::Float;
1716
1717                #[test]
1718                fn zero() {
1719                    test_zero::<RealRugStrictFinite<64>>();
1720                    test_zero::<RealRugStrictFinite<PRECISION>>();
1721                }
1722
1723                #[test]
1724                fn one() {
1725                    test_one::<RealRugStrictFinite<64>>();
1726                    test_one::<RealRugStrictFinite<PRECISION>>();
1727                }
1728
1729                #[test]
1730                fn recip() {
1731                    test_recip::<RealRugStrictFinite<64>>();
1732                    test_recip::<RealRugStrictFinite<PRECISION>>();
1733                }
1734
1735                #[test]
1736                fn add() {
1737                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
1738                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1739                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
1740                    test_add(a, b, c_expected);
1741                }
1742
1743                #[test]
1744                fn sub() {
1745                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
1746                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1747                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.0).unwrap();
1748                    test_sub(a, b, c_expected);
1749                }
1750
1751                #[test]
1752                fn mul() {
1753                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
1754                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
1755                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(6.0).unwrap();
1756                    test_mul(a, b, c_expected);
1757                }
1758
1759                #[test]
1760                fn div() {
1761                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(6.).unwrap();
1762                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.).unwrap();
1763                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(3.).unwrap();
1764
1765                    test_div(a, b, c_expected);
1766                }
1767
1768                #[test]
1769                fn neg_assign() {
1770                    test_neg_assign_real::<RealRugStrictFinite<PRECISION>>();
1771                }
1772
1773                #[test]
1774                fn add_assign() {
1775                    test_add_assign_real::<RealRugStrictFinite<PRECISION>>();
1776                }
1777
1778                #[test]
1779                fn sub_assign() {
1780                    test_sub_assign_real::<RealRugStrictFinite<PRECISION>>();
1781                }
1782
1783                #[test]
1784                fn mul_assign() {
1785                    test_mul_assign_real::<RealRugStrictFinite<PRECISION>>();
1786                }
1787
1788                #[test]
1789                fn div_assign() {
1790                    test_div_assign_real::<RealRugStrictFinite<PRECISION>>();
1791                }
1792
1793                #[test]
1794                fn mul_add_ref() {
1795                    test_mul_add_ref_real::<RealRugStrictFinite<PRECISION>>();
1796                }
1797
1798                #[test]
1799                fn abs() {
1800                    test_abs_real::<RealRugStrictFinite<PRECISION>>();
1801                }
1802
1803                #[test]
1804                fn acos() {
1805                    {
1806                        let a = RealRugStrictFinite::<53>::zero();
1807                        let pi_over_2 = RealRugStrictFinite::<53>::acos(a);
1808                        let expected = rug::Float::with_val(53, std::f64::consts::FRAC_PI_2);
1809                        assert_eq!(pi_over_2.as_ref(), &expected);
1810                    }
1811                    {
1812                        let a = RealRugStrictFinite::<100>::zero();
1813                        let pi_over_2 = RealRugStrictFinite::<100>::acos(a);
1814                        let expected = rug::Float::with_val(
1815                            100,
1816                            rug::Float::parse("1.5707963267948966192313216916397").unwrap(),
1817                        );
1818                        assert_eq!(pi_over_2.as_ref(), &expected);
1819                    }
1820                }
1821
1822                #[test]
1823                fn asin() {
1824                    {
1825                        let a = RealRugStrictFinite::<53>::one();
1826                        let pi_over_2 = RealRugStrictFinite::<53>::asin(a);
1827                        let expected = rug::Float::with_val(53, std::f64::consts::FRAC_PI_2);
1828                        assert_eq!(pi_over_2.as_ref(), &expected);
1829                    }
1830                    {
1831                        let a = RealRugStrictFinite::<100>::one();
1832                        let pi_over_2 = RealRugStrictFinite::<100>::asin(a);
1833                        let expected = rug::Float::with_val(
1834                            100,
1835                            rug::Float::parse("1.5707963267948966192313216916397").unwrap(),
1836                        );
1837                        assert_eq!(pi_over_2.as_ref(), &expected);
1838                    }
1839                }
1840
1841                #[test]
1842                fn cos() {
1843                    test_cos_real::<RealRugStrictFinite<64>>();
1844                    test_cos_real::<RealRugStrictFinite<PRECISION>>();
1845                }
1846
1847                #[test]
1848                fn sin() {
1849                    test_sin_real::<RealRugStrictFinite<64>>();
1850                    test_sin_real::<RealRugStrictFinite<PRECISION>>();
1851                }
1852
1853                #[test]
1854                fn dot_product() {
1855                    let a = &[
1856                        RealRugStrictFinite::<100>::one(),
1857                        RealRugStrictFinite::<100>::try_from_f64(2.).unwrap(),
1858                    ];
1859
1860                    let b = &[
1861                        RealRugStrictFinite::<100>::try_from_f64(2.).unwrap(),
1862                        RealRugStrictFinite::<100>::try_from_f64(-1.).unwrap(),
1863                    ];
1864
1865                    let a: Vec<_> = a.iter().map(|a_i| a_i.as_ref()).collect();
1866                    let b: Vec<_> = b.iter().map(|b_i| b_i.as_ref()).collect();
1867
1868                    let value = RealRugStrictFinite::<100>::try_new(
1869                        rug::Float::dot(a.into_iter().zip(b)).complete(100),
1870                    )
1871                    .unwrap();
1872
1873                    assert_eq!(value.as_ref(), &rug::Float::with_val(100, 0.));
1874                }
1875                #[test]
1876                fn test_acos() {
1877                    let value =
1878                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1879                            .unwrap();
1880                    let result = value.clone().acos();
1881                    assert_eq!(
1882                        result,
1883                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1884                            PRECISION,
1885                            value.into_inner().acos()
1886                        ))
1887                        .unwrap()
1888                    );
1889                }
1890
1891                #[test]
1892                fn test_acosh() {
1893                    let value =
1894                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.5))
1895                            .unwrap();
1896                    let result = value.clone().acosh();
1897                    assert_eq!(
1898                        result,
1899                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1900                            PRECISION,
1901                            value.into_inner().acosh()
1902                        ))
1903                        .unwrap()
1904                    );
1905                }
1906
1907                #[test]
1908                fn test_asin() {
1909                    let value =
1910                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1911                            .unwrap();
1912                    let result = value.clone().asin();
1913                    assert_eq!(
1914                        result,
1915                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1916                            PRECISION,
1917                            value.into_inner().asin()
1918                        ))
1919                        .unwrap()
1920                    );
1921                }
1922
1923                #[test]
1924                fn test_asinh() {
1925                    let value =
1926                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1927                            .unwrap();
1928                    let result = value.clone().asinh();
1929                    assert_eq!(
1930                        result,
1931                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1932                            PRECISION,
1933                            value.into_inner().asinh()
1934                        ))
1935                        .unwrap()
1936                    );
1937                }
1938
1939                #[test]
1940                fn test_atan() {
1941                    let value =
1942                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1943                            .unwrap();
1944                    let result = value.clone().atan();
1945                    assert_eq!(
1946                        result,
1947                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1948                            PRECISION,
1949                            value.into_inner().atan()
1950                        ))
1951                        .unwrap()
1952                    );
1953                }
1954
1955                #[test]
1956                fn test_atanh() {
1957                    let value =
1958                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1959                            .unwrap();
1960                    let result = value.clone().atanh();
1961                    assert_eq!(
1962                        result,
1963                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1964                            PRECISION,
1965                            value.into_inner().atanh()
1966                        ))
1967                        .unwrap()
1968                    );
1969                }
1970
1971                #[test]
1972                fn test_cos_02() {
1973                    let value =
1974                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1975                            .unwrap();
1976                    let result = value.clone().cos();
1977                    assert_eq!(
1978                        result,
1979                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1980                            PRECISION,
1981                            value.into_inner().cos()
1982                        ))
1983                        .unwrap()
1984                    );
1985                }
1986
1987                #[test]
1988                fn test_cosh() {
1989                    let value =
1990                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
1991                            .unwrap();
1992                    let result = value.clone().cosh();
1993                    assert_eq!(
1994                        result,
1995                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
1996                            PRECISION,
1997                            value.into_inner().cosh()
1998                        ))
1999                        .unwrap()
2000                    );
2001                }
2002
2003                #[test]
2004                fn test_exp() {
2005                    let value =
2006                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2007                            .unwrap();
2008                    let result = value.clone().exp();
2009                    println!("result = {result:?}");
2010                    assert_eq!(
2011                        result,
2012                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2013                            PRECISION,
2014                            value.into_inner().exp()
2015                        ))
2016                        .unwrap()
2017                    );
2018                }
2019
2020                #[test]
2021                fn test_is_finite() {
2022                    let value =
2023                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2024                            .unwrap();
2025                    assert!(value.is_finite());
2026
2027                    let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2028                        PRECISION,
2029                        f64::INFINITY,
2030                    ));
2031                    assert!(value.is_err());
2032                }
2033
2034                #[test]
2035                fn test_is_infinite() {
2036                    let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2037                        PRECISION,
2038                        f64::INFINITY,
2039                    ));
2040                    assert!(value.is_err());
2041
2042                    let value =
2043                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2044                            .unwrap();
2045                    assert!(!value.is_infinite());
2046                }
2047
2048                #[test]
2049                fn test_ln() {
2050                    let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2051                        PRECISION,
2052                        std::f64::consts::E,
2053                    ))
2054                    .unwrap();
2055                    let result = value.clone().ln();
2056                    println!("result = {result:?}");
2057                    assert_eq!(
2058                        result,
2059                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2060                            PRECISION,
2061                            value.into_inner().ln()
2062                        ))
2063                        .unwrap()
2064                    );
2065                }
2066
2067                #[test]
2068                fn test_log10() {
2069                    let value =
2070                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 10.0))
2071                            .unwrap();
2072                    let result = value.clone().log10();
2073                    println!("result = {result:?}");
2074                    assert_eq!(
2075                        result,
2076                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2077                            PRECISION,
2078                            value.into_inner().log10()
2079                        ))
2080                        .unwrap()
2081                    );
2082                }
2083
2084                #[test]
2085                fn test_log2() {
2086                    let value =
2087                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 8.0))
2088                            .unwrap();
2089                    let result = value.clone().log2();
2090                    println!("result = {result:?}");
2091                    assert_eq!(
2092                        result,
2093                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2094                            PRECISION,
2095                            value.into_inner().log2()
2096                        ))
2097                        .unwrap()
2098                    );
2099                }
2100
2101                #[test]
2102                fn test_recip_02() {
2103                    let value =
2104                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
2105                            .unwrap();
2106                    let result = value.clone().try_reciprocal().unwrap();
2107                    assert_eq!(
2108                        result,
2109                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2110                            PRECISION,
2111                            value.into_inner().recip()
2112                        ))
2113                        .unwrap()
2114                    );
2115                }
2116
2117                #[test]
2118                fn test_sin_02() {
2119                    let value =
2120                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2121                            .unwrap();
2122                    let result = value.clone().sin();
2123                    assert_eq!(
2124                        result,
2125                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2126                            PRECISION,
2127                            value.into_inner().sin()
2128                        ))
2129                        .unwrap()
2130                    );
2131                }
2132
2133                #[test]
2134                fn test_sinh() {
2135                    let value =
2136                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2137                            .unwrap();
2138                    let result = value.clone().sinh();
2139                    assert_eq!(
2140                        result,
2141                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2142                            PRECISION,
2143                            value.into_inner().sinh()
2144                        ))
2145                        .unwrap()
2146                    );
2147                }
2148
2149                #[test]
2150                fn sqrt() {
2151                    let value =
2152                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
2153                            .unwrap();
2154                    let result = value.clone().sqrt();
2155                    assert_eq!(
2156                        result,
2157                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2158                            PRECISION,
2159                            value.into_inner().sqrt()
2160                        ))
2161                        .unwrap()
2162                    );
2163                }
2164
2165                #[test]
2166                fn try_sqrt() {
2167                    let value =
2168                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
2169                            .unwrap();
2170                    let result = value.clone().try_sqrt().unwrap();
2171                    assert_eq!(
2172                        result,
2173                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2174                            PRECISION,
2175                            value.into_inner().sqrt()
2176                        ))
2177                        .unwrap()
2178                    );
2179
2180                    assert!(
2181                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -4.0))
2182                            .unwrap()
2183                            .try_sqrt()
2184                            .is_err()
2185                    )
2186                }
2187
2188                #[test]
2189                fn test_tan() {
2190                    let value =
2191                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2192                            .unwrap();
2193                    let result = value.clone().tan();
2194                    assert_eq!(
2195                        result,
2196                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2197                            PRECISION,
2198                            value.into_inner().tan()
2199                        ))
2200                        .unwrap()
2201                    );
2202                }
2203
2204                #[test]
2205                fn test_tanh() {
2206                    let value =
2207                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
2208                            .unwrap();
2209                    let result = value.clone().tanh();
2210                    assert_eq!(
2211                        result,
2212                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
2213                            PRECISION,
2214                            value.into_inner().tanh()
2215                        ))
2216                        .unwrap()
2217                    );
2218                }
2219
2220                #[test]
2221                fn test_mul_add() {
2222                    let a =
2223                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
2224                            .unwrap();
2225                    let b =
2226                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
2227                            .unwrap();
2228                    let c =
2229                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
2230                            .unwrap();
2231                    let result = a.clone().mul_add_ref(&b, &c);
2232                    assert_eq!(
2233                        result,
2234                        RealRugStrictFinite::<PRECISION>::try_new(
2235                            a.into_inner() * b.as_ref() + c.as_ref()
2236                        )
2237                        .unwrap()
2238                    );
2239                }
2240            }
2241
2242            mod complex {
2243                use super::*;
2244                //use rug::Complex;
2245                use rug::Float;
2246
2247                #[test]
2248                fn add() {
2249                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
2250                        .unwrap();
2251                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 4.))
2252                        .unwrap();
2253                    let c_expected =
2254                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(4., 6.))
2255                            .unwrap();
2256                    test_add(a, b, c_expected);
2257                }
2258
2259                #[test]
2260                fn sub() {
2261                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
2262                        .unwrap();
2263                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
2264                        .unwrap();
2265                    let c_expected =
2266                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., -2.))
2267                            .unwrap();
2268                    test_sub(a, b, c_expected);
2269                }
2270
2271                #[test]
2272                fn mul() {
2273                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
2274                        .unwrap();
2275                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
2276                        .unwrap();
2277                    let c_expected =
2278                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-5., 14.))
2279                            .unwrap();
2280                    test_mul(a, b, c_expected);
2281                }
2282
2283                #[test]
2284                fn div() {
2285                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-5., 14.))
2286                        .unwrap();
2287                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
2288                        .unwrap();
2289                    let c_expected =
2290                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
2291                            .unwrap();
2292                    test_div(a, b, c_expected);
2293                }
2294
2295                #[test]
2296                fn add_assign() {
2297                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
2298                        .unwrap();
2299                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 4.))
2300                        .unwrap();
2301
2302                    a += &b;
2303                    let a_expected =
2304                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(4., 6.))
2305                            .unwrap();
2306                    assert_eq!(a, a_expected);
2307
2308                    a += b;
2309                    let a_expected =
2310                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(7., 10.))
2311                            .unwrap();
2312                    assert_eq!(a, a_expected);
2313                }
2314
2315                #[test]
2316                fn sub_assign() {
2317                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
2318                        .unwrap();
2319                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
2320                        .unwrap();
2321
2322                    a -= &b;
2323                    let a_expected =
2324                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., -2.))
2325                            .unwrap();
2326                    assert_eq!(a, a_expected);
2327
2328                    a -= b;
2329                    let a_expected =
2330                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., -6.))
2331                            .unwrap();
2332                    assert_eq!(a, a_expected);
2333                }
2334
2335                #[test]
2336                fn mul_assign() {
2337                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
2338                        .unwrap();
2339                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
2340                        .unwrap();
2341
2342                    a *= &b;
2343                    let a_expected =
2344                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., 16.))
2345                            .unwrap();
2346                    assert_eq!(a, a_expected);
2347
2348                    a *= b;
2349                    let a_expected =
2350                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-68., 24.))
2351                            .unwrap();
2352                    assert_eq!(a, a_expected);
2353                }
2354
2355                #[test]
2356                fn div_assign() {
2357                    let mut a =
2358                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-68., 24.))
2359                            .unwrap();
2360                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
2361                        .unwrap();
2362
2363                    a /= &b;
2364                    let a_expected =
2365                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., 16.))
2366                            .unwrap();
2367                    assert_eq!(a, a_expected);
2368
2369                    a /= b;
2370                    let a_expected =
2371                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
2372                            .unwrap();
2373                    assert_eq!(a, a_expected);
2374                }
2375
2376                #[test]
2377                fn from_f64() {
2378                    let v_100bits =
2379                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(16.25, 2.))
2380                            .unwrap();
2381                    assert_eq!(
2382                        ComplexRugStrictFinite::<PRECISION>::real_part(&v_100bits),
2383                        16.25
2384                    );
2385                    assert_eq!(
2386                        ComplexRugStrictFinite::<PRECISION>::imag_part(&v_100bits),
2387                        2.
2388                    );
2389
2390                    let v_53bits =
2391                        ComplexRugStrictFinite::<53>::try_from(Complex::new(16.25, 2.)).unwrap();
2392                    assert_eq!(ComplexRugStrictFinite::<53>::real_part(&v_53bits), 16.25);
2393                    assert_eq!(ComplexRugStrictFinite::<53>::imag_part(&v_53bits), 2.);
2394
2395                    // 16.25 has seven significant bits (binary 10000.01)
2396                    let v_7bits =
2397                        ComplexRugStrictFinite::<7>::try_from(Complex::new(16.25, 2.)).unwrap();
2398                    assert_eq!(ComplexRugStrictFinite::<7>::real_part(&v_7bits), 16.25);
2399                    assert_eq!(ComplexRugStrictFinite::<7>::imag_part(&v_7bits), 2.);
2400                }
2401
2402                #[test]
2403                #[should_panic]
2404                fn from_f64_failing() {
2405                    // this should fail because 16.25 has seven significant bits (binary 10000.01) and we ask a float with 6 significant bits
2406                    let _v_6bits =
2407                        ComplexRugStrictFinite::<6>::try_from(Complex::new(16.25, 2.)).unwrap();
2408                }
2409
2410                #[test]
2411                fn conj() {
2412                    let v = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(16.25, 2.))
2413                        .unwrap();
2414
2415                    let v_conj = ComplexRugStrictFinite::<PRECISION>::conjugate(v);
2416                    assert_eq!(
2417                        ComplexRugStrictFinite::<PRECISION>::real_part(&v_conj),
2418                        16.25
2419                    );
2420                    assert_eq!(ComplexRugStrictFinite::<PRECISION>::imag_part(&v_conj), -2.);
2421                }
2422
2423                #[test]
2424                fn neg_assign() {
2425                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
2426                        .unwrap();
2427                    a.neg_assign();
2428
2429                    let a_expected =
2430                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., -2.))
2431                            .unwrap();
2432                    assert_eq!(a, a_expected);
2433                }
2434
2435                #[test]
2436                fn abs() {
2437                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-3., 4.))
2438                        .unwrap();
2439
2440                    let abs = a.abs();
2441                    let abs_expected = RealRugStrictFinite::<100>::try_from_f64(5.).unwrap();
2442                    assert_eq!(abs, abs_expected);
2443                }
2444
2445                #[test]
2446                fn mul_add_ref() {
2447                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., -3.))
2448                        .unwrap();
2449                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 1.))
2450                        .unwrap();
2451                    let c = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., -4.))
2452                        .unwrap();
2453
2454                    let d_expected =
2455                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(10., -11.))
2456                            .unwrap();
2457
2458                    let d = a.mul_add_ref(&b, &c);
2459                    assert_eq!(d, d_expected);
2460                }
2461
2462                #[test]
2463                fn mul_complex_with_real() {
2464                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
2465                        .unwrap();
2466                    let b = RealRugStrictFinite::<100>::try_from_f64(3.).unwrap();
2467
2468                    let a_times_b_expected =
2469                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 6.))
2470                            .unwrap();
2471
2472                    test_mul_complex_with_real(a, b, a_times_b_expected);
2473                }
2474
2475                #[test]
2476                fn mul_assign_complex_with_real() {
2477                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
2478                        .unwrap();
2479                    let b = RealRugStrictFinite::<100>::try_from_f64(3.).unwrap();
2480
2481                    let a_times_b_expected =
2482                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 6.))
2483                            .unwrap();
2484
2485                    test_mul_assign_complex_with_real(a, b, a_times_b_expected);
2486                }
2487
2488                #[test]
2489                fn dot_product() {
2490                    let a = &[
2491                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 3.))
2492                            .unwrap(),
2493                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
2494                            .unwrap(),
2495                    ];
2496
2497                    let b = &[
2498                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., -5.))
2499                            .unwrap(),
2500                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., 6.))
2501                            .unwrap(),
2502                    ];
2503
2504                    let a: Vec<_> = a.iter().map(|a_i| a_i.as_ref()).collect();
2505                    let b: Vec<_> = b.iter().map(|b_i| b_i.as_ref()).collect();
2506
2507                    // computes a * a^T
2508                    let a_times_a = ComplexRugStrictFinite::<PRECISION>::try_new(
2509                        rug::Complex::dot(a.clone().into_iter().zip(a.clone()))
2510                            .complete((100, 100)),
2511                    )
2512                    .unwrap();
2513                    assert_eq!(
2514                        a_times_a.as_ref(),
2515                        &rug::Complex::with_val(100, (-20., 22.))
2516                    );
2517
2518                    // computes a * b^T
2519                    let a_times_b = ComplexRugStrictFinite::<PRECISION>::try_new(
2520                        rug::Complex::dot(a.clone().into_iter().zip(b.clone()))
2521                            .complete((100, 100)),
2522                    )
2523                    .unwrap();
2524                    assert_eq!(
2525                        a_times_b.as_ref(),
2526                        &rug::Complex::with_val(100, (-13., -3.))
2527                    );
2528
2529                    // computes b * a^T
2530                    let b_times_a = ComplexRugStrictFinite::<PRECISION>::try_new(
2531                        rug::Complex::dot(b.into_iter().zip(a)).complete((100, 100)),
2532                    )
2533                    .unwrap();
2534                    assert_eq!(
2535                        b_times_a.as_ref(),
2536                        &rug::Complex::with_val(100, (-13., -3.))
2537                    );
2538                }
2539
2540                #[test]
2541                fn test_acos() {
2542                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2543                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2544                    )
2545                    .unwrap();
2546                    let result = value.clone().acos();
2547                    assert_eq!(
2548                        result,
2549                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2550                            PRECISION,
2551                            value.into_inner().acos()
2552                        ))
2553                        .unwrap()
2554                    );
2555                }
2556
2557                #[test]
2558                fn test_acosh() {
2559                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2560                        rug::Complex::with_val(PRECISION, (1.5, 0.5)),
2561                    )
2562                    .unwrap();
2563                    let result = value.clone().acosh();
2564                    assert_eq!(
2565                        result,
2566                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2567                            PRECISION,
2568                            value.into_inner().acosh()
2569                        ))
2570                        .unwrap()
2571                    );
2572                }
2573
2574                #[test]
2575                fn test_asin() {
2576                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2577                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2578                    )
2579                    .unwrap();
2580                    let result = value.clone().asin();
2581                    assert_eq!(
2582                        result,
2583                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2584                            PRECISION,
2585                            value.into_inner().asin()
2586                        ))
2587                        .unwrap()
2588                    );
2589                }
2590
2591                #[test]
2592                fn test_asinh() {
2593                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2594                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2595                    )
2596                    .unwrap();
2597                    let result = value.clone().asinh();
2598                    assert_eq!(
2599                        result,
2600                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2601                            PRECISION,
2602                            value.into_inner().asinh()
2603                        ))
2604                        .unwrap()
2605                    );
2606                }
2607
2608                #[test]
2609                fn test_atan() {
2610                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2611                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2612                    )
2613                    .unwrap();
2614                    let result = value.clone().atan();
2615                    assert_eq!(
2616                        result,
2617                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2618                            PRECISION,
2619                            value.into_inner().atan()
2620                        ))
2621                        .unwrap()
2622                    );
2623                }
2624
2625                #[test]
2626                fn test_atanh() {
2627                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2628                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2629                    )
2630                    .unwrap();
2631                    let result = value.clone().atanh();
2632                    assert_eq!(
2633                        result,
2634                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2635                            PRECISION,
2636                            value.into_inner().atanh()
2637                        ))
2638                        .unwrap()
2639                    );
2640                }
2641
2642                #[test]
2643                fn test_cos_01() {
2644                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2645                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2646                    )
2647                    .unwrap();
2648                    let result = value.clone().cos();
2649                    assert_eq!(
2650                        result,
2651                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2652                            PRECISION,
2653                            value.into_inner().cos()
2654                        ))
2655                        .unwrap()
2656                    );
2657                }
2658
2659                #[test]
2660                fn test_cosh() {
2661                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2662                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2663                    )
2664                    .unwrap();
2665                    let result = value.clone().cosh();
2666                    assert_eq!(
2667                        result,
2668                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2669                            PRECISION,
2670                            value.into_inner().cosh()
2671                        ))
2672                        .unwrap()
2673                    );
2674                }
2675
2676                #[test]
2677                fn test_exp() {
2678                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2679                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2680                    )
2681                    .unwrap();
2682                    let result = value.clone().exp();
2683                    println!("result = {result:?}");
2684                    assert_eq!(
2685                        result,
2686                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2687                            PRECISION,
2688                            value.into_inner().exp()
2689                        ))
2690                        .unwrap()
2691                    );
2692                }
2693
2694                #[test]
2695                fn test_is_finite() {
2696                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2697                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2698                    )
2699                    .unwrap();
2700                    assert!(value.is_finite());
2701
2702                    let value =
2703                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2704                            100,
2705                            (Float::with_val(PRECISION, f64::INFINITY), 0.5),
2706                        ));
2707                    assert!(value.is_err());
2708                }
2709
2710                #[test]
2711                fn test_is_infinite() {
2712                    let value =
2713                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2714                            100,
2715                            (Float::with_val(PRECISION, f64::INFINITY), 0.5),
2716                        ));
2717                    assert!(value.is_err());
2718
2719                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2720                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2721                    )
2722                    .unwrap();
2723                    assert!(!value.is_infinite());
2724                }
2725
2726                #[test]
2727                fn test_ln() {
2728                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2729                        rug::Complex::with_val(PRECISION, (std::f64::consts::E, 1.0)),
2730                    )
2731                    .unwrap();
2732                    let result = value.clone().ln();
2733                    println!("result = {result:?}");
2734                    assert_eq!(
2735                        result,
2736                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2737                            PRECISION,
2738                            value.into_inner().ln()
2739                        ))
2740                        .unwrap()
2741                    );
2742                }
2743
2744                #[test]
2745                fn test_log10() {
2746                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2747                        rug::Complex::with_val(PRECISION, (10.0, 1.0)),
2748                    )
2749                    .unwrap();
2750                    let result = value.clone().log10();
2751                    println!("result = {result:?}");
2752                    assert_eq!(
2753                        result,
2754                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2755                            PRECISION,
2756                            value.into_inner().log10()
2757                        ))
2758                        .unwrap()
2759                    );
2760                }
2761
2762                #[test]
2763                fn test_log2() {
2764                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2765                        rug::Complex::with_val(PRECISION, (8.0, 1.0)),
2766                    )
2767                    .unwrap();
2768                    let result = value.clone().log2();
2769                    println!("result = {result:?}");
2770                    assert_eq!(
2771                        result,
2772                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2773                            PRECISION,
2774                            value.into_inner().ln() / rug::Float::with_val(PRECISION, 2.).ln()
2775                        ))
2776                        .unwrap()
2777                    );
2778                }
2779
2780                #[test]
2781                fn test_recip() {
2782                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2783                        rug::Complex::with_val(PRECISION, (2.0, 0.0)),
2784                    )
2785                    .unwrap();
2786                    let result = value.clone().try_reciprocal().unwrap();
2787                    assert_eq!(
2788                        result,
2789                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2790                            PRECISION,
2791                            value.into_inner().recip()
2792                        ))
2793                        .unwrap()
2794                    );
2795                }
2796
2797                #[test]
2798                fn test_sin_01() {
2799                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2800                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2801                    )
2802                    .unwrap();
2803                    let result = value.clone().sin();
2804                    assert_eq!(
2805                        result,
2806                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2807                            PRECISION,
2808                            value.into_inner().sin()
2809                        ))
2810                        .unwrap()
2811                    );
2812                }
2813
2814                #[test]
2815                fn test_sinh() {
2816                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2817                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2818                    )
2819                    .unwrap();
2820                    let result = value.clone().sinh();
2821                    assert_eq!(
2822                        result,
2823                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2824                            PRECISION,
2825                            value.into_inner().sinh()
2826                        ))
2827                        .unwrap()
2828                    );
2829                }
2830
2831                #[test]
2832                fn sqrt() {
2833                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2834                        rug::Complex::with_val(PRECISION, (4.0, 1.0)),
2835                    )
2836                    .unwrap();
2837                    let result = value.clone().sqrt();
2838                    assert_eq!(
2839                        result,
2840                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2841                            PRECISION,
2842                            value.into_inner().sqrt()
2843                        ))
2844                        .unwrap()
2845                    );
2846                }
2847
2848                #[test]
2849                fn try_sqrt() {
2850                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2851                        rug::Complex::with_val(PRECISION, (4.0, 1.0)),
2852                    )
2853                    .unwrap();
2854                    let result = value.clone().try_sqrt().unwrap();
2855                    assert_eq!(
2856                        result,
2857                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2858                            PRECISION,
2859                            value.into_inner().sqrt()
2860                        ))
2861                        .unwrap()
2862                    );
2863                }
2864
2865                #[test]
2866                fn test_tan() {
2867                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2868                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2869                    )
2870                    .unwrap();
2871                    let result = value.clone().tan();
2872                    assert_eq!(
2873                        result,
2874                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2875                            PRECISION,
2876                            value.into_inner().tan()
2877                        ))
2878                        .unwrap()
2879                    );
2880                }
2881
2882                #[test]
2883                fn test_tanh() {
2884                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
2885                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
2886                    )
2887                    .unwrap();
2888                    let result = value.clone().tanh();
2889                    assert_eq!(
2890                        result,
2891                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2892                            PRECISION,
2893                            value.into_inner().tanh()
2894                        ))
2895                        .unwrap()
2896                    );
2897                }
2898
2899                #[test]
2900                fn test_mul_add() {
2901                    let a = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2902                        PRECISION,
2903                        (2.0, 1.0),
2904                    ))
2905                    .unwrap();
2906                    let b = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2907                        PRECISION,
2908                        (3.0, 1.0),
2909                    ))
2910                    .unwrap();
2911                    let c = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2912                        PRECISION,
2913                        (4.0, 1.0),
2914                    ))
2915                    .unwrap();
2916                    let result = a.clone().mul_add_ref(&b, &c);
2917                    assert_eq!(
2918                        result,
2919                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
2920                            PRECISION,
2921                            a.as_ref() * b.as_ref() + c.as_ref()
2922                        ))
2923                        .unwrap()
2924                    );
2925                }
2926            }
2927        }
2928    }
2929
2930    mod functions_real_type {
2931        use super::*;
2932
2933        mod native64 {
2934
2935            use super::*;
2936
2937            #[test]
2938            fn test_atan2() {
2939                let a: f64 = 27.0;
2940                let b: f64 = 13.0;
2941
2942                let result = a.atan2(b);
2943                assert_eq!(result, a.atan2(b));
2944            }
2945
2946            #[test]
2947            fn test_ceil() {
2948                let value: f64 = 3.7;
2949                let result = value.kernel_ceil();
2950                assert_eq!(result, value.ceil());
2951            }
2952
2953            #[test]
2954            fn test_clamp() {
2955                let value: f64 = 5.0;
2956                let min: f64 = 3.0;
2957                let max: f64 = 7.0;
2958                let result = value.kernel_clamp(&min, &max);
2959                assert_eq!(result, value.clamp(min, max));
2960            }
2961
2962            #[test]
2963            fn test_classify() {
2964                let value: f64 = 3.7;
2965                let result = value.kernel_classify();
2966                assert_eq!(result, value.classify());
2967            }
2968
2969            #[test]
2970            fn test_copysign() {
2971                let value: f64 = 3.5;
2972                let sign: f64 = -1.0;
2973                let result = value.kernel_copysign(&sign);
2974                assert_eq!(result, value.copysign(sign));
2975            }
2976
2977            #[test]
2978            fn test_epsilon() {
2979                let eps = f64::epsilon();
2980                assert_eq!(eps, f64::EPSILON);
2981            }
2982
2983            #[test]
2984            fn test_exp_m1() {
2985                let value: f64 = 0.5;
2986                let result = value.kernel_exp_m1();
2987                assert_eq!(result, value.exp_m1());
2988            }
2989
2990            #[test]
2991            fn test_floor() {
2992                let value: f64 = 3.7;
2993                let result = value.kernel_floor();
2994                assert_eq!(result, value.floor());
2995            }
2996
2997            #[test]
2998            fn test_fract() {
2999                let value: f64 = 3.7;
3000                let result = value.kernel_fract();
3001                assert_eq!(result, value.fract());
3002            }
3003
3004            #[test]
3005            fn test_hypot() {
3006                let a: f64 = 3.0;
3007                let b: f64 = 4.0;
3008                let result = a.kernel_hypot(&b);
3009                assert_eq!(result, a.hypot(b));
3010            }
3011
3012            #[test]
3013            fn test_is_sign_negative() {
3014                let value: f64 = -1.0;
3015                assert!(value.kernel_is_sign_negative());
3016
3017                let value: f64 = -0.0;
3018                assert!(value.kernel_is_sign_negative());
3019
3020                let value: f64 = 0.0;
3021                assert!(!value.kernel_is_sign_negative());
3022
3023                let value: f64 = 1.0;
3024                assert!(!value.kernel_is_sign_negative());
3025            }
3026
3027            #[test]
3028            fn test_is_sign_positive() {
3029                let value: f64 = -1.0;
3030                assert!(!value.kernel_is_sign_positive());
3031
3032                let value: f64 = -0.0;
3033                assert!(!value.kernel_is_sign_positive());
3034
3035                let value: f64 = 0.0;
3036                assert!(value.kernel_is_sign_positive());
3037
3038                let value: f64 = 1.0;
3039                assert!(value.kernel_is_sign_positive());
3040            }
3041
3042            #[test]
3043            fn test_ln_1p() {
3044                let value: f64 = 0.5;
3045                let result = value.kernel_ln_1p();
3046                assert_eq!(result, value.ln_1p());
3047            }
3048
3049            #[test]
3050            fn test_max() {
3051                let a: f64 = 3.0;
3052                let b: f64 = 4.0;
3053                let result = a.max(b);
3054                assert_eq!(result, a.max(b));
3055            }
3056
3057            #[test]
3058            fn test_min() {
3059                let a: f64 = 3.0;
3060                let b: f64 = 4.0;
3061                let result = a.min(b);
3062                assert_eq!(result, a.min(b));
3063            }
3064
3065            #[test]
3066            fn max_finite() {
3067                let max = f64::max_finite();
3068                assert_eq!(max, f64::MAX);
3069            }
3070
3071            #[test]
3072            fn min_finite() {
3073                let min = f64::min_finite();
3074                assert_eq!(min, f64::MIN);
3075            }
3076
3077            #[test]
3078            fn test_mul_add_mul_mut() {
3079                let mut a: f64 = 2.0;
3080                let b: f64 = 3.0;
3081                let c: f64 = 4.0;
3082                let d: f64 = -1.0;
3083                let mut result = a;
3084                result.kernel_mul_add_mul_mut(&b, &c, &d);
3085
3086                a.mul_add_assign(b, c * d);
3087                assert_eq!(result, a);
3088            }
3089
3090            #[test]
3091            fn test_mul_sub_mul_mut() {
3092                let mut a: f64 = 2.0;
3093                let b: f64 = 3.0;
3094                let c: f64 = 4.0;
3095                let d: f64 = -1.0;
3096                let mut result = a;
3097                result.kernel_mul_sub_mul_mut(&b, &c, &d);
3098
3099                a.mul_add_assign(b, -c * d);
3100                assert_eq!(result, a);
3101            }
3102
3103            #[test]
3104            fn test_negative_one() {
3105                let value = f64::negative_one();
3106                assert_eq!(value, -1.0);
3107            }
3108
3109            #[test]
3110            fn test_one() {
3111                let value = f64::one();
3112                assert_eq!(value, 1.0);
3113            }
3114
3115            #[test]
3116            fn test_round() {
3117                let value: f64 = 3.5;
3118                let result = value.kernel_round();
3119                assert_eq!(result, value.round());
3120            }
3121
3122            #[test]
3123            fn test_round_ties_even() {
3124                let value: f64 = 3.5;
3125                let result = value.kernel_round_ties_even();
3126                assert_eq!(result, value.round_ties_even());
3127            }
3128
3129            #[test]
3130            fn test_signum() {
3131                let value: f64 = -3.5;
3132                let result = value.kernel_signum();
3133                assert_eq!(result, value.signum());
3134            }
3135
3136            #[test]
3137            fn test_total_cmp() {
3138                let a: f64 = 3.0;
3139                let b: f64 = 4.0;
3140                let result = a.total_cmp(&b);
3141                assert_eq!(result, a.total_cmp(&b));
3142            }
3143
3144            #[test]
3145            fn test_try_from_64() {
3146                let result = f64::try_from_f64(3.7);
3147                assert!(result.is_ok());
3148            }
3149
3150            #[test]
3151            fn test_try_from_64_error_infinite() {
3152                let result = f64::try_from_f64(f64::INFINITY);
3153                assert!(result.is_err());
3154            }
3155
3156            #[test]
3157            fn test_try_from_64_error_nan() {
3158                let result = f64::try_from_f64(f64::NAN);
3159                assert!(result.is_err());
3160            }
3161
3162            #[test]
3163            fn test_trunc() {
3164                let value: f64 = 3.7;
3165                let result = value.kernel_trunc();
3166                assert_eq!(result, value.trunc());
3167            }
3168
3169            #[test]
3170            fn test_two() {
3171                let value = f64::two();
3172                assert_eq!(value, 2.0);
3173            }
3174        }
3175
3176        #[cfg(feature = "rug")]
3177        mod rug100 {
3178            use super::*;
3179            use crate::kernels::rug::RealRugStrictFinite;
3180            use rug::{Float, ops::CompleteRound};
3181            use try_create::{IntoInner, TryNew};
3182
3183            const PRECISION: u32 = 100;
3184
3185            #[test]
3186            fn from_f64() {
3187                let v_100bits = RealRugStrictFinite::<100>::try_from_f64(16.25).unwrap();
3188
3189                assert_eq!(v_100bits, 16.25);
3190
3191                let v_53bits = RealRugStrictFinite::<53>::try_from_f64(16.25).unwrap();
3192                assert_eq!(v_53bits, 16.25);
3193
3194                // 16.25 has seven significant bits (binary 10000.01)
3195                let v_7bits = RealRugStrictFinite::<7>::try_from_f64(16.25).unwrap();
3196                assert_eq!(v_7bits, 16.25);
3197            }
3198
3199            #[test]
3200            #[should_panic]
3201            fn from_f64_failing() {
3202                // this should fail because 16.25 has seven significant bits (binary 10000.01) and we ask a float with 6 significant bits
3203                let _v_6bits = RealRugStrictFinite::<6>::try_from_f64(16.25).unwrap();
3204            }
3205
3206            #[test]
3207            fn max_finite() {
3208                let max = RealRugStrictFinite::<53>::max_finite();
3209                assert_eq!(
3210                    max.as_ref(),
3211                    &rug::Float::with_val(
3212                        53,
3213                        rug::Float::parse("1.0492893582336937e323228496").unwrap()
3214                    )
3215                );
3216            }
3217
3218            #[test]
3219            fn min_finite() {
3220                let min = RealRugStrictFinite::<53>::min_finite();
3221                assert_eq!(
3222                    min.as_ref(),
3223                    &rug::Float::with_val(
3224                        53,
3225                        rug::Float::parse("-1.0492893582336937e323228496").unwrap()
3226                    )
3227                );
3228            }
3229
3230            #[test]
3231            fn test_atan2() {
3232                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 27.0))
3233                    .unwrap();
3234                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 13.0))
3235                    .unwrap();
3236                let result = a.clone().atan2(&b);
3237                assert_eq!(
3238                    result,
3239                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3240                        PRECISION,
3241                        a.into_inner().atan2(b.as_ref())
3242                    ))
3243                    .unwrap()
3244                );
3245            }
3246
3247            #[test]
3248            fn test_ceil() {
3249                let value =
3250                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
3251                        .unwrap();
3252                let result = value.clone().kernel_ceil();
3253                assert_eq!(
3254                    result,
3255                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3256                        PRECISION,
3257                        value.into_inner().ceil()
3258                    ))
3259                    .unwrap()
3260                );
3261            }
3262
3263            #[test]
3264            fn test_clamp() {
3265                let value =
3266                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0))
3267                        .unwrap();
3268                let min =
3269                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3270                        .unwrap();
3271                let max =
3272                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 7.0))
3273                        .unwrap();
3274                let result = value.clone().kernel_clamp(&min, &max);
3275                assert_eq!(
3276                    result,
3277                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3278                        PRECISION,
3279                        value.into_inner().clamp(min.as_ref(), max.as_ref())
3280                    ))
3281                    .unwrap()
3282                );
3283            }
3284
3285            #[test]
3286            fn test_classify() {
3287                let value =
3288                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
3289                        .unwrap();
3290                let result = value.kernel_classify();
3291                assert_eq!(result, value.into_inner().classify());
3292            }
3293
3294            #[test]
3295            fn test_copysign() {
3296                let value =
3297                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
3298                        .unwrap();
3299                let sign =
3300                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
3301                        .unwrap();
3302                let result = value.clone().kernel_copysign(&sign);
3303                assert_eq!(
3304                    result,
3305                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3306                        PRECISION,
3307                        value.into_inner().copysign(sign.as_ref())
3308                    ))
3309                    .unwrap()
3310                );
3311            }
3312
3313            #[test]
3314            fn test_epsilon() {
3315                let rug_eps = rug::Float::u_pow_u(2, PRECISION - 1)
3316                    .complete(PRECISION)
3317                    .recip();
3318                //println!("eps: {}", rug_eps);
3319
3320                let eps = RealRugStrictFinite::<PRECISION>::epsilon();
3321                assert_eq!(
3322                    eps,
3323                    RealRugStrictFinite::<PRECISION>::try_new(rug_eps.clone()).unwrap()
3324                );
3325
3326                // here we compute new_eps as the difference between 1 and the next larger floating point number
3327                let mut new_eps = Float::with_val(PRECISION, 1.);
3328                new_eps.next_up();
3329                new_eps -= Float::with_val(PRECISION, 1.);
3330                assert_eq!(new_eps, rug_eps.clone());
3331
3332                //println!("new_eps: {new_eps}");
3333
3334                let one = RealRugStrictFinite::<PRECISION>::one();
3335                let result = RealRugStrictFinite::<PRECISION>::try_new(
3336                    new_eps / Float::with_val(PRECISION, 2.),
3337                )
3338                .unwrap()
3339                    + &one;
3340                assert_eq!(result, one);
3341            }
3342
3343            #[test]
3344            fn test_exp_m1() {
3345                let value =
3346                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3347                        .unwrap();
3348                let result = value.clone().kernel_exp_m1();
3349                assert_eq!(
3350                    result,
3351                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3352                        PRECISION,
3353                        value.into_inner().exp_m1()
3354                    ))
3355                    .unwrap()
3356                );
3357            }
3358
3359            #[test]
3360            fn test_floor() {
3361                let value =
3362                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
3363                        .unwrap();
3364                let result = value.clone().kernel_floor();
3365                assert_eq!(
3366                    result,
3367                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3368                        PRECISION,
3369                        value.into_inner().floor()
3370                    ))
3371                    .unwrap()
3372                );
3373            }
3374
3375            #[test]
3376            fn test_fract() {
3377                let value =
3378                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
3379                        .unwrap();
3380                let result = value.clone().kernel_fract();
3381                assert_eq!(
3382                    result,
3383                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3384                        PRECISION,
3385                        value.into_inner().fract()
3386                    ))
3387                    .unwrap()
3388                );
3389            }
3390
3391            #[test]
3392            fn test_hypot() {
3393                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3394                    .unwrap();
3395                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3396                    .unwrap();
3397                let result = a.clone().kernel_hypot(&b);
3398                assert_eq!(
3399                    result,
3400                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3401                        PRECISION,
3402                        a.into_inner().hypot(b.as_ref())
3403                    ))
3404                    .unwrap()
3405                );
3406            }
3407
3408            #[test]
3409            fn test_is_sign_negative() {
3410                let value =
3411                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
3412                        .unwrap();
3413                assert!(value.kernel_is_sign_negative());
3414
3415                let value =
3416                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -0.0))
3417                        .unwrap();
3418                assert!(value.kernel_is_sign_negative());
3419
3420                let value =
3421                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0))
3422                        .unwrap();
3423                assert!(!value.kernel_is_sign_negative());
3424
3425                let value =
3426                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
3427                        .unwrap();
3428                assert!(!value.kernel_is_sign_negative());
3429            }
3430
3431            #[test]
3432            fn test_is_sign_positive() {
3433                let value =
3434                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
3435                        .unwrap();
3436                assert!(!value.kernel_is_sign_positive());
3437
3438                let value =
3439                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -0.0))
3440                        .unwrap();
3441                assert!(!value.kernel_is_sign_positive());
3442
3443                let value =
3444                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0))
3445                        .unwrap();
3446                assert!(value.kernel_is_sign_positive());
3447
3448                let value =
3449                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
3450                        .unwrap();
3451                assert!(value.kernel_is_sign_positive());
3452            }
3453
3454            #[test]
3455            fn test_ln_1p() {
3456                let value =
3457                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3458                        .unwrap();
3459                let result = value.clone().kernel_ln_1p();
3460                assert_eq!(
3461                    result,
3462                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3463                        PRECISION,
3464                        value.into_inner().ln_1p()
3465                    ))
3466                    .unwrap()
3467                );
3468            }
3469
3470            #[test]
3471            fn test_max() {
3472                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3473                    .unwrap();
3474                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3475                    .unwrap();
3476                let result = a.max(&b);
3477                assert_eq!(
3478                    result,
3479                    &RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3480                        PRECISION,
3481                        a.clone().into_inner().max(b.as_ref())
3482                    ))
3483                    .unwrap()
3484                );
3485            }
3486
3487            #[test]
3488            fn test_min() {
3489                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3490                    .unwrap();
3491                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3492                    .unwrap();
3493                let result = a.min(&b);
3494                assert_eq!(
3495                    result,
3496                    &RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3497                        PRECISION,
3498                        a.clone().into_inner().min(b.as_ref())
3499                    ))
3500                    .unwrap()
3501                );
3502            }
3503
3504            #[test]
3505            fn test_mul_add_mul_mut() {
3506                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
3507                    .unwrap();
3508                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3509                    .unwrap();
3510                let c = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3511                    .unwrap();
3512                let d = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
3513                    .unwrap();
3514                let mut result = a.clone();
3515                result.kernel_mul_add_mul_mut(&b, &c, &d);
3516                assert_eq!(
3517                    result,
3518                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3519                        PRECISION,
3520                        a.into_inner()
3521                            .mul_add_ref(b.as_ref(), &(c.into_inner() * d.as_ref()))
3522                    ))
3523                    .unwrap()
3524                );
3525            }
3526
3527            #[test]
3528            fn test_mul_sub_mul_mut() {
3529                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
3530                    .unwrap();
3531                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3532                    .unwrap();
3533                let c = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3534                    .unwrap();
3535                let d = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
3536                    .unwrap();
3537                let mut result = a.clone();
3538                result.kernel_mul_sub_mul_mut(&b, &c, &d);
3539                assert_eq!(
3540                    result,
3541                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3542                        PRECISION,
3543                        a.into_inner()
3544                            .mul_add_ref(b.as_ref(), &(-c.into_inner() * d.as_ref()))
3545                    ))
3546                    .unwrap()
3547                );
3548            }
3549
3550            #[test]
3551            fn test_negative_one() {
3552                let value = RealRugStrictFinite::<PRECISION>::negative_one();
3553                assert_eq!(
3554                    value,
3555                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
3556                        .unwrap()
3557                );
3558            }
3559
3560            #[test]
3561            fn test_one() {
3562                let value = RealRugStrictFinite::<PRECISION>::one();
3563                assert_eq!(
3564                    value,
3565                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
3566                        .unwrap()
3567                );
3568            }
3569
3570            #[test]
3571            fn test_round() {
3572                let value =
3573                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
3574                        .unwrap();
3575                let result = value.clone().kernel_round();
3576                assert_eq!(
3577                    result,
3578                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3579                        PRECISION,
3580                        value.into_inner().round()
3581                    ))
3582                    .unwrap()
3583                );
3584            }
3585
3586            #[test]
3587            fn test_round_ties_even() {
3588                let value =
3589                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
3590                        .unwrap();
3591                let result = value.clone().kernel_round_ties_even();
3592                assert_eq!(
3593                    result,
3594                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3595                        PRECISION,
3596                        value.into_inner().round_even()
3597                    ))
3598                    .unwrap()
3599                );
3600            }
3601
3602            #[test]
3603            fn test_signum() {
3604                let value =
3605                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.5))
3606                        .unwrap();
3607                let result = value.clone().kernel_signum();
3608                assert_eq!(
3609                    result,
3610                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3611                        PRECISION,
3612                        value.into_inner().signum()
3613                    ))
3614                    .unwrap()
3615                );
3616            }
3617
3618            #[test]
3619            fn test_total_cmp() {
3620                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3621                    .unwrap();
3622                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3623                    .unwrap();
3624                let result = a.total_cmp(&b);
3625                assert_eq!(result, a.into_inner().total_cmp(b.as_ref()));
3626            }
3627
3628            #[test]
3629            fn test_try_from_64() {
3630                let result = RealRugStrictFinite::<PRECISION>::try_from_f64(3.7);
3631                assert!(result.is_ok());
3632            }
3633
3634            #[test]
3635            fn test_try_from_64_error_infinite() {
3636                let result = RealRugStrictFinite::<PRECISION>::try_from_f64(f64::INFINITY);
3637                assert!(result.is_err());
3638            }
3639
3640            #[test]
3641            fn test_try_from_64_error_nan() {
3642                let result = RealRugStrictFinite::<PRECISION>::try_from_f64(f64::NAN);
3643                assert!(result.is_err());
3644            }
3645
3646            #[test]
3647            fn test_trunc() {
3648                let value =
3649                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
3650                        .unwrap();
3651                let result = value.clone().kernel_trunc();
3652                assert_eq!(
3653                    result,
3654                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3655                        PRECISION,
3656                        value.into_inner().trunc()
3657                    ))
3658                    .unwrap()
3659                );
3660            }
3661
3662            #[test]
3663            fn test_two() {
3664                let value = RealRugStrictFinite::<PRECISION>::two();
3665                assert_eq!(
3666                    value,
3667                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
3668                        .unwrap()
3669                );
3670            }
3671        }
3672    }
3673
3674    mod util_funcs {
3675        use crate::{
3676            kernels::native64_validated::RealNative64StrictFinite, new_random_vec,
3677            try_vec_f64_into_vec_real,
3678        };
3679        use rand::{SeedableRng, distr::Uniform, rngs::StdRng};
3680
3681        #[test]
3682        fn test_new_random_vec_deterministic() {
3683            let seed = [42; 32];
3684            let mut rng1 = StdRng::from_seed(seed);
3685            let mut rng2 = StdRng::from_seed(seed);
3686            let uniform = Uniform::new(-1.0, 1.0).unwrap();
3687
3688            let vec1: Vec<f64> = new_random_vec(10, &uniform, &mut rng1);
3689            let vec2: Vec<RealNative64StrictFinite> = new_random_vec(10, &uniform, &mut rng2);
3690
3691            assert_eq!(vec1.len(), 10);
3692            assert_eq!(vec2.len(), 10);
3693            for i in 0..10 {
3694                assert_eq!(&vec1[i], vec2[i].as_ref());
3695            }
3696        }
3697
3698        #[test]
3699        fn test_try_vec_f64_into_vec_real_success() {
3700            let input = vec![1.0, -2.5, 1e10];
3701            let result = try_vec_f64_into_vec_real::<RealNative64StrictFinite>(input);
3702            assert!(result.is_ok());
3703            let output = result.unwrap();
3704            assert_eq!(output[0].as_ref(), &1.0);
3705            assert_eq!(output[1].as_ref(), &-2.5);
3706        }
3707
3708        #[test]
3709        fn test_try_vec_f64_into_vec_real_fail() {
3710            let input = vec![1.0, f64::NAN, 3.0];
3711            let result = try_vec_f64_into_vec_real::<RealNative64StrictFinite>(input);
3712            assert!(result.is_err());
3713        }
3714    }
3715}