1use std::{
2 fmt::Display,
3 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
4};
5
6#[cfg(any(feature = "cuda", feature = "cuda-oxide"))]
7pub mod cuda;
8
9use crate::vector::VectorView;
10
11pub trait Scalar:
27 num_traits::Signed
28 + num_traits::Pow<Self, Output = Self>
29 + num_traits::Pow<i32, Output = Self>
30 + num_traits::FromPrimitive
31 + num_traits::ToPrimitive
32 + Display
33 + std::fmt::Debug
34 + Copy
35 + PartialEq
36 + PartialOrd
37 + AddAssign
38 + SubAssign
39 + MulAssign
40 + std::ops::DivAssign
41 + Send
42 + Sync
43 + 'static
44{
45 const EPSILON: Self;
47 const INFINITY: Self;
49 const NAN: Self;
51 fn is_nan(self) -> bool;
53 fn sqrt(self) -> Self;
55 fn cbrt(self) -> Self;
57 fn exp(self) -> Self;
59 fn sin(self) -> Self;
61 fn cos(self) -> Self;
63 fn max(self, other: Self) -> Self;
65
66 fn algebraic_add(self, other: Self) -> Self {
68 self + other
69 }
70 fn algebraic_sub(self, other: Self) -> Self {
72 self - other
73 }
74 fn algebraic_mul(self, other: Self) -> Self {
76 self * other
77 }
78 fn algebraic_div(self, other: Self) -> Self {
80 self / other
81 }
82}
83
84pub trait NalgebraScalar:
86 Scalar + nalgebra::Scalar + nalgebra::SimdRealField + nalgebra::ComplexField<RealField = Self>
87{
88}
89
90impl<T> NalgebraScalar for T where
91 T: Scalar
92 + nalgebra::Scalar
93 + nalgebra::SimdRealField
94 + nalgebra::ComplexField<RealField = Self>
95{
96}
97
98pub trait FaerScalar: Scalar + faer::traits::ComplexField + faer::traits::RealField {}
100
101impl<T> FaerScalar for T where T: Scalar + faer::traits::ComplexField + faer::traits::RealField {}
102
103pub type IndexType = usize;
105
106impl Scalar for f64 {
107 const EPSILON: Self = f64::EPSILON;
108 const INFINITY: Self = f64::INFINITY;
109 const NAN: Self = f64::NAN;
110 fn is_nan(self) -> bool {
111 self.is_nan()
112 }
113 fn sqrt(self) -> Self {
114 self.sqrt()
115 }
116 fn cbrt(self) -> Self {
117 self.cbrt()
118 }
119 fn exp(self) -> Self {
120 self.exp()
121 }
122 fn sin(self) -> Self {
123 self.sin()
124 }
125 fn cos(self) -> Self {
126 self.cos()
127 }
128 fn max(self, other: Self) -> Self {
129 self.max(other)
130 }
131 #[cfg(feature = "algebraic-ops")]
132 fn algebraic_add(self, other: Self) -> Self {
133 self.algebraic_add(other)
134 }
135 #[cfg(feature = "algebraic-ops")]
136 fn algebraic_sub(self, other: Self) -> Self {
137 self.algebraic_sub(other)
138 }
139 #[cfg(feature = "algebraic-ops")]
140 fn algebraic_mul(self, other: Self) -> Self {
141 self.algebraic_mul(other)
142 }
143 #[cfg(feature = "algebraic-ops")]
144 fn algebraic_div(self, other: Self) -> Self {
145 self.algebraic_div(other)
146 }
147}
148
149impl Scalar for f32 {
150 const EPSILON: Self = f32::EPSILON;
151 const INFINITY: Self = f32::INFINITY;
152 const NAN: Self = f32::NAN;
153 fn is_nan(self) -> bool {
154 self.is_nan()
155 }
156 fn sqrt(self) -> Self {
157 self.sqrt()
158 }
159 fn cbrt(self) -> Self {
160 self.cbrt()
161 }
162 fn exp(self) -> Self {
163 self.exp()
164 }
165 fn sin(self) -> Self {
166 self.sin()
167 }
168 fn cos(self) -> Self {
169 self.cos()
170 }
171 fn max(self, other: Self) -> Self {
172 self.max(other)
173 }
174 #[cfg(feature = "algebraic-ops")]
175 fn algebraic_add(self, other: Self) -> Self {
176 self.algebraic_add(other)
177 }
178 #[cfg(feature = "algebraic-ops")]
179 fn algebraic_sub(self, other: Self) -> Self {
180 self.algebraic_sub(other)
181 }
182 #[cfg(feature = "algebraic-ops")]
183 fn algebraic_mul(self, other: Self) -> Self {
184 self.algebraic_mul(other)
185 }
186 #[cfg(feature = "algebraic-ops")]
187 fn algebraic_div(self, other: Self) -> Self {
188 self.algebraic_div(other)
189 }
190}
191
192impl<T: FaerScalar> From<faer::Scale<T>> for Scale<T> {
193 fn from(s: faer::Scale<T>) -> Self {
194 Scale(s.0)
195 }
196}
197impl<T: FaerScalar> From<Scale<T>> for faer::Scale<T> {
198 fn from(s: Scale<T>) -> Self {
199 faer::Scale(s.value())
200 }
201}
202impl<T: Scalar> From<T> for Scale<T> {
203 fn from(s: T) -> Self {
204 Scale(s)
205 }
206}
207
208#[derive(Copy, Clone, Debug)]
210pub struct Scale<E: Scalar>(pub E);
211
212impl<E: Scalar> Scale<E> {
213 #[inline]
215 pub fn value(self) -> E {
216 self.0
217 }
218}
219
220#[inline]
224pub fn scale<E: Scalar>(value: E) -> Scale<E> {
225 Scale(value)
226}
227
228macro_rules! impl_bin_op {
229 ($trait:ident, $method:ident, $operator:tt) => {
230 impl<E: Scalar> $trait<Scale<E>> for Scale<E> {
231 type Output = Scale<E>;
232
233 #[inline]
234 fn $method(self, rhs: Scale<E>) -> Self::Output {
235 Scale(self.0 $operator rhs.0)
236 }
237 }
238 };
239}
240
241macro_rules! impl_assign_bin_op {
242 ($trait:ident, $method:ident, $operator:tt) => {
243 impl<E: Scalar> $trait<Scale<E>> for Scale<E> {
244 #[inline]
245 fn $method(&mut self, rhs: Scale<E>) {
246 self.0 = self.0 $operator rhs.0
247 }
248 }
249 };
250}
251
252impl_bin_op!(Mul, mul, *);
253impl_bin_op!(Add, add, +);
254impl_bin_op!(Sub, sub, -);
255
256impl_assign_bin_op!(MulAssign, mul_assign, *);
257impl_assign_bin_op!(AddAssign, add_assign, +);
258impl_assign_bin_op!(SubAssign, sub_assign, -);
259
260impl<E: Scalar> PartialEq for Scale<E> {
261 #[inline]
262 fn eq(&self, rhs: &Self) -> bool {
263 self.0 == rhs.0
264 }
265}
266
267impl<V: VectorView<'static, T = E>, E: Scalar> Mul<V> for Scale<E> {
268 type Output = V::Owned;
269 #[inline]
270 fn mul(self, rhs: V) -> Self::Output {
271 rhs * scale(self.0)
272 }
273}
274
275#[test]
276fn test_scale() {
277 assert_eq!(scale(2.0) * scale(3.0), scale(6.0));
278}