1use crate::default::Default;
8use crate::matrix::Matrix;
9use crate::pointer::CPtr;
10use crate::scalar::Scalar;
11use crate::vector::ll::*;
12use crate::vector::Vector;
13use num_complex::{Complex, Complex32, Complex64};
14use std::cmp;
15
16pub trait Copy: Sized {
17 fn copy<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(src: &V, dst: &mut W);
19 fn copy_mat(src: &dyn Matrix<Self>, dst: &mut dyn Matrix<Self>);
21}
22
23macro_rules! copy_impl(($($t: ident), +) => (
24 $(
25 impl Copy for $t {
26 fn copy<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(src: &V, dst: &mut W) {
27 unsafe {
28 prefix!($t, copy)(dst.len(),
29 src.as_ptr().as_c_ptr(), src.inc(),
30 dst.as_mut_ptr().as_c_ptr(), dst.inc());
31 }
32 }
33
34 fn copy_mat(src: &dyn Matrix<Self>, dst: &mut dyn Matrix<Self>) {
35 let len = dst.rows() * dst.cols();
36
37 unsafe {
38 prefix!($t, copy)(len,
39 src.as_ptr().as_c_ptr(), 1,
40 dst.as_mut_ptr().as_c_ptr(), 1);
41 }
42 }
43 }
44 )+
45));
46
47copy_impl!(f32, f64, Complex32, Complex64);
48
49pub trait Axpy: Sized {
51 fn axpy<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(alpha: &Self, x: &V, y: &mut W);
52 fn axpy_mat(alpha: &Self, x: &dyn Matrix<Self>, y: &mut dyn Matrix<Self>);
53}
54
55macro_rules! axpy_impl(($($t: ident), +) => (
56 $(
57 impl Axpy for $t {
58 fn axpy<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(alpha: &$t, x: &V, y: &mut W) {
59 unsafe {
60 let n = cmp::min(x.len(), y.len());
61
62 prefix!($t, axpy)(n,
63 alpha.as_const(),
64 x.as_ptr().as_c_ptr(), x.inc(),
65 y.as_mut_ptr().as_c_ptr(), y.inc());
66 }
67 }
68
69 fn axpy_mat(alpha: &$t, x: &dyn Matrix<$t>, y: &mut dyn Matrix<$t>) {
70 unsafe {
71 let x_len = x.rows() * x.cols();
72 let y_len = y.rows() * y.cols();
73 let n = cmp::min(x_len, y_len);
74
75 prefix!($t, axpy)(n,
76 alpha.as_const(),
77 x.as_ptr().as_c_ptr(), 1,
78 y.as_mut_ptr().as_c_ptr(), 1);
79 }
80 }
81 }
82 )+
83));
84
85axpy_impl!(f32, f64, Complex32, Complex64);
86
87#[cfg(test)]
88mod axpy_tests {
89 use crate::vector::ops::Axpy;
90 use num_complex::Complex;
91
92 #[test]
93 fn real() {
94 let x = vec![1f32, -2f32, 3f32, 4f32];
95 let y = vec![3f32, 7f32, -2f32, 2f32];
96 let mut z = y.clone();
97
98 Axpy::axpy(&1f32, &y, &mut z);
99 Axpy::axpy(&1f32, &x, &mut z);
100 assert_eq!(z, vec![7f32, 12f32, -1f32, 8f32]);
101 }
102
103 #[test]
104 fn slice() {
105 let x = vec![1f32, -2f32, 3f32, 4f32, 5f32];
106 let y = vec![3f32, 7f32, -2f32, 2f32];
107 let mut z = y.clone();
108
109 Axpy::axpy(&1f32, &y, &mut z);
110 Axpy::axpy(&1f32, &x[..4], &mut z);
111 assert_eq!(z, vec![7f32, 12f32, -1f32, 8f32]);
112 }
113
114 #[test]
115 fn complex() {
116 let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
117 let y = vec![Complex::new(3f32, -2f32), Complex::new(2f32, 3f32)];
118 let mut z = x.clone();
119
120 Axpy::axpy(&Complex::new(-1f32, 1f32), &y, &mut z);
121 assert_eq!(z, vec![Complex::new(0f32, 6f32), Complex::new(-4f32, 2f32)]);
122 }
123}
124
125pub trait Scal: Sized {
127 fn scal<V: ?Sized + Vector<Self>>(alpha: &Self, x: &mut V);
128 fn scal_mat(alpha: &Self, x: &mut dyn Matrix<Self>);
129}
130
131macro_rules! scal_impl(($($t: ident), +) => (
132 $(
133 impl Scal for $t {
134 #[inline]
135 fn scal<V: ?Sized + Vector<Self>>(alpha: &$t, x: &mut V) {
136 unsafe {
137 prefix!($t, scal)(x.len(),
138 alpha.as_const(),
139 x.as_mut_ptr().as_c_ptr(), x.inc());
140 }
141 }
142
143 fn scal_mat(alpha: &$t, x: &mut dyn Matrix<$t>) {
144 unsafe {
145 prefix!($t, scal)(x.rows() * x.cols(),
146 alpha.as_const(),
147 x.as_mut_ptr().as_c_ptr(), 1);
148 }
149 }
150 }
151 )+
152));
153
154scal_impl!(f32, f64, Complex32, Complex64);
155
156#[cfg(test)]
157mod scal_tests {
158 use crate::vector::ops::Scal;
159 use num_complex::Complex;
160
161 #[test]
162 fn real() {
163 let mut x = vec![1f32, -2f32, 3f32, 4f32];
164
165 Scal::scal(&-2f32, &mut x);
166 assert_eq!(x, vec![-2f32, 4f32, -6f32, -8f32]);
167 }
168
169 #[test]
170 fn slice() {
171 let mut x = vec![1f32, -2f32, 3f32, 4f32];
172
173 Scal::scal(&-2f32, &mut x[..3]);
174 assert_eq!(x, vec![-2f32, 4f32, -6f32, 4f32]);
175 }
176
177 #[test]
178 fn complex() {
179 let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
180
181 Scal::scal(&Complex::new(1f32, 1f32), &mut x);
182 assert_eq!(x, vec![Complex::new(0f32, 2f32), Complex::new(-2f32, 4f32)]);
183 }
184
185 #[test]
186 fn complex_real() {
187 let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
188
189 Scal::scal(&Complex::new(2f32, 0f32), &mut x);
190 assert_eq!(x, vec![Complex::new(2f32, 2f32), Complex::new(2f32, 6f32)]);
191 }
192}
193
194pub trait Swap: Sized {
196 fn swap<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &mut V, y: &mut W);
198}
199
200macro_rules! swap_impl(($($t: ident), +) => (
201 $(
202 impl Swap for $t {
203 fn swap<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &mut V, y: &mut W) {
204 unsafe {
205 let n = cmp::min(x.len(), y.len());
206
207 prefix!($t, swap)(n,
208 x.as_mut_ptr().as_c_ptr(), x.inc(),
209 y.as_mut_ptr().as_c_ptr(), y.inc());
210 }
211 }
212 }
213 )+
214));
215
216swap_impl!(f32, f64, Complex32, Complex64);
217
218#[cfg(test)]
219mod swap_tests {
220 use crate::vector::ops::Swap;
221 use num_complex::Complex;
222
223 #[test]
224 fn real() {
225 let mut x = vec![1f32, -2f32, 3f32, 4f32];
226 let mut y = vec![2f32, -3f32, 4f32, 1f32];
227 let xr = y.clone();
228 let yr = x.clone();
229
230 Swap::swap(&mut x, &mut y);
231 assert_eq!(x, xr);
232 assert_eq!(y, yr);
233 }
234
235 #[test]
236 fn slice() {
237 let mut x = [1f32, -2f32, 3f32, 4f32];
238 let mut y = [2f32, -3f32, 4f32, 1f32];
239 let xr = [2f32, -3f32, 4f32, 1f32];
240 let yr = [1f32, -2f32, 3f32, 4f32];
241
242 Swap::swap(&mut x[..], &mut y[..]);
243 assert_eq!(x, xr);
244 assert_eq!(y, yr);
245 }
246
247 #[test]
248 fn complex() {
249 let mut x = vec![Complex::new(2f32, -3f32)];
250 let mut y = vec![Complex::new(-1f32, 4f32)];
251 let xr = y.clone();
252 let yr = x.clone();
253
254 Swap::swap(&mut x, &mut y);
255 assert_eq!(x, xr);
256 assert_eq!(y, yr);
257 }
258}
259
260pub trait Dot: Sized {
262 fn dot<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &V, y: &W) -> Self;
263}
264
265macro_rules! real_dot_impl(($($t: ident), +) => (
266 $(
267 impl Dot for $t {
268 fn dot<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &V, y: &W) -> $t {
269 unsafe {
270 let n = cmp::min(x.len(), y.len());
271
272 prefix!($t, dot)(n,
273 x.as_ptr().as_c_ptr(), x.inc(),
274 y.as_ptr().as_c_ptr(), y.inc())
275 }
276 }
277 }
278 )+
279));
280
281macro_rules! complex_dot_impl(($($t: ident), +) => (
282 $(
283 impl Dot for $t {
284 fn dot<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &V, y: &W) -> $t {
285 let result: $t = Default::zero();
286
287 unsafe {
288 let n = cmp::min(x.len(), y.len());
289
290 prefix!($t, dotu_sub)(n,
291 x.as_ptr().as_c_ptr(), x.inc(),
292 y.as_ptr().as_c_ptr(), y.inc(),
293 (&result).as_mut());
294 }
295
296 result
297 }
298 }
299 )+
300));
301
302real_dot_impl!(f32, f64);
303complex_dot_impl!(Complex32, Complex64);
304
305#[cfg(test)]
306mod dot_tests {
307 use crate::vector::ops::Dot;
308 use num_complex::Complex;
309
310 #[test]
311 fn real() {
312 let x = vec![1f32, -2f32, 3f32, 4f32];
313 let y = vec![1f32, 1f32, 1f32, 1f32];
314
315 let xr: f32 = Dot::dot(&x, &y);
316 assert_eq!(xr, 6f32);
317 }
318
319 #[test]
320 fn slice() {
321 let x = [1f32, -2f32, 3f32, 4f32];
322 let y = [1f32, 1f32, 1f32, 1f32];
323
324 let xr: f32 = Dot::dot(&x[..], &y[..]);
325 assert_eq!(xr, 6f32);
326 }
327
328 #[test]
329 fn complex() {
330 let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
331 let y = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 1f32)];
332
333 let xr: Complex<f32> = Dot::dot(&x, &y);
334 assert_eq!(xr, Complex::new(-2f32, 6f32));
335 }
336}
337
338pub trait Dotc: Sized + Dot {
340 fn dotc<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &V, y: &W) -> Self {
341 Dot::dot(x, y)
342 }
343}
344
345macro_rules! dotc_impl(($($t: ident), +) => (
346 $(
347 impl Dotc for $t {
348 fn dotc<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &V, y: &W) -> $t {
349 let result: $t = Default::zero();
350
351 unsafe {
352 let n = cmp::min(x.len(), y.len());
353
354 prefix!($t, dotc_sub)(n,
355 x.as_ptr().as_c_ptr(), x.inc(),
356 y.as_ptr().as_c_ptr(), y.inc(),
357 (&result).as_mut());
358 }
359
360 result
361 }
362 }
363 )+
364));
365
366impl Dotc for f32 {}
367impl Dotc for f64 {}
368dotc_impl!(Complex32, Complex64);
369
370#[cfg(test)]
371mod dotc_tests {
372 use crate::vector::ops::Dotc;
373 use num_complex::Complex;
374
375 #[test]
376 fn complex_conj() {
377 let x = vec![Complex::new(1f32, -1f32), Complex::new(1f32, -3f32)];
378 let y = vec![Complex::new(1f32, 2f32), Complex::new(1f32, 3f32)];
379
380 let xr: Complex<f32> = Dotc::dotc(&x, &y);
381 assert_eq!(xr, Complex::new(-9f32, 9f32));
382 }
383}
384
385pub trait Asum: Sized {
389 fn asum<V: ?Sized + Vector<Self>>(x: &V) -> Self;
390}
391
392pub trait Nrm2: Sized {
394 fn nrm2<V: ?Sized + Vector<Self>>(x: &V) -> Self;
395}
396
397macro_rules! real_norm_impl(($trait_name: ident, $fn_name: ident, $($t: ident), +) => (
398 $(
399 impl $trait_name for $t {
400 fn $fn_name<V: ?Sized + Vector<Self>>(x: &V) -> $t {
401 unsafe {
402 prefix!($t, $fn_name)(x.len(),
403 x.as_ptr().as_c_ptr(), x.inc())
404 }
405 }
406 }
407 )+
408));
409
410macro_rules! complex_norm_impl(
411 ($trait_name: ident, $fn_name: ident, $t: ty, $norm_fn: expr) => (
412 impl $trait_name for $t {
413 fn $fn_name<V: ?Sized + Vector<Self>>(x: &V) -> $t {
414 let re = unsafe {
415 $norm_fn(x.len(),
416 x.as_ptr().as_c_ptr(), x.inc())
417 };
418
419 Complex { im: 0.0, re: re }
420 }
421 }
422 );
423);
424
425real_norm_impl!(Asum, asum, f32, f64);
426real_norm_impl!(Nrm2, nrm2, f32, f64);
427complex_norm_impl!(Asum, asum, Complex32, cblas_s::casum);
428complex_norm_impl!(Asum, asum, Complex64, cblas_d::zasum);
429complex_norm_impl!(Nrm2, nrm2, Complex32, cblas_s::cnrm2);
430complex_norm_impl!(Nrm2, nrm2, Complex64, cblas_d::znrm2);
431
432#[cfg(test)]
433mod asum_tests {
434 use crate::vector::ops::Asum;
435 use num_complex::Complex;
436
437 #[test]
438 fn real() {
439 let x = vec![1f32, -2f32, 3f32, 4f32];
440
441 let r: f32 = Asum::asum(&x);
442 assert_eq!(r, 10f32);
443 }
444
445 #[test]
446 fn slice() {
447 let x = [1f32, -2f32, 3f32, 4f32];
448
449 let r: f32 = Asum::asum(&x[..]);
450 assert_eq!(r, 10f32);
451 }
452
453 #[test]
454 fn complex() {
455 let x = vec![Complex::new(3f32, 4f32)];
456
457 let r: Complex<f32> = Asum::asum(&x);
458 assert_eq!(r, Complex { im: 0.0, re: 7f32 });
459 }
460}
461
462#[cfg(test)]
463mod nrm2_tests {
464 use crate::vector::ops::Nrm2;
465 use num_complex::Complex;
466
467 #[test]
468 fn real() {
469 let x = vec![3f32, -4f32];
470
471 let xr: f32 = Nrm2::nrm2(&x);
472 assert_eq!(xr, 5f32);
473 }
474
475 #[test]
476 fn slice() {
477 let x = [3f32, -4f32];
478
479 let xr: f32 = Nrm2::nrm2(&x[..]);
480 assert_eq!(xr, 5f32);
481 }
482
483 #[test]
484 fn complex() {
485 let x = vec![Complex::new(3f32, 4f32)];
486
487 let xr: Complex<f32> = Nrm2::nrm2(&x);
488 assert_eq!(xr, Complex { im: 0.0, re: 5f32 });
489 }
490}
491
492pub trait Iamax: Sized {
498 fn iamax<V: ?Sized + Vector<Self>>(x: &V) -> usize;
499}
500
501macro_rules! iamax_impl(
502 ($t: ty, $iamax: expr) => (
503 impl Iamax for $t {
504 fn iamax<V: ?Sized + Vector<Self>>(x: &V) -> usize {
505 unsafe {
506 $iamax(x.len(),
507 x.as_ptr().as_c_ptr(), x.inc()) as usize
508 }
509 }
510 }
511 );
512);
513
514iamax_impl!(f32, cblas_i::samax);
515iamax_impl!(f64, cblas_i::damax);
516iamax_impl!(Complex32, cblas_i::camax);
517iamax_impl!(Complex64, cblas_i::zamax);
518
519#[cfg(test)]
520mod iamax_tests {
521 use crate::vector::ops::Iamax;
522 use num_complex::Complex;
523
524 #[test]
525 fn real() {
526 let x = vec![1f32, -2f32, 3f32, 4f32];
527
528 let xr = Iamax::iamax(&x);
529 assert_eq!(xr, 3usize);
530 }
531
532 #[test]
533 fn slice() {
534 let x = [1f32, -2f32, 3f32, 4f32];
535
536 let xr = Iamax::iamax(&x[..]);
537 assert_eq!(xr, 3usize);
538 }
539
540 #[test]
541 fn complex() {
542 let x = vec![Complex::new(3f32, 4f32), Complex::new(3f32, 5f32)];
543
544 let xr = Iamax::iamax(&x);
545 assert_eq!(xr, 1usize);
546 }
547}
548
549pub trait Rot: Sized {
553 fn rot<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(
554 x: &mut V,
555 y: &mut W,
556 cos: &Self,
557 sin: &Self,
558 );
559}
560
561macro_rules! rot_impl(($($t: ident), +) => (
562 $(
563 impl Rot for $t {
564 fn rot<V: ?Sized + Vector<Self>, W: ?Sized + Vector<Self>>(x: &mut V, y: &mut W, cos: &$t, sin: &$t) {
565 unsafe {
566 prefix!($t, rot)(cmp::min(x.len(), y.len()),
567 x.as_mut_ptr().as_c_ptr(), x.inc(),
568 y.as_mut_ptr().as_c_ptr(), y.inc(),
569 cos.as_const(), sin.as_const());
570 }
571 }
572 }
573 )+
574));
575
576rot_impl!(f32, f64);
577
578#[cfg(test)]
579mod rot_tests {
580 use crate::vector::ops::{Rot, Scal};
581
582 #[test]
583 fn real() {
584 let mut x = vec![1f32, -2f32, 3f32, 4f32];
585 let mut y = vec![3f32, 7f32, -2f32, 2f32];
586 let cos = 0f32;
587 let sin = 1f32;
588
589 let xr = y.clone();
590 let mut yr = x.clone();
591 Scal::scal(&-1f32, &mut yr);
592
593 Rot::rot(&mut x, &mut y, &cos, &sin);
594 assert_eq!(x, xr);
595 assert_eq!(y, yr);
596 }
597}