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