num_valid/
lib.rs

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