tensor4all_tcicore/
scalar.rs1use crate::matrix::BlasMul;
11use num_complex::{Complex32, Complex64};
12use num_traits::{Float, One, Zero};
13
14pub trait Scalar:
41 Clone
42 + Copy
43 + Zero
44 + One
45 + std::ops::Add<Output = Self>
46 + std::ops::Sub<Output = Self>
47 + std::ops::Mul<Output = Self>
48 + std::ops::Div<Output = Self>
49 + std::ops::Neg<Output = Self>
50 + Default
51 + Send
52 + Sync
53 + BlasMul
54 + 'static
55{
56 fn conj(self) -> Self;
58
59 fn abs_sq(self) -> f64;
61
62 fn abs(self) -> Self;
67
68 fn abs_val(self) -> f64 {
70 self.abs_sq().sqrt()
71 }
72
73 fn from_f64(val: f64) -> Self;
75
76 fn is_nan(self) -> bool;
78
79 fn epsilon() -> f64 {
84 f64::EPSILON
85 }
86}
87
88impl Scalar for f64 {
89 #[inline]
90 fn conj(self) -> Self {
91 self
92 }
93
94 #[inline]
95 fn abs_sq(self) -> f64 {
96 self * self
97 }
98
99 #[inline]
100 fn abs(self) -> Self {
101 Float::abs(self)
102 }
103
104 #[inline]
105 fn abs_val(self) -> f64 {
106 Float::abs(self)
107 }
108
109 #[inline]
110 fn from_f64(val: f64) -> Self {
111 val
112 }
113
114 #[inline]
115 fn is_nan(self) -> bool {
116 Float::is_nan(self)
117 }
118}
119
120impl Scalar for f32 {
121 #[inline]
122 fn conj(self) -> Self {
123 self
124 }
125
126 #[inline]
127 fn abs_sq(self) -> f64 {
128 (self * self) as f64
129 }
130
131 #[inline]
132 fn abs(self) -> Self {
133 Float::abs(self)
134 }
135
136 #[inline]
137 fn abs_val(self) -> f64 {
138 Float::abs(self) as f64
139 }
140
141 #[inline]
142 fn from_f64(val: f64) -> Self {
143 val as f32
144 }
145
146 #[inline]
147 fn is_nan(self) -> bool {
148 Float::is_nan(self)
149 }
150}
151
152impl Scalar for Complex64 {
153 #[inline]
154 fn conj(self) -> Self {
155 Complex64::conj(&self)
156 }
157
158 #[inline]
159 fn abs_sq(self) -> f64 {
160 self.norm_sqr()
161 }
162
163 #[inline]
164 fn abs(self) -> Self {
165 Complex64::new(self.norm(), 0.0)
166 }
167
168 #[inline]
169 fn abs_val(self) -> f64 {
170 self.norm()
171 }
172
173 #[inline]
174 fn from_f64(val: f64) -> Self {
175 Complex64::new(val, 0.0)
176 }
177
178 #[inline]
179 fn is_nan(self) -> bool {
180 self.re.is_nan() || self.im.is_nan()
181 }
182}
183
184impl Scalar for Complex32 {
185 #[inline]
186 fn conj(self) -> Self {
187 Complex32::conj(&self)
188 }
189
190 #[inline]
191 fn abs_sq(self) -> f64 {
192 self.norm_sqr() as f64
193 }
194
195 #[inline]
196 fn abs(self) -> Self {
197 Complex32::new(self.norm(), 0.0)
198 }
199
200 #[inline]
201 fn abs_val(self) -> f64 {
202 self.norm() as f64
203 }
204
205 #[inline]
206 fn from_f64(val: f64) -> Self {
207 Complex32::new(val as f32, 0.0)
208 }
209
210 #[inline]
211 fn is_nan(self) -> bool {
212 self.re.is_nan() || self.im.is_nan()
213 }
214}
215
216#[macro_export]
230macro_rules! scalar_tests {
231 ($name:ident, $test_fn:ident) => {
232 paste::paste! {
233 #[test]
234 fn [<$name _f64>]() {
235 $test_fn::<f64>();
236 }
237
238 #[test]
239 fn [<$name _c64>]() {
240 $test_fn::<num_complex::Complex64>();
241 }
242 }
243 };
244}
245
246#[cfg(test)]
247mod tests;