Skip to main content

oxiblas_core/scalar/
traits.rs

1//! Core scalar trait definitions: Scalar, Real, ComplexScalar, and Field.
2
3use core::fmt::{Debug, Display};
4use core::iter::Sum;
5use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
6use num_traits::{FromPrimitive, NumAssign, One, Zero};
7
8/// Base trait for all scalar types used in OxiBLAS.
9///
10/// This trait provides the fundamental requirements for any numeric type
11/// that can be used in matrix operations.
12pub trait Scalar:
13    Copy
14    + Clone
15    + Debug
16    + Display
17    + Default
18    + Send
19    + Sync
20    + PartialEq
21    + Zero
22    + One
23    + Add<Output = Self>
24    + Sub<Output = Self>
25    + Mul<Output = Self>
26    + Div<Output = Self>
27    + AddAssign
28    + SubAssign
29    + MulAssign
30    + DivAssign
31    + Neg<Output = Self>
32    + Sum
33    + NumAssign
34    + FromPrimitive
35    + 'static
36{
37    /// The real component type (for complex numbers, this is the component type).
38    type Real: Real;
39
40    /// Returns the absolute value (modulus for complex numbers).
41    fn abs(self) -> Self::Real;
42
43    /// Returns the complex conjugate. For real numbers, returns self.
44    fn conj(self) -> Self;
45
46    /// Returns true if this is a real type (not complex).
47    fn is_real() -> bool;
48
49    /// Returns the real part.
50    fn real(self) -> Self::Real;
51
52    /// Returns the imaginary part (zero for real types).
53    fn imag(self) -> Self::Real;
54
55    /// Creates a scalar from real and imaginary parts.
56    fn from_real_imag(re: Self::Real, im: Self::Real) -> Self;
57
58    /// Creates a scalar from just the real part (imaginary = 0).
59    fn from_real(re: Self::Real) -> Self {
60        Self::from_real_imag(re, Self::Real::zero())
61    }
62
63    /// Square of the absolute value (more efficient than abs().powi(2)).
64    fn abs_sq(self) -> Self::Real {
65        let re = self.real();
66        let im = self.imag();
67        re * re + im * im
68    }
69
70    /// Machine epsilon for this type.
71    fn epsilon() -> Self::Real;
72
73    /// Smallest positive normal value.
74    fn min_positive() -> Self::Real;
75
76    /// Largest finite value.
77    fn max_value() -> Self::Real;
78
79    /// Size of the type in bytes.
80    const SIZE: usize = core::mem::size_of::<Self>();
81
82    /// Alignment requirement.
83    const ALIGN: usize = core::mem::align_of::<Self>();
84}
85
86/// Trait for real number types (f32, f64).
87pub trait Real: Scalar<Real = Self> + num_traits::Float + PartialOrd {
88    /// Square root.
89    fn sqrt(self) -> Self;
90
91    /// Natural logarithm.
92    fn ln(self) -> Self;
93
94    /// Exponential function.
95    fn exp(self) -> Self;
96
97    /// Sine.
98    fn sin(self) -> Self;
99
100    /// Cosine.
101    fn cos(self) -> Self;
102
103    /// Arctangent of y/x with correct quadrant.
104    fn atan2(self, other: Self) -> Self;
105
106    /// Power function.
107    fn powf(self, n: Self) -> Self;
108
109    /// Sign function: 1.0 if positive, -1.0 if negative, 0.0 if zero.
110    fn signum(self) -> Self;
111
112    /// Fused multiply-add: self * a + b
113    fn mul_add(self, a: Self, b: Self) -> Self;
114
115    /// Floor function.
116    fn floor(self) -> Self;
117
118    /// Ceiling function.
119    fn ceil(self) -> Self;
120
121    /// Round to nearest integer.
122    fn round(self) -> Self;
123
124    /// Truncate toward zero.
125    fn trunc(self) -> Self;
126
127    /// Safe reciprocal (returns None if self is zero or would overflow).
128    fn safe_recip(self) -> Option<Self> {
129        if Scalar::abs(self) < Self::min_positive() {
130            None
131        } else {
132            Some(Self::one() / self)
133        }
134    }
135
136    /// Hypot: sqrt(self^2 + other^2) computed without overflow.
137    fn hypot(self, other: Self) -> Self;
138}
139
140/// Trait for complex scalar types.
141pub trait ComplexScalar: Scalar {
142    /// Creates a complex number from real and imaginary parts.
143    fn new(re: Self::Real, im: Self::Real) -> Self;
144
145    /// Returns the argument (phase angle) of the complex number.
146    fn arg(self) -> Self::Real;
147
148    /// Returns the polar form (r, theta) where self = r * e^(i*theta).
149    fn to_polar(self) -> (Self::Real, Self::Real) {
150        (self.abs(), self.arg())
151    }
152
153    /// Creates a complex number from polar form.
154    fn from_polar(r: Self::Real, theta: Self::Real) -> Self;
155
156    /// Complex exponential.
157    fn cexp(self) -> Self;
158
159    /// Complex logarithm (principal branch).
160    fn cln(self) -> Self;
161
162    /// Complex square root (principal branch).
163    fn csqrt(self) -> Self;
164}
165
166/// Field trait - complete algebraic structure with all operations.
167///
168/// This is the main trait used throughout OxiBLAS for generic programming
169/// over numeric types.
170pub trait Field: Scalar {
171    /// Computes self * alpha + other * beta
172    #[inline]
173    fn scale_add(self, alpha: Self, other: Self, beta: Self) -> Self {
174        self * alpha + other * beta
175    }
176
177    /// Computes self * conj(other) for complex, self * other for real.
178    fn mul_conj(self, other: Self) -> Self;
179
180    /// Computes conj(self) * other for complex, self * other for real.
181    fn conj_mul(self, other: Self) -> Self;
182
183    /// Reciprocal (1/self).
184    fn recip(self) -> Self;
185
186    /// Integer power.
187    fn powi(self, n: i32) -> Self;
188}