num_valid/functions.rs
1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! # Scalar Numerical Functions Module
4//!
5//! This module provides a collection of traits and error types for common mathematical
6//! functions operating on scalar numerical values. These functions are designed to be
7//! generic over different floating-point and complex number types, including support
8//! for arbitrary-precision numbers via the [`rug`](https://crates.io/crates/rug) library (when the "rug" feature is enabled).
9//!
10//! ## Core Concepts
11//!
12//! - **Function Traits**: Each mathematical operation (e.g., [`Exp`], [`Ln`], [`Sin`], [`Pow`], etc.)
13//! is defined by a trait. These traits typically offer two methods:
14//! - `try_xxx()`: A fallible method that performs comprehensive validation of inputs
15//! and outputs, returning a [`Result`].
16//! - `xxx()`: An infallible method that aims for performance, especially in release
17//! builds. In debug builds, it usually calls `try_xxx().unwrap()`.
18//!
19//! - **Error Handling**: Errors are structured using the [`FunctionErrors`] enum, which
20//! distinguishes between input validation failures and output validation failures.
21//! Each function trait usually has an associated error type (e.g., [`ExpErrors`], [`LogarithmRealErrors`], etc.)
22//! that is a type alias for [`FunctionErrors`] specialized with function-specific
23//! input error enums (e.g., [`ExpInputErrors`], [`LogarithmRealInputErrors`], etc.).
24//!
25//! - **Validation**: Input and output values are typically validated using policies defined
26//! in the [`validation`](crate::validation) module (as implementation of the
27//! [`ValidationPolicy`](try_create::ValidationPolicy) trait from the [`try_create`](https://crates.io/crates/try_create) crate),
28//! with [`StrictFinitePolicy`](crate::validation::StrictFinitePolicy) being commonly used to ensure
29//! values are not NaN, Infinity, or subnormal.
30//!
31//! ## Provided Functions
32//!
33//! The module re-exports traits and error types for various categories of functions:
34//!
35//! - **Basic Operations**:
36//! - [`Abs`]: Absolute value.
37//! - [`NegAssign`]: In-place negation.
38//! - [`Reciprocal`]: Reciprocal (`1/x`).
39//! - [`Pow`]: Power function (`base^exponent`).
40//! - [`Sqrt`]: Square root.
41//! - **Exponential and Logarithmic**:
42//! - [`Exp`]: Exponential function (`e^x`).
43//! - [`Ln`]: Natural logarithm.
44//! - [`Log2`]: Base-2 logarithm.
45//! - [`Log10`]: Base-10 logarithm.
46//! - **Trigonometric**:
47//! - [`Sin`], [`Cos`], [`Tan`]: Basic trigonometric functions.
48//! - [`ASin`], [`ACos`], [`ATan`]: Inverse trigonometric functions.
49//! - [`ATan2`]: Four-quadrant inverse tangent.
50//! - **Hyperbolic**:
51//! - [`SinH`], [`CosH`], [`TanH`]: Hyperbolic functions.
52//! - [`ASinH`], [`ACosH`], [`ATanH`]: Inverse hyperbolic functions.
53//! - **Complex Number Operations**:
54//! - [`Arg`]: Argument (phase) of a complex number.
55//! - [`Conjugate`]: Complex conjugate.
56//! - **Comparison**:
57//! - [`Max`], [`Min`]: Maximum and minimum of two numbers.
58//!
59//! Each function is organized into its own submodule (e.g., `abs`, `exp`) and its
60//! public interface is re-exported here.
61
62use std::{
63 fmt::LowerExp,
64 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
65};
66use thiserror::Error;
67
68mod abs;
69pub(crate) mod complex;
70mod exponential;
71mod hyperbolic;
72mod logarithm;
73mod max_min;
74mod neg_assign;
75pub(crate) mod pow;
76mod real;
77mod reciprocal;
78pub(crate) mod sqrt;
79mod trigonometric;
80
81pub use abs::{Abs, AbsComplexErrors, AbsInputErrors, AbsRealErrors};
82pub use complex::{
83 Arg, ArgErrors, ArgInputErrors, ComplexScalarConstructors, ComplexScalarGetParts,
84 ComplexScalarMutateParts, ComplexScalarSetParts, Conjugate,
85};
86pub use exponential::{Exp, ExpErrors, ExpInputErrors};
87pub use hyperbolic::{
88 ACosH, ACosHErrors, ACosHInputErrors, ASinH, ASinHErrors, ASinHInputErrors, ATanH, ATanHErrors,
89 ATanHInputErrors, CosH, CosHErrors, CosHInputErrors, HyperbolicFunctions, SinH, SinHErrors,
90 SinHInputErrors, TanH, TanHComplexErrors, TanHComplexInputErrors, TanHRealErrors,
91 TanHRealInputErrors,
92};
93pub use logarithm::{
94 Ln, Log2, Log10, LogarithmComplexErrors, LogarithmComplexInputErrors, LogarithmFunctions,
95 LogarithmRealErrors, LogarithmRealInputErrors,
96};
97pub use max_min::{Max, Min};
98pub use neg_assign::NegAssign;
99pub use pow::{
100 Pow, PowComplexBaseRealExponentErrors, PowComplexBaseRealExponentInputErrors, PowIntExponent,
101 PowIntExponentErrors, PowIntExponentInputErrors, PowRealBaseRealExponentErrors,
102 PowRealBaseRealExponentInputErrors,
103};
104pub use real::{Clamp, Classify, ExpM1, Hypot, Ln1p, TotalCmp};
105pub use reciprocal::{Reciprocal, ReciprocalErrors, ReciprocalInputErrors};
106pub use sqrt::{
107 Sqrt, SqrtComplexErrors, SqrtComplexInputErrors, SqrtRealErrors, SqrtRealInputErrors,
108};
109pub use trigonometric::{
110 ACos, ACosComplexErrors, ACosComplexInputErrors, ACosRealErrors, ACosRealInputErrors, ASin,
111 ASinComplexErrors, ASinComplexInputErrors, ASinRealErrors, ASinRealInputErrors, ATan, ATan2,
112 ATan2Errors, ATan2InputErrors, ATanComplexErrors, ATanComplexInputErrors, ATanRealErrors,
113 ATanRealInputErrors, Cos, CosErrors, CosInputErrors, Sin, SinErrors, SinInputErrors, Tan,
114 TanComplexErrors, TanComplexInputErrors, TanRealErrors, TanRealInputErrors,
115 TrigonometricFunctions,
116};
117
118//-------------------------------------------------------------
119/// A convenience trait that aggregates the standard arithmetic operations.
120///
121/// This trait bundles the common arithmetic operator traits from `std::ops`
122/// (e.g., [`Add`], [`Sub`], [`Mul`], [`Div`], and their `*Assign` variants)
123/// into a single super-trait. It is used as a bound on [`FpScalar`](crate::FpScalar) to ensure
124/// all scalar types support basic arithmetic.
125///
126/// This trait does **not** require `Copy`. Instead, it explicitly requires that
127/// arithmetic operations are implemented for both owned values (`Self`) and
128/// references (`&Self`). This provides flexibility for both move and copy semantics,
129/// allowing implementors to avoid unnecessary clones in performance-sensitive code.
130pub trait Arithmetic:
131 Sized
132 + Add<Self, Output = Self>
133 + for<'a> Add<&'a Self, Output = Self>
134 + AddAssign
135 + for<'a> AddAssign<&'a Self>
136 + Sub<Output = Self>
137 + for<'a> Sub<&'a Self, Output = Self>
138 + SubAssign
139 + for<'a> SubAssign<&'a Self>
140 + Mul<Output = Self>
141 + for<'a> Mul<&'a Self, Output = Self>
142 + MulAssign
143 + for<'a> MulAssign<&'a Self>
144 + Div<Output = Self>
145 + for<'a> Div<&'a Self, Output = Self>
146 + DivAssign
147 + for<'a> DivAssign<&'a Self>
148 + Neg<Output = Self>
149 + NegAssign
150 + LowerExp
151{
152}
153//------------------------------------------------------------------------------------------------------------
154
155/// A generic error type for fallible numerical function computations.
156///
157/// This enum is used as a standard wrapper for function-specific errors,
158/// distinguishing between failures that occur during input validation and those
159/// that occur during output validation (or due to the computation itself resulting
160/// in an invalid value according to the defined policy).
161///
162/// # Type Parameters
163///
164/// - `InputError`: The type of the error that occurs if input validation fails.
165/// This is typically a function-specific enum detailing various input-related
166/// problems (e.g., [`ExpInputErrors`],, [`LogarithmRealInputErrors`], etc.).
167/// - `OutputError`: The type of the error that occurs if output validation fails.
168/// This is usually an error type related to the properties of the scalar value itself,
169/// often from the [`validation`](crate::validation) module (e.g.,
170/// [`ErrorsValidationRawReal`](crate::validation::ErrorsValidationRawReal) or
171/// [`ErrorsValidationRawComplex`](crate::validation::ErrorsValidationRawComplex)), indicating
172/// that the computed result is not valid (e.g., NaN, Infinity).
173#[derive(Debug, Error)]
174pub enum FunctionErrors<InputError: std::error::Error, OutputError: std::error::Error> {
175 /// Error due to invalid input values.
176 ///
177 /// This variant is returned when initial validation of the function's arguments
178 /// fails according to the defined validation policy (e.g.,
179 /// [`StrictFinitePolicy`](crate::validation::StrictFinitePolicy)) or due to
180 /// domain-specific constraints (e.g., negative input to a real logarithm).
181 #[error("the input value is not valid accordingly to the used validation policy!")]
182 Input {
183 /// The source error that occurred during input validation.
184 /// This provides specific details about why the input was considered invalid.
185 #[from] // Allows easy conversion from InputError to FunctionErrors::Input
186 source: InputError,
187 },
188
189 /// Error due to the computed output failing validation.
190 ///
191 /// This variant is returned if the result of the computation, even from
192 /// valid inputs, fails validation according to the defined policy. This
193 /// typically means the result was non-finite (NaN or Infinity) or otherwise
194 /// did not meet the criteria for a valid output.
195 #[error("the output value is not valid accordingly to the used validation policy!")]
196 Output {
197 /// The source error that occurred during output validation.
198 /// This provides specific details about why the computed output was
199 /// considered invalid.
200 #[source] // Indicates that `source` is the underlying cause of this error
201 #[backtrace] // Captures a backtrace when this error variant is created
202 source: OutputError,
203 },
204}
205
206//------------------------------------------------------------------------------------------------
207/// Trait for fused multiply-add operations.
208///
209/// This trait provides methods for computing `(self * b) + c` efficiently.
210///
211/// ## Why a custom `MulAddRef` trait?
212///
213/// This trait is distinct from [`num_traits::MulAdd`] primarily in its method signatures,
214/// which take `b` and `c` by reference (`&Self`). This is a deliberate design choice to:
215/// 1. **Maintain API Consistency:** Aligns with the other operator traits in this library that
216/// support by-reference operations.
217/// 2. **Reduce Cloning:** Allows implementors to avoid cloning values in performance-sensitive
218/// contexts, which is especially important for non-`Copy` types like [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
219///
220/// Implementors should aim to use hardware FMA (Fused Multiply-Add) instructions
221/// where available and appropriate for the underlying scalar type to improve
222/// performance and accuracy.
223pub trait MulAddRef {
224 /// Multiplies and adds in one fused operation, rounding to the nearest with only one rounding error.
225 ///
226 /// `a.mul_add_ref(b, c)` produces a result like `a * &b + &c`.
227 fn mul_add_ref(self, b: &Self, c: &Self) -> Self;
228}
229//------------------------------------------------------------------------------------------------
230
231/// Provides methods for rounding floating-point numbers.
232pub trait Rounding {
233 /// Returns the smallest integer greater than or equal to `self`.
234 fn kernel_ceil(self) -> Self;
235
236 /// Returns the largest integer smaller than or equal to `self`.
237 fn kernel_floor(self) -> Self;
238
239 /// Returns the fractional part of `self`.
240 fn kernel_fract(self) -> Self;
241
242 /// Rounds `self` to the nearest integer, rounding half-way cases away from zero.
243 fn kernel_round(self) -> Self;
244
245 /// Returns the nearest integer to a number. Rounds half-way cases to the number with an even least significant digit.
246 ///
247 /// This function always returns the precise result.
248 ///
249 /// # Examples
250 /// ```
251 /// use num_valid::functions::Rounding;
252 ///
253 /// let f = 3.3_f64;
254 /// let g = -3.3_f64;
255 /// let h = 3.5_f64;
256 /// let i = 4.5_f64;
257 ///
258 /// assert_eq!(f.kernel_round_ties_even(), 3.0);
259 /// assert_eq!(g.kernel_round_ties_even(), -3.0);
260 /// assert_eq!(h.kernel_round_ties_even(), 4.0);
261 /// assert_eq!(i.kernel_round_ties_even(), 4.0);
262 /// ```
263 fn kernel_round_ties_even(self) -> Self;
264
265 /// Returns the integer part of `self`. This means that non-integer numbers are always truncated towards zero.
266 ///
267 /// # Examples
268 /// ```
269 /// use num_valid::{RealScalar, functions::Rounding};
270 ///
271 /// let f = 3.7_f64;
272 /// let g = 3.0_f64;
273 /// let h = -3.7_f64;
274 ///
275 /// assert_eq!(f.kernel_trunc(), 3.0);
276 /// assert_eq!(g.kernel_trunc(), 3.0);
277 /// assert_eq!(h.kernel_trunc(), -3.0);
278 /// ```
279 fn kernel_trunc(self) -> Self;
280}
281
282/// Provides methods for sign manipulation and checking.
283pub trait Sign {
284 /// Returns a number with the magnitude of `self` and the sign of `sign`.
285 fn kernel_copysign(self, sign: &Self) -> Self;
286
287 /// Computes the signum.
288 ///
289 /// The returned value is:
290 /// - `1.0` if the value is positive, +0.0 or +∞
291 /// - `−1.0` if the value is negative, −0.0 or −∞
292 /// - `NaN` if the value is NaN
293 fn kernel_signum(self) -> Self;
294
295 /// Returns `true` if the value is negative, −0 or NaN with a negative sign.
296 fn kernel_is_sign_negative(&self) -> bool;
297
298 /// Returns `true` if the value is positive, +0 or NaN with a positive sign.
299 fn kernel_is_sign_positive(&self) -> bool;
300}