Skip to main content

num_valid/
lib.rs

1#![deny(rustdoc::broken_intra_doc_links)]
2#![feature(error_generic_member_access)]
3#![feature(trait_alias)]
4
5//! [`num-valid`](crate) is a Rust library designed for robust, generic, and high-performance numerical computation.
6//! It provides an extensible framework for working with both real and complex numbers, addressing the challenges
7//! of floating-point arithmetic through validation policies and fallible operations.
8//!
9//! # Key Features \& Architecture
10//!
11//! - **Safety by Construction with Validated Types:** Instead of using raw primitives like [`f64`] or [`Complex<f64>`](num::Complex)
12//!   directly, [`num-valid`](crate) encourages the use of validated wrappers like [`RealValidated`]
13//!   and [`ComplexValidated`]. With an always-validating policy, these types guarantee that the value
14//!   they hold conforms to that policy (for example, is finite), eliminating entire classes of numerical bugs.
15//!
16//! - **Enhanced Type Safety with Hashing Support:** Types validated with policies that guarantee
17//!   finite values (like [`Native64StrictFinite`]) automatically
18//!   implement [`Eq`] and [`Hash`]. This enables their use as keys in [`HashMap`](std::collections::HashMap) and other
19//!   hash-based collections, while maintaining compatibility with the library's [`PartialOrd`]-based
20//!   comparison functions. The hashing implementation properly handles IEEE 754 floating-point
21//!   edge cases and ensures that mathematically equal values produce identical hash codes.
22//!
23//! - **Support for Real and Complex Numbers:** The library supports both real and complex numbers,
24//!   with specific validation policies for each type.
25//!
26//! - **Layered and Extensible Design:** The library has a well-defined, layered, and highly generic architecture.
27//!   It abstracts the concept of a "numerical kernel" (the underlying number representation and its operations) from the high-level mathematical traits.
28//!
29//!   The architecture can be understood in four main layers:
30//!   - **Layer 1: Raw Trait Contracts** ([`kernels`] module):
31//!     - The [`RawScalarTrait`], [`RawRealTrait`], and [`RawComplexTrait`](crate::kernels::RawComplexTrait) define the low-level, "unchecked" contract
32//!       for any number type.
33//!     - These traits are the foundation, providing a standard set of `unchecked_*` methods.
34//!     - 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.
35//!
36//!     This design separates the pure, high-performance computational logic from the safety and validation logic.
37//!     It creates a clear, minimal contract for backend implementors and allows the validated wrappers in Layer 3
38//!     to be built on a foundation of trusted, high-speed operations.
39//!
40//!   - **Layer 2: Validation Policies** ([`core::policies`] module):
41//!     - The [`NumKernel`] trait is the bridge between the raw types and the validated wrappers.
42//!     - It bundles together the raw real/complex types and their corresponding validation policies
43//!       (e.g., [`Native64StrictFinite`], [`Native64StrictFiniteInDebug`],
44//!       etc.). This allows the entire behavior of the validated types to be configured with a single generic parameter.
45//!
46//!     It acts as the central policy configuration point. By choosing a [`NumKernel`], a user selects both a
47//!     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::core::policies::StrictFinitePolicy)
48//!     vs. [`DebugValidationPolicy`](crate::core::policies::DebugValidationPolicy)) for real and complex numbers,
49//!     with a single generic parameter. This dramatically simplifies writing generic code that can be configured for
50//!     different safety and performance trade-offs.
51//!
52//!     **Policy Comparison:**
53//!
54//!     | Type Alias | Policy | Debug Build | Release Build | Use Case |
55//!     |------------|--------|-------------|---------------|----------|
56//!     | [`RealNative64StrictFinite`] | [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy) | ✅ Validates | ✅ Validates | Safety-critical code, HashMap keys |
57//!     | [`RealNative64StrictFiniteInDebug`] | [`DebugValidationPolicy`](crate::core::policies::DebugValidationPolicy) | ✅ Validates | ❌ No validation | Performance-critical hot paths |
58//!     | [`RealNative32StrictFinite`] | [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy) | ✅ Validates | ✅ Validates | Native single-precision code |
59//!     | `RealRugStrictFinite<P>` | [`StrictFinitePolicy`](crate::core::policies::StrictFinitePolicy) | ✅ Validates | ✅ Validates | High-precision calculations |
60//!
61//!     **Key Differences:**
62//!     - **StrictFinite**: Always validates, implements [`Eq`] + [`Hash`] (safe for [`HashMap`](std::collections::HashMap) keys)
63//!     - **StrictFiniteInDebug**: Zero overhead in release, catches bugs during development
64//!
65//!   - **Layer 3: Validated Wrappers**:
66//!     - [`RealValidated<K>`] and [`ComplexValidated<K>`]
67//!       are the primary user-facing types.
68//!     - 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).
69//!     - They use extensive macros to implement high-level traits. The logic is clean: perform a check (if necessary) on the input value,
70//!       then call the corresponding `unchecked_*` method from the raw trait, and then perform a check on the output value before returning it.
71//!       This ensures safety and correctness.
72//!
73//!     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
74//!     of [`RealValidated`] has passed the validation policy. Always-validating policies therefore eliminate
75//!     entire classes of errors (like `NaN` propagation) in user code.
76//!
77//!   - **Layer 4: High-Level Abstraction Traits**:
78//!     - The [`FpScalar`] trait is the central abstraction, defining a common interface for all scalar types. It uses an associated type sealed type (`Kind`),
79//!       to enforce that a scalar is either real or complex, but not both.
80//!     - [`RealScalar`] and [`ComplexScalar`] are specialized sub-traits of [`FpScalar`] that serve as markers for real and complex numbers, respectively.
81//!     - Generic code in a consumer crate is written against these high-level traits.
82//!     - The [`RealValidated`] and [`ComplexValidated`] structs from Layer 3 are the concrete implementors of these traits.
83//!
84//!     These traits provide the final, safe, and generic public API. Library consumers write their algorithms
85//!     against these traits, making their code independent of the specific numerical kernel being used.
86//!
87//!   This layered approach is powerful, providing both high performance (by using unchecked methods internally) and safety
88//!   (through the validated wrappers). The use of generics and traits makes it extensible to new numerical backends (as demonstrated by the rug implementation).
89//!
90//! - **Multiple Numerical Backends**. At the time of writing, 2 numerical backends can be used:
91//!   - the standard (high-performance) numerical backend is the one in which the raw floating point and complex numbers are
92//!     described by Rust's native [`f32`] and [`f64`] and their [`Complex<f32>`]/[`Complex<f64>`](num::Complex) types;
93//!   - an optional (high-precision) numerical backend is available if the library is compiled with the optional flag `--features=rug`,
94//!     and uses the arbitrary precision raw types `rug::Float` and `rug::Complex` from the Rust library [`rug`](https://crates.io/crates/rug).
95//! - **Comprehensive Mathematical Library**. It includes a wide range of mathematical functions for
96//!   trigonometry, logarithms, exponentials, and more, all implemented as traits (e.g., [`functions::Sin`], [`functions::Cos`], [`functions::Sqrt`]) and available on the validated types.
97//! - **Numerically Robust Implementations**. The library commits to numerical accuracy:
98//!   - Neumaier compensated summation (`NeumaierSum`) for the default [`std::iter::Sum`] implementation to minimize precision loss.
99//!   - BLAS/LAPACK-style L2 norm (`algorithms::vector_norms::vector_norm_l2`) with incremental scaling to prevent overflow and underflow.
100//! - **Robust Error Handling:** The library defines detailed error types for various numerical operations,
101//!   ensuring that invalid inputs and outputs are properly handled and reported.
102//!   Errors are categorized into input and output errors, with specific variants for different types of numerical
103//!   issues such as division by zero, invalid values, and subnormal numbers.
104//! - **Conditional Backtrace Capture:** Backtrace capture in error types is disabled by default for maximum
105//!   performance. Enable the `backtrace` feature flag for debugging to get full stack traces in error types.
106//! - **Conditional `Copy` Implementation:** Validated types ([`RealValidated`], [`ComplexValidated`]) automatically
107//!   implement [`Copy`] when their underlying raw types support it. This enables zero-cost pass-by-value semantics
108//!   for native 64-bit types while correctly requiring [`Clone`] for non-[`Copy`] backends like `rug`.
109//! - **Constrained Scalar Types:** The [`scalars`] module provides validated wrapper types for common domain-specific
110//!   constraints: [`scalars::AbsoluteTolerance`] (non-negative), [`scalars::RelativeTolerance`] (non-negative, with
111//!   conversion to absolute), [`scalars::PositiveRealScalar`] (strictly > 0), and [`scalars::NonNegativeRealScalar`]
112//!   (≥ 0). [`scalars::HashableScalar`] wraps finite real or complex [`FpScalar`] values to provide [`Eq`] and
113//!   [`Hash`] for hash-based collections. The constrained scalar types are generic over any [`RealScalar`] backend.
114//! - **Approximate Equality Comparisons:** All validated types implement the [`approx`] crate traits
115//!   ([`AbsDiffEq`](approx::AbsDiffEq), [`RelativeEq`](approx::RelativeEq), [`UlpsEq`](approx::UlpsEq))
116//!   for tolerance-based floating-point comparisons. This is essential for testing numerical algorithms
117//!   and handling floating-point precision limitations. The `approx` crate is re-exported for convenience.
118//! - **Comprehensive Documentation:** The library includes detailed documentation for each struct, trait, method,
119//!   and error type, making it easy for users to understand and utilize the provided functionality.
120//!   Examples are provided for key functions to demonstrate their usage and expected behavior.
121//! - **Zero-Copy Conversions:** The native 64-bit validated types ([`RealNative64StrictFinite`], [`RealNative64StrictFiniteInDebug`])
122//!   implement [`bytemuck::CheckedBitPattern`](https://docs.rs/bytemuck/latest/bytemuck/checked/trait.CheckedBitPattern.html)
123//!   and [`bytemuck::NoUninit`](https://docs.rs/bytemuck/latest/bytemuck/trait.NoUninit.html),
124//!   enabling safe, zero-copy conversions between byte representations and validated types. This is particularly useful for
125//!   interoperability with binary data formats, serialization, and performance-critical code. The conversion automatically
126//!   validates the bit pattern at runtime, rejecting invalid values (NaN, Infinity, subnormal numbers) before exposing a validated reference.
127//!
128//! # Architecture Deep Dive
129//!
130//! For a comprehensive understanding of the library's architecture, design patterns, and implementation details,
131//! see the **[Architecture Guide](https://gitlab.com/max.martinelli/num-valid/-/blob/master/docs/ARCHITECTURE.md)**
132//! (also available in the repository at `docs/ARCHITECTURE.md`).
133//!
134//! The guide covers:
135//! - **Detailed explanation of the 4-layer design** with examples and rationale
136//! - **How to add a new numerical backend** (step-by-step guide with checklist)
137//! - **How to implement new mathematical functions** (complete template)
138//! - **Error handling architecture** (two-phase error model, backtrace handling)
139//! - **Performance considerations** (zero-cost abstractions, optimization patterns)
140//! - **Macro system** (code generation patterns and proposals)
141//! - **Design patterns reference** (newtype, marker traits, sealed traits, etc.)
142//!
143//! **For Contributors**: Reading the architecture guide is essential before submitting PRs, as it explains
144//! the design philosophy and implementation conventions that keep the codebase consistent and maintainable.
145//!
146//! # Compiler Requirement: Rust Nightly
147//! This library currently requires the **nightly** toolchain because it uses some unstable Rust features which,
148//! at the time of writing (August 2026), are not yet available in stable or beta releases. These features are:
149//!   - `trait_alias`: For ergonomic trait combinations
150//!   - `error_generic_member_access`: For advanced error handling
151//!
152//! If these features are stabilized in a future Rust release, the library will be updated to support the stable compiler.
153//!
154//! To use the nightly toolchain, please run:
155//!
156//! ```bash
157//! rustup install nightly
158//! rustup override set nightly
159//! ```
160//!
161//! This will set your environment to use the nightly compiler, enabling compatibility with the current version of the
162//! library.
163//!
164//! # Getting Started
165//!
166//! This guide will walk you through the basics of using [`num-valid`](crate).
167//!
168//! ## 1. Add [`num-valid`](crate) to your Project
169//!
170//! Add the following to your `Cargo.toml` (change the versions to the latest ones):
171//!
172//! ```toml
173//! [dependencies]
174//! num-valid = "0.6.0"    # Change to the latest version
175//! ```
176//!
177//! ## 1.5. Quick Start with Literal Macros (Recommended)
178//!
179//! The easiest way to create validated numbers is using the [`real!`] and [`complex!`] macros:
180//!
181//! ```rust
182//! use num_valid::{real, complex};
183//! use std::f64::consts::PI;
184//!
185//! // Create validated real numbers from literals
186//! let x = real!(3.14159);
187//! let angle = real!(PI / 4.0);
188//! let radius = real!(5.0);
189//!
190//! // Create validated complex numbers (real, imaginary)
191//! let z1 = complex!(1.0, 2.0);   // 1 + 2i
192//! let z2 = complex!(-3.0, 4.0);  // -3 + 4i
193//!
194//! // StrictFinite values remain finite; fallible operations report domain and overflow errors.
195//! let area = real!(PI) * radius.clone() * radius;  // Type-safe area calculation
196//! let product = z1 * z2;                           // Safe complex arithmetic
197//! ```
198//!
199//! **Why use macros?**
200//! - **Ergonomic**: Concise syntax similar to Rust's built-in `vec![]`, `format!()`, etc.
201//! - **Safe with `StrictFinite`**: Validates at construction time and after operations, rejecting non-finite values
202//! - **Clear panics**: Invalid literals (like `real!(f64::NAN)`) panic immediately with descriptive messages
203//! - **Compile-time friendly**: Works with constants and expressions evaluated at compile time
204//!
205//! For single-precision values, use [`real32!`] and [`complex32!`], the [`f32`] counterparts
206//! of [`real!`] and [`complex!`]:
207//!
208//! ```rust
209//! use num_valid::{real32, complex32};
210//!
211//! let x = real32!(3.14159);
212//! let y = real32!(std::f32::consts::PI);
213//! let z = complex32!(1.0, 2.0);
214//! ```
215//!
216//! For runtime values or when you need error handling, see the manual construction methods below.
217//!
218//! ### Feature Flags
219//!
220//! The library provides several optional feature flags:
221//!
222//! | Feature | Description |
223//! |---------|-------------|
224//! | `rug` | Enables the high-precision arbitrary arithmetic backend using [`rug`](https://crates.io/crates/rug). See LGPL-3.0 notice below. |
225//! | `backtrace` | Enables backtrace capture in error types for debugging. Disabled by default for performance. |
226//!
227//! Example with multiple features:
228//!
229//! ```toml
230//! [dependencies]
231//! num-valid = { version = "0.6.0", features = ["rug", "backtrace"] }
232//! ```
233//!
234//! ## 2. Core Concept: Validated Types
235//!
236//! The central idea in [`num-valid`](crate) is to use **validated types** instead of raw primitives like [`f64`].
237//! These are wrappers that guarantee their inner value is always valid (e.g., not `NaN` or `Infinity`) according to
238//! a specific policy.
239//!
240//! The most common type you'll use is [`RealNative64StrictFinite`], which wraps an [`f64`] and ensures it's always finite,
241//! both in Debug and Release mode. For a similar type wrapping an [`f64`] that ensures it's always finite, but with the
242//! validity checks executed only in Debug mode (providing performance equal to the raw [`f64`] type), you can use
243//! [`RealNative64StrictFiniteInDebug`].
244//!
245//! ## 3. Your First Calculation
246//!
247//! Let's perform a square root calculation. You'll need to bring the necessary traits into scope.
248//!
249//! ```rust
250//! // Import the validated type and necessary traits
251//! use num_valid::{*, functions::{Sqrt, SqrtRealInputErrors, SqrtRealErrors}};
252//! use num_valid::TryNew;
253//!
254//! // 1. Create a validated number. try_new() returns a Result.
255//! let x = RealNative64StrictFinite::try_new(4.0).unwrap();
256//!
257//! // 2. Use the direct method for operations.
258//! // This will panic if the operation is invalid (e.g., sqrt of a negative).
259//! let sqrt_x = x.sqrt();
260//! assert_eq!(sqrt_x.as_raw_scalar_ref(), &2.0);
261//!
262//! // 3. Use the `try_*` methods for error handling.
263//! // This is the safe way to handle inputs that might be out of the function's domain.
264//! let neg_x = RealNative64StrictFinite::try_new(-4.0).unwrap();
265//! let sqrt_neg_x_result = neg_x.try_sqrt();
266//!
267//! // The operation fails gracefully, returning an Err.
268//! assert!(sqrt_neg_x_result.is_err());
269//!
270//! // The error gives information about the problem that occurred
271//! if let Err(SqrtRealErrors::Input(source)) = sqrt_neg_x_result {
272//!     assert!(matches!(source, SqrtRealInputErrors::NegativeValue { .. }));
273//! }
274//! ```
275//!
276//! ## 4. Writing Generic Functions
277//!
278//! The real power of [`num-valid`](crate) comes from writing generic functions that work with any
279//! supported numerical type. You can do this by using the [`FpScalar`] and [`RealScalar`] traits as bounds.
280//!
281//! ```rust
282//! use num_valid::{
283//!     RealScalar, RealNative64StrictFinite, FpScalar,
284//!     functions::{Abs, Sin, Cos},
285//! };
286//! use num::One;
287//! use num_valid::TryNew;
288//! use try_create::IntoInner;
289//!
290//! // This function works for any type that implements RealScalar,
291//! // including f64, RealNative64StrictFinite, and RealRugStrictFinite.
292//! fn verify_trig_identity<T: RealScalar>(angle: T) -> T {
293//!     // We can use .sin(), .cos(), and arithmetic ops because they are
294//!     // required by the RealScalar trait.
295//!     let sin_x = angle.clone().sin();
296//!     let cos_x = angle.cos();
297//!     (sin_x.clone() * sin_x) + (cos_x.clone() * cos_x)
298//! }
299//!
300//! // Define a type alias for convenience
301//! type MyReal = RealNative64StrictFinite;
302//!
303//! // Call it with a validated f64 type.
304//! let angle = MyReal::try_from_f64(0.5).unwrap();
305//! let identity = verify_trig_identity(angle);
306//!
307//! // The result should be very close to 1.0.
308//! let one = MyReal::one();
309//! assert!((identity - one).abs().into_inner() < MyReal::try_from_f64(1e-15).unwrap());
310//! ```
311//!
312//! If the `rug` feature is enabled, you could call the exact same
313//! function with a high-precision number changing only the definition
314//! of the alias type `MyReal`. For example, for real numbers with precision of 100 bits:
315//! ```rust
316//! # #[cfg(feature = "rug")] {
317//! // Import the rug-based types
318//! use num_valid::{
319//!     RealScalar, RealRugStrictFinite, FpScalar,
320//!     functions::{Abs, Sin, Cos},
321//! };
322//! use num::One;
323//! use num_valid::TryNew;
324//! use try_create::IntoInner;
325//!
326//! // This function works for any type that implements RealScalar,
327//! // including f64, RealNative64StrictFinite, and RealRugStrictFinite.
328//! fn verify_trig_identity<T: RealScalar>(angle: T) -> T {
329//!     // We can use .sin(), .cos(), and arithmetic ops because they are
330//!     // required by the RealScalar trait.
331//!     let sin_x = angle.clone().sin();
332//!     let cos_x = angle.cos();
333//!     (sin_x.clone() * sin_x) + (cos_x.clone() * cos_x)
334//! }
335//!
336//! // Define a type alias for convenience - real number with precision of 100 bits
337//! type MyReal = RealRugStrictFinite<100>;
338//!
339//! // Initialize it with an f64 value.
340//! let angle = MyReal::try_from_f64(0.5).unwrap();
341//! let identity = verify_trig_identity(angle);
342//!
343//! // The result should be very close to 1.0.
344//! let one = MyReal::one();
345//! assert!((identity - one).abs().into_inner() < MyReal::try_from_f64(1e-15).unwrap());
346//! # }
347//! ```
348//!
349//! ## 5. Working with Complex Numbers
350//!
351//! The library also provides validated complex number types:
352//!
353//! ```rust
354//! use num_valid::{*, functions::Abs};
355//! use num::Complex;
356//! use num_valid::TryNew;
357//!
358//! // Create a validated complex number
359//! let z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
360//!
361//! // Complex operations work the same way
362//! let magnitude = z.abs();
363//! assert_eq!(magnitude.as_raw_scalar_ref(), &5.0); // |3 + 4i| = 5
364//! ```
365//!
366//! ## 6. Zero-Copy Conversions with Bytemuck
367//!
368//! For performance-critical applications working with binary data, the library provides safe, zero-copy
369//! conversions through the [`bytemuck`](https://docs.rs/bytemuck) crate. The native 64-bit validated types
370//! ([`RealNative64StrictFinite`], [`RealNative64StrictFiniteInDebug`]) implement
371//! [`CheckedBitPattern`](https://docs.rs/bytemuck/latest/bytemuck/checked/trait.CheckedBitPattern.html)
372//! and [`NoUninit`](https://docs.rs/bytemuck/latest/bytemuck/trait.NoUninit.html), enabling safe conversions
373//! that automatically validate bit patterns:
374//!
375//! ```rust
376//! use num_valid::*;
377//! use bytemuck::checked::try_from_bytes;
378//!
379//! // Convert from bytes - validation happens automatically
380//! let value = 42.0_f64;
381//! let bytes = value.to_ne_bytes();
382//! let validated: &RealNative64StrictFinite = try_from_bytes(&bytes).unwrap();
383//! assert_eq!(validated.as_raw_scalar_ref(), &42.0);
384//!
385//! // Invalid values (NaN, Infinity, subnormals) are rejected
386//! let nan_bytes = f64::NAN.to_ne_bytes();
387//! assert!(try_from_bytes::<RealNative64StrictFinite>(&nan_bytes).is_err());
388//! ```
389//!
390//! This is particularly useful for:
391//! - Loading validated numbers from binary file formats
392//! - Interoperability with serialization libraries
393//! - Processing validated numerical data in performance-critical loops
394//! - Working with memory-mapped files containing numerical data
395//!
396//! For comprehensive examples including slice operations and error handling, see the test module
397//! in the [`backends::native::validated`] module source code.
398//!
399//! ## 7. Validated Tolerances and Constrained Scalars
400//!
401//! The [`scalars`] module provides validated wrapper types for common domain-specific constraints:
402//!
403//! ```rust
404//! use num_valid::*;
405//! use num_valid::scalars::{
406//!     AbsoluteTolerance, RelativeTolerance,
407//!     PositiveRealScalar, NonNegativeRealScalar, HashableScalar,
408//! };
409//! use num_valid::TryNew;
410//! use std::collections::HashMap;
411//!
412//! // AbsoluteTolerance: Non-negative tolerance (≥ 0)
413//! let abs_tol = AbsoluteTolerance::try_new(
414//!     RealNative64StrictFinite::from_f64(1e-10)
415//! )?;
416//!
417//! // RelativeTolerance: Non-negative, with conversion to absolute tolerance
418//! let rel_tol = RelativeTolerance::try_new(
419//!     RealNative64StrictFinite::from_f64(1e-6)
420//! )?;
421//! let reference = RealNative64StrictFinite::from_f64(1000.0);
422//! let abs_from_rel = rel_tol.absolute_tolerance(reference); // = 1e-3
423//!
424//! // PositiveRealScalar: Strictly positive (> 0), rejects zero
425//! let step_size = PositiveRealScalar::try_new(
426//!     RealNative64StrictFinite::from_f64(0.001)
427//! )?;
428//! // PositiveRealScalar::try_new(zero) would return an error!
429//!
430//! // NonNegativeRealScalar: Non-negative (≥ 0), accepts zero
431//! let threshold = NonNegativeRealScalar::try_new(
432//!     RealNative64StrictFinite::from_f64(0.0)
433//! )?;  // OK!
434//!
435//! // HashableScalar: finite real or complex value usable as a hash-map key
436//! let key = HashableScalar::try_new(RealNative64StrictFinite::from_f64(42.0))?;
437//! let mut labels = HashMap::new();
438//! labels.insert(key, "answer");
439//! # Ok::<(), Box<dyn std::error::Error>>(())
440//! ```
441//!
442//! **Key differences:**
443//! - [`scalars::PositiveRealScalar`]: Rejects zero (useful for divisors, step sizes)
444//! - [`scalars::NonNegativeRealScalar`]: Accepts zero (useful for thresholds, counts)
445//! - [`scalars::HashableScalar`]: Rejects non-finite values and enables [`Eq`] and [`Hash`] for hash-based collections
446//! - All types are generic over any [`RealScalar`] backend
447//!
448//! # Common Pitfalls
449//!
450//! Here are common mistakes to avoid when using [`num-valid`](crate):
451//!
452//! ## 1. Forgetting `Clone` for Reused Values
453//!
454//! Validated types consume `self` in mathematical operations. Clone before reuse:
455//!
456//! ```rust
457//! use num_valid::{real, functions::{Sin, Cos}};
458//! let x = real!(1.0);
459//!
460//! // ❌ Wrong - x is moved after first use:
461//! // let sin_x = x.sin();
462//! // let cos_x = x.cos(); // Error: x already moved!
463//!
464//! // ✅ Correct - clone before move:
465//! let sin_x = x.clone().sin();
466//! let cos_x = x.cos();
467//! ```
468//!
469//! ## 2. Using `from_f64` with Untrusted Input
470//!
471//! [`RealScalar::from_f64`] panics on invalid input. Use [`RealScalar::try_from_f64`] for user data:
472//!
473//! ```rust
474//! use num_valid::*;
475//!
476//! fn process_user_input(user_input: f64) -> Result<(), Box<dyn std::error::Error>> {
477//!     // ❌ Dangerous - panics on NaN/Inf:
478//!     // let x = RealNative64StrictFinite::from_f64(user_input);
479//!
480//!     // ✅ Safe - handles errors gracefully:
481//!     let x = RealNative64StrictFinite::try_from_f64(user_input)?;
482//!     println!("Validated: {}", x);
483//!     Ok(())
484//! }
485//! # process_user_input(42.0).unwrap();
486//! ```
487//!
488//! ## 3. Validation Policy Mismatch
489//!
490//! Choose the right policy for your use case:
491//!
492//! | Policy | Debug Build | Release Build | Use Case |
493//! |--------|-------------|---------------|----------|
494//! | `StrictFinite` | ✅ Validates | ✅ Validates | Safety-critical code |
495//! | `StrictFiniteInDebug` | ✅ Validates | ❌ No validation | Performance-critical code |
496//!
497//! ```rust
498//! use num_valid::{RealNative64StrictFinite, RealNative64StrictFiniteInDebug};
499//!
500//! // For safety-critical code (always validated)
501//! type SafeReal = RealNative64StrictFinite;
502//!
503//! // For performance-critical code (validated only in debug builds)
504//! type FastReal = RealNative64StrictFiniteInDebug;
505//! ```
506//!
507//! ## 4. Ignoring `#[must_use]` Warnings
508//!
509//! All `try_*` methods return [`Result`]. Don't ignore them:
510//!
511//! ```rust
512//! use num_valid::{RealNative64StrictFinite, functions::Sqrt};
513//! use try_create::TryNew;
514//!
515//! let x = RealNative64StrictFinite::try_new(4.0).unwrap();
516//!
517//! // ❌ Compiler warning: unused Result
518//! // x.try_sqrt();
519//!
520//! // ✅ Handle the result
521//! let sqrt_x = x.try_sqrt()?;
522//! # Ok::<(), Box<dyn std::error::Error>>(())
523//! ```
524//!
525//! # License
526//! Copyright 2023-2025, C.N.R. - Consiglio Nazionale delle Ricerche
527//!
528//! Licensed under either of
529//! - Apache License, Version 2.0
530//! - MIT license
531//!
532//! at your option.
533//!
534//! Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you,
535//! as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
536//!
537//! ## License Notice for Optional Feature Dependencies (LGPL-3.0 Compliance)
538//! If you enable the `rug` feature, this project will depend on the [`rug`](https://crates.io/crates/rug) library,
539//! which is licensed under the LGPL-3.0 license. Activating this feature may introduce LGPL-3.0 requirements to your
540//! project. Please review the terms of the LGPL-3.0 license to ensure compliance.
541
542pub mod algorithms;
543pub mod backends;
544pub mod core;
545pub mod functions;
546pub mod kernels;
547pub mod prelude;
548pub mod scalars;
549
550mod macros;
551// Macros are exported at crate root via #[macro_export]
552
553use crate::{
554    algorithms::accumulators::NeumaierAddable,
555    core::{
556        errors::{
557            ErrorsRawRealToInteger, ErrorsValidationRawComplex, ErrorsValidationRawReal,
558            RawRealConversionError,
559        },
560        traits::{
561            NumKernel,
562            raw::TryConvertFromRawReal,
563            validation::{FpChecks, sealed::NativeReal},
564        },
565    },
566    functions::{
567        ACos, ACosH, ASin, ASinH, ATan, ATan2, ATanH, Abs, Arg, Arithmetic, Clamp, Classify,
568        ComplexScalarConstructors, ComplexScalarGetParts, ComplexScalarMutateParts,
569        ComplexScalarSetParts, Conjugate, Cos, CosH, Exp, ExpM1, HyperbolicFunctions, Hypot, Ln,
570        Ln1p, Log2, Log10, LogarithmFunctions, Max, Min, MulAddRef, Pow,
571        PowComplexBaseRealExponentErrors, PowIntExponentErrors, PowRealBaseRealExponentErrors,
572        Reciprocal, Rounding, Sign, Sin, SinH, Sqrt, Tan, TanH, TotalCmp, TrigonometricFunctions,
573    },
574    kernels::{ComplexValidated, RawRealTrait, RawScalarTrait, RealValidated},
575    scalars::NonNegativeRealScalar,
576};
577use duplicate::duplicate_item;
578use num::{Complex, FromPrimitive, One, PrimInt, Zero};
579use rand::{Rng, distr::Distribution};
580use serde::{Deserialize, Serialize};
581use std::{
582    fmt::{Debug, Display},
583    ops::{Mul, MulAssign, Neg},
584};
585use thiserror::Error;
586use try_create::IntoInner;
587
588/// Re-export of [`try_create::TryNew`], the public fallible constructor trait
589/// implemented by validated scalar types.
590pub use try_create::TryNew;
591
592pub use crate::backends::native::validated::{
593    ComplexNative32StrictFinite, ComplexNative64StrictFinite, ComplexNative64StrictFiniteInDebug,
594    Native32StrictFinite, Native32StrictFiniteInDebug, Native64StrictFinite,
595    Native64StrictFiniteInDebug, RealNative32StrictFinite, RealNative64StrictFinite,
596    RealNative64StrictFiniteInDebug,
597};
598
599pub use crate::kernels::PrecisionBits;
600
601#[cfg(feature = "rug")]
602pub use crate::backends::rug::validated::{
603    ComplexRugStrictFinite, RealRugStrictFinite, RugStrictFinite,
604};
605
606/// Re-export the `approx` crate for convenient access to approximate comparison traits.
607///
608/// This allows users to use `num_valid::approx` instead of adding `approx` as a separate dependency.
609/// The validated types [`RealValidated`] and [`ComplexValidated`] implement the following traits:
610/// - [`AbsDiffEq`](approx::AbsDiffEq): Absolute difference equality
611/// - [`RelativeEq`](approx::RelativeEq): Relative difference equality  
612/// - [`UlpsEq`](approx::UlpsEq): Units in Last Place equality
613///
614/// # Example
615///
616/// ```rust
617/// use num_valid::*;
618/// use num_valid::scalars::AbsoluteTolerance;
619/// use num_valid::approx::assert_abs_diff_eq;
620/// use num_valid::TryNew;
621///
622/// let a = RealNative64StrictFinite::from_f64(1.0);
623/// let b = RealNative64StrictFinite::from_f64(1.0 + 1e-10);
624/// let eps = AbsoluteTolerance::try_new(
625///     RealNative64StrictFinite::from_f64(1e-9)
626/// ).unwrap();
627/// assert_abs_diff_eq!(a, b, epsilon = eps);
628/// ```
629pub use approx;
630
631//------------------------------------------------------------------------------------------------
632/// Private module to encapsulate implementation details of the scalar kind for mutual exclusion.
633///
634/// This module provides the sealed trait pattern to ensure that scalar types can only be
635/// either real or complex, but never both. The sealed nature prevents external crates
636/// from implementing the trait, maintaining the library's type safety guarantees.
637pub(crate) mod scalar_kind {
638    /// A sealed trait to mark the "kind" of a scalar.
639    ///
640    /// External users cannot implement this trait due to the sealed pattern.
641    /// This ensures that only the library-defined scalar kinds (Real and Complex)
642    /// can be used with the [`FpScalar`](super::FpScalar) trait.
643    pub trait Sealed {}
644
645    /// A marker type for real scalar types.
646    ///
647    /// This type is used as the `Kind` associated type for real number types
648    /// in the [`FpScalar`](super::FpScalar) trait, ensuring type-level distinction
649    /// between real and complex scalars.
650    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
651    pub struct Real;
652    impl Sealed for Real {}
653
654    /// A marker type for complex scalar types.
655    ///
656    /// This type is used as the `Kind` associated type for complex number types
657    /// in the [`FpScalar`](super::FpScalar) trait, ensuring type-level distinction
658    /// between real and complex scalars.
659    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
660    pub struct Complex;
661    impl Sealed for Complex {}
662}
663//------------------------------------------------------------------------------------------------
664
665//------------------------------------------------------------------------------------------------
666/// Fundamental trait defining core requirements for all scalar types.
667///
668/// [`ScalarCore`] aggregates the essential traits that every scalar type in [`num-valid`](crate)
669/// must implement, regardless of whether it's real or complex, native or arbitrary-precision.
670/// This trait provides a single, maintainable definition of the foundational capabilities
671/// required by all floating-point scalar types.
672///
673/// ## Included Traits
674///
675/// - **[`Sized`]**: Types must have a known size at compile time
676/// - **[`Clone`]**: Values can be duplicated (note: not necessarily [`Copy`])
677/// - **[`Debug`]**: Supports formatted debugging output with `{:?}`
678/// - **[`Display`]**: Supports user-facing formatted output with `{}`
679/// - **[`PartialEq`]**: Supports equality comparisons (may upgrade to [`Eq`] with finite guarantees)
680/// - **[`Send`]**: Safe to transfer ownership across thread boundaries
681/// - **[`Sync`]**: Safe to share references across threads
682/// - **[`Serialize`]**: Can be serialized (via [`serde`])
683/// - **[`Deserialize`]**: Can be deserialized (via [`serde`])
684/// - **`'static`**: Contains no non-static references
685///
686/// ## Design Rationale
687///
688/// This trait serves several important purposes:
689///
690/// 1. **Single Source of Truth**: Defines core requirements in one place, reducing duplication
691/// 2. **Maintainability**: Changes to fundamental requirements only need to be made once
692/// 3. **Readability**: Simplifies trait bounds in [`FpScalar`] and other high-level traits
693/// 4. **Consistency**: Ensures all scalar types share the same baseline capabilities
694///
695/// ## Usage in Type Bounds
696///
697/// [`ScalarCore`] is primarily used as a super-trait bound in [`FpScalar`]:
698///
699/// ```rust
700/// # use num_valid::ScalarCore;
701/// // Instead of listing all traits individually:
702/// // pub trait FpScalar: Sized + Clone + Debug + Display + PartialEq + Send + Sync + ...
703///
704/// // We use the core trait:
705/// pub trait FpScalar: ScalarCore + /* other mathematical traits */ {
706///     // ...
707/// }
708/// ```
709///
710/// ## Thread Safety
711///
712/// The inclusion of [`Send`] and [`Sync`] makes all scalar types safe for concurrent use:
713/// - **[`Send`]**: Scalars can be moved between threads
714/// - **[`Sync`]**: Scalars can be shared via `&T` between threads
715///
716/// This enables parallel numerical computations without additional synchronization overhead.
717///
718/// ## Serialization Support
719///
720/// All scalar types support serialization through [`serde`]:
721///
722/// ```rust,ignore
723/// use num_valid::RealNative64StrictFinite;
724/// use num_valid::TryNew;
725/// use serde_json;
726///
727/// let value = RealNative64StrictFinite::try_new(3.14159).unwrap();
728///
729/// // Serialize to JSON
730/// let json = serde_json::to_string(&value).unwrap();
731/// assert_eq!(json, "3.14159");
732///
733/// // Deserialize from JSON
734/// let deserialized: RealNative64StrictFinite = serde_json::from_str(&json).unwrap();
735/// assert_eq!(value, deserialized);
736/// ```
737///
738/// ## Relationship to Other Traits
739///
740/// - **[`FpScalar`]**: Extends [`ScalarCore`] with mathematical operations and floating-point checks
741/// - **[`RealScalar`]**: Further specializes [`FpScalar`] for real numbers
742/// - **[`ComplexScalar`]**: Further specializes [`FpScalar`] for complex numbers
743///
744/// ## Implementation Note
745///
746/// Implementors define the raw scalar representation through [`ScalarCore::RawScalarType`]
747/// and provide borrowed and owned access to it through [`ScalarCore::as_raw_scalar_ref`] and
748/// [`ScalarCore::into_raw_scalar`].
749///
750/// Some wrapper types (e.g. in [`scalars`]) additionally derive `AsRef`/`IntoInner`.
751/// Those only peel off one layer of wrapping and return the *next* inner type (which may itself
752/// still be a validated scalar), whereas `as_raw_scalar_ref`/`into_raw_scalar` always unwrap all the
753/// way down to the underlying [`ScalarCore::RawScalarType`] (e.g. `f64`), regardless
754/// of how many layers of wrapping separate the two.
755///
756/// ## See Also
757///
758/// - [`FpScalar`]: The main scalar trait that uses [`ScalarCore`] as a foundation
759/// - [`RealScalar`]: Specialized trait for real number types
760/// - [`ComplexScalar`]: Specialized trait for complex number types
761pub trait ScalarCore:
762    Sized
763    + Clone
764    + Debug
765    + Display
766    + PartialEq
767    + Send
768    + Sync
769    + Serialize
770    + for<'a> Deserialize<'a>
771    + 'static
772{
773    /// The type of the inner value that will be extracted.
774    type RawScalarType: RawScalarTrait;
775
776    /// Returns a reference to the inner value.
777    fn as_raw_scalar_ref(&self) -> &Self::RawScalarType;
778
779    /// Consumes the scalar and returns its inner raw scalar value.
780    ///
781    /// # Example
782    ///
783    /// ```rust,ignore
784    /// let value: T = ...;
785    /// let raw: T::RawScalarType = value.into_raw_scalar();
786    /// ```
787    fn into_raw_scalar(self) -> Self::RawScalarType;
788
789    /// Compares this scalar with a value in its underlying raw representation.
790    ///
791    /// ```
792    /// use num_valid::{RealNative64StrictFinite, ScalarCore};
793    /// use num_valid::TryNew;
794    ///
795    /// let value = RealNative64StrictFinite::try_new(3.5).unwrap();
796    /// assert!(value.eq_raw(&3.5));
797    /// ```
798    #[inline(always)]
799    fn eq_raw(&self, other: &Self::RawScalarType) -> bool {
800        self.as_raw_scalar_ref().eq(other)
801    }
802}
803
804#[duplicate_item(
805    T;
806    [f32];
807    [f64];
808)]
809impl ScalarCore for T {
810    type RawScalarType = Self;
811
812    fn as_raw_scalar_ref(&self) -> &Self::RawScalarType {
813        self
814    }
815
816    fn into_raw_scalar(self) -> Self::RawScalarType {
817        self
818    }
819}
820
821impl<T: NativeReal> ScalarCore for Complex<T> {
822    type RawScalarType = Self;
823
824    fn as_raw_scalar_ref(&self) -> &Self::RawScalarType {
825        self
826    }
827
828    fn into_raw_scalar(self) -> Self::RawScalarType {
829        self
830    }
831}
832//------------------------------------------------------------------------------------------------
833
834//------------------------------------------------------------------------------------------------
835/// A trait alias for scalar types that can be raised to the power of any primitive integer.
836///
837/// This alias requires [`ScalarCore`], so the raw type used by every [`Pow`] error is
838/// [`ScalarCore::RawScalarType`]. It also requires a [`Pow`] implementation for each
839/// signed and unsigned primitive integer exponent.
840pub trait PowIntExponent = ScalarCore
841    + Pow<i8, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, i8>>
842    + Pow<u8, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, u8>>
843    + Pow<i16, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, i16>>
844    + Pow<u16, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, u16>>
845    + Pow<i32, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, i32>>
846    + Pow<u32, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, u32>>
847    + Pow<i64, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, i64>>
848    + Pow<u64, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, u64>>
849    + Pow<i128, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, i128>>
850    + Pow<u128, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, u128>>
851    + Pow<isize, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, isize>>
852    + Pow<usize, Error = PowIntExponentErrors<<Self as ScalarCore>::RawScalarType, usize>>;
853//------------------------------------------------------------------------------------------------
854
855//------------------------------------------------------------------------------------------------
856/// # Core trait for a floating-point scalar number (real or complex)
857///
858/// [`FpScalar`] is a fundamental trait in [`num-valid`](crate) that provides a common interface
859/// for all floating-point scalar types, whether they are real or complex, and regardless
860/// of their underlying numerical kernel (e.g., native [`f64`] or arbitrary-precision [`rug`](https://docs.rs/rug/latest/rug/index.html) types).
861///
862/// This trait serves as a primary bound for generic functions and structures that need to
863/// operate on scalar values capable of floating-point arithmetic. It aggregates a large
864/// number of mathematical function traits (e.g., [`functions::Sin`], [`functions::Cos`], [`functions::Exp`], [`functions::Sqrt`]) and
865/// core properties.
866///
867/// ## Key Responsibilities and Associated Types:
868///
869/// - **Scalar Kind (`FpScalar::Kind`):**
870///   This associated type specifies the fundamental nature of the scalar, which can be
871///   either `scalar_kind::Real` or `scalar_kind::Complex`. It is bound by the private,
872///   sealed trait `scalar_kind::Sealed`. This design enforces **mutual exclusion**:
873///   since a type can only implement [`FpScalar`] once, it can only have one `Kind`,
874///   making it impossible for a type to be both a `RealScalar` and a `ComplexScalar` simultaneously.
875///
876/// - **Real Type Component ([`FpScalar::RealType`]):**
877///   Specifies the real number type corresponding to this scalar via [`RealType`](FpScalar::RealType).
878///   - For real scalars (e.g., [`f64`], [`RealNative64StrictFinite`], [`RealNative64StrictFiniteInDebug`],
879///     `RealRugStrictFinite`, etc.), [`FpScalar::RealType`] is `Self`.
880///   - For complex scalars (e.g., [`Complex<f64>`](num::Complex), [`ComplexNative64StrictFinite`], [`ComplexNative64StrictFiniteInDebug`],
881///     `ComplexRugStrictFinite`, etc.), [`FpScalar::RealType`] is their underlying real component type
882///     (e.g., [`f64`], [`RealNative64StrictFinite`], [`RealNative64StrictFiniteInDebug`], `RealRugStrictFinite`, etc.).
883///  
884///   Crucially, this [`FpScalar::RealType`] is constrained to implement [`RealScalar`], ensuring consistency.
885///
886/// - **Core Floating-Point Properties:**
887///   [`FpScalar`] requires implementations of the trait [`FpChecks`], which provides fundamental floating-point checks:
888///   - [`is_finite()`](FpChecks::is_finite): Checks if the number is finite.
889///   - [`is_infinite()`](FpChecks::is_infinite): Checks if the number is positive or negative infinity.
890///   - [`is_nan()`](FpChecks::is_nan): Checks if the number is "Not a Number".
891///   - [`is_normal()`](FpChecks::is_normal): Checks if the number is a normal (not zero, subnormal, infinite, or NaN).
892///
893/// ## Trait Bounds:
894///
895/// [`FpScalar`] itself has several important trait bounds:
896/// - `Sized + Clone + Debug + Display + PartialEq`: Standard utility traits. Note that scalar
897///   types are [`Clone`] but not necessarily [`Copy`].
898/// - [`Zero`] + [`One`]: From `num_traits`, ensuring the type has additive and multiplicative identities.
899/// - [`Neg<Output = Self>`](Neg): Ensures the type can be negated.
900/// - [`Arithmetic`]: A custom aggregate trait in [`num-valid`](crate) that bundles standard
901///   arithmetic operator traits (like [`Add`](std::ops::Add), [`Sub`](std::ops::Sub), [`Mul`], [`Div`](std::ops::Div)).
902/// - `Send + Sync + 'static`: Makes the scalar types suitable for use in concurrent contexts.
903/// - A comprehensive suite of mathematical function traits like [`functions::Sin`], [`functions::Cos`], [`functions::Exp`], [`functions::Ln`], [`functions::Sqrt`], etc.
904///
905/// ## Relationship to Other Traits:
906///
907/// - [`RealScalar`]: A sub-trait of [`FpScalar`] for real numbers, defined by the constraint `FpScalar<Kind = scalar_kind::Real>`.
908/// - [`ComplexScalar`]: A sub-trait of [`FpScalar`] for complex numbers, defined by the constraint `FpScalar<Kind = scalar_kind::Complex>`.
909/// - [`NumKernel`]: Policies like [`Native64StrictFinite`]
910///   are used to validate the raw values that are wrapped inside types implementing `FpScalar`.
911///
912/// ## Example: Generic Function
913///
914/// Here is how you can write a generic function that works with any scalar type
915/// implementing `FpScalar`.
916///
917/// ```rust
918/// use num_valid::{*, functions::{MulAddRef, Sqrt}};
919/// use num::Zero;
920/// use num_valid::TryNew;
921///
922/// // This function works with any FpScalar type.
923/// fn norm_and_sqrt<T: FpScalar>(a: T, b: T) -> T {
924///     let val = a.clone().mul_add_ref(&a, &(b.clone() * b)); // a*a + b*b
925///     val.sqrt()
926/// }
927///
928/// // Also this function works with any FpScalar type.
929/// fn multiply_if_not_zero<T: FpScalar>(a: T, b: T) -> T {
930///     if !a.is_zero() && !b.is_zero() {
931///         a * b
932///     } else {
933///         T::zero()
934///     }
935/// }
936///
937/// // Example usage
938/// let a = RealNative64StrictFinite::try_new(3.0).unwrap();
939/// let b = RealNative64StrictFinite::try_new(4.0).unwrap();
940/// let result = norm_and_sqrt(a, b);
941/// assert_eq!(result.into_raw_scalar(), 5.0);
942/// ```
943pub trait FpScalar:
944    PowIntExponent
945    + Zero
946    + One
947    + IntoInner<InnerType = Self::RawScalarType>
948    + Arithmetic
949    + Abs<Output = NonNegativeRealScalar<Self::RealType>>
950    + Sqrt
951    + TrigonometricFunctions
952    + HyperbolicFunctions
953    + LogarithmFunctions
954    + Exp
955    + FpChecks
956    + Neg<Output = Self>
957    + MulAddRef
958    + Reciprocal
959    + NeumaierAddable
960{
961    /// The kind of scalar this is, e.g., `Real` or `Complex`.
962    /// This is a sealed trait to prevent external implementations.
963    type Kind: scalar_kind::Sealed;
964
965    /// The real number type corresponding to this scalar.
966    ///
967    /// - For real scalars (e.g., `f64`), `RealType` is `Self`.
968    /// - For complex scalars (e.g., `Complex<f64>`), `RealType` is their underlying
969    ///   real component type (e.g., `f64`).
970    ///
971    /// This `RealType` is guaranteed to implement [`RealScalar`] and belong to the
972    /// same numerical kernel as `Self`.
973    type RealType: RealScalar<RealType = Self::RealType>;
974}
975//-------------------------------------------------------------------------------------------------------------
976
977//-------------------------------------------------------------------------------------------------------------
978
979/// Provides fundamental mathematical constants for floating-point scalar types.
980///
981/// This trait defines methods to obtain commonly used mathematical constants
982/// in the appropriate precision and type for the implementing scalar type.
983/// All constants are guaranteed to be finite and valid according to the
984/// scalar's validation policy.
985///
986/// ## Design Principles
987///
988/// - **Type-Appropriate Precision**: Constants are provided at the precision
989///   of the implementing type (e.g., `f64` precision for native types,
990///   arbitrary precision for `rug` types).
991/// - **Validation Compliance**: All returned constants are guaranteed to pass
992///   the validation policy of the implementing type.
993/// - **Mathematical Accuracy**: Constants use the most accurate representation
994///   available for the underlying numerical type.
995///
996/// ## Usage Examples
997///
998/// ```rust
999/// use num_valid::{RealNative64StrictFinite, Constants, functions::Exp};
1000/// use num_valid::TryNew;
1001///
1002/// // Get mathematical constants
1003/// let pi = RealNative64StrictFinite::pi();
1004/// let e = RealNative64StrictFinite::e();
1005/// let eps = RealNative64StrictFinite::epsilon();
1006///
1007/// // Use in calculations
1008/// let circle_area = pi.clone() * &(pi * RealNative64StrictFinite::two());
1009/// let exp_1 = e.exp(); // e^e
1010/// ```
1011///
1012/// ## Backend-Specific Behavior
1013///
1014/// ### Native `f64` Backend
1015/// - Uses standard library constants like `std::f64::consts::PI`
1016/// - IEEE 754 double precision (53-bit significand)
1017/// - Hardware-optimized representations
1018///
1019/// ### Arbitrary-Precision (`rug`) Backend
1020/// - Constants computed at compile-time specified precision
1021/// - Exact representations within precision limits
1022/// - May use higher-precision intermediate calculations
1023pub trait Constants: Sized {
1024    /// [Machine epsilon] value for `Self`.
1025    ///
1026    /// This is the difference between `1.0` and the next larger representable number.
1027    /// It represents the relative precision of the floating-point format.
1028    ///
1029    /// ## Examples
1030    ///
1031    /// ```rust
1032    /// use num_valid::{RealNative64StrictFinite, Constants};
1033    ///
1034    /// let eps = RealNative64StrictFinite::epsilon();
1035    /// // For f64, this is approximately 2.220446049250313e-16
1036    /// ```
1037    ///
1038    /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
1039    fn epsilon() -> Self;
1040
1041    /// Build and return the (floating point) value -1. represented by the proper type.
1042    fn negative_one() -> Self;
1043
1044    /// Build and return the (floating point) value 0.5 represented by the proper type.
1045    fn one_div_2() -> Self;
1046
1047    /// Build and return the (floating point) value `π` represented by the proper type.
1048    fn pi() -> Self;
1049
1050    /// Build and return the (floating point) value `2 π` represented by the proper type.
1051    fn two_pi() -> Self;
1052
1053    /// Build and return the (floating point) value `π/2` represented by the proper type.
1054    fn pi_div_2() -> Self;
1055
1056    /// Build and return the (floating point) value 2. represented by the proper type.
1057    fn two() -> Self;
1058
1059    /// Build and return the maximum finite value allowed by the current floating point representation.
1060    fn max_finite() -> Self;
1061
1062    /// Build and return the minimum finite (i.e., the most negative) value allowed by the current floating point representation.
1063    fn min_finite() -> Self;
1064
1065    /// Build and return the natural logarithm of 2, i.e. the (floating point) value `ln(2)`, represented by the proper type.
1066    fn ln_2() -> Self;
1067
1068    /// Build and return the natural logarithm of 10, i.e. the (floating point) value `ln(10)`, represented by the proper type.
1069    fn ln_10() -> Self;
1070
1071    /// Build and return the base-10 logarithm of 2, i.e. the (floating point) value `Log_10(2)`, represented by the proper type.
1072    fn log10_2() -> Self;
1073
1074    /// Build and return the base-2 logarithm of 10, i.e. the (floating point) value `Log_2(10)`, represented by the proper type.
1075    fn log2_10() -> Self;
1076
1077    /// Build and return the base-2 logarithm of `e`, i.e. the (floating point) value `Log_2(e)`, represented by the proper type.
1078    fn log2_e() -> Self;
1079
1080    /// Build and return the base-10 logarithm of `e`, i.e. the (floating point) value `Log_10(e)`, represented by the proper type.
1081    fn log10_e() -> Self;
1082
1083    /// Build and return the (floating point) value `e` represented by the proper type.
1084    fn e() -> Self;
1085}
1086
1087/// # Trait for scalar real numbers
1088///
1089/// [`RealScalar`] extends the fundamental [`FpScalar`] trait, providing an interface
1090/// specifically for real (non-complex) floating-point numbers. It introduces
1091/// operations and properties that are unique to real numbers, such as ordering,
1092/// rounding, and clamping.
1093///
1094/// This trait is implemented by real scalar types within each numerical kernel,
1095/// for example, [`f64`] for the native kernel,
1096/// and `RealRugStrictFinite` for the `rug` kernel (when the `rug` feature is enabled).
1097///
1098/// ## Key Design Principles
1099///
1100/// - **Inheritance from [`FpScalar`]:** As a sub-trait of [`FpScalar`], any `RealScalar`
1101///   type automatically gains all the capabilities of a general floating-point number,
1102///   including basic arithmetic and standard mathematical functions (e.g., `sin`, `exp`, `sqrt`).
1103/// - **Raw Underlying Type ([`RawReal`](Self::RawReal)):**
1104///   This associated type specifies the most fundamental, "raw" representation of the real number,
1105///   which implements the [`RawRealTrait`]. This is the type used for low-level, unchecked
1106///   operations within the library's internal implementation.
1107///   - For [`f64`], [`RealNative64StrictFinite`] and [`RealNative64StrictFiniteInDebug`], `RawReal` is [`f64`].
1108///   - For `RealRugStrictFinite<P>`, `RawReal` is [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
1109/// - **Reference-Based Operations**: Many operations take arguments by reference (`&Self`)
1110///   to avoid unnecessary clones of potentially expensive arbitrary-precision numbers.
1111/// - **Fallible Constructors**: [`try_from_f64()`](Self::try_from_f64) validates inputs
1112///   and ensures exact representability for arbitrary-precision types.
1113///
1114/// ## Creating Validated Real Numbers
1115///
1116/// There are multiple ways to create validated real scalar instances, depending on your
1117/// source data and use case:
1118///
1119/// ### 1. From f64 Values (Most Common)
1120///
1121/// Use [`try_from_f64()`](Self::try_from_f64) for fallible conversion with error handling,
1122/// or [`from_f64()`](Self::from_f64) for infallible conversion that panics on invalid input:
1123///
1124/// ```rust
1125/// use num_valid::*;
1126///
1127/// // Fallible conversion (recommended for runtime values)
1128/// let x = RealNative64StrictFinite::try_from_f64(3.14)?;
1129/// assert_eq!(x.as_raw_scalar_ref(), &3.14);
1130///
1131/// // Panicking conversion (safe for known-valid constants)
1132/// let pi = RealNative64StrictFinite::from_f64(std::f64::consts::PI);
1133/// let e = RealNative64StrictFinite::from_f64(std::f64::consts::E);
1134///
1135/// // For convenience with literals, consider using the real!() macro:
1136/// use num_valid::real;
1137/// let quick = real!(3.14);  // Equivalent to from_f64(3.14)
1138///
1139/// // Error handling for invalid values
1140/// let invalid = RealNative64StrictFinite::try_from_f64(f64::NAN);
1141/// assert!(invalid.is_err()); // NaN is rejected
1142/// # Ok::<(), Box<dyn std::error::Error>>(())
1143/// ```
1144///
1145/// ### 2. From Raw Values (Advanced)
1146///
1147/// Use [`try_new()`](try_create::TryNew::try_new) when working with the raw underlying type directly:
1148///
1149/// ```rust
1150/// use num_valid::RealNative64StrictFinite;
1151/// use num_valid::TryNew;
1152///
1153/// // For native f64 types
1154/// let x = RealNative64StrictFinite::try_new(42.0)?;
1155///
1156/// // For arbitrary-precision types (with rug feature)
1157/// # #[cfg(feature = "rug")] {
1158/// use num_valid::RealRugStrictFinite;
1159/// let high_precision = RealRugStrictFinite::<200>::try_new(
1160///     rug::Float::with_val(200, 1.5)
1161/// )?;
1162/// # }
1163/// # Ok::<(), Box<dyn std::error::Error>>(())
1164/// ```
1165///
1166/// ### 3. Using Constants
1167///
1168/// Leverage the [`Constants`] trait for mathematical constants:
1169///
1170/// ```rust
1171/// use num_valid::{RealNative64StrictFinite, Constants};
1172///
1173/// let pi = RealNative64StrictFinite::pi();
1174/// let e = RealNative64StrictFinite::e();
1175/// let two = RealNative64StrictFinite::two();
1176/// let epsilon = RealNative64StrictFinite::epsilon();
1177/// ```
1178///
1179/// ### 4. From Arithmetic Operations
1180///
1181/// Create values through validated arithmetic on existing validated numbers:
1182///
1183/// ```rust
1184/// use num_valid::RealNative64StrictFinite;
1185/// use num_valid::TryNew;
1186///
1187/// let a = RealNative64StrictFinite::try_new(2.0)?;
1188/// let b = RealNative64StrictFinite::try_new(3.0)?;
1189///
1190/// let sum = a.clone() + b.clone(); // Automatically validated
1191/// let product = &a * &b;           // Also works with references
1192/// # Ok::<(), Box<dyn std::error::Error>>(())
1193/// ```
1194///
1195/// ### 5. Using Zero and One Traits
1196///
1197/// For generic code, use [`num::Zero`] and [`num::One`]:
1198///
1199/// ```rust
1200/// use num_valid::*;
1201/// use num::{Zero, One};
1202///
1203/// let zero = RealNative64StrictFinite::zero();
1204/// let one = RealNative64StrictFinite::one();
1205/// assert_eq!(zero.as_raw_scalar_ref(), &0.0);
1206/// assert_eq!(one.as_raw_scalar_ref(), &1.0);
1207/// ```
1208///
1209/// ### Choosing the Right Method
1210///
1211/// | Method | Use When | Panics? | Example |
1212/// |--------|----------|---------|---------|
1213/// | `from_f64()` | Value is guaranteed valid (constants) | Yes | `from_f64(PI)` |
1214/// | `try_from_f64()` | Value might be invalid (user input) | No | `try_from_f64(x)?` |
1215/// | `try_new()` | Working with raw backend types | No | `try_new(raw_val)?` |
1216/// | Constants trait | Need mathematical constants | No | `pi()`, `e()` |
1217/// | Arithmetic | Deriving from other validated values | No | `a + b` |
1218///
1219/// ## Type Safety with Validated Types
1220///
1221/// Real scalars that use validation policies implementing finite value guarantees
1222/// automatically gain:
1223/// - **Full Equality ([`Eq`])**: Well-defined, symmetric equality comparisons
1224/// - **Hashing ([`Hash`])**: Use as keys in [`HashMap`](std::collections::HashMap) and [`HashSet`](std::collections::HashSet)
1225/// - **Total Ordering ([`Ord`])**: Available when the validation policy guarantees finite
1226///   values, enabling ordered collections and standard sorting.
1227/// - **Reference-Based Selection**: [`functions::Max`] and [`functions::Min`] remain
1228///   available for generic code that does not require `Ord`.
1229///
1230/// ## Mathematical Operations
1231///
1232/// ### Core Arithmetic
1233/// All standard arithmetic operations are available through the [`Arithmetic`] trait,
1234/// supporting both value and reference semantics:
1235/// ```rust
1236/// use num_valid::RealNative64StrictFinite;
1237/// use num_valid::TryNew;
1238///
1239/// let a = RealNative64StrictFinite::try_new(2.0).unwrap();
1240/// let b = RealNative64StrictFinite::try_new(3.0).unwrap();
1241///
1242/// // All combinations supported: T op T, T op &T, &T op T, &T op &T
1243/// let sum1 = a.clone() + b.clone();
1244/// let sum2 = &a + &b;
1245/// let sum3 = a.clone() + &b;
1246/// let sum4 = &a + b.clone();
1247///
1248/// assert_eq!(sum1, sum2);
1249/// assert_eq!(sum2, sum3);
1250/// assert_eq!(sum3, sum4);
1251/// ```
1252///
1253/// ### Advanced Functions
1254///
1255/// In addition to the functions from [`FpScalar`], `RealScalar` provides a suite of methods common in real number arithmetic.
1256/// Methods prefixed with `kernel_` provide direct access to underlying mathematical operations with minimal overhead:
1257///
1258/// - **Rounding ([`Rounding`]):**
1259///   [`kernel_ceil()`](Rounding::kernel_ceil), [`kernel_floor()`](Rounding::kernel_floor),
1260///   [`kernel_round()`](Rounding::kernel_round), [`kernel_round_ties_even()`](Rounding::kernel_round_ties_even),
1261///   [`kernel_trunc()`](Rounding::kernel_trunc), and [`kernel_fract()`](Rounding::kernel_fract).
1262///
1263/// - **Sign Manipulation ([`Sign`]):**
1264///   [`kernel_copysign()`](Sign::kernel_copysign), [`kernel_signum()`](Sign::kernel_signum),
1265///   [`kernel_is_sign_positive()`](Sign::kernel_is_sign_positive), and [`kernel_is_sign_negative()`](Sign::kernel_is_sign_negative).
1266///
1267/// - **Comparison and Ordering:**
1268///   - From [`functions::Max`]/[`functions::Min`]: [`max_by_ref()`](functions::Max::max_by_ref) and [`min_by_ref()`](functions::Min::min_by_ref).
1269///   - From [`TotalCmp`]: [`total_cmp()`](TotalCmp::total_cmp) for a total ordering compliant with IEEE 754.
1270///   - From [`Clamp`]: [`clamp_ref()`](Clamp::clamp_ref).
1271///
1272/// - **Specialized Functions:**
1273///   - From [`ATan2`]: [`atan2()`](ATan2::atan2).
1274///   - From [`ExpM1`]/[`Ln1p`]: [`exp_m1()`](ExpM1::exp_m1) and [`ln_1p()`](Ln1p::ln_1p).
1275///   - From [`Hypot`]: [`hypot()`](Hypot::hypot) for computing sqrt(a² + b²).
1276///   - From [`Classify`]: [`classify()`](Classify::classify).
1277///
1278/// - **Fused Multiply-Add Variants:**
1279///   [`kernel_mul_add_mul_mut()`](Self::kernel_mul_add_mul_mut) and
1280///   [`kernel_mul_sub_mul_mut()`](Self::kernel_mul_sub_mul_mut).
1281///
1282/// ### Constants and Utilities
1283///
1284/// ```rust
1285/// use num_valid::{RealNative64StrictFinite, Constants};
1286///
1287/// let pi = RealNative64StrictFinite::pi();
1288/// let e = RealNative64StrictFinite::e();
1289/// let eps = RealNative64StrictFinite::epsilon();
1290/// let max_val = RealNative64StrictFinite::max_finite();
1291/// ```
1292///
1293/// ## Naming Convention for `kernel_*` Methods
1294///
1295/// Methods prefixed with `kernel_` (e.g., `kernel_ceil`, `kernel_copysign`) are
1296/// part of the low-level kernel interface. They typically delegate directly to the
1297/// most efficient implementation for the underlying type (like `f64::ceil`) without
1298/// adding extra validation layers. They are intended to be fast primitives upon which
1299/// safer, higher-level abstractions can be built.
1300///
1301/// ## Critical Trait Bounds
1302///
1303/// - `Self: FpScalar<RealType = Self>`: This is the defining constraint. It ensures that the type
1304///   has all basic floating-point capabilities and confirms that its associated real type is itself.
1305/// - `Self: PartialOrd`: Real scalar types must support ordering against values of the same type.
1306///   Generic code should not assume direct comparison against native `f64` constants; use
1307///   raw-typed constants or validated constructors instead.
1308///
1309/// ## Backend-Specific Behavior
1310///
1311/// ### Native `f64` Backend
1312/// - Direct delegation to standard library functions
1313/// - IEEE 754 compliance
1314/// - Maximum performance
1315///
1316/// ### Arbitrary-Precision (`rug`) Backend
1317/// - Configurable precision at compile-time
1318/// - Exact arithmetic within precision limits
1319/// - [`try_from_f64()`](Self::try_from_f64) validates exact representability
1320///
1321/// ## Error Handling
1322///
1323/// Operations that can fail provide both panicking and non-panicking variants:
1324/// ```rust
1325/// use num_valid::{*, functions::Sqrt};
1326/// use num_valid::TryNew;
1327///
1328/// let positive = RealNative64StrictFinite::try_new(4.0).unwrap();
1329/// let negative = RealNative64StrictFinite::try_new(-4.0).unwrap();
1330///
1331/// // Panicking version (use when input validity is guaranteed)
1332/// let sqrt_pos = positive.sqrt();
1333/// assert_eq!(sqrt_pos.as_raw_scalar_ref(), &2.0);
1334///
1335/// // Non-panicking version (use for potentially invalid inputs)
1336/// let sqrt_neg_result = negative.try_sqrt();
1337/// assert!(sqrt_neg_result.is_err());
1338/// ```
1339pub trait RealScalar:
1340    FpScalar<RealType = Self, InnerType = Self::RawReal, RawScalarType = Self::RawReal>
1341    + Sign
1342    + Rounding
1343    + Constants
1344    + PartialOrd
1345    + Max
1346    + Min
1347    + ATan2
1348    + for<'a> Pow<&'a Self, Error = PowRealBaseRealExponentErrors<Self::RawReal>>
1349    + Clamp
1350    + Classify
1351    + ExpM1
1352    + Hypot
1353    + Ln1p
1354    + TotalCmp
1355{
1356    /// The most fundamental, "raw" representation of this real number.
1357    ///
1358    /// This type provides the foundation for all mathematical operations and
1359    /// is used to parameterize error types for this scalar.
1360    ///
1361    /// # Examples
1362    /// - For [`f64`]: `RawReal = f64`
1363    /// - For [`RealNative64StrictFinite`]: `RawReal = f64`
1364    /// - For `RealRugStrictFinite<P>`: `RawReal = rug::Float`
1365    type RawReal: RawRealTrait;
1366
1367    /// Constructs `Self` directly from its own raw representation, without any raw-to-raw conversion.
1368    ///
1369    /// Unlike [`try_convert_and_new_raw`](Self::try_convert_and_new_raw), this method never converts
1370    /// between different `RawReal` types; it only performs the construction/validation step
1371    /// specific to `Self` (e.g., a kernel's validation policy).
1372    fn try_new_raw(value: Self::RawReal) -> Result<Self, ErrorsValidationRawReal<Self::RawReal>>;
1373
1374    /// The target precision (in bits) used when converting a foreign `RawReal` into
1375    /// `Self::RawReal` in [`try_convert_and_new_raw`](Self::try_convert_and_new_raw).
1376    ///
1377    /// For fixed-precision types (`f32`, `f64`), this is the type's mantissa width.
1378    /// For arbitrary-precision types (e.g., `rug`-based kernels), this is the kernel's
1379    /// configured precision.
1380    fn target_precision() -> u32;
1381
1382    /// Multiplies two products and adds them in one fused operation, rounding to the nearest with only one rounding error.
1383    /// `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.
1384    fn kernel_mul_add_mul_mut(&mut self, mul: &Self, add_mul1: &Self, add_mul2: &Self);
1385
1386    /// Multiplies two products and subtracts them in one fused operation, rounding to the nearest with only one rounding error.
1387    /// `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.
1388    fn kernel_mul_sub_mul_mut(&mut self, mul: &Self, sub_mul1: &Self, sub_mul2: &Self);
1389
1390    /// Tries to create an instance of `Self` from a [`f64`].
1391    ///
1392    /// This conversion is fallible and validates the input `value`. For `rug`-based types,
1393    /// it also ensures that the `f64` can be represented exactly at the target precision.
1394    ///
1395    /// # Errors
1396    /// Returns [`RawRealConversionError`] if the `value` is not finite or cannot be
1397    /// represented exactly by `Self`.
1398    ///
1399    /// # Examples
1400    ///
1401    /// ## Quick Creation (Using Macros - Recommended)
1402    /// ```
1403    /// use num_valid::real;
1404    ///
1405    /// let x = real!(3.14);  // Concise, panics on invalid input
1406    /// let pi = real!(std::f64::consts::PI);
1407    /// ```
1408    ///
1409    /// ## Explicit Creation (Error Handling)
1410    /// ```
1411    /// use num_valid::*;
1412    ///
1413    /// // Fallible - returns Result
1414    /// let x = RealNative64StrictFinite::try_from_f64(3.14)?;
1415    /// assert_eq!(x.as_raw_scalar_ref(), &3.14);
1416    ///
1417    /// // Invalid value (NaN)
1418    /// assert!(RealNative64StrictFinite::try_from_f64(f64::NAN).is_err());
1419    /// # Ok::<(), Box<dyn std::error::Error>>(())
1420    /// ```
1421    ///
1422    /// See also: [`real!`] macro for the most ergonomic way to create validated real numbers.
1423    #[must_use = "this `Result` may contain an error that should be handled"]
1424    #[inline(always)]
1425    fn try_from_f64(value: f64) -> Result<Self, RawRealConversionError<f64, Self::RawReal>>
1426    where
1427        Self::RawReal: TryConvertFromRawReal<f64>,
1428    {
1429        Self::try_convert_and_new_raw(value)
1430    }
1431
1432    /// Tries to create an instance of `Self` from a [`f32`].
1433    ///
1434    /// Equivalent to [`try_from_f64`](Self::try_from_f64), but for [`f32`] inputs. For
1435    /// arbitrary-precision types, it also ensures that the `f32` can be represented exactly
1436    /// at the target precision.
1437    ///
1438    /// # Errors
1439    /// Returns [`RawRealConversionError`] if the `value` is not finite or cannot be
1440    /// represented exactly by `Self`.
1441    ///
1442    /// # Examples
1443    ///
1444    /// ```
1445    /// use num_valid::*;
1446    ///
1447    /// let x = RealNative64StrictFinite::try_from_f32(3.14_f32)?;
1448    /// assert!(RealNative64StrictFinite::try_from_f32(f32::NAN).is_err());
1449    /// # Ok::<(), Box<dyn std::error::Error>>(())
1450    /// ```
1451    #[must_use = "this `Result` may contain an error that should be handled"]
1452    #[inline(always)]
1453    fn try_from_f32(value: f32) -> Result<Self, RawRealConversionError<f32, Self::RawReal>>
1454    where
1455        Self::RawReal: TryConvertFromRawReal<f32>,
1456    {
1457        Self::try_convert_and_new_raw(value)
1458    }
1459
1460    /// Tries to create an instance of `Self` from another raw real type, converting it first.
1461    ///
1462    /// Converts `value` into `Self::RawReal` at [`target_precision`](Self::target_precision) (see
1463    /// [`RawRealTrait::try_convert`]), then constructs `Self` from the converted value via
1464    /// [`try_new_raw`](Self::try_new_raw).
1465    #[inline(always)]
1466    fn try_convert_and_new_raw<RawRealIn>(
1467        value: RawRealIn,
1468    ) -> Result<Self, RawRealConversionError<RawRealIn, Self::RawReal>>
1469    where
1470        RawRealIn: RawRealTrait,
1471        Self::RawReal: TryConvertFromRawReal<RawRealIn>,
1472    {
1473        let converted = value.try_convert::<Self::RawReal>(Self::target_precision())?;
1474        Self::try_new_raw(converted)
1475            .map_err(|e| RawRealConversionError::OutputValidation { source: e })
1476    }
1477
1478    /// Creates an instance of `Self` from a [`f64`], panicking if the value is invalid.
1479    ///
1480    /// This is a convenience method for cases where you know the value is valid (e.g., constants).
1481    /// For error handling without panics, use [`try_from_f64`](Self::try_from_f64).
1482    ///
1483    /// # Panics
1484    ///
1485    /// Panics if the input value fails validation (e.g., NaN, infinity, or subnormal for strict policies).
1486    ///
1487    /// # Examples
1488    ///
1489    /// ```
1490    /// use num_valid::*;
1491    ///
1492    /// // Valid constants - cleaner syntax without unwrap()
1493    /// let pi = RealNative64StrictFinite::from_f64(std::f64::consts::PI);
1494    /// let e = RealNative64StrictFinite::from_f64(std::f64::consts::E);
1495    /// let sqrt2 = RealNative64StrictFinite::from_f64(std::f64::consts::SQRT_2);
1496    ///
1497    /// assert_eq!(pi.as_raw_scalar_ref(), &std::f64::consts::PI);
1498    /// ```
1499    ///
1500    /// ```should_panic
1501    /// use num_valid::*;
1502    ///
1503    /// // This will panic because NaN is invalid
1504    /// let invalid = RealNative64StrictFinite::from_f64(f64::NAN);
1505    /// ```
1506    fn from_f64(value: f64) -> Self
1507    where
1508        Self::RawReal: TryConvertFromRawReal<f64>,
1509    {
1510        Self::try_from_f64(value)
1511            .expect("RealScalar::try_from_f64() failed: invalid conversion from f64 value")
1512    }
1513
1514    /// Creates an instance of `Self` from a [`f32`], panicking if the value is invalid.
1515    ///
1516    /// Equivalent to [`from_f64`](Self::from_f64), but for [`f32`] inputs. For error handling
1517    /// without panics, use [`try_from_f32`](Self::try_from_f32).
1518    ///
1519    /// # Panics
1520    ///
1521    /// Panics if the input value fails validation (e.g., NaN, infinity, or subnormal for strict policies).
1522    ///
1523    /// # Examples
1524    ///
1525    /// ```
1526    /// use num_valid::*;
1527    ///
1528    /// let pi = RealNative64StrictFinite::from_f32(std::f32::consts::PI);
1529    /// ```
1530    fn from_f32(value: f32) -> Self
1531    where
1532        Self::RawReal: TryConvertFromRawReal<f32>,
1533    {
1534        Self::try_from_f32(value)
1535            .expect("RealScalar::try_from_f32() failed: invalid conversion from f32 value")
1536    }
1537
1538    /// Safely converts the truncated value to `usize`.
1539    ///
1540    /// Truncates toward zero and validates the result is a valid `usize`.
1541    ///
1542    /// # Returns
1543    ///
1544    /// - `Ok(usize)`: If truncated value is in `0..=usize::MAX`
1545    /// - `Err(_)`: If value is not finite or out of range
1546    ///
1547    /// # Examples
1548    ///
1549    /// ```rust
1550    /// use num_valid::*;
1551    /// use try_create::TryNew;
1552    ///
1553    /// let x = RealNative64StrictFinite::try_new(42.9)?;
1554    /// assert_eq!(x.truncate_to_usize()?, 42);
1555    ///
1556    /// let neg = RealNative64StrictFinite::try_new(-1.0)?;
1557    /// assert!(neg.truncate_to_usize().is_err());
1558    /// # Ok::<(), Box<dyn std::error::Error>>(())
1559    /// ```
1560    ///
1561    /// <details>
1562    /// <summary>Detailed Behavior and Edge Cases</summary>
1563    ///
1564    /// ## Truncation Rules
1565    ///
1566    /// The fractional part is discarded, moving toward zero:
1567    /// - `3.7` → `3`
1568    /// - `-2.9` → `-2`
1569    /// - `0.9` → `0`
1570    ///
1571    /// ## Error Conditions
1572    ///
1573    /// - [`NotFinite`](ErrorsRawRealToInteger::NotFinite): Value is `NaN` or `±∞`
1574    /// - [`OutOfRange`](ErrorsRawRealToInteger::OutOfRange): Value is negative or > `usize::MAX`
1575    ///
1576    /// ## Additional Examples
1577    ///
1578    /// ```rust
1579    /// use num_valid::{RealNative64StrictFinite, RealScalar, core::errors::ErrorsRawRealToInteger};
1580    /// use try_create::TryNew;
1581    ///
1582    /// // Zero
1583    /// let zero = RealNative64StrictFinite::try_new(0.0)?;
1584    /// assert_eq!(zero.truncate_to_usize()?, 0);
1585    ///
1586    /// // Large valid values
1587    /// let large = RealNative64StrictFinite::try_new(1_000_000.7)?;
1588    /// assert_eq!(large.truncate_to_usize()?, 1_000_000);
1589    ///
1590    /// // Values too large for usize
1591    /// let too_large = RealNative64StrictFinite::try_new(1e20)?;
1592    /// assert!(matches!(too_large.truncate_to_usize(), Err(ErrorsRawRealToInteger::OutOfRange { .. })));
1593    /// # Ok::<(), Box<dyn std::error::Error>>(())
1594    /// ```
1595    ///
1596    /// ## Practical Usage
1597    ///
1598    /// ```rust
1599    /// use num_valid::*;
1600    /// use try_create::TryNew;
1601    ///
1602    /// fn create_vector_with_size<T: Default + Clone>(
1603    ///     size_float: RealNative64StrictFinite
1604    /// ) -> Result<Vec<T>, Box<dyn std::error::Error>> {
1605    ///     let size = size_float.truncate_to_usize()?;
1606    ///     Ok(vec![T::default(); size])
1607    /// }
1608    ///
1609    /// let size = RealNative64StrictFinite::try_new(10.7)?;
1610    /// let vec: Vec<i32> = create_vector_with_size(size)?;
1611    /// assert_eq!(vec.len(), 10); // Truncated from 10.7
1612    /// # Ok::<(), Box<dyn std::error::Error>>(())
1613    /// ```
1614    ///
1615    /// ## Comparison with Alternatives
1616    ///
1617    /// | Method | Behavior | Range Check | Fractional |
1618    /// |--------|----------|-------------|------------|
1619    /// | `truncate_to_usize()` | Towards zero | ✓ | Discarded |
1620    /// | `as usize` (raw) | Undefined | ✗ | Undefined |
1621    /// | `round().as usize` | Nearest | ✗ | Rounded |
1622    /// | `floor().as usize` | Towards -∞ | ✗ | Discarded |
1623    /// | `ceil().as usize` | Towards +∞ | ✗ | Discarded |
1624    ///
1625    /// ## Backend-Specific Notes
1626    ///
1627    /// - **Native f64**: Uses `az::CheckedAs` for safe conversion with overflow detection
1628    /// - **Arbitrary-precision (rug)**: Respects current precision, may adjust for very large numbers
1629    ///
1630    /// </details>
1631    fn truncate_to_usize(self) -> Result<usize, ErrorsRawRealToInteger<Self::RawReal, usize>> {
1632        let raw: Self::RawReal = self.into_inner();
1633        raw.truncate_to_usize()
1634    }
1635}
1636
1637/// # Trait for complex scalar numbers
1638///
1639/// [`ComplexScalar`] is a specialized trait for complex number types that extends the
1640/// core [`FpScalar`] functionality with complex-specific operations. It provides a
1641/// unified interface for working with complex numbers across different validation
1642/// policies and underlying representations.
1643///
1644/// ## Design Philosophy
1645///
1646/// This trait bridges the gap between raw complex number operations and the validated
1647/// complex number types in [`num-valid`](crate). It ensures that complex-specific
1648/// operations like conjugation, argument calculation, and real-number scaling are
1649/// available in a type-safe, validated context.
1650///
1651/// ## Core Capabilities
1652///
1653/// The trait provides several key features:
1654///
1655/// - **Component manipulation**: Through [`ComplexScalarMutateParts`], allowing safe
1656///   modification of real and imaginary parts
1657/// - **Conjugation**: Via the [`functions::Conjugate`] trait for computing complex conjugates
1658/// - **Argument calculation**: Through [`functions::Arg`] for computing the phase angle
1659/// - **Real scaling**: Multiplication and assignment with real numbers
1660/// - **Power operations**: Raising complex numbers to real exponents
1661/// - **Convenience methods**: Like [`scale`](Self::scale) and [`scale_mut`](Self::scale_mut)
1662///   for efficient real-number scaling
1663///
1664/// ## Type Relationships
1665///
1666/// Types implementing [`ComplexScalar`] must also implement [`FpScalar`] with
1667/// `Kind = scalar_kind::Complex`, establishing them as complex number types within
1668/// the [`num-valid`](crate) type system.
1669///
1670/// # Quick Start
1671///
1672/// The easiest way to create complex numbers is using the [`complex!`] macro:
1673///
1674/// ```
1675/// use num_valid::complex;
1676///
1677/// let z1 = complex!(1.0, 2.0);   // 1 + 2i
1678/// let z2 = complex!(-3.0, 4.0);  // -3 + 4i
1679/// let i = complex!(0.0, 1.0);    // Imaginary unit
1680/// ```
1681///
1682/// For runtime values or error handling, use explicit construction:
1683///
1684/// ```
1685/// use num_valid::{ComplexNative64StrictFinite, functions::ComplexScalarConstructors};
1686/// use num::Complex;
1687/// use num_valid::TryNew;
1688///
1689/// // From Complex<f64>
1690/// let z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0))?;
1691///
1692/// // From two f64 values
1693/// let z = ComplexNative64StrictFinite::try_new_complex(3.0, 4.0)?;
1694/// # Ok::<(), Box<dyn std::error::Error>>(())
1695/// ```
1696///
1697/// ## Usage Examples
1698///
1699/// ### Basic Complex Operations
1700/// ```rust
1701/// use num_valid::{ComplexNative64StrictFinite, RealNative64StrictFinite, ComplexScalar};
1702/// use num::Complex;
1703/// use num_valid::TryNew;
1704///
1705/// let z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
1706/// let factor = RealNative64StrictFinite::try_new(2.5).unwrap();
1707///
1708/// // Scale by a real number
1709/// let scaled = z.scale(&factor);
1710/// // Result: (7.5, 10.0)
1711/// ```
1712///
1713/// ### In-place Operations
1714/// ```rust
1715/// use num_valid::{ComplexNative64StrictFinite, RealNative64StrictFinite, ComplexScalar};
1716/// use num::Complex;
1717/// use num_valid::TryNew;
1718///
1719/// let mut z = ComplexNative64StrictFinite::try_new(Complex::new(1.0, 2.0)).unwrap();
1720/// let factor = RealNative64StrictFinite::try_new(3.0).unwrap();
1721///
1722/// z.scale_mut(&factor);
1723/// // z is now (3.0, 6.0)
1724/// ```
1725///
1726/// ## See Also
1727///
1728/// - [`FpScalar`]: The base trait for all floating-point scalars
1729/// - [`RealScalar`]: The equivalent trait for real numbers
1730/// - [`ComplexScalarMutateParts`]: For component-wise operations
1731/// - [`functions`]: Module containing mathematical functions for complex numbers
1732/// - [`complex!`]: Macro for the most ergonomic way to create validated complex numbers
1733pub trait ComplexScalar:
1734    ComplexScalarMutateParts
1735    + Conjugate
1736    + Arg<Output = Self::RealType>
1737    + for<'a> Mul<&'a Self::RealType, Output = Self>
1738    + for<'a> MulAssign<&'a Self::RealType>
1739    + for<'a> Pow<&'a Self::RealType, Error = PowComplexBaseRealExponentErrors<Self::RawComplex>>
1740{
1741    /// Scale the complex number `self` by the real coefficient `c`.
1742    ///
1743    /// This is equivalent to complex multiplication by a real number,
1744    /// scaling both the real and imaginary parts by the same factor.
1745    ///
1746    /// ## Examples
1747    ///
1748    /// ```rust
1749    /// use num_valid::{ComplexNative64StrictFinite, RealNative64StrictFinite, ComplexScalar};
1750    /// use num::Complex;
1751    /// use num_valid::TryNew;
1752    ///
1753    /// let z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
1754    /// let factor = RealNative64StrictFinite::try_new(2.0).unwrap();
1755    ///
1756    /// let scaled = z.scale(&factor);
1757    /// // Result: (6.0, 8.0)
1758    /// ```
1759    #[inline(always)]
1760    fn scale(self, c: &Self::RealType) -> Self {
1761        self * c
1762    }
1763
1764    /// Scale (in-place) the complex number `self` by the real coefficient `c`.
1765    ///
1766    /// This modifies the complex number in place, scaling both components
1767    /// by the real factor.
1768    ///
1769    /// ## Examples
1770    ///
1771    /// ```rust
1772    /// use num_valid::{ComplexNative64StrictFinite, RealNative64StrictFinite, ComplexScalar};
1773    /// use num::Complex;
1774    /// use num_valid::TryNew;
1775    ///
1776    /// let mut z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
1777    /// let factor = RealNative64StrictFinite::try_new(2.0).unwrap();
1778    ///
1779    /// z.scale_mut(&factor);
1780    /// // z is now (6.0, 8.0)
1781    /// ```
1782    #[inline(always)]
1783    fn scale_mut(&mut self, c: &Self::RealType) {
1784        *self *= c;
1785    }
1786
1787    /// Consumes the complex number and returns its real and imaginary parts as a tuple.
1788    ///
1789    /// This method moves ownership of the complex number and extracts its two components,
1790    /// returning them as separate real scalar values. This is useful when you need to
1791    /// work with the components independently and no longer need the original complex value.
1792    ///
1793    /// # Returns
1794    ///
1795    /// A tuple `(real, imaginary)` where:
1796    /// - `real` is the real part of the complex number
1797    /// - `imaginary` is the imaginary part of the complex number
1798    ///
1799    /// # Examples
1800    ///
1801    /// ```rust
1802    /// use num_valid::*;
1803    /// use num::Complex;
1804    /// use try_create::TryNew;
1805    ///
1806    /// let z = ComplexNative64StrictFinite::try_new(Complex::new(3.0, 4.0)).unwrap();
1807    ///
1808    /// // Consume z and extract its parts
1809    /// let (real, imag) = z.into_parts();
1810    ///
1811    /// assert_eq!(real.as_raw_scalar_ref(), &3.0);
1812    /// assert_eq!(imag.as_raw_scalar_ref(), &4.0);
1813    /// // z is no longer available here (moved)
1814    /// ```
1815    ///
1816    /// # See Also
1817    ///
1818    /// - [`ComplexScalarGetParts::real_part`]: Get the real part without consuming
1819    /// - [`ComplexScalarGetParts::imag_part`]: Get the imaginary part without consuming
1820    fn into_parts(self) -> (Self::RealType, Self::RealType);
1821}
1822
1823//------------------------------------------------------------------------------------------------------------
1824
1825//------------------------------------------------------------------------------------------------------------
1826pub trait IntegerScalar: PrimInt + FromPrimitive {}
1827
1828impl<I: PrimInt + FromPrimitive> IntegerScalar for I {}
1829
1830//------------------------------------------------------------------------------------------------------------
1831
1832//------------------------------------------------------------------------------------------------------------
1833/// Attempts to convert a vector of raw real values into a vector of the specified real scalar type.
1834///
1835/// This function provides a fallible conversion that validates each input value according
1836/// to the target type's validation policy. If any value fails validation, the entire
1837/// operation fails and returns an error.
1838///
1839/// ## Parameters
1840///
1841/// * `vec`: A vector of raw real values (any type implementing [`RawRealTrait`] and
1842///   convertible into `RealType::RawReal`) to convert
1843///
1844/// ## Return Value
1845///
1846/// * `Ok(Vec<RealType>)`: If all values can be successfully converted and validated
1847/// * `Err(RawRealConversionError)`: If any value fails validation, containing details about the failure
1848///
1849/// ## Usage Examples
1850///
1851/// ### Successful Conversion
1852/// ```rust
1853/// use num_valid::*;
1854///
1855/// let input = vec![1.0, -2.5, 3.14159];
1856/// let result = try_vec_raw_into_vec_real::<RealNative64StrictFinite, _>(input);
1857/// assert!(result.is_ok());
1858///
1859/// let validated_vec = result.unwrap();
1860/// assert_eq!(validated_vec.len(), 3);
1861/// assert_eq!(validated_vec[0].as_raw_scalar_ref(), &1.0);
1862/// ```
1863///
1864/// ### Failed Conversion
1865/// ```rust
1866/// use num_valid::*;
1867///
1868/// let input = vec![1.0, f64::NAN, 3.0]; // Contains NaN
1869/// let result = try_vec_raw_into_vec_real::<RealNative64StrictFinite, _>(input);
1870/// assert!(result.is_err()); // Fails due to NaN value
1871/// ```
1872#[inline(always)]
1873pub fn try_vec_raw_into_vec_real<RealType: RealScalar, RawReal: RawRealTrait>(
1874    vec: Vec<RawReal>,
1875) -> Result<Vec<RealType>, RawRealConversionError<RawReal, RealType::RawReal>>
1876where
1877    RealType::RawReal: TryConvertFromRawReal<RawReal>,
1878{
1879    vec.into_iter()
1880        .map(|v| RealType::try_convert_and_new_raw(v))
1881        .collect()
1882}
1883
1884/// Converts a vector of raw real values into a vector of the specified real scalar type.
1885///
1886/// This is the panicking version of [`try_vec_raw_into_vec_real`]. It converts each
1887/// raw real value to the target real scalar type, panicking if any conversion fails.
1888/// Use this function only when you are certain that all input values are valid for
1889/// the target type.
1890///
1891/// ## Parameters
1892///
1893/// * `vec`: A vector of raw real values (any type implementing [`RawRealTrait`] and
1894///   convertible into `RealType::RawReal`) to convert
1895///
1896/// ## Return Value
1897///
1898/// A vector of validated real scalar values of type `RealType`.
1899///
1900/// ## Panics
1901///
1902/// Panics if any value in the input vector cannot be converted to `RealType`.
1903/// This can happen for various reasons:
1904/// - Input contains `NaN` or infinite values when using strict finite validation
1905/// - Precision loss when converting to arbitrary-precision types
1906/// - Values outside the representable range of the target type
1907///
1908/// ## Usage Examples
1909///
1910/// ### Successful Conversion
1911/// ```rust
1912/// use num_valid::*;
1913///
1914/// let input = vec![0.0, 1.0, -2.5, 3.14159];
1915/// let validated_vec: Vec<RealNative64StrictFinite> = vec_raw_into_vec_real(input);
1916///
1917/// assert_eq!(validated_vec.len(), 4);
1918/// assert_eq!(validated_vec[0].as_raw_scalar_ref(), &0.0);
1919/// assert_eq!(validated_vec[1].as_raw_scalar_ref(), &1.0);
1920/// ```
1921///
1922/// ## When to Use
1923///
1924/// - **Use this function when**: You are certain all input values are valid for the target type
1925/// - **Use [`try_vec_raw_into_vec_real`] when**: Input validation is uncertain and you want to handle errors gracefully
1926#[inline(always)]
1927pub fn vec_raw_into_vec_real<RealType: RealScalar, RawReal: RawRealTrait>(
1928    vec: Vec<RawReal>,
1929) -> Vec<RealType>
1930where
1931    RealType::RawReal: TryConvertFromRawReal<RawReal>,
1932{
1933    try_vec_raw_into_vec_real(vec).expect(
1934        "The conversion from RawReal to RealType failed, which should not happen in a well-defined numerical kernel."
1935    )
1936}
1937//------------------------------------------------------------------------------------------------------------
1938
1939//------------------------------------------------------------------------------------------------------------
1940/// Errors that can occur while constructing a complex random sample.
1941#[derive(Debug, Error)]
1942pub enum RandomSampleComplexErrors<RawReal: TryRandomSampleRawReal> {
1943    /// The sampled real component could not be converted to the target raw real type.
1944    #[error("the sampled real component is invalid")]
1945    Real {
1946        /// The conversion error for the real component.
1947        #[source]
1948        source: RawRealConversionError<RawReal::Sample, RawReal>,
1949    },
1950
1951    /// The sampled imaginary component could not be converted to the target raw real type.
1952    #[error("the sampled imaginary component is invalid")]
1953    Imaginary {
1954        /// The conversion error for the imaginary component.
1955        #[source]
1956        source: RawRealConversionError<RawReal::Sample, RawReal>,
1957    },
1958
1959    /// The constructed complex value failed the target validation policy.
1960    #[error("the constructed complex sample is invalid")]
1961    Output {
1962        /// The validation error for the constructed complex value.
1963        #[source]
1964        source: ErrorsValidationRawComplex<ErrorsValidationRawReal<RawReal>>,
1965    },
1966}
1967
1968/// A fallible conversion from a distribution sample into `Self` at a requested precision.
1969///
1970/// `precision_out` is interpreted by the target type. Fixed-precision targets such as
1971/// `f32` and `f64` require their respective mantissa widths (24 and 53), while
1972/// `rug::Float` uses it as the precision of the constructed value.
1973pub trait TryRandomSampleFrom: Sized {
1974    type Sample: RawRealTrait;
1975
1976    /// The error returned when a sample cannot be converted or validated.
1977    type Error: std::error::Error;
1978
1979    /// Samples a value and converts it to `Self` at `precision_out`.
1980    fn try_sample_from<D, R>(
1981        distribution: &D,
1982        rng: &mut R,
1983        precision_out: u32,
1984    ) -> Result<Self, Self::Error>
1985    where
1986        D: Distribution<Self::Sample>,
1987        R: Rng + ?Sized;
1988}
1989
1990pub trait TryRandomSampleRawReal: RawRealTrait
1991    + TryRandomSampleFrom<Error = RawRealConversionError<<Self as TryRandomSampleFrom>::Sample, Self>>
1992{
1993}
1994
1995impl<T> TryRandomSampleRawReal for T where
1996    T: RawRealTrait
1997        + TryRandomSampleFrom<
1998            Error = RawRealConversionError<<Self as TryRandomSampleFrom>::Sample, Self>,
1999        >
2000{
2001}
2002
2003#[duplicate_item(
2004    T;
2005    [f64];
2006    [f32];
2007)]
2008impl TryRandomSampleFrom for T {
2009    type Sample = T;
2010    type Error = RawRealConversionError<T, T>;
2011
2012    #[inline]
2013    fn try_sample_from<D, R>(
2014        distribution: &D,
2015        rng: &mut R,
2016        precision_out: u32,
2017    ) -> Result<Self, Self::Error>
2018    where
2019        D: Distribution<T>,
2020        R: Rng + ?Sized,
2021    {
2022        T::try_convert_from_raw_real(distribution.sample(rng), precision_out)
2023    }
2024}
2025
2026#[cfg(feature = "rug")]
2027impl TryRandomSampleFrom for rug::Float {
2028    type Sample = f64;
2029    type Error = RawRealConversionError<f64, rug::Float>;
2030
2031    #[inline]
2032    fn try_sample_from<D, R>(
2033        distribution: &D,
2034        rng: &mut R,
2035        precision_out: u32,
2036    ) -> Result<Self, Self::Error>
2037    where
2038        D: Distribution<f64>,
2039        R: Rng + ?Sized,
2040    {
2041        rug::Float::try_convert_from_raw_real(distribution.sample(rng), precision_out)
2042    }
2043}
2044
2045impl<T> TryRandomSampleFrom for Complex<T>
2046where
2047    T: TryRandomSampleRawReal,
2048{
2049    type Sample = T::Sample;
2050    type Error = RandomSampleComplexErrors<T>;
2051
2052    #[inline]
2053    fn try_sample_from<D, R>(
2054        distribution: &D,
2055        rng: &mut R,
2056        precision_out: u32,
2057    ) -> Result<Self, Self::Error>
2058    where
2059        D: Distribution<Self::Sample>,
2060        R: Rng + ?Sized,
2061    {
2062        let real = T::try_sample_from(distribution, rng, precision_out)
2063            .map_err(|source| RandomSampleComplexErrors::Real { source })?;
2064        let imaginary = T::try_sample_from(distribution, rng, precision_out)
2065            .map_err(|source| RandomSampleComplexErrors::Imaginary { source })?;
2066        Ok(Complex::new(real, imaginary))
2067    }
2068}
2069
2070impl<K> TryRandomSampleFrom for RealValidated<K>
2071where
2072    K: NumKernel,
2073    K::RawReal: TryRandomSampleRawReal,
2074{
2075    type Sample = <K::RawReal as TryRandomSampleFrom>::Sample;
2076    type Error = RawRealConversionError<Self::Sample, K::RawReal>;
2077
2078    #[inline]
2079    fn try_sample_from<D, R>(
2080        distribution: &D,
2081        rng: &mut R,
2082        precision_out: u32,
2083    ) -> Result<Self, Self::Error>
2084    where
2085        D: Distribution<Self::Sample>,
2086        R: Rng + ?Sized,
2087    {
2088        let raw = K::RawReal::try_sample_from(distribution, rng, precision_out)?;
2089        Self::try_new_raw(raw).map_err(|source| RawRealConversionError::OutputValidation { source })
2090    }
2091}
2092
2093impl<K> TryRandomSampleFrom for ComplexValidated<K>
2094where
2095    K: NumKernel,
2096    K::RawReal: TryRandomSampleRawReal,
2097{
2098    type Sample = <K::RawReal as TryRandomSampleFrom>::Sample;
2099    type Error = RandomSampleComplexErrors<K::RawReal>;
2100
2101    #[inline]
2102    fn try_sample_from<D, R>(
2103        distribution: &D,
2104        rng: &mut R,
2105        precision_out: u32,
2106    ) -> Result<Self, Self::Error>
2107    where
2108        D: Distribution<Self::Sample>,
2109        R: Rng + ?Sized,
2110    {
2111        let real = K::RawReal::try_sample_from(distribution, rng, precision_out)
2112            .map_err(|source| RandomSampleComplexErrors::Real { source })?;
2113        let imaginary = K::RawReal::try_sample_from(distribution, rng, precision_out)
2114            .map_err(|source| RandomSampleComplexErrors::Imaginary { source })?;
2115        Self::try_new_complex(real, imaginary)
2116            .map_err(|source| RandomSampleComplexErrors::Output { source })
2117    }
2118}
2119
2120//------------------------------------------------------------------------------------------------------------
2121
2122//------------------------------------------------------------------------------------------------------------
2123/// Generates a vector of random values, converting every sample at `precision_out`.
2124///
2125/// The operation stops at the first conversion or validation failure instead of retrying
2126/// indefinitely. `precision_out` must match the fixed precision of `f32` and `f64`; it
2127/// configures the precision of a `rug::Float` target.
2128pub fn try_random_vec<T, D, R>(
2129    n: usize,
2130    distribution: &D,
2131    rng: &mut R,
2132    precision_out: u32,
2133) -> Result<Vec<T>, T::Error>
2134where
2135    T: TryRandomSampleFrom,
2136    D: Distribution<T::Sample>,
2137    R: Rng + ?Sized,
2138{
2139    (0..n)
2140        .map(|_| T::try_sample_from(distribution, rng, precision_out))
2141        .collect()
2142}
2143//------------------------------------------------------------------------------------------------------------
2144
2145//------------------------------------------------------------------------------------------------------------
2146#[cfg(test)]
2147mod tests {
2148    use super::*;
2149    use num::Complex;
2150    use num_traits::MulAddAssign;
2151    use std::ops::{Add, Div, Sub};
2152    use try_create::TryNew;
2153
2154    mod functions_general_type {
2155        use super::*;
2156
2157        fn test_recip<RealType: RealScalar>() {
2158            let a = RealType::two();
2159
2160            let a = a.try_reciprocal().unwrap();
2161            let expected = RealType::one_div_2();
2162            assert_eq!(a, expected);
2163        }
2164
2165        fn test_zero<RealType: RealScalar>() {
2166            let a = RealType::zero();
2167
2168            assert!(a.is_zero());
2169        }
2170
2171        fn test_one<RealType: RealScalar>() {
2172            let _a = RealType::one();
2173        }
2174
2175        fn test_add<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
2176        where
2177            for<'a> &'a ScalarType:
2178                Add<ScalarType, Output = ScalarType> + Add<&'a ScalarType, Output = ScalarType>,
2179        {
2180            let c = a.clone() + &b;
2181            assert_eq!(c, c_expected);
2182
2183            let c = &a + b.clone();
2184            assert_eq!(c, c_expected);
2185
2186            let c = a.clone() + b.clone();
2187            assert_eq!(c, c_expected);
2188
2189            let c = &a + &b;
2190            assert_eq!(c, c_expected);
2191        }
2192
2193        fn test_sub<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
2194        where
2195            for<'a> &'a ScalarType:
2196                Sub<ScalarType, Output = ScalarType> + Sub<&'a ScalarType, Output = ScalarType>,
2197        {
2198            let c = a.clone() - &b;
2199            assert_eq!(c, c_expected);
2200
2201            let c = &a - b.clone();
2202            assert_eq!(c, c_expected);
2203
2204            let c = a.clone() - b.clone();
2205            assert_eq!(c, c_expected);
2206
2207            let c = &a - &b;
2208            assert_eq!(c, c_expected);
2209        }
2210
2211        fn test_mul<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
2212        where
2213            for<'a> &'a ScalarType:
2214                Mul<ScalarType, Output = ScalarType> + Mul<&'a ScalarType, Output = ScalarType>,
2215        {
2216            let c = a.clone() * &b;
2217            assert_eq!(c, c_expected);
2218
2219            let c = &a * b.clone();
2220            assert_eq!(c, c_expected);
2221
2222            let c = a.clone() * b.clone();
2223            assert_eq!(c, c_expected);
2224
2225            let c = &a * &b;
2226            assert_eq!(c, c_expected);
2227        }
2228
2229        fn test_div<ScalarType: FpScalar>(a: ScalarType, b: ScalarType, c_expected: ScalarType)
2230        where
2231            for<'a> &'a ScalarType:
2232                Div<ScalarType, Output = ScalarType> + Div<&'a ScalarType, Output = ScalarType>,
2233        {
2234            let c = a.clone() / &b;
2235            assert_eq!(c, c_expected);
2236
2237            let c = &a / b.clone();
2238            assert_eq!(c, c_expected);
2239
2240            let c = a.clone() / b.clone();
2241            assert_eq!(c, c_expected);
2242
2243            let c = &a / &b;
2244            assert_eq!(c, c_expected);
2245        }
2246
2247        fn test_mul_complex_with_real<ComplexType: ComplexScalar>(
2248            a: ComplexType,
2249            b: ComplexType::RealType,
2250            a_times_b_expected: ComplexType,
2251        ) {
2252            let a_times_b = a.clone().scale(&b);
2253            assert_eq!(a_times_b, a_times_b_expected);
2254
2255            let a_times_b = a.clone() * &b;
2256            assert_eq!(a_times_b, a_times_b_expected);
2257
2258            /*
2259            let b_times_a_expected = a_times_b_expected.clone();
2260
2261            let b_times_a = &b * a.clone();
2262            assert_eq!(b_times_a, b_times_a_expected);
2263
2264            let b_times_a = b.clone() * a.clone();
2265            assert_eq!(b_times_a, b_times_a_expected);
2266            */
2267        }
2268
2269        fn test_mul_assign_complex_with_real<ComplexType: ComplexScalar>(
2270            a: ComplexType,
2271            b: ComplexType::RealType,
2272            a_times_b_expected: ComplexType,
2273        ) {
2274            let mut a_times_b = a.clone();
2275            a_times_b.scale_mut(&b);
2276            assert_eq!(a_times_b, a_times_b_expected);
2277
2278            //        let mut a_times_b = a.clone();
2279            //        a_times_b *= b;
2280            //        assert_eq!(a_times_b, a_times_b_expected);
2281        }
2282
2283        fn test_neg_assign_real<RealType: RealScalar>()
2284        where
2285            RealType::RawReal: TryConvertFromRawReal<f64>,
2286        {
2287            let mut a = RealType::one();
2288            a.neg_assign();
2289
2290            let a_expected = RealType::try_from_f64(-1.).unwrap();
2291            assert_eq!(a, a_expected);
2292        }
2293
2294        fn test_add_assign_real<RealType: RealScalar>()
2295        where
2296            RealType::RawReal: TryConvertFromRawReal<f64>,
2297        {
2298            let mut a = RealType::try_from_f64(1.0).unwrap();
2299            let b = RealType::try_from_f64(2.0).unwrap();
2300
2301            a += &b;
2302            let a_expected = RealType::try_from_f64(3.0).unwrap();
2303            assert_eq!(a, a_expected);
2304
2305            a += b;
2306            let a_expected = RealType::try_from_f64(5.0).unwrap();
2307            assert_eq!(a, a_expected);
2308        }
2309
2310        fn test_sub_assign_real<RealType: RealScalar>()
2311        where
2312            RealType::RawReal: TryConvertFromRawReal<f64>,
2313        {
2314            let mut a = RealType::try_from_f64(1.0).unwrap();
2315            let b = RealType::try_from_f64(2.0).unwrap();
2316
2317            a -= &b;
2318            let a_expected = RealType::try_from_f64(-1.0).unwrap();
2319            assert_eq!(a, a_expected);
2320
2321            a -= b;
2322            let a_expected = RealType::try_from_f64(-3.0).unwrap();
2323            assert_eq!(a, a_expected);
2324        }
2325
2326        fn test_mul_assign_real<RealType: RealScalar>()
2327        where
2328            RealType::RawReal: TryConvertFromRawReal<f64>,
2329        {
2330            let mut a = RealType::try_from_f64(1.0).unwrap();
2331            let b = RealType::try_from_f64(2.0).unwrap();
2332
2333            a *= &b;
2334            let a_expected = RealType::try_from_f64(2.0).unwrap();
2335            assert_eq!(a, a_expected);
2336
2337            a *= b;
2338            let a_expected = RealType::try_from_f64(4.0).unwrap();
2339            assert_eq!(a, a_expected);
2340        }
2341
2342        fn test_div_assign_real<RealType: RealScalar>()
2343        where
2344            RealType::RawReal: TryConvertFromRawReal<f64>,
2345        {
2346            let mut a = RealType::try_from_f64(4.0).unwrap();
2347            let b = RealType::try_from_f64(2.0).unwrap();
2348
2349            a /= &b;
2350            let a_expected = RealType::try_from_f64(2.0).unwrap();
2351            assert_eq!(a, a_expected);
2352
2353            a /= b;
2354            let a_expected = RealType::try_from_f64(1.0).unwrap();
2355            assert_eq!(a, a_expected);
2356        }
2357
2358        fn test_mul_add_ref_real<RealType: RealScalar>()
2359        where
2360            RealType::RawReal: TryConvertFromRawReal<f64>,
2361        {
2362            let a = RealType::try_from_f64(2.0).unwrap();
2363            let b = RealType::try_from_f64(3.0).unwrap();
2364            let c = RealType::try_from_f64(1.0).unwrap();
2365
2366            let d_expected = RealType::try_from_f64(7.0).unwrap();
2367
2368            let d = a.mul_add_ref(&b, &c);
2369            assert_eq!(d, d_expected);
2370        }
2371
2372        fn test_sin_real<RealType: RealScalar>() {
2373            let a = RealType::zero();
2374
2375            let a = a.sin();
2376            let expected = RealType::zero();
2377            assert_eq!(a, expected);
2378        }
2379
2380        fn test_cos_real<RealType: RealScalar>() {
2381            let a = RealType::zero();
2382
2383            let a = a.cos();
2384            let expected = RealType::one();
2385            assert_eq!(a, expected);
2386        }
2387
2388        fn test_abs_real<RealType: RealScalar>()
2389        where
2390            RealType::RawReal: TryConvertFromRawReal<f64>,
2391        {
2392            let a = RealType::try_from_f64(-1.).unwrap();
2393
2394            let abs = a.abs();
2395            let expected = NonNegativeRealScalar::one();
2396            assert_eq!(abs, expected);
2397        }
2398
2399        mod native {
2400            use super::*;
2401
2402            mod real {
2403                use super::*;
2404
2405                #[test]
2406                fn zero() {
2407                    test_zero::<f64>();
2408                }
2409
2410                #[test]
2411                fn one() {
2412                    test_one::<f64>();
2413                }
2414
2415                #[test]
2416                fn recip() {
2417                    test_recip::<f64>();
2418                }
2419
2420                #[test]
2421                fn add() {
2422                    let a = 1.0;
2423                    let b = 2.0;
2424                    let c_expected = 3.0;
2425                    test_add(a, b, c_expected);
2426                }
2427
2428                #[test]
2429                fn sub() {
2430                    let a = 1.0;
2431                    let b = 2.0;
2432                    let c_expected = -1.0;
2433                    test_sub(a, b, c_expected);
2434                }
2435
2436                #[test]
2437                fn mul() {
2438                    let a = 2.0;
2439                    let b = 3.0;
2440                    let c_expected = 6.0;
2441                    test_mul(a, b, c_expected);
2442                }
2443
2444                #[test]
2445                fn div() {
2446                    let a = 6.;
2447                    let b = 2.;
2448                    let c_expected = 3.;
2449                    test_div(a, b, c_expected);
2450                }
2451
2452                #[test]
2453                fn neg_assign() {
2454                    test_neg_assign_real::<f64>();
2455                }
2456
2457                #[test]
2458                fn add_assign() {
2459                    test_add_assign_real::<f64>();
2460                }
2461
2462                #[test]
2463                fn sub_assign() {
2464                    test_sub_assign_real::<f64>();
2465                }
2466
2467                #[test]
2468                fn mul_assign() {
2469                    test_mul_assign_real::<f64>();
2470                }
2471
2472                #[test]
2473                fn div_assign() {
2474                    test_div_assign_real::<f64>();
2475                }
2476                #[test]
2477                fn mul_add_ref() {
2478                    test_mul_add_ref_real::<f64>();
2479                }
2480
2481                #[test]
2482                fn from_f64() {
2483                    let v_native64 = f64::try_from_f64(16.25).unwrap();
2484                    assert_eq!(v_native64, 16.25);
2485                }
2486
2487                #[test]
2488                fn abs() {
2489                    test_abs_real::<f64>();
2490                }
2491
2492                #[test]
2493                fn acos() {
2494                    let a = 0.;
2495
2496                    let pi_over_2 = a.acos();
2497                    let expected = std::f64::consts::FRAC_PI_2;
2498                    assert_eq!(pi_over_2, expected);
2499                }
2500
2501                #[test]
2502                fn asin() {
2503                    let a = 1.;
2504
2505                    let pi_over_2 = a.asin();
2506                    let expected = std::f64::consts::FRAC_PI_2;
2507                    assert_eq!(pi_over_2, expected);
2508                }
2509
2510                #[test]
2511                fn cos() {
2512                    test_cos_real::<f64>();
2513                }
2514
2515                #[test]
2516                fn sin() {
2517                    test_sin_real::<f64>();
2518                }
2519
2520                #[test]
2521                fn test_acos() {
2522                    let value: f64 = 0.5;
2523                    let result = value.acos();
2524                    assert_eq!(result, value.acos());
2525                }
2526
2527                #[test]
2528                fn test_acosh() {
2529                    let value: f64 = 1.5;
2530                    let result = value.acosh();
2531                    assert_eq!(result, value.acosh());
2532                }
2533
2534                #[test]
2535                fn test_asin() {
2536                    let value: f64 = 0.5;
2537                    let result = value.asin();
2538                    assert_eq!(result, value.asin());
2539                }
2540
2541                #[test]
2542                fn test_asinh() {
2543                    let value: f64 = 0.5;
2544                    let result = value.asinh();
2545                    assert_eq!(result, value.asinh());
2546                }
2547
2548                #[test]
2549                fn test_atan() {
2550                    let value: f64 = 0.5;
2551                    let result = value.atan();
2552                    assert_eq!(result, value.atan());
2553                }
2554
2555                #[test]
2556                fn test_atanh() {
2557                    let value: f64 = 0.5;
2558                    let result = value.atanh();
2559                    assert_eq!(result, value.atanh());
2560                }
2561
2562                #[test]
2563                fn test_cos_02() {
2564                    let value: f64 = 0.5;
2565                    let result = value.cos();
2566                    assert_eq!(result, value.cos());
2567                }
2568
2569                #[test]
2570                fn test_cosh() {
2571                    let value: f64 = 0.5;
2572                    let result = value.cosh();
2573                    assert_eq!(result, value.cosh());
2574                }
2575
2576                #[test]
2577                fn test_exp() {
2578                    let value: f64 = 0.5;
2579                    let result = value.exp();
2580                    println!("result = {result:?}");
2581
2582                    assert_eq!(result, value.exp());
2583                }
2584
2585                #[test]
2586                fn test_is_finite() {
2587                    let value: f64 = 0.5;
2588                    assert!(value.is_finite());
2589
2590                    let value: f64 = f64::INFINITY;
2591                    assert!(!value.is_finite());
2592                }
2593
2594                #[test]
2595                fn test_is_infinite() {
2596                    let value: f64 = f64::INFINITY;
2597                    assert!(value.is_infinite());
2598
2599                    let value: f64 = 0.5;
2600                    assert!(!value.is_infinite());
2601                }
2602
2603                #[test]
2604                fn test_ln() {
2605                    let value: f64 = std::f64::consts::E;
2606                    let result = value.ln();
2607                    println!("result = {result:?}");
2608                    assert_eq!(result, value.ln());
2609                }
2610
2611                #[test]
2612                fn test_log10() {
2613                    let value: f64 = 10.0;
2614                    let result = value.log10();
2615                    println!("result = {result:?}");
2616                    assert_eq!(result, value.log10());
2617                }
2618
2619                #[test]
2620                fn test_log2() {
2621                    let value: f64 = 8.0;
2622                    let result = value.log2();
2623                    println!("result = {result:?}");
2624                    assert_eq!(result, value.log2());
2625                }
2626
2627                #[test]
2628                fn test_recip_02() {
2629                    let value: f64 = 2.0;
2630                    let result = value.try_reciprocal().unwrap();
2631                    assert_eq!(result, value.recip());
2632                }
2633
2634                #[test]
2635                fn test_sin_02() {
2636                    let value: f64 = 0.5;
2637                    let result = value.sin();
2638                    assert_eq!(result, value.sin());
2639                }
2640
2641                #[test]
2642                fn test_sinh() {
2643                    let value: f64 = 0.5;
2644                    let result = value.sinh();
2645                    assert_eq!(result, value.sinh());
2646                }
2647
2648                #[test]
2649                fn sqrt() {
2650                    let value: f64 = 4.0;
2651                    let result = value.sqrt();
2652                    assert_eq!(result, value.sqrt());
2653                }
2654
2655                #[test]
2656                #[cfg(debug_assertions)]
2657                fn try_sqrt() {
2658                    let value: f64 = 4.0;
2659                    let result = value.try_sqrt().unwrap();
2660                    assert_eq!(result, value.sqrt());
2661
2662                    assert!((-1.0).try_sqrt().is_err());
2663                }
2664
2665                #[test]
2666                fn test_tan() {
2667                    let value: f64 = 0.5;
2668                    let result = value.tan();
2669                    assert_eq!(result, value.tan());
2670                }
2671
2672                #[test]
2673                fn test_tanh() {
2674                    let value: f64 = 0.5;
2675                    let result = value.tanh();
2676                    assert_eq!(result, value.tanh());
2677                }
2678            }
2679
2680            mod complex {
2681                use super::*;
2682
2683                #[test]
2684                fn add() {
2685                    let a = Complex::new(1., 2.);
2686                    let b = Complex::new(3., 4.);
2687
2688                    let c_expected = Complex::new(4., 6.);
2689
2690                    test_add(a, b, c_expected);
2691                }
2692
2693                #[test]
2694                fn sub() {
2695                    let a = Complex::new(3., 2.);
2696                    let b = Complex::new(1., 4.);
2697
2698                    let c_expected = Complex::new(2., -2.);
2699
2700                    test_sub(a, b, c_expected);
2701                }
2702
2703                #[test]
2704                fn mul() {
2705                    let a = Complex::new(3., 2.);
2706                    let b = Complex::new(1., 4.);
2707                    let c_expected = Complex::new(-5., 14.);
2708                    test_mul(a, b, c_expected);
2709                }
2710
2711                #[test]
2712                fn div() {
2713                    let a = Complex::new(-5., 14.);
2714                    let b = Complex::new(1., 4.);
2715
2716                    let c_expected = Complex::new(3., 2.);
2717
2718                    test_div(a, b, c_expected);
2719                }
2720
2721                #[test]
2722                fn add_assign() {
2723                    let mut a = Complex::new(1., 2.);
2724                    let b = Complex::new(3., 4.);
2725
2726                    a += &b;
2727                    let a_expected = Complex::new(4., 6.);
2728                    assert_eq!(a, a_expected);
2729
2730                    a += b;
2731                    let a_expected = Complex::new(7., 10.);
2732                    assert_eq!(a, a_expected);
2733                }
2734
2735                #[test]
2736                fn sub_assign() {
2737                    let mut a = Complex::new(3., 2.);
2738                    let b = Complex::new(2., 4.);
2739
2740                    a -= &b;
2741                    let a_expected = Complex::new(1., -2.);
2742                    assert_eq!(a, a_expected);
2743
2744                    a -= b;
2745                    let a_expected = Complex::new(-1., -6.);
2746                    assert_eq!(a, a_expected);
2747                }
2748
2749                #[test]
2750                fn mul_assign() {
2751                    let mut a = Complex::new(3., 2.);
2752                    let b = Complex::new(2., 4.);
2753
2754                    a *= &b;
2755                    let a_expected = Complex::new(-2., 16.);
2756                    assert_eq!(a, a_expected);
2757
2758                    a *= b;
2759                    let a_expected = Complex::new(-68., 24.);
2760                    assert_eq!(a, a_expected);
2761                }
2762
2763                #[test]
2764                fn div_assign() {
2765                    let mut a = Complex::new(-68., 24.);
2766                    let b = Complex::new(2., 4.);
2767
2768                    a /= &b;
2769                    let a_expected = Complex::new(-2., 16.);
2770                    assert_eq!(a, a_expected);
2771
2772                    a /= b;
2773                    let a_expected = Complex::new(3., 2.);
2774                    assert_eq!(a, a_expected);
2775                }
2776
2777                #[test]
2778                fn from_f64() {
2779                    let v = Complex::new(16.25, 2.);
2780                    assert_eq!(v.real_part(), 16.25);
2781                    assert_eq!(v.imag_part(), 2.);
2782                }
2783
2784                #[test]
2785                fn conj() {
2786                    let v = Complex::new(16.25, 2.);
2787
2788                    let v_conj = v.conjugate();
2789                    assert_eq!(v_conj.real_part(), 16.25);
2790                    assert_eq!(v_conj.imag_part(), -2.);
2791                }
2792
2793                #[test]
2794                fn neg_assign() {
2795                    let mut a = Complex::new(1., 2.);
2796                    a.neg_assign();
2797
2798                    let a_expected = Complex::new(-1., -2.);
2799                    assert_eq!(a, a_expected);
2800                }
2801
2802                #[test]
2803                fn abs() {
2804                    let a = Complex::new(-3., 4.);
2805
2806                    let abs = a.abs();
2807                    let expected = NonNegativeRealScalar::try_new(5.).unwrap();
2808                    assert_eq!(abs, expected);
2809                }
2810
2811                #[test]
2812                fn mul_add_ref() {
2813                    let a = Complex::new(2., -3.);
2814                    let b = Complex::new(3., 1.);
2815                    let c = Complex::new(1., -4.);
2816
2817                    let d_expected = Complex::new(10., -11.);
2818
2819                    let d = a.mul_add_ref(&b, &c);
2820                    assert_eq!(d, d_expected);
2821                }
2822
2823                #[test]
2824                fn mul_complex_with_real() {
2825                    let a = Complex::new(1., 2.);
2826                    let b = 3.;
2827
2828                    let a_times_b_expected = Complex::new(3., 6.);
2829
2830                    test_mul_complex_with_real(a, b, a_times_b_expected);
2831                }
2832
2833                #[test]
2834                fn mul_assign_complex_with_real() {
2835                    let a = Complex::new(1., 2.);
2836                    let b = 3.;
2837
2838                    let a_times_b_expected = Complex::new(3., 6.);
2839
2840                    test_mul_assign_complex_with_real(a, b, a_times_b_expected);
2841                }
2842
2843                #[test]
2844                fn test_acos() {
2845                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2846                    let result = value.acos();
2847                    assert_eq!(result, value.acos());
2848                }
2849
2850                #[test]
2851                fn test_acosh() {
2852                    let value: Complex<f64> = Complex::new(1.5, 0.5);
2853                    let result = value.acosh();
2854                    assert_eq!(result, value.acosh());
2855                }
2856
2857                #[test]
2858                fn test_asin() {
2859                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2860                    let result = value.asin();
2861                    assert_eq!(result, value.asin());
2862                }
2863
2864                #[test]
2865                fn test_asinh() {
2866                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2867                    let result = value.asinh();
2868                    assert_eq!(result, value.asinh());
2869                }
2870
2871                #[test]
2872                fn test_atan() {
2873                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2874                    let result = value.atan();
2875                    assert_eq!(result, value.atan());
2876                }
2877
2878                #[test]
2879                fn test_atanh() {
2880                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2881                    let result = value.atanh();
2882                    assert_eq!(result, value.atanh());
2883                }
2884
2885                #[test]
2886                fn test_cos_01() {
2887                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2888                    let result = value.cos();
2889                    assert_eq!(result, value.cos());
2890                }
2891
2892                #[test]
2893                fn test_cosh() {
2894                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2895                    let result = value.cosh();
2896                    assert_eq!(result, value.cosh());
2897                }
2898
2899                #[test]
2900                fn test_exp() {
2901                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2902                    let result = value.exp();
2903                    println!("result = {result:?}");
2904                    assert_eq!(result, value.exp());
2905                }
2906
2907                /*
2908                #[test]
2909                fn test_is_finite() {
2910                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2911                    assert!(value.is_finite());
2912
2913                    let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
2914                    assert!(!value.is_finite());
2915                }
2916
2917                #[test]
2918                fn test_is_infinite() {
2919                    let value: Complex<f64> = Complex::new(f64::INFINITY, 0.5);
2920                    assert!(value.is_infinite());
2921
2922                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2923                    assert!(!value.is_infinite());
2924                }
2925                */
2926
2927                #[test]
2928                fn test_ln() {
2929                    let value: Complex<f64> = Complex::new(std::f64::consts::E, 1.0);
2930                    let result = value.ln();
2931                    println!("result = {result:?}");
2932                    assert_eq!(result, value.ln());
2933                }
2934
2935                #[test]
2936                fn test_log10() {
2937                    let value: Complex<f64> = Complex::new(10.0, 1.0);
2938                    let result = value.log10();
2939                    println!("result = {result:?}");
2940                    assert_eq!(result, value.log10());
2941                }
2942
2943                #[test]
2944                fn test_log2() {
2945                    let value: Complex<f64> = Complex::new(8.0, 1.0);
2946                    let result = value.log2();
2947                    println!("result = {result:?}");
2948                    assert_eq!(result, value.log2());
2949                }
2950
2951                #[test]
2952                fn test_recip() {
2953                    let value: Complex<f64> = Complex::new(2.0, 0.0);
2954                    let result = value.try_reciprocal().unwrap();
2955                    assert_eq!(result, value.finv());
2956                }
2957
2958                #[test]
2959                fn test_sin_01() {
2960                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2961                    let result = value.sin();
2962                    assert_eq!(result, value.sin());
2963                }
2964
2965                #[test]
2966                fn test_sinh() {
2967                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2968                    let result = value.sinh();
2969                    assert_eq!(result, value.sinh());
2970                }
2971
2972                #[test]
2973                fn sqrt() {
2974                    let value: Complex<f64> = Complex::new(4.0, 1.0);
2975                    let result = value.sqrt();
2976                    assert_eq!(result, value.sqrt());
2977                }
2978
2979                #[test]
2980                fn try_sqrt() {
2981                    let value: Complex<f64> = Complex::new(4.0, 1.0);
2982                    let result = value.try_sqrt().unwrap();
2983                    assert_eq!(result, value.sqrt());
2984                }
2985
2986                #[test]
2987                fn test_tan() {
2988                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2989                    let result = value.tan();
2990                    assert_eq!(result, value.tan());
2991                }
2992
2993                #[test]
2994                fn test_tanh() {
2995                    let value: Complex<f64> = Complex::new(0.5, 0.5);
2996                    let result = value.tanh();
2997                    assert_eq!(result, value.tanh());
2998                }
2999            }
3000        }
3001
3002        #[cfg(feature = "rug")]
3003        mod rug_ {
3004            use super::*;
3005            use crate::backends::rug::validated::{ComplexRugStrictFinite, RealRugStrictFinite};
3006            use rug::ops::CompleteRound;
3007            use try_create::{IntoInner, TryNew};
3008
3009            const PRECISION: u32 = 100;
3010
3011            mod real {
3012                use super::*;
3013                use rug::Float;
3014
3015                #[test]
3016                fn zero() {
3017                    test_zero::<RealRugStrictFinite<64>>();
3018                    test_zero::<RealRugStrictFinite<PRECISION>>();
3019                }
3020
3021                #[test]
3022                fn one() {
3023                    test_one::<RealRugStrictFinite<64>>();
3024                    test_one::<RealRugStrictFinite<PRECISION>>();
3025                }
3026
3027                #[test]
3028                fn recip() {
3029                    test_recip::<RealRugStrictFinite<64>>();
3030                    test_recip::<RealRugStrictFinite<PRECISION>>();
3031                }
3032
3033                #[test]
3034                fn add() {
3035                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
3036                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
3037                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
3038                    test_add(a, b, c_expected);
3039                }
3040
3041                #[test]
3042                fn sub() {
3043                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(1.0).unwrap();
3044                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
3045                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(-1.0).unwrap();
3046                    test_sub(a, b, c_expected);
3047                }
3048
3049                #[test]
3050                fn mul() {
3051                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(2.0).unwrap();
3052                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(3.0).unwrap();
3053                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(6.0).unwrap();
3054                    test_mul(a, b, c_expected);
3055                }
3056
3057                #[test]
3058                fn div() {
3059                    let a = RealRugStrictFinite::<PRECISION>::try_from_f64(6.).unwrap();
3060                    let b = RealRugStrictFinite::<PRECISION>::try_from_f64(2.).unwrap();
3061                    let c_expected = RealRugStrictFinite::<PRECISION>::try_from_f64(3.).unwrap();
3062
3063                    test_div(a, b, c_expected);
3064                }
3065
3066                #[test]
3067                fn neg_assign() {
3068                    test_neg_assign_real::<RealRugStrictFinite<PRECISION>>();
3069                }
3070
3071                #[test]
3072                fn add_assign() {
3073                    test_add_assign_real::<RealRugStrictFinite<PRECISION>>();
3074                }
3075
3076                #[test]
3077                fn sub_assign() {
3078                    test_sub_assign_real::<RealRugStrictFinite<PRECISION>>();
3079                }
3080
3081                #[test]
3082                fn mul_assign() {
3083                    test_mul_assign_real::<RealRugStrictFinite<PRECISION>>();
3084                }
3085
3086                #[test]
3087                fn div_assign() {
3088                    test_div_assign_real::<RealRugStrictFinite<PRECISION>>();
3089                }
3090
3091                #[test]
3092                fn mul_add_ref() {
3093                    test_mul_add_ref_real::<RealRugStrictFinite<PRECISION>>();
3094                }
3095
3096                #[test]
3097                fn abs() {
3098                    test_abs_real::<RealRugStrictFinite<PRECISION>>();
3099                }
3100
3101                #[test]
3102                fn acos() {
3103                    {
3104                        let a = RealRugStrictFinite::<53>::zero();
3105                        let pi_over_2 = RealRugStrictFinite::<53>::acos(a);
3106                        let expected = rug::Float::with_val(53, std::f64::consts::FRAC_PI_2);
3107                        assert_eq!(pi_over_2.as_raw_scalar_ref(), &expected);
3108                    }
3109                    {
3110                        let a = RealRugStrictFinite::<100>::zero();
3111                        let pi_over_2 = RealRugStrictFinite::<100>::acos(a);
3112                        let expected = rug::Float::with_val(
3113                            100,
3114                            rug::Float::parse("1.5707963267948966192313216916397").unwrap(),
3115                        );
3116                        assert_eq!(pi_over_2.as_raw_scalar_ref(), &expected);
3117                    }
3118                }
3119
3120                #[test]
3121                fn asin() {
3122                    {
3123                        let a = RealRugStrictFinite::<53>::one();
3124                        let pi_over_2 = RealRugStrictFinite::<53>::asin(a);
3125                        let expected = rug::Float::with_val(53, std::f64::consts::FRAC_PI_2);
3126                        assert_eq!(pi_over_2.as_raw_scalar_ref(), &expected);
3127                    }
3128                    {
3129                        let a = RealRugStrictFinite::<100>::one();
3130                        let pi_over_2 = RealRugStrictFinite::<100>::asin(a);
3131                        let expected = rug::Float::with_val(
3132                            100,
3133                            rug::Float::parse("1.5707963267948966192313216916397").unwrap(),
3134                        );
3135                        assert_eq!(pi_over_2.as_raw_scalar_ref(), &expected);
3136                    }
3137                }
3138
3139                #[test]
3140                fn cos() {
3141                    test_cos_real::<RealRugStrictFinite<64>>();
3142                    test_cos_real::<RealRugStrictFinite<PRECISION>>();
3143                }
3144
3145                #[test]
3146                fn sin() {
3147                    test_sin_real::<RealRugStrictFinite<64>>();
3148                    test_sin_real::<RealRugStrictFinite<PRECISION>>();
3149                }
3150
3151                #[test]
3152                fn dot_product() {
3153                    let a = &[
3154                        RealRugStrictFinite::<100>::one(),
3155                        RealRugStrictFinite::<100>::try_from_f64(2.).unwrap(),
3156                    ];
3157
3158                    let b = &[
3159                        RealRugStrictFinite::<100>::try_from_f64(2.).unwrap(),
3160                        RealRugStrictFinite::<100>::try_from_f64(-1.).unwrap(),
3161                    ];
3162
3163                    let a: Vec<_> = a.iter().map(|a_i| a_i.as_raw_scalar_ref()).collect();
3164                    let b: Vec<_> = b.iter().map(|b_i| b_i.as_raw_scalar_ref()).collect();
3165
3166                    let value = RealRugStrictFinite::<100>::try_new(
3167                        rug::Float::dot(a.into_iter().zip(b)).complete(100),
3168                    )
3169                    .unwrap();
3170
3171                    assert_eq!(value.as_raw_scalar_ref(), &rug::Float::with_val(100, 0.));
3172                }
3173                #[test]
3174                fn test_acos() {
3175                    let value =
3176                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3177                            .unwrap();
3178                    let result = value.clone().acos();
3179                    assert_eq!(
3180                        result,
3181                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3182                            PRECISION,
3183                            value.into_inner().acos()
3184                        ))
3185                        .unwrap()
3186                    );
3187                }
3188
3189                #[test]
3190                fn test_acosh() {
3191                    let value =
3192                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.5))
3193                            .unwrap();
3194                    let result = value.clone().acosh();
3195                    assert_eq!(
3196                        result,
3197                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3198                            PRECISION,
3199                            value.into_inner().acosh()
3200                        ))
3201                        .unwrap()
3202                    );
3203                }
3204
3205                #[test]
3206                fn test_asin() {
3207                    let value =
3208                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3209                            .unwrap();
3210                    let result = value.clone().asin();
3211                    assert_eq!(
3212                        result,
3213                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3214                            PRECISION,
3215                            value.into_inner().asin()
3216                        ))
3217                        .unwrap()
3218                    );
3219                }
3220
3221                #[test]
3222                fn test_asinh() {
3223                    let value =
3224                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3225                            .unwrap();
3226                    let result = value.clone().asinh();
3227                    assert_eq!(
3228                        result,
3229                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3230                            PRECISION,
3231                            value.into_inner().asinh()
3232                        ))
3233                        .unwrap()
3234                    );
3235                }
3236
3237                #[test]
3238                fn test_atan() {
3239                    let value =
3240                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3241                            .unwrap();
3242                    let result = value.clone().atan();
3243                    assert_eq!(
3244                        result,
3245                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3246                            PRECISION,
3247                            value.into_inner().atan()
3248                        ))
3249                        .unwrap()
3250                    );
3251                }
3252
3253                #[test]
3254                fn test_atanh() {
3255                    let value =
3256                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3257                            .unwrap();
3258                    let result = value.clone().atanh();
3259                    assert_eq!(
3260                        result,
3261                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3262                            PRECISION,
3263                            value.into_inner().atanh()
3264                        ))
3265                        .unwrap()
3266                    );
3267                }
3268
3269                #[test]
3270                fn test_cos_02() {
3271                    let value =
3272                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3273                            .unwrap();
3274                    let result = value.clone().cos();
3275                    assert_eq!(
3276                        result,
3277                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3278                            PRECISION,
3279                            value.into_inner().cos()
3280                        ))
3281                        .unwrap()
3282                    );
3283                }
3284
3285                #[test]
3286                fn test_cosh() {
3287                    let value =
3288                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3289                            .unwrap();
3290                    let result = value.clone().cosh();
3291                    assert_eq!(
3292                        result,
3293                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3294                            PRECISION,
3295                            value.into_inner().cosh()
3296                        ))
3297                        .unwrap()
3298                    );
3299                }
3300
3301                #[test]
3302                fn test_exp() {
3303                    let value =
3304                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3305                            .unwrap();
3306                    let result = value.clone().exp();
3307                    println!("result = {result:?}");
3308                    assert_eq!(
3309                        result,
3310                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3311                            PRECISION,
3312                            value.into_inner().exp()
3313                        ))
3314                        .unwrap()
3315                    );
3316                }
3317
3318                #[test]
3319                fn test_is_finite() {
3320                    let value =
3321                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3322                            .unwrap();
3323                    assert!(value.is_finite());
3324
3325                    let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3326                        PRECISION,
3327                        f64::INFINITY,
3328                    ));
3329                    assert!(value.is_err());
3330                }
3331
3332                #[test]
3333                fn test_is_infinite() {
3334                    let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3335                        PRECISION,
3336                        f64::INFINITY,
3337                    ));
3338                    assert!(value.is_err());
3339
3340                    let value =
3341                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3342                            .unwrap();
3343                    assert!(!value.is_infinite());
3344                }
3345
3346                #[test]
3347                fn test_ln() {
3348                    let value = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3349                        PRECISION,
3350                        std::f64::consts::E,
3351                    ))
3352                    .unwrap();
3353                    let result = value.clone().ln();
3354                    println!("result = {result:?}");
3355                    assert_eq!(
3356                        result,
3357                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3358                            PRECISION,
3359                            value.into_inner().ln()
3360                        ))
3361                        .unwrap()
3362                    );
3363                }
3364
3365                #[test]
3366                fn test_log10() {
3367                    let value =
3368                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 10.0))
3369                            .unwrap();
3370                    let result = value.clone().log10();
3371                    println!("result = {result:?}");
3372                    assert_eq!(
3373                        result,
3374                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3375                            PRECISION,
3376                            value.into_inner().log10()
3377                        ))
3378                        .unwrap()
3379                    );
3380                }
3381
3382                #[test]
3383                fn test_log2() {
3384                    let value =
3385                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 8.0))
3386                            .unwrap();
3387                    let result = value.clone().log2();
3388                    println!("result = {result:?}");
3389                    assert_eq!(
3390                        result,
3391                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3392                            PRECISION,
3393                            value.into_inner().log2()
3394                        ))
3395                        .unwrap()
3396                    );
3397                }
3398
3399                #[test]
3400                fn test_recip_02() {
3401                    let value =
3402                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
3403                            .unwrap();
3404                    let result = value.clone().try_reciprocal().unwrap();
3405                    assert_eq!(
3406                        result,
3407                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3408                            PRECISION,
3409                            value.into_inner().recip()
3410                        ))
3411                        .unwrap()
3412                    );
3413                }
3414
3415                #[test]
3416                fn test_sin_02() {
3417                    let value =
3418                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3419                            .unwrap();
3420                    let result = value.clone().sin();
3421                    assert_eq!(
3422                        result,
3423                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3424                            PRECISION,
3425                            value.into_inner().sin()
3426                        ))
3427                        .unwrap()
3428                    );
3429                }
3430
3431                #[test]
3432                fn test_sinh() {
3433                    let value =
3434                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3435                            .unwrap();
3436                    let result = value.clone().sinh();
3437                    assert_eq!(
3438                        result,
3439                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3440                            PRECISION,
3441                            value.into_inner().sinh()
3442                        ))
3443                        .unwrap()
3444                    );
3445                }
3446
3447                #[test]
3448                fn sqrt() {
3449                    let value =
3450                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3451                            .unwrap();
3452                    let result = value.clone().sqrt();
3453                    assert_eq!(
3454                        result,
3455                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3456                            PRECISION,
3457                            value.into_inner().sqrt()
3458                        ))
3459                        .unwrap()
3460                    );
3461                }
3462
3463                #[test]
3464                fn try_sqrt() {
3465                    let value =
3466                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3467                            .unwrap();
3468                    let result = value.clone().try_sqrt().unwrap();
3469                    assert_eq!(
3470                        result,
3471                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3472                            PRECISION,
3473                            value.into_inner().sqrt()
3474                        ))
3475                        .unwrap()
3476                    );
3477
3478                    assert!(
3479                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -4.0))
3480                            .unwrap()
3481                            .try_sqrt()
3482                            .is_err()
3483                    )
3484                }
3485
3486                #[test]
3487                fn test_tan() {
3488                    let value =
3489                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3490                            .unwrap();
3491                    let result = value.clone().tan();
3492                    assert_eq!(
3493                        result,
3494                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3495                            PRECISION,
3496                            value.into_inner().tan()
3497                        ))
3498                        .unwrap()
3499                    );
3500                }
3501
3502                #[test]
3503                fn test_tanh() {
3504                    let value =
3505                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
3506                            .unwrap();
3507                    let result = value.clone().tanh();
3508                    assert_eq!(
3509                        result,
3510                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
3511                            PRECISION,
3512                            value.into_inner().tanh()
3513                        ))
3514                        .unwrap()
3515                    );
3516                }
3517
3518                #[test]
3519                fn test_mul_add() {
3520                    let a =
3521                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
3522                            .unwrap();
3523                    let b =
3524                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
3525                            .unwrap();
3526                    let c =
3527                        RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
3528                            .unwrap();
3529                    let result = a.clone().mul_add_ref(&b, &c);
3530                    assert_eq!(
3531                        result,
3532                        RealRugStrictFinite::<PRECISION>::try_new(
3533                            a.into_inner() * b.as_raw_scalar_ref() + c.as_raw_scalar_ref()
3534                        )
3535                        .unwrap()
3536                    );
3537                }
3538            }
3539
3540            mod complex {
3541                use super::*;
3542                //use rug::Complex;
3543                use rug::Float;
3544
3545                #[test]
3546                fn add() {
3547                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
3548                        .unwrap();
3549                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 4.))
3550                        .unwrap();
3551                    let c_expected =
3552                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(4., 6.))
3553                            .unwrap();
3554                    test_add(a, b, c_expected);
3555                }
3556
3557                #[test]
3558                fn sub() {
3559                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
3560                        .unwrap();
3561                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
3562                        .unwrap();
3563                    let c_expected =
3564                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., -2.))
3565                            .unwrap();
3566                    test_sub(a, b, c_expected);
3567                }
3568
3569                #[test]
3570                fn mul() {
3571                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
3572                        .unwrap();
3573                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
3574                        .unwrap();
3575                    let c_expected =
3576                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-5., 14.))
3577                            .unwrap();
3578                    test_mul(a, b, c_expected);
3579                }
3580
3581                #[test]
3582                fn div() {
3583                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-5., 14.))
3584                        .unwrap();
3585                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 4.))
3586                        .unwrap();
3587                    let c_expected =
3588                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
3589                            .unwrap();
3590                    test_div(a, b, c_expected);
3591                }
3592
3593                #[test]
3594                fn add_assign() {
3595                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
3596                        .unwrap();
3597                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 4.))
3598                        .unwrap();
3599
3600                    a += &b;
3601                    let a_expected =
3602                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(4., 6.))
3603                            .unwrap();
3604                    assert_eq!(a, a_expected);
3605
3606                    a += b;
3607                    let a_expected =
3608                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(7., 10.))
3609                            .unwrap();
3610                    assert_eq!(a, a_expected);
3611                }
3612
3613                #[test]
3614                fn sub_assign() {
3615                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
3616                        .unwrap();
3617                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
3618                        .unwrap();
3619
3620                    a -= &b;
3621                    let a_expected =
3622                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., -2.))
3623                            .unwrap();
3624                    assert_eq!(a, a_expected);
3625
3626                    a -= b;
3627                    let a_expected =
3628                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., -6.))
3629                            .unwrap();
3630                    assert_eq!(a, a_expected);
3631                }
3632
3633                #[test]
3634                fn mul_assign() {
3635                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
3636                        .unwrap();
3637                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
3638                        .unwrap();
3639
3640                    a *= &b;
3641                    let a_expected =
3642                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., 16.))
3643                            .unwrap();
3644                    assert_eq!(a, a_expected);
3645
3646                    a *= b;
3647                    let a_expected =
3648                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-68., 24.))
3649                            .unwrap();
3650                    assert_eq!(a, a_expected);
3651                }
3652
3653                #[test]
3654                fn div_assign() {
3655                    let mut a =
3656                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-68., 24.))
3657                            .unwrap();
3658                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
3659                        .unwrap();
3660
3661                    a /= &b;
3662                    let a_expected =
3663                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., 16.))
3664                            .unwrap();
3665                    assert_eq!(a, a_expected);
3666
3667                    a /= b;
3668                    let a_expected =
3669                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 2.))
3670                            .unwrap();
3671                    assert_eq!(a, a_expected);
3672                }
3673
3674                #[test]
3675                fn from_f64() {
3676                    let v_100bits =
3677                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(16.25, 2.))
3678                            .unwrap();
3679                    assert_eq!(
3680                        ComplexRugStrictFinite::<PRECISION>::real_part(&v_100bits)
3681                            .as_raw_scalar_ref(),
3682                        &16.25
3683                    );
3684                    assert_eq!(
3685                        ComplexRugStrictFinite::<PRECISION>::imag_part(&v_100bits)
3686                            .as_raw_scalar_ref(),
3687                        &2.
3688                    );
3689
3690                    let v_53bits =
3691                        ComplexRugStrictFinite::<53>::try_from(Complex::new(16.25, 2.)).unwrap();
3692                    assert_eq!(
3693                        ComplexRugStrictFinite::<53>::real_part(&v_53bits).as_raw_scalar_ref(),
3694                        &16.25
3695                    );
3696                    assert_eq!(
3697                        ComplexRugStrictFinite::<53>::imag_part(&v_53bits).as_raw_scalar_ref(),
3698                        &2.
3699                    );
3700
3701                    // 16.25 can be exactly represented with far fewer than 53 bits, so it is
3702                    // not suitable for testing the minimum f64-equivalent precision boundary.
3703                    let v_53bits_2 =
3704                        ComplexRugStrictFinite::<53>::try_from(Complex::new(16.25, 2.)).unwrap();
3705                    assert_eq!(
3706                        ComplexRugStrictFinite::<53>::real_part(&v_53bits_2).as_raw_scalar_ref(),
3707                        &16.25
3708                    );
3709                    assert_eq!(
3710                        ComplexRugStrictFinite::<53>::imag_part(&v_53bits_2).as_raw_scalar_ref(),
3711                        &2.
3712                    );
3713                }
3714
3715                #[test]
3716                #[should_panic]
3717                fn from_f64_failing() {
3718                    // `1.0 + f64::EPSILON` uses the least significant f64 mantissa bit, so it
3719                    // requires the full 53-bit f64 precision and must fail at 52 bits.
3720                    let value = 1.0 + f64::EPSILON;
3721                    let _v_52bits =
3722                        ComplexRugStrictFinite::<52>::try_from(Complex::new(value, 2.)).unwrap();
3723                }
3724
3725                #[test]
3726                fn conj() {
3727                    let v = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(16.25, 2.))
3728                        .unwrap();
3729
3730                    let v_conj = ComplexRugStrictFinite::<PRECISION>::conjugate(v);
3731                    assert_eq!(
3732                        ComplexRugStrictFinite::<PRECISION>::real_part(&v_conj).as_raw_scalar_ref(),
3733                        &16.25
3734                    );
3735                    assert_eq!(
3736                        ComplexRugStrictFinite::<PRECISION>::imag_part(&v_conj).as_raw_scalar_ref(),
3737                        &-2.
3738                    );
3739                }
3740
3741                #[test]
3742                fn neg_assign() {
3743                    let mut a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
3744                        .unwrap();
3745                    a.neg_assign();
3746
3747                    let a_expected =
3748                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., -2.))
3749                            .unwrap();
3750                    assert_eq!(a, a_expected);
3751                }
3752
3753                #[test]
3754                fn abs() {
3755                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-3., 4.))
3756                        .unwrap();
3757
3758                    let abs = a.abs();
3759                    let abs_expected = NonNegativeRealScalar::try_new(
3760                        RealRugStrictFinite::<100>::try_from_f64(5.).unwrap(),
3761                    )
3762                    .unwrap();
3763                    assert_eq!(abs, abs_expected);
3764                }
3765
3766                #[test]
3767                fn mul_add_ref() {
3768                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., -3.))
3769                        .unwrap();
3770                    let b = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 1.))
3771                        .unwrap();
3772                    let c = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., -4.))
3773                        .unwrap();
3774
3775                    let d_expected =
3776                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(10., -11.))
3777                            .unwrap();
3778
3779                    let d = a.mul_add_ref(&b, &c);
3780                    assert_eq!(d, d_expected);
3781                }
3782
3783                #[test]
3784                fn mul_complex_with_real() {
3785                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
3786                        .unwrap();
3787                    let b = RealRugStrictFinite::<100>::try_from_f64(3.).unwrap();
3788
3789                    let a_times_b_expected =
3790                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 6.))
3791                            .unwrap();
3792
3793                    test_mul_complex_with_real(a, b, a_times_b_expected);
3794                }
3795
3796                #[test]
3797                fn mul_assign_complex_with_real() {
3798                    let a = ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 2.))
3799                        .unwrap();
3800                    let b = RealRugStrictFinite::<100>::try_from_f64(3.).unwrap();
3801
3802                    let a_times_b_expected =
3803                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(3., 6.))
3804                            .unwrap();
3805
3806                    test_mul_assign_complex_with_real(a, b, a_times_b_expected);
3807                }
3808
3809                #[test]
3810                fn dot_product() {
3811                    let a = &[
3812                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(1., 3.))
3813                            .unwrap(),
3814                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(2., 4.))
3815                            .unwrap(),
3816                    ];
3817
3818                    let b = &[
3819                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-2., -5.))
3820                            .unwrap(),
3821                        ComplexRugStrictFinite::<PRECISION>::try_from(Complex::new(-1., 6.))
3822                            .unwrap(),
3823                    ];
3824
3825                    let a: Vec<_> = a.iter().map(|a_i| a_i.as_raw_scalar_ref()).collect();
3826                    let b: Vec<_> = b.iter().map(|b_i| b_i.as_raw_scalar_ref()).collect();
3827
3828                    // computes a * a^T
3829                    let a_times_a = ComplexRugStrictFinite::<PRECISION>::try_new(
3830                        rug::Complex::dot(a.clone().into_iter().zip(a.clone()))
3831                            .complete((100, 100)),
3832                    )
3833                    .unwrap();
3834                    assert_eq!(
3835                        a_times_a.as_raw_scalar_ref(),
3836                        &rug::Complex::with_val(100, (-20., 22.))
3837                    );
3838
3839                    // computes a * b^T
3840                    let a_times_b = ComplexRugStrictFinite::<PRECISION>::try_new(
3841                        rug::Complex::dot(a.clone().into_iter().zip(b.clone()))
3842                            .complete((100, 100)),
3843                    )
3844                    .unwrap();
3845                    assert_eq!(
3846                        a_times_b.as_raw_scalar_ref(),
3847                        &rug::Complex::with_val(100, (-13., -3.))
3848                    );
3849
3850                    // computes b * a^T
3851                    let b_times_a = ComplexRugStrictFinite::<PRECISION>::try_new(
3852                        rug::Complex::dot(b.into_iter().zip(a)).complete((100, 100)),
3853                    )
3854                    .unwrap();
3855                    assert_eq!(
3856                        b_times_a.as_raw_scalar_ref(),
3857                        &rug::Complex::with_val(100, (-13., -3.))
3858                    );
3859                }
3860
3861                #[test]
3862                fn test_acos() {
3863                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3864                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3865                    )
3866                    .unwrap();
3867                    let result = value.clone().acos();
3868                    assert_eq!(
3869                        result,
3870                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3871                            PRECISION,
3872                            value.into_inner().acos()
3873                        ))
3874                        .unwrap()
3875                    );
3876                }
3877
3878                #[test]
3879                fn test_acosh() {
3880                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3881                        rug::Complex::with_val(PRECISION, (1.5, 0.5)),
3882                    )
3883                    .unwrap();
3884                    let result = value.clone().acosh();
3885                    assert_eq!(
3886                        result,
3887                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3888                            PRECISION,
3889                            value.into_inner().acosh()
3890                        ))
3891                        .unwrap()
3892                    );
3893                }
3894
3895                #[test]
3896                fn test_asin() {
3897                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3898                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3899                    )
3900                    .unwrap();
3901                    let result = value.clone().asin();
3902                    assert_eq!(
3903                        result,
3904                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3905                            PRECISION,
3906                            value.into_inner().asin()
3907                        ))
3908                        .unwrap()
3909                    );
3910                }
3911
3912                #[test]
3913                fn test_asinh() {
3914                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3915                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3916                    )
3917                    .unwrap();
3918                    let result = value.clone().asinh();
3919                    assert_eq!(
3920                        result,
3921                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3922                            PRECISION,
3923                            value.into_inner().asinh()
3924                        ))
3925                        .unwrap()
3926                    );
3927                }
3928
3929                #[test]
3930                fn test_atan() {
3931                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3932                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3933                    )
3934                    .unwrap();
3935                    let result = value.clone().atan();
3936                    assert_eq!(
3937                        result,
3938                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3939                            PRECISION,
3940                            value.into_inner().atan()
3941                        ))
3942                        .unwrap()
3943                    );
3944                }
3945
3946                #[test]
3947                fn test_atanh() {
3948                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3949                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3950                    )
3951                    .unwrap();
3952                    let result = value.clone().atanh();
3953                    assert_eq!(
3954                        result,
3955                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3956                            PRECISION,
3957                            value.into_inner().atanh()
3958                        ))
3959                        .unwrap()
3960                    );
3961                }
3962
3963                #[test]
3964                fn test_cos_01() {
3965                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3966                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3967                    )
3968                    .unwrap();
3969                    let result = value.clone().cos();
3970                    assert_eq!(
3971                        result,
3972                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3973                            PRECISION,
3974                            value.into_inner().cos()
3975                        ))
3976                        .unwrap()
3977                    );
3978                }
3979
3980                #[test]
3981                fn test_cosh() {
3982                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
3983                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
3984                    )
3985                    .unwrap();
3986                    let result = value.clone().cosh();
3987                    assert_eq!(
3988                        result,
3989                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
3990                            PRECISION,
3991                            value.into_inner().cosh()
3992                        ))
3993                        .unwrap()
3994                    );
3995                }
3996
3997                #[test]
3998                fn test_exp() {
3999                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4000                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4001                    )
4002                    .unwrap();
4003                    let result = value.clone().exp();
4004                    println!("result = {result:?}");
4005                    assert_eq!(
4006                        result,
4007                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4008                            PRECISION,
4009                            value.into_inner().exp()
4010                        ))
4011                        .unwrap()
4012                    );
4013                }
4014
4015                #[test]
4016                fn test_is_finite() {
4017                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4018                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4019                    )
4020                    .unwrap();
4021                    assert!(value.is_finite());
4022
4023                    let value =
4024                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4025                            100,
4026                            (Float::with_val(PRECISION, f64::INFINITY), 0.5),
4027                        ));
4028                    assert!(value.is_err());
4029                }
4030
4031                #[test]
4032                fn test_is_infinite() {
4033                    let value =
4034                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4035                            100,
4036                            (Float::with_val(PRECISION, f64::INFINITY), 0.5),
4037                        ));
4038                    assert!(value.is_err());
4039
4040                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4041                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4042                    )
4043                    .unwrap();
4044                    assert!(!value.is_infinite());
4045                }
4046
4047                #[test]
4048                fn test_ln() {
4049                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4050                        rug::Complex::with_val(PRECISION, (std::f64::consts::E, 1.0)),
4051                    )
4052                    .unwrap();
4053                    let result = value.clone().ln();
4054                    println!("result = {result:?}");
4055                    assert_eq!(
4056                        result,
4057                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4058                            PRECISION,
4059                            value.into_inner().ln()
4060                        ))
4061                        .unwrap()
4062                    );
4063                }
4064
4065                #[test]
4066                fn test_log10() {
4067                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4068                        rug::Complex::with_val(PRECISION, (10.0, 1.0)),
4069                    )
4070                    .unwrap();
4071                    let result = value.clone().log10();
4072                    println!("result = {result:?}");
4073                    assert_eq!(
4074                        result,
4075                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4076                            PRECISION,
4077                            value.into_inner().log10()
4078                        ))
4079                        .unwrap()
4080                    );
4081                }
4082
4083                #[test]
4084                fn test_log2() {
4085                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4086                        rug::Complex::with_val(PRECISION, (8.0, 1.0)),
4087                    )
4088                    .unwrap();
4089                    let result = value.clone().log2();
4090                    println!("result = {result:?}");
4091                    assert_eq!(
4092                        result,
4093                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4094                            PRECISION,
4095                            value.into_inner().ln() / rug::Float::with_val(PRECISION, 2.).ln()
4096                        ))
4097                        .unwrap()
4098                    );
4099                }
4100
4101                #[test]
4102                fn test_recip() {
4103                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4104                        rug::Complex::with_val(PRECISION, (2.0, 0.0)),
4105                    )
4106                    .unwrap();
4107                    let result = value.clone().try_reciprocal().unwrap();
4108                    assert_eq!(
4109                        result,
4110                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4111                            PRECISION,
4112                            value.into_inner().recip()
4113                        ))
4114                        .unwrap()
4115                    );
4116                }
4117
4118                #[test]
4119                fn test_sin_01() {
4120                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4121                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4122                    )
4123                    .unwrap();
4124                    let result = value.clone().sin();
4125                    assert_eq!(
4126                        result,
4127                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4128                            PRECISION,
4129                            value.into_inner().sin()
4130                        ))
4131                        .unwrap()
4132                    );
4133                }
4134
4135                #[test]
4136                fn test_sinh() {
4137                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4138                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4139                    )
4140                    .unwrap();
4141                    let result = value.clone().sinh();
4142                    assert_eq!(
4143                        result,
4144                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4145                            PRECISION,
4146                            value.into_inner().sinh()
4147                        ))
4148                        .unwrap()
4149                    );
4150                }
4151
4152                #[test]
4153                fn sqrt() {
4154                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4155                        rug::Complex::with_val(PRECISION, (4.0, 1.0)),
4156                    )
4157                    .unwrap();
4158                    let result = value.clone().sqrt();
4159                    assert_eq!(
4160                        result,
4161                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4162                            PRECISION,
4163                            value.into_inner().sqrt()
4164                        ))
4165                        .unwrap()
4166                    );
4167                }
4168
4169                #[test]
4170                fn try_sqrt() {
4171                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4172                        rug::Complex::with_val(PRECISION, (4.0, 1.0)),
4173                    )
4174                    .unwrap();
4175                    let result = value.clone().try_sqrt().unwrap();
4176                    assert_eq!(
4177                        result,
4178                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4179                            PRECISION,
4180                            value.into_inner().sqrt()
4181                        ))
4182                        .unwrap()
4183                    );
4184                }
4185
4186                #[test]
4187                fn test_tan() {
4188                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4189                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4190                    )
4191                    .unwrap();
4192                    let result = value.clone().tan();
4193                    assert_eq!(
4194                        result,
4195                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4196                            PRECISION,
4197                            value.into_inner().tan()
4198                        ))
4199                        .unwrap()
4200                    );
4201                }
4202
4203                #[test]
4204                fn test_tanh() {
4205                    let value = ComplexRugStrictFinite::<PRECISION>::try_new(
4206                        rug::Complex::with_val(PRECISION, (0.5, 0.5)),
4207                    )
4208                    .unwrap();
4209                    let result = value.clone().tanh();
4210                    assert_eq!(
4211                        result,
4212                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4213                            PRECISION,
4214                            value.into_inner().tanh()
4215                        ))
4216                        .unwrap()
4217                    );
4218                }
4219
4220                #[test]
4221                fn test_mul_add() {
4222                    let a = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4223                        PRECISION,
4224                        (2.0, 1.0),
4225                    ))
4226                    .unwrap();
4227                    let b = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4228                        PRECISION,
4229                        (3.0, 1.0),
4230                    ))
4231                    .unwrap();
4232                    let c = ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4233                        PRECISION,
4234                        (4.0, 1.0),
4235                    ))
4236                    .unwrap();
4237                    let result = a.clone().mul_add_ref(&b, &c);
4238                    assert_eq!(
4239                        result,
4240                        ComplexRugStrictFinite::<PRECISION>::try_new(rug::Complex::with_val(
4241                            PRECISION,
4242                            a.as_raw_scalar_ref() * b.as_raw_scalar_ref() + c.as_raw_scalar_ref()
4243                        ))
4244                        .unwrap()
4245                    );
4246                }
4247            }
4248        }
4249    }
4250
4251    mod functions_real_type {
4252        use super::*;
4253
4254        mod native {
4255
4256            use super::*;
4257
4258            #[test]
4259            fn test_atan2() {
4260                let a: f64 = 27.0;
4261                let b: f64 = 13.0;
4262
4263                let result = a.atan2(b);
4264                assert_eq!(result, a.atan2(b));
4265            }
4266
4267            #[test]
4268            fn test_ceil() {
4269                let value: f64 = 3.7;
4270                let result = value.kernel_ceil();
4271                assert_eq!(result, value.ceil());
4272            }
4273
4274            #[test]
4275            fn test_clamp() {
4276                let value: f64 = 5.0;
4277                let min: f64 = 3.0;
4278                let max: f64 = 7.0;
4279                let result = Clamp::clamp_ref(value, &min, &max);
4280                assert_eq!(result, f64::clamp(value, min, max));
4281            }
4282
4283            #[test]
4284            fn test_classify() {
4285                let value: f64 = 3.7;
4286                let result = Classify::classify(&value);
4287                assert_eq!(result, f64::classify(value));
4288            }
4289
4290            #[test]
4291            fn test_copysign() {
4292                let value: f64 = 3.5;
4293                let sign: f64 = -1.0;
4294                let result = value.kernel_copysign(&sign);
4295                assert_eq!(result, value.copysign(sign));
4296            }
4297
4298            #[test]
4299            fn test_epsilon() {
4300                let eps = f64::epsilon();
4301                assert_eq!(eps, f64::EPSILON);
4302            }
4303
4304            #[test]
4305            fn test_exp_m1() {
4306                let value: f64 = 0.5;
4307                let result = ExpM1::exp_m1(value);
4308                assert_eq!(result, f64::exp_m1(value));
4309            }
4310
4311            #[test]
4312            fn test_floor() {
4313                let value: f64 = 3.7;
4314                let result = value.kernel_floor();
4315                assert_eq!(result, value.floor());
4316            }
4317
4318            #[test]
4319            fn test_fract() {
4320                let value: f64 = 3.7;
4321                let result = value.kernel_fract();
4322                assert_eq!(result, value.fract());
4323            }
4324
4325            #[test]
4326            fn test_hypot() {
4327                let a: f64 = 3.0;
4328                let b: f64 = 4.0;
4329                let result = Hypot::hypot(a, &b);
4330                assert_eq!(result, f64::hypot(a, b));
4331            }
4332
4333            #[test]
4334            fn test_is_sign_negative() {
4335                let value: f64 = -1.0;
4336                assert!(value.kernel_is_sign_negative());
4337
4338                let value: f64 = -0.0;
4339                assert!(value.kernel_is_sign_negative());
4340
4341                let value: f64 = 0.0;
4342                assert!(!value.kernel_is_sign_negative());
4343
4344                let value: f64 = 1.0;
4345                assert!(!value.kernel_is_sign_negative());
4346            }
4347
4348            #[test]
4349            fn test_is_sign_positive() {
4350                let value: f64 = -1.0;
4351                assert!(!value.kernel_is_sign_positive());
4352
4353                let value: f64 = -0.0;
4354                assert!(!value.kernel_is_sign_positive());
4355
4356                let value: f64 = 0.0;
4357                assert!(value.kernel_is_sign_positive());
4358
4359                let value: f64 = 1.0;
4360                assert!(value.kernel_is_sign_positive());
4361            }
4362
4363            #[test]
4364            fn test_ln_1p() {
4365                let value: f64 = 0.5;
4366                let result = Ln1p::ln_1p(value);
4367                assert_eq!(result, f64::ln_1p(value));
4368            }
4369
4370            #[test]
4371            fn test_max() {
4372                let a: f64 = 3.0;
4373                let b: f64 = 4.0;
4374                let result = a.max(b);
4375                assert_eq!(result, a.max(b));
4376            }
4377
4378            #[test]
4379            fn test_min() {
4380                let a: f64 = 3.0;
4381                let b: f64 = 4.0;
4382                let result = a.min(b);
4383                assert_eq!(result, a.min(b));
4384            }
4385
4386            #[test]
4387            fn max_finite() {
4388                let max = f64::max_finite();
4389                assert_eq!(max, f64::MAX);
4390            }
4391
4392            #[test]
4393            fn min_finite() {
4394                let min = f64::min_finite();
4395                assert_eq!(min, f64::MIN);
4396            }
4397
4398            #[test]
4399            fn test_mul_add_mul_mut() {
4400                let mut a: f64 = 2.0;
4401                let b: f64 = 3.0;
4402                let c: f64 = 4.0;
4403                let d: f64 = -1.0;
4404                let mut result = a;
4405                result.kernel_mul_add_mul_mut(&b, &c, &d);
4406
4407                a.mul_add_assign(b, c * d);
4408                assert_eq!(result, a);
4409            }
4410
4411            #[test]
4412            fn test_mul_sub_mul_mut() {
4413                let mut a: f64 = 2.0;
4414                let b: f64 = 3.0;
4415                let c: f64 = 4.0;
4416                let d: f64 = -1.0;
4417                let mut result = a;
4418                result.kernel_mul_sub_mul_mut(&b, &c, &d);
4419
4420                a.mul_add_assign(b, -c * d);
4421                assert_eq!(result, a);
4422            }
4423
4424            #[test]
4425            fn test_negative_one() {
4426                let value = f64::negative_one();
4427                assert_eq!(value, -1.0);
4428            }
4429
4430            #[test]
4431            fn test_one() {
4432                let value = f64::one();
4433                assert_eq!(value, 1.0);
4434            }
4435
4436            #[test]
4437            fn test_round() {
4438                let value: f64 = 3.5;
4439                let result = value.kernel_round();
4440                assert_eq!(result, value.round());
4441            }
4442
4443            #[test]
4444            fn test_round_ties_even() {
4445                let value: f64 = 3.5;
4446                let result = value.kernel_round_ties_even();
4447                assert_eq!(result, value.round_ties_even());
4448            }
4449
4450            #[test]
4451            fn test_signum() {
4452                let value: f64 = -3.5;
4453                let result = value.kernel_signum();
4454                assert_eq!(result, value.signum());
4455            }
4456
4457            #[test]
4458            fn test_total_cmp() {
4459                let a: f64 = 3.0;
4460                let b: f64 = 4.0;
4461                let result = a.total_cmp(&b);
4462                assert_eq!(result, a.total_cmp(&b));
4463            }
4464
4465            #[test]
4466            fn test_try_from_64() {
4467                let result = f64::try_from_f64(3.7);
4468                assert!(result.is_ok());
4469            }
4470
4471            #[test]
4472            #[cfg(debug_assertions)]
4473            fn test_try_from_64_error_infinite() {
4474                let result = f64::try_from_f64(f64::INFINITY);
4475                assert!(result.is_err());
4476            }
4477
4478            #[test]
4479            #[cfg(debug_assertions)]
4480            fn test_try_from_64_error_nan() {
4481                let result = f64::try_from_f64(f64::NAN);
4482                assert!(result.is_err());
4483            }
4484
4485            #[test]
4486            fn test_try_from_32() {
4487                let result = f64::try_from_f32(3.7_f32);
4488                assert!(result.is_ok());
4489            }
4490
4491            #[test]
4492            #[cfg(debug_assertions)]
4493            fn test_try_from_32_error_infinite() {
4494                let result = f64::try_from_f32(f32::INFINITY);
4495                assert!(result.is_err());
4496            }
4497
4498            #[test]
4499            #[cfg(debug_assertions)]
4500            fn test_try_from_32_error_nan() {
4501                let result = f64::try_from_f32(f32::NAN);
4502                assert!(result.is_err());
4503            }
4504
4505            #[test]
4506            fn test_trunc() {
4507                let value: f64 = 3.7;
4508                let result = value.kernel_trunc();
4509                assert_eq!(result, value.trunc());
4510            }
4511
4512            #[test]
4513            fn test_two() {
4514                let value = f64::two();
4515                assert_eq!(value, 2.0);
4516            }
4517        }
4518
4519        #[cfg(feature = "rug")]
4520        mod rug100 {
4521            use super::*;
4522            use crate::backends::rug::validated::RealRugStrictFinite;
4523            use rug::{Float, ops::CompleteRound};
4524            use try_create::{IntoInner, TryNew};
4525
4526            const PRECISION: u32 = 100;
4527
4528            #[test]
4529            fn from_f64() {
4530                let v_100bits = RealRugStrictFinite::<100>::try_from_f64(16.25).unwrap();
4531
4532                assert_eq!(v_100bits.as_raw_scalar_ref(), &16.25);
4533
4534                let v_53bits = RealRugStrictFinite::<53>::try_from_f64(16.25).unwrap();
4535                assert_eq!(v_53bits.as_raw_scalar_ref(), &16.25);
4536
4537                // 16.25 can be exactly represented with far fewer than 53 bits, so it is
4538                // not suitable for testing the minimum f64-equivalent precision boundary.
4539                let v_53bits_2 = RealRugStrictFinite::<53>::try_from_f64(16.25).unwrap();
4540                assert_eq!(v_53bits_2.as_raw_scalar_ref(), &16.25);
4541            }
4542
4543            #[test]
4544            #[should_panic]
4545            fn from_f64_failing() {
4546                // `1.0 + f64::EPSILON` uses the least significant f64 mantissa bit, so it
4547                // requires the full 53-bit f64 precision and must fail at 52 bits.
4548                let value = 1.0 + f64::EPSILON;
4549                let _v_52bits = RealRugStrictFinite::<52>::try_from_f64(value).unwrap();
4550            }
4551
4552            #[test]
4553            fn max_finite() {
4554                let max = RealRugStrictFinite::<53>::max_finite();
4555                assert_eq!(
4556                    max.as_raw_scalar_ref(),
4557                    &rug::Float::with_val(
4558                        53,
4559                        rug::Float::parse("1.0492893582336937e323228496").unwrap()
4560                    )
4561                );
4562            }
4563
4564            #[test]
4565            fn min_finite() {
4566                let min = RealRugStrictFinite::<53>::min_finite();
4567                assert_eq!(
4568                    min.as_raw_scalar_ref(),
4569                    &rug::Float::with_val(
4570                        53,
4571                        rug::Float::parse("-1.0492893582336937e323228496").unwrap()
4572                    )
4573                );
4574            }
4575
4576            #[test]
4577            fn test_atan2() {
4578                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 27.0))
4579                    .unwrap();
4580                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 13.0))
4581                    .unwrap();
4582                let result = a.clone().atan2(&b);
4583                assert_eq!(
4584                    result,
4585                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4586                        PRECISION,
4587                        a.into_inner().atan2(b.as_raw_scalar_ref())
4588                    ))
4589                    .unwrap()
4590                );
4591            }
4592
4593            #[test]
4594            fn test_ceil() {
4595                let value =
4596                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
4597                        .unwrap();
4598                let result = value.clone().kernel_ceil();
4599                assert_eq!(
4600                    result,
4601                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4602                        PRECISION,
4603                        value.into_inner().ceil()
4604                    ))
4605                    .unwrap()
4606                );
4607            }
4608
4609            #[test]
4610            fn test_clamp() {
4611                let value =
4612                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 5.0))
4613                        .unwrap();
4614                let min =
4615                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4616                        .unwrap();
4617                let max =
4618                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 7.0))
4619                        .unwrap();
4620                let result = value.clone().clamp_ref(&min, &max);
4621                assert_eq!(
4622                    result,
4623                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4624                        PRECISION,
4625                        value
4626                            .into_inner()
4627                            .clamp_ref(min.as_raw_scalar_ref(), max.as_raw_scalar_ref())
4628                    ))
4629                    .unwrap()
4630                );
4631            }
4632
4633            #[test]
4634            fn test_classify() {
4635                let value =
4636                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
4637                        .unwrap();
4638                let result = value.classify();
4639                assert_eq!(result, value.into_inner().classify());
4640            }
4641
4642            #[test]
4643            fn test_copysign() {
4644                let value =
4645                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
4646                        .unwrap();
4647                let sign =
4648                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
4649                        .unwrap();
4650                let result = value.clone().kernel_copysign(&sign);
4651                assert_eq!(
4652                    result,
4653                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4654                        PRECISION,
4655                        value.into_inner().copysign(sign.as_raw_scalar_ref())
4656                    ))
4657                    .unwrap()
4658                );
4659            }
4660
4661            #[test]
4662            fn test_epsilon() {
4663                let rug_eps = rug::Float::u_pow_u(2, PRECISION - 1)
4664                    .complete(PRECISION)
4665                    .recip();
4666                //println!("eps: {}", rug_eps);
4667
4668                let eps = RealRugStrictFinite::<PRECISION>::epsilon();
4669                assert_eq!(
4670                    eps,
4671                    RealRugStrictFinite::<PRECISION>::try_new(rug_eps.clone()).unwrap()
4672                );
4673
4674                // here we compute new_eps as the difference between 1 and the next larger floating point number
4675                let mut new_eps = Float::with_val(PRECISION, 1.);
4676                new_eps.next_up();
4677                new_eps -= Float::with_val(PRECISION, 1.);
4678                assert_eq!(new_eps, rug_eps.clone());
4679
4680                //println!("new_eps: {new_eps}");
4681
4682                let one = RealRugStrictFinite::<PRECISION>::one();
4683                let result = RealRugStrictFinite::<PRECISION>::try_new(
4684                    new_eps / Float::with_val(PRECISION, 2.),
4685                )
4686                .unwrap()
4687                    + &one;
4688                assert_eq!(result, one);
4689            }
4690
4691            #[test]
4692            fn test_exp_m1() {
4693                let value =
4694                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
4695                        .unwrap();
4696                let result = value.clone().exp_m1();
4697                assert_eq!(
4698                    result,
4699                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4700                        PRECISION,
4701                        value.into_inner().exp_m1()
4702                    ))
4703                    .unwrap()
4704                );
4705            }
4706
4707            #[test]
4708            fn test_floor() {
4709                let value =
4710                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
4711                        .unwrap();
4712                let result = value.clone().kernel_floor();
4713                assert_eq!(
4714                    result,
4715                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4716                        PRECISION,
4717                        value.into_inner().floor()
4718                    ))
4719                    .unwrap()
4720                );
4721            }
4722
4723            #[test]
4724            fn test_fract() {
4725                let value =
4726                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
4727                        .unwrap();
4728                let result = value.clone().kernel_fract();
4729                assert_eq!(
4730                    result,
4731                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4732                        PRECISION,
4733                        value.into_inner().fract()
4734                    ))
4735                    .unwrap()
4736                );
4737            }
4738
4739            #[test]
4740            fn test_hypot() {
4741                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4742                    .unwrap();
4743                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
4744                    .unwrap();
4745                let result = a.clone().hypot(&b);
4746                assert_eq!(
4747                    result,
4748                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4749                        PRECISION,
4750                        a.into_inner().hypot(b.as_raw_scalar_ref())
4751                    ))
4752                    .unwrap()
4753                );
4754            }
4755
4756            #[test]
4757            fn test_is_sign_negative() {
4758                let value =
4759                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
4760                        .unwrap();
4761                assert!(value.kernel_is_sign_negative());
4762
4763                let value =
4764                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -0.0))
4765                        .unwrap();
4766                assert!(value.kernel_is_sign_negative());
4767
4768                let value =
4769                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0))
4770                        .unwrap();
4771                assert!(!value.kernel_is_sign_negative());
4772
4773                let value =
4774                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
4775                        .unwrap();
4776                assert!(!value.kernel_is_sign_negative());
4777            }
4778
4779            #[test]
4780            fn test_is_sign_positive() {
4781                let value =
4782                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
4783                        .unwrap();
4784                assert!(!value.kernel_is_sign_positive());
4785
4786                let value =
4787                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -0.0))
4788                        .unwrap();
4789                assert!(!value.kernel_is_sign_positive());
4790
4791                let value =
4792                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.0))
4793                        .unwrap();
4794                assert!(value.kernel_is_sign_positive());
4795
4796                let value =
4797                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
4798                        .unwrap();
4799                assert!(value.kernel_is_sign_positive());
4800            }
4801
4802            #[test]
4803            fn test_ln_1p() {
4804                let value =
4805                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 0.5))
4806                        .unwrap();
4807                let result = value.clone().ln_1p();
4808                assert_eq!(
4809                    result,
4810                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4811                        PRECISION,
4812                        value.into_inner().ln_1p()
4813                    ))
4814                    .unwrap()
4815                );
4816            }
4817
4818            #[test]
4819            fn test_max() {
4820                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4821                    .unwrap();
4822                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
4823                    .unwrap();
4824                let result = a.max_by_ref(&b);
4825                assert_eq!(
4826                    result,
4827                    &RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4828                        PRECISION,
4829                        a.clone().into_inner().max(b.as_raw_scalar_ref())
4830                    ))
4831                    .unwrap()
4832                );
4833            }
4834
4835            #[test]
4836            fn test_min() {
4837                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4838                    .unwrap();
4839                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
4840                    .unwrap();
4841                let result = a.min_by_ref(&b);
4842                assert_eq!(
4843                    result,
4844                    &RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4845                        PRECISION,
4846                        a.clone().into_inner().min(b.as_raw_scalar_ref())
4847                    ))
4848                    .unwrap()
4849                );
4850            }
4851
4852            #[test]
4853            fn test_mul_add_mul_mut() {
4854                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
4855                    .unwrap();
4856                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4857                    .unwrap();
4858                let c = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
4859                    .unwrap();
4860                let d = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
4861                    .unwrap();
4862                let mut result = a.clone();
4863                result.kernel_mul_add_mul_mut(&b, &c, &d);
4864                assert_eq!(
4865                    result,
4866                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4867                        PRECISION,
4868                        a.into_inner().mul_add_ref(
4869                            b.as_raw_scalar_ref(),
4870                            &(c.into_inner() * d.as_raw_scalar_ref())
4871                        )
4872                    ))
4873                    .unwrap()
4874                );
4875            }
4876
4877            #[test]
4878            fn test_mul_sub_mul_mut() {
4879                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
4880                    .unwrap();
4881                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4882                    .unwrap();
4883                let c = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
4884                    .unwrap();
4885                let d = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
4886                    .unwrap();
4887                let mut result = a.clone();
4888                result.kernel_mul_sub_mul_mut(&b, &c, &d);
4889                assert_eq!(
4890                    result,
4891                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4892                        PRECISION,
4893                        a.into_inner().mul_add_ref(
4894                            b.as_raw_scalar_ref(),
4895                            &(-c.into_inner() * d.as_raw_scalar_ref())
4896                        )
4897                    ))
4898                    .unwrap()
4899                );
4900            }
4901
4902            #[test]
4903            fn test_negative_one() {
4904                let value = RealRugStrictFinite::<PRECISION>::negative_one();
4905                assert_eq!(
4906                    value,
4907                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -1.0))
4908                        .unwrap()
4909                );
4910            }
4911
4912            #[test]
4913            fn test_one() {
4914                let value = RealRugStrictFinite::<PRECISION>::one();
4915                assert_eq!(
4916                    value,
4917                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 1.0))
4918                        .unwrap()
4919                );
4920            }
4921
4922            #[test]
4923            fn test_round() {
4924                let value =
4925                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
4926                        .unwrap();
4927                let result = value.clone().kernel_round();
4928                assert_eq!(
4929                    result,
4930                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4931                        PRECISION,
4932                        value.into_inner().round()
4933                    ))
4934                    .unwrap()
4935                );
4936            }
4937
4938            #[test]
4939            fn test_round_ties_even() {
4940                let value =
4941                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.5))
4942                        .unwrap();
4943                let result = value.clone().kernel_round_ties_even();
4944                assert_eq!(
4945                    result,
4946                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4947                        PRECISION,
4948                        value.into_inner().round_even()
4949                    ))
4950                    .unwrap()
4951                );
4952            }
4953
4954            #[test]
4955            fn test_signum() {
4956                let value =
4957                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, -3.5))
4958                        .unwrap();
4959                let result = value.clone().kernel_signum();
4960                assert_eq!(
4961                    result,
4962                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
4963                        PRECISION,
4964                        value.into_inner().signum()
4965                    ))
4966                    .unwrap()
4967                );
4968            }
4969
4970            #[test]
4971            fn test_total_cmp() {
4972                let a = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.0))
4973                    .unwrap();
4974                let b = RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 4.0))
4975                    .unwrap();
4976                let result = a.total_cmp(&b);
4977                assert_eq!(result, a.into_inner().total_cmp(b.as_raw_scalar_ref()));
4978            }
4979
4980            #[test]
4981            fn test_try_from_64() {
4982                let result = RealRugStrictFinite::<PRECISION>::try_from_f64(3.7);
4983                assert!(result.is_ok());
4984            }
4985
4986            #[test]
4987            fn test_try_from_64_error_infinite() {
4988                let result = RealRugStrictFinite::<PRECISION>::try_from_f64(f64::INFINITY);
4989                assert!(result.is_err());
4990            }
4991
4992            #[test]
4993            fn test_try_from_64_error_nan() {
4994                let result = RealRugStrictFinite::<PRECISION>::try_from_f64(f64::NAN);
4995                assert!(result.is_err());
4996            }
4997
4998            #[test]
4999            fn test_try_from_32() {
5000                let result = RealRugStrictFinite::<PRECISION>::try_from_f32(3.7_f32);
5001                assert!(result.is_ok());
5002            }
5003
5004            #[test]
5005            fn test_try_from_32_error_infinite() {
5006                let result = RealRugStrictFinite::<PRECISION>::try_from_f32(f32::INFINITY);
5007                assert!(result.is_err());
5008            }
5009
5010            #[test]
5011            fn test_try_from_32_error_nan() {
5012                let result = RealRugStrictFinite::<PRECISION>::try_from_f32(f32::NAN);
5013                assert!(result.is_err());
5014            }
5015
5016            #[test]
5017            fn test_trunc() {
5018                let value =
5019                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 3.7))
5020                        .unwrap();
5021                let result = value.clone().kernel_trunc();
5022                assert_eq!(
5023                    result,
5024                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(
5025                        PRECISION,
5026                        value.into_inner().trunc()
5027                    ))
5028                    .unwrap()
5029                );
5030            }
5031
5032            #[test]
5033            fn test_two() {
5034                let value = RealRugStrictFinite::<PRECISION>::two();
5035                assert_eq!(
5036                    value,
5037                    RealRugStrictFinite::<PRECISION>::try_new(Float::with_val(PRECISION, 2.0))
5038                        .unwrap()
5039                );
5040            }
5041        }
5042    }
5043
5044    mod util_funcs {
5045        use crate::*;
5046        use rand::{SeedableRng, distr::Uniform, rngs::StdRng};
5047
5048        #[test]
5049        fn test_new_random_vec_deterministic() {
5050            let seed = [42; 32];
5051            let mut rng1 = StdRng::from_seed(seed);
5052            let mut rng2 = StdRng::from_seed(seed);
5053            let uniform = Uniform::new(-1.0, 1.0).unwrap();
5054
5055            let vec1: Vec<f64> = try_random_vec(10, &uniform, &mut rng1, 53).unwrap();
5056            let vec2: Vec<RealNative64StrictFinite> =
5057                try_random_vec(10, &uniform, &mut rng2, 53).unwrap();
5058
5059            assert_eq!(vec1.len(), 10);
5060            assert_eq!(vec2.len(), 10);
5061            for i in 0..10 {
5062                assert_eq!(&vec1[i], vec2[i].as_raw_scalar_ref());
5063            }
5064        }
5065
5066        #[test]
5067        fn test_try_sample_f32_requires_native_precision() {
5068            let mut rng = StdRng::from_seed([7; 32]);
5069            let distribution = Uniform::new(-1.0_f32, 1.0_f32).unwrap();
5070
5071            assert!(f32::try_sample_from(&distribution, &mut rng, 24).is_ok());
5072            assert!(matches!(
5073                f32::try_sample_from(&distribution, &mut rng, 53),
5074                Err(RawRealConversionError::InvalidOutputPrecision { .. })
5075            ));
5076        }
5077
5078        #[test]
5079        fn test_try_sample_f64_rejects_nan() {
5080            struct AlwaysNan;
5081
5082            impl rand::distr::Distribution<f64> for AlwaysNan {
5083                fn sample<R: Rng + ?Sized>(&self, _rng: &mut R) -> f64 {
5084                    f64::NAN
5085                }
5086            }
5087
5088            let mut rng = StdRng::from_seed([9; 32]);
5089            assert!(matches!(
5090                f64::try_sample_from(&AlwaysNan, &mut rng, 53),
5091                Err(RawRealConversionError::InputValidation { .. })
5092            ));
5093        }
5094
5095        #[cfg(feature = "rug")]
5096        #[test]
5097        fn test_try_sample_rug_float_uses_requested_precision() {
5098            let mut rng = StdRng::from_seed([8; 32]);
5099            let distribution = Uniform::new(-1.0, 1.0).unwrap();
5100
5101            let value = rug::Float::try_sample_from(&distribution, &mut rng, 100).unwrap();
5102            assert_eq!(value.precision_bits(), 100);
5103        }
5104
5105        #[test]
5106        fn test_try_vec_raw_into_vec_real_success() {
5107            let input = vec![1.0, -2.5, 1e10];
5108            let result = try_vec_raw_into_vec_real::<RealNative64StrictFinite, _>(input);
5109            assert!(result.is_ok());
5110            let output = result.unwrap();
5111            assert_eq!(output[0].as_raw_scalar_ref(), &1.0);
5112            assert_eq!(output[1].as_raw_scalar_ref(), &-2.5);
5113        }
5114
5115        #[test]
5116        fn test_try_vec_raw_into_vec_real_fail() {
5117            let input = vec![1.0, f64::NAN, 3.0];
5118            let result = try_vec_raw_into_vec_real::<RealNative64StrictFinite, _>(input);
5119            assert!(result.is_err());
5120        }
5121    }
5122}