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