1use std::{
2 fmt::Display,
3 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
4};
5
6#[cfg(feature = "cuda")]
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 exp(self) -> Self;
57 fn sin(self) -> Self;
59 fn cos(self) -> Self;
61 fn max(self, other: Self) -> Self;
63}
64
65pub trait NalgebraScalar:
67 Scalar + nalgebra::Scalar + nalgebra::SimdRealField + nalgebra::ComplexField<RealField = Self>
68{
69}
70
71impl<T> NalgebraScalar for T where
72 T: Scalar
73 + nalgebra::Scalar
74 + nalgebra::SimdRealField
75 + nalgebra::ComplexField<RealField = Self>
76{
77}
78
79pub trait FaerScalar: Scalar + faer::traits::ComplexField + faer::traits::RealField {}
81
82impl<T> FaerScalar for T where T: Scalar + faer::traits::ComplexField + faer::traits::RealField {}
83
84pub type IndexType = usize;
86
87impl Scalar for f64 {
88 const EPSILON: Self = f64::EPSILON;
89 const INFINITY: Self = f64::INFINITY;
90 const NAN: Self = f64::NAN;
91 fn is_nan(self) -> bool {
92 self.is_nan()
93 }
94 fn sqrt(self) -> Self {
95 self.sqrt()
96 }
97 fn exp(self) -> Self {
98 self.exp()
99 }
100 fn sin(self) -> Self {
101 self.sin()
102 }
103 fn cos(self) -> Self {
104 self.cos()
105 }
106 fn max(self, other: Self) -> Self {
107 self.max(other)
108 }
109}
110
111impl Scalar for f32 {
112 const EPSILON: Self = f32::EPSILON;
113 const INFINITY: Self = f32::INFINITY;
114 const NAN: Self = f32::NAN;
115 fn is_nan(self) -> bool {
116 self.is_nan()
117 }
118 fn sqrt(self) -> Self {
119 self.sqrt()
120 }
121 fn exp(self) -> Self {
122 self.exp()
123 }
124 fn sin(self) -> Self {
125 self.sin()
126 }
127 fn cos(self) -> Self {
128 self.cos()
129 }
130 fn max(self, other: Self) -> Self {
131 self.max(other)
132 }
133}
134
135impl<T: FaerScalar> From<faer::Scale<T>> for Scale<T> {
136 fn from(s: faer::Scale<T>) -> Self {
137 Scale(s.0)
138 }
139}
140impl<T: FaerScalar> From<Scale<T>> for faer::Scale<T> {
141 fn from(s: Scale<T>) -> Self {
142 faer::Scale(s.value())
143 }
144}
145impl<T: Scalar> From<T> for Scale<T> {
146 fn from(s: T) -> Self {
147 Scale(s)
148 }
149}
150
151#[derive(Copy, Clone, Debug)]
153pub struct Scale<E: Scalar>(pub E);
154
155impl<E: Scalar> Scale<E> {
156 #[inline]
158 pub fn value(self) -> E {
159 self.0
160 }
161}
162
163#[inline]
167pub fn scale<E: Scalar>(value: E) -> Scale<E> {
168 Scale(value)
169}
170
171macro_rules! impl_bin_op {
172 ($trait:ident, $method:ident, $operator:tt) => {
173 impl<E: Scalar> $trait<Scale<E>> for Scale<E> {
174 type Output = Scale<E>;
175
176 #[inline]
177 fn $method(self, rhs: Scale<E>) -> Self::Output {
178 Scale(self.0 $operator rhs.0)
179 }
180 }
181 };
182}
183
184macro_rules! impl_assign_bin_op {
185 ($trait:ident, $method:ident, $operator:tt) => {
186 impl<E: Scalar> $trait<Scale<E>> for Scale<E> {
187 #[inline]
188 fn $method(&mut self, rhs: Scale<E>) {
189 self.0 = self.0 $operator rhs.0
190 }
191 }
192 };
193}
194
195impl_bin_op!(Mul, mul, *);
196impl_bin_op!(Add, add, +);
197impl_bin_op!(Sub, sub, -);
198
199impl_assign_bin_op!(MulAssign, mul_assign, *);
200impl_assign_bin_op!(AddAssign, add_assign, +);
201impl_assign_bin_op!(SubAssign, sub_assign, -);
202
203impl<E: Scalar> PartialEq for Scale<E> {
204 #[inline]
205 fn eq(&self, rhs: &Self) -> bool {
206 self.0 == rhs.0
207 }
208}
209
210impl<V: VectorView<'static, T = E>, E: Scalar> Mul<V> for Scale<E> {
211 type Output = V::Owned;
212 #[inline]
213 fn mul(self, rhs: V) -> Self::Output {
214 rhs * scale(self.0)
215 }
216}
217
218#[test]
219fn test_scale() {
220 assert_eq!(scale(2.0) * scale(3.0), scale(6.0));
221}