1use crate::matrix::DenseMatrix;
2use crate::scalar::Scale;
3use crate::{Context, IndexType, Scalar};
4use num_traits::Zero;
5use std::fmt::Debug;
6use std::ops::{Add, AddAssign, Div, Index, IndexMut, Mul, MulAssign, Sub, SubAssign};
7
8#[cfg(feature = "faer")]
9pub mod faer_serial;
10#[cfg(feature = "nalgebra")]
11pub mod nalgebra_serial;
12
13#[cfg(feature = "cuda")]
14pub mod cuda;
15
16#[macro_use]
17mod utils;
18
19pub trait VectorIndex: Sized + Debug + Clone {
24 type C: Context;
25 fn context(&self) -> &Self::C;
26 fn zeros(len: IndexType, ctx: Self::C) -> Self;
27 fn len(&self) -> IndexType;
28 fn clone_as_vec(&self) -> Vec<IndexType>;
29 fn is_empty(&self) -> bool {
30 self.len() == 0
31 }
32 fn from_vec(v: Vec<IndexType>, ctx: Self::C) -> Self;
33}
34
35pub trait VectorCommon: Sized + Debug {
37 type T: Scalar;
38 type C: Context;
39 type Inner;
40
41 fn inner(&self) -> &Self::Inner;
42}
43
44impl<V> VectorCommon for &V
45where
46 V: VectorCommon,
47{
48 type T = V::T;
49 type C = V::C;
50 type Inner = V::Inner;
51 fn inner(&self) -> &Self::Inner {
52 V::inner(self)
53 }
54}
55
56impl<V> VectorCommon for &mut V
57where
58 V: VectorCommon,
59{
60 type T = V::T;
61 type C = V::C;
62 type Inner = V::Inner;
63 fn inner(&self) -> &Self::Inner {
64 V::inner(self)
65 }
66}
67
68pub trait VectorOpsByValue<Rhs = Self, Output = Self>:
72 VectorCommon + Add<Rhs, Output = Output> + Sub<Rhs, Output = Output>
73{
74}
75
76impl<V, Rhs, Output> VectorOpsByValue<Rhs, Output> for V where
77 V: VectorCommon + Add<Rhs, Output = Output> + Sub<Rhs, Output = Output>
78{
79}
80
81pub trait VectorMutOpsByValue<Rhs = Self>: VectorCommon + AddAssign<Rhs> + SubAssign<Rhs> {}
85
86impl<V, Rhs> VectorMutOpsByValue<Rhs> for V where V: VectorCommon + AddAssign<Rhs> + SubAssign<Rhs> {}
87
88pub trait VectorRef<V: Vector>:
93 VectorOpsByValue<V, V>
94 + for<'a> VectorOpsByValue<&'a V, V>
95 + for<'a> VectorOpsByValue<V::View<'a>, V>
96 + for<'a, 'b> VectorOpsByValue<&'a V::View<'b>, V>
97 + Mul<Scale<V::T>, Output = V>
98{
99}
100
101impl<RefT, V: Vector> VectorRef<V> for RefT where
102 RefT: VectorOpsByValue<V, V>
103 + for<'a> VectorOpsByValue<&'a V, V>
104 + for<'a> VectorOpsByValue<V::View<'a>, V>
105 + for<'a, 'b> VectorOpsByValue<&'a V::View<'b>, V>
106 + Mul<Scale<V::T>, Output = V>
107{
108}
109
110pub trait VectorViewMut<'a>:
116 VectorMutOpsByValue<Self::View>
117 + VectorMutOpsByValue<Self::Owned>
118 + for<'b> VectorMutOpsByValue<&'b Self::View>
119 + for<'b> VectorMutOpsByValue<&'b Self::Owned>
120 + MulAssign<Scale<Self::T>>
121{
122 type Owned;
123 type View;
124 type Index: VectorIndex;
125 fn copy_from(&mut self, other: &Self::Owned);
127 fn copy_from_view(&mut self, other: &Self::View);
129 fn axpy(&mut self, alpha: Self::T, x: &Self::Owned, beta: Self::T);
131 fn set_index(&mut self, index: IndexType, value: Self::T);
133}
134
135pub trait VectorView<'a>:
141 VectorOpsByValue<Self, Self::Owned>
142 + VectorOpsByValue<Self::Owned, Self::Owned>
143 + for<'b> VectorOpsByValue<&'b Self::Owned, Self::Owned>
144 + for<'b> VectorOpsByValue<&'b Self, Self::Owned>
145 + Mul<Scale<Self::T>, Output = Self::Owned>
146{
147 type Owned;
148 fn get_index(&self, index: IndexType) -> Self::T;
150 fn squared_norm(&self, y: &Self::Owned, atol: &Self::Owned, rtol: Self::T) -> Self::T;
154 fn into_owned(self) -> Self::Owned;
156}
157
158pub trait Vector:
164 VectorOpsByValue<Self>
165 + for<'b> VectorOpsByValue<&'b Self>
166 + for<'a> VectorOpsByValue<Self::View<'a>>
167 + for<'a, 'b> VectorOpsByValue<&'b Self::View<'a>>
168 + Mul<Scale<Self::T>, Output = Self>
169 + Div<Scale<Self::T>, Output = Self>
170 + VectorMutOpsByValue<Self>
171 + for<'a> VectorMutOpsByValue<Self::View<'a>>
172 + for<'b> VectorMutOpsByValue<&'b Self>
173 + for<'a, 'b> VectorMutOpsByValue<&'b Self::View<'a>>
174 + MulAssign<Scale<Self::T>>
175 + Clone
176 + Send
177{
178 type View<'a>: VectorView<'a, T = Self::T, Owned = Self>
179 where
180 Self: 'a;
181 type ViewMut<'a>: VectorViewMut<'a, T = Self::T, Owned = Self, View = Self::View<'a>>
182 where
183 Self: 'a;
184 type Index: VectorIndex;
185
186 fn context(&self) -> &Self::C;
188
189 fn inner_mut(&mut self) -> &mut Self::Inner;
191
192 fn set_index(&mut self, index: IndexType, value: Self::T);
194
195 fn get_index(&self, index: IndexType) -> Self::T;
197
198 fn norm(&self, k: i32) -> Self::T;
200
201 fn squared_norm(&self, y: &Self, atol: &Self, rtol: Self::T) -> Self::T;
205
206 fn len(&self) -> IndexType;
209
210 fn total_len(&self) -> IndexType {
213 self.len() * self.context().nbatch()
214 }
215
216 fn is_empty(&self) -> bool {
218 self.len() == 0
219 }
220
221 fn from_element(nstates: usize, value: Self::T, ctx: Self::C) -> Self;
223
224 fn zeros(nstates: usize, ctx: Self::C) -> Self {
226 Self::from_element(nstates, Self::T::zero(), ctx)
227 }
228
229 fn fill(&mut self, value: Self::T);
231
232 fn as_view(&self) -> Self::View<'_>;
234
235 fn as_view_mut(&mut self) -> Self::ViewMut<'_>;
237
238 fn get_batch(&self, batch: usize) -> Self::View<'_>;
240
241 fn get_batch_mut(&mut self, batch: usize) -> Self::ViewMut<'_>;
243
244 fn copy_from(&mut self, other: &Self);
246
247 fn copy_from_view(&mut self, other: &Self::View<'_>);
249
250 fn from_vec(vec: Vec<Self::T>, ctx: Self::C) -> Self;
253
254 fn from_slice(slice: &[Self::T], ctx: Self::C) -> Self;
256
257 fn clone_as_vec(&self) -> Vec<Self::T>;
260
261 fn axpy(&mut self, alpha: Self::T, x: &Self, beta: Self::T);
263
264 fn axpy_v(&mut self, alpha: Self::T, x: &Self::View<'_>, beta: Self::T);
266
267 fn batched_axpy(&mut self, alpha: &[Self::T], x: &Self, beta: Self::T);
273
274 fn component_mul_assign(&mut self, other: &Self);
276
277 fn component_div_assign(&mut self, other: &Self);
279
280 fn root_finding(&self, g1: &Self) -> (bool, Self::T, i32);
287
288 fn assign_at_indices(&mut self, indices: &Self::Index, value: Self::T);
290
291 fn copy_from_indices(&mut self, other: &Self, indices: &Self::Index);
293
294 fn gather(&mut self, other: &Self, indices: &Self::Index);
296
297 fn scatter(&self, indices: &Self::Index, other: &mut Self);
299
300 fn assert_eq_st(&self, other: &Self, tol: Self::T) {
302 let tol = vec![tol; self.total_len()];
303 Self::assert_eq_vec(self.clone_as_vec(), other.clone_as_vec(), tol);
304 }
305
306 fn assert_eq_norm(&self, other: &Self, atol: &Self, rtol: Self::T, factor: Self::T) {
311 let error = self.clone() - other.clone();
312 let error_norm = error.squared_norm(other, atol, rtol).sqrt();
313 assert!(
314 error_norm < factor,
315 "error_norm: {error_norm}. self: {self:?}, other: {other:?}",
316 );
317 }
318
319 fn assert_eq(&self, other: &Self, tol: &Self) {
321 assert_eq!(
322 self.len(),
323 other.len(),
324 "Vector length mismatch: {} != {}",
325 self.len(),
326 other.len()
327 );
328 let s = self.clone_as_vec();
329 let other = other.clone_as_vec();
330 let tol = tol.clone_as_vec();
331 Self::assert_eq_vec(s, other, tol);
332 }
333
334 fn assert_eq_vec(s: Vec<Self::T>, other: Vec<Self::T>, tol: Vec<Self::T>) {
335 for i in 0..s.len() {
336 if num_traits::abs(s[i] - other[i]) > tol[i] {
337 eprintln!(
338 "Vector element mismatch at index {i}: {} != {}",
339 s[i], other[i]
340 );
341 if s.len() <= 3 {
342 eprintln!("left: {s:?}");
343 eprintln!("right: {other:?}");
344 } else if i == 0 {
345 eprintln!(
346 "left: [{}, {}, {}] != [{}, {}, {}]",
347 s[0], s[1], s[2], other[0], other[1], other[2]
348 );
349 } else if i == s.len() - 1 {
350 eprintln!(
351 "left: [..., {}, {}, {}] != [..., {}, {}, {}]",
352 s[i - 2],
353 s[i - 1],
354 s[i],
355 other[i - 2],
356 other[i - 1],
357 other[i]
358 );
359 } else {
360 eprintln!(
361 "left: [..., {}, {}, {}, ...] != [..., {}, {}, {}, ...]",
362 s[i - 1],
363 s[i],
364 s[i + 1],
365 other[i - 1],
366 other[i],
367 other[i + 1]
368 );
369 }
370 panic!(
371 "Vector element mismatch at index {}: {} != {}",
372 i, s[i], other[i]
373 );
374 }
375 }
376 }
377}
378
379pub trait VectorHost:
385 Vector + Index<IndexType, Output = Self::T> + IndexMut<IndexType, Output = Self::T>
386{
387 fn as_slice(&self) -> &[Self::T];
389
390 fn as_mut_slice(&mut self) -> &mut [Self::T];
392}
393
394pub trait DefaultDenseMatrix: Vector {
399 type M: DenseMatrix<V = Self, T = Self::T, C = Self::C>;
400}
401
402#[cfg(test)]
403pub(crate) mod tests {
404 use std::panic::{catch_unwind, AssertUnwindSafe};
405
406 use super::{Vector, VectorCommon, VectorIndex, VectorView, VectorViewMut};
407 use crate::context::nalgebra::NalgebraContext;
408 use crate::scalar::Scale;
409 use crate::vector::nalgebra_serial::NalgebraVec;
410 use crate::Context;
411 use num_traits::FromPrimitive;
412
413 fn f<V: Vector>(x: f64) -> V::T {
414 V::T::from_f64(x).unwrap()
415 }
416
417 fn fv<V: Vector>(xs: &[f64]) -> Vec<V::T> {
418 xs.iter().map(|&x| f::<V>(x)).collect()
419 }
420
421 pub fn test_root_finding<V: Vector>() {
422 let g0 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
423 let g1 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
424 let (found_root, max_frac, max_frac_index) = g0.root_finding(&g1);
425 assert!(!found_root);
426 assert_eq!(max_frac, f::<V>(0.5));
427 assert_eq!(max_frac_index, 1);
428
429 let g0 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
430 let g1 = V::from_vec(fv::<V>(&[1.0, 2.0, 0.0]), Default::default());
431 let (found_root, max_frac, max_frac_index) = g0.root_finding(&g1);
432 assert!(found_root);
433 assert_eq!(max_frac, f::<V>(0.5));
434 assert_eq!(max_frac_index, 1);
435
436 let g0 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
437 let g1 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
438 let (found_root, max_frac, max_frac_index) = g0.root_finding(&g1);
439 assert!(!found_root);
440 assert_eq!(max_frac, f::<V>(0.0));
441 assert_eq!(max_frac_index, -1);
442 }
443
444 pub fn test_from_slice<V: Vector>() {
445 let slice = fv::<V>(&[1.0, 2.0, 3.0]);
446 let v = V::from_slice(&slice, Default::default());
447 assert_eq!(v.clone_as_vec(), slice);
448 }
449
450 pub fn test_mul_scalar<V: Vector>() {
451 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
452 let result = v * Scale(f::<V>(2.0));
453 assert_eq!(result.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
454 }
455
456 pub fn test_div_scalar<V: Vector>() {
457 let v = V::from_vec(fv::<V>(&[2.0, 4.0, 6.0]), Default::default());
458 let result = v / Scale(f::<V>(2.0));
459 assert_eq!(result.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
460 }
461
462 pub fn test_axpy<V: Vector>() {
463 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
464 let x = V::from_vec(fv::<V>(&[4.0, 5.0, 6.0]), Default::default());
465 y.axpy(f::<V>(2.0), &x, f::<V>(1.0));
466 assert_eq!(y.clone_as_vec(), fv::<V>(&[9.0, 12.0, 15.0]));
467 y.axpy(f::<V>(2.0), &x, f::<V>(0.0));
468 assert_eq!(y.clone_as_vec(), fv::<V>(&[8.0, 10.0, 12.0]));
469 y.axpy(f::<V>(0.0), &x, f::<V>(1.0));
470 assert_eq!(y.clone_as_vec(), fv::<V>(&[8.0, 10.0, 12.0]));
471 }
472
473 pub fn test_copy_from_indices<V: Vector>() {
474 let mut v1 = V::zeros(5, Default::default());
475 let v2 = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0]), Default::default());
476 let indices = V::Index::from_vec(vec![0, 2, 4], Default::default());
477 v1.copy_from_indices(&v2, &indices);
478 assert_eq!(v1.clone_as_vec(), fv::<V>(&[10.0, 0.0, 30.0, 0.0, 50.0]));
479 }
480
481 pub fn test_gather<V: Vector>() {
482 let mut result = V::zeros(3, Default::default());
483 let v = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), Default::default());
484 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
485 result.gather(&v, &indices);
486 assert_eq!(result.clone_as_vec(), fv::<V>(&[40.0, 10.0, 30.0]));
487 }
488
489 pub fn test_scatter<V: Vector>() {
490 let v = V::from_vec(fv::<V>(&[40.0, 10.0, 30.0]), Default::default());
491 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
492 let mut result = V::zeros(4, Default::default());
493 v.scatter(&indices, &mut result);
494 assert_eq!(result.clone_as_vec(), fv::<V>(&[10.0, 0.0, 30.0, 40.0]));
495 }
496
497 pub fn test_copy_from_via_view_mut<V: Vector>() {
498 let mut v1 = V::zeros(3, Default::default());
499 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
500 v1.as_view_mut().copy_from(&v2);
501 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
502 }
503
504 pub fn test_set_index<V: Vector>() {
505 let mut v = V::zeros(3, Default::default());
506 v.set_index(1, f::<V>(42.0));
507 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 42.0, 0.0]));
508 }
509
510 pub fn test_get_index<V: Vector>() {
511 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
512 assert_eq!(v.get_index(0), f::<V>(1.0));
513 assert_eq!(v.get_index(2), f::<V>(3.0));
514 }
515
516 pub fn test_norm<V: Vector>() {
517 let v = V::from_vec(fv::<V>(&[3.0, 4.0]), Default::default());
518 let norm = v.norm(2);
519 let diff = norm - f::<V>(5.0);
520 assert!(num_traits::abs(diff) < f::<V>(1e-12));
521 }
522
523 pub fn test_norm_l1<V: Vector>() {
524 let v = V::from_vec(fv::<V>(&[3.0, -4.0]), Default::default());
525 let norm = v.norm(1);
526 let diff = norm - f::<V>(7.0);
527 assert!(num_traits::abs(diff) < f::<V>(1e-12));
528 }
529
530 pub fn test_squared_norm<V: Vector>() {
531 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), Default::default());
532 let y = V::from_vec(fv::<V>(&[1.0, 1.0]), Default::default());
533 let atol = V::from_vec(fv::<V>(&[1e-3, 1e-3]), Default::default());
534 let rtol = f::<V>(1e-2);
535 let norm = x.squared_norm(&y, &atol, rtol);
536 let denom = f::<V>(1.0) * rtol + f::<V>(1e-3);
537 let err0 = f::<V>(1.0) / denom;
538 let err1 = f::<V>(2.0) / denom;
539 let expected = (err0 * err0 + err1 * err1) / f::<V>(2.0);
540 assert!(num_traits::abs(norm - expected) < f::<V>(1e-12));
541 }
542
543 pub fn test_fill<V: Vector>() {
544 let mut v = V::zeros(3, Default::default());
545 v.fill(f::<V>(7.0));
546 assert_eq!(v.clone_as_vec(), fv::<V>(&[7.0, 7.0, 7.0]));
547 }
548
549 pub fn test_from_element<V: Vector>() {
550 let v = V::from_element(2, f::<V>(5.0), Default::default());
551 assert_eq!(v.clone_as_vec(), fv::<V>(&[5.0, 5.0]));
552 }
553
554 pub fn test_copy_from<V: Vector>() {
555 let mut v1 = V::zeros(3, Default::default());
556 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
557 v1.copy_from(&v2);
558 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
559 }
560
561 pub fn test_from_vec<V: Vector>() {
562 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
563 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
564 }
565
566 pub fn test_component_mul_assign<V: Vector>() {
567 let mut a = V::from_vec(fv::<V>(&[2.0, 3.0]), Default::default());
568 let b = V::from_vec(fv::<V>(&[10.0, 20.0]), Default::default());
569 a.component_mul_assign(&b);
570 assert_eq!(a.clone_as_vec(), fv::<V>(&[20.0, 60.0]));
571 }
572
573 pub fn test_component_div_assign<V: Vector>() {
574 let mut a = V::from_vec(fv::<V>(&[6.0, 12.0]), Default::default());
575 let b = V::from_vec(fv::<V>(&[2.0, 3.0]), Default::default());
576 a.component_div_assign(&b);
577 assert_eq!(a.clone_as_vec(), fv::<V>(&[3.0, 4.0]));
578 }
579
580 pub fn test_assign_at_indices<V: Vector>() {
581 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
582 let indices = V::Index::from_vec(vec![0, 2], Default::default());
583 v.assign_at_indices(&indices, f::<V>(0.0));
584 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 2.0, 0.0]));
585 }
586
587 pub fn test_add<V: Vector>() {
588 let a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
589 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
590 let c = a + b;
591 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
592 }
593
594 pub fn test_sub<V: Vector>() {
595 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
596 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
597 let c = a - b;
598 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0]));
599 }
600
601 pub fn test_add_assign<V: Vector>() {
602 let mut a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
603 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
604 a += b;
605 assert_eq!(a.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
606 }
607
608 pub fn test_sub_assign<V: Vector>() {
609 let mut a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
610 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
611 a -= b;
612 assert_eq!(a.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0]));
613 }
614
615 pub fn test_axpy_v<V: Vector>() {
616 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
617 let x = V::from_vec(fv::<V>(&[4.0, 5.0, 6.0]), Default::default());
618 let x_view = x.as_view();
619 y.axpy_v(f::<V>(2.0), &x_view, f::<V>(1.0));
620 assert_eq!(y.clone_as_vec(), fv::<V>(&[9.0, 12.0, 15.0]));
621 }
622
623 pub fn test_mul_assign_scalar<V: Vector>() {
624 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
625 v *= Scale(f::<V>(2.0));
626 assert_eq!(v.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
627 }
628
629 pub fn test_copy_from_view<V: Vector>() {
630 let mut v1 = V::zeros(3, Default::default());
631 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
632 let view = v2.as_view();
633 v1.copy_from_view(&view);
634 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
635 }
636
637 pub fn test_view_squared_norm<V: Vector>() {
638 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), Default::default());
639 let y = V::from_vec(fv::<V>(&[1.0, 1.0]), Default::default());
640 let atol = V::from_vec(fv::<V>(&[1e-3, 1e-3]), Default::default());
641 let rtol = f::<V>(1e-2);
642 let view = x.as_view();
643 let norm = VectorView::squared_norm(&view, &y, &atol, rtol);
644 let denom = f::<V>(1.0) * rtol + f::<V>(1e-3);
645 let err0 = f::<V>(1.0) / denom;
646 let err1 = f::<V>(2.0) / denom;
647 let expected = (err0 * err0 + err1 * err1) / f::<V>(2.0);
648 assert!(num_traits::abs(norm - expected) < f::<V>(1e-12));
649 }
650
651 pub fn test_view_into_owned<V: Vector>() {
652 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
653 let view = v.as_view();
654 let owned = view.into_owned();
655 assert_eq!(owned.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
656 }
657
658 pub fn test_view_get_index<V: Vector>() {
659 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
660 let view = v.as_view();
661 assert_eq!(view.get_index(1), f::<V>(2.0));
662 assert_eq!(view.get_index(2), f::<V>(3.0));
663 }
664
665 pub fn test_view_mut_axpy<V: Vector>() {
666 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
667 let x = V::from_vec(fv::<V>(&[4.0, 5.0, 6.0]), Default::default());
668 {
669 let mut y_view = y.as_view_mut();
670 y_view.axpy(f::<V>(2.0), &x, f::<V>(1.0));
671 }
672 assert_eq!(y.clone_as_vec(), fv::<V>(&[9.0, 12.0, 15.0]));
673 }
674
675 pub fn test_view_mut_set_index<V: Vector>() {
676 let mut v = V::zeros(3, Default::default());
677 {
678 let mut view = v.as_view_mut();
679 view.set_index(1, f::<V>(42.0));
680 }
681 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 42.0, 0.0]));
682 }
683
684 pub fn test_view_mut_mul_assign_scalar<V: Vector>() {
685 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
686 {
687 let mut view = v.as_view_mut();
688 view *= Scale(f::<V>(2.0));
689 }
690 assert_eq!(v.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
691 }
692
693 pub fn test_view_mut_copy_from_view<V: Vector>() {
694 let mut v1 = V::zeros(3, Default::default());
695 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
696 {
697 let v2_view = v2.as_view();
698 let mut v1_view = v1.as_view_mut();
699 v1_view.copy_from_view(&v2_view);
700 }
701 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
702 }
703
704 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
705 pub fn test_batched_len_and_total_len<V: Vector>(ctx: V::C) {
706 let nbatch = ctx.nbatch();
707 assert!(nbatch > 1);
708 let v = V::zeros(4, ctx);
709 assert_eq!(v.len(), 4);
710 assert_eq!(v.total_len(), 4 * nbatch);
711 }
712
713 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
714 pub fn test_batched_from_vec<V: Vector>(ctx: V::C) {
715 assert_eq!(ctx.nbatch(), 2);
716 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]), ctx);
717 assert_eq!(v.len(), 3);
718 assert_eq!(v.total_len(), 6);
719 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]));
720 }
721
722 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
723 pub fn test_batched_from_vec_bad_length<V: Vector>(ctx: V::C) {
724 assert_eq!(ctx.nbatch(), 2);
725 let _v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), ctx);
726 }
727
728 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
729 pub fn test_batched_from_element<V: Vector>(ctx: V::C) {
730 assert_eq!(ctx.nbatch(), 3);
731 let v = V::from_element(2, f::<V>(5.0), ctx);
732 assert_eq!(v.len(), 2);
733 assert_eq!(v.clone_as_vec(), fv::<V>(&[5.0, 5.0, 5.0, 5.0, 5.0, 5.0]));
734 }
735
736 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
737 pub fn test_batched_axpy<V: Vector>(ctx: V::C) {
738 assert_eq!(ctx.nbatch(), 2);
739 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
740 let x = V::from_vec(fv::<V>(&[3.0, 4.0, 30.0, 40.0]), ctx);
741 y.axpy(f::<V>(2.0), &x, f::<V>(1.0));
742 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 70.0, 100.0]));
743 }
744
745 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
746 pub fn test_batched_add<V: Vector>(ctx: V::C) {
747 assert_eq!(ctx.nbatch(), 2);
748 let a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx.clone());
749 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
750 let c = a + b;
751 assert_eq!(c.len(), 2);
752 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0, 44.0]));
753 }
754
755 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
756 pub fn test_batched_norm_max_across_batches<V: Vector>(ctx: V::C) {
757 assert_eq!(ctx.nbatch(), 2);
758 let v = V::from_vec(fv::<V>(&[1.0, 0.0, 0.0, 3.0]), ctx);
759 let norm = v.norm(2);
760 let diff = norm - f::<V>(3.0);
761 assert!(num_traits::abs(diff) < f::<V>(1e-12));
762 }
763
764 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
765 pub fn test_batched_norm_l1<V: Vector>(ctx: V::C) {
766 assert_eq!(ctx.nbatch(), 2);
767 let v = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0, 0.0]), ctx);
768 let norm = v.norm(1);
769 let diff = norm - f::<V>(3.0);
771 assert!(num_traits::abs(diff) < f::<V>(1e-12));
772 }
773
774 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
775 pub fn test_batched_squared_norm<V: Vector>(ctx: V::C) {
776 assert_eq!(ctx.nbatch(), 2);
777 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx.clone());
778 let y = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0, 1.0]), ctx);
779 let atol = V::from_vec(fv::<V>(&[1e-3, 1e-3]), V::C::default());
780 let rtol = f::<V>(1e-2);
781 let norm = x.squared_norm(&y, &atol, rtol);
782 let denom = f::<V>(1.0) * rtol + f::<V>(1e-3);
783 let err3 = f::<V>(3.0) / denom;
784 let err4 = f::<V>(4.0) / denom;
785 let batch1 = (err3 * err3 + err4 * err4) / f::<V>(2.0);
786 let diff = norm - batch1;
787 assert!(num_traits::abs(diff) < f::<V>(1e-12));
788 }
789
790 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
791 pub fn test_batched_set_index<V: Vector>(ctx: V::C) {
792 assert_eq!(ctx.nbatch(), 3);
793 let mut v = V::zeros(2, ctx);
794 v.set_index(0, f::<V>(42.0));
795 assert_eq!(
796 v.clone_as_vec(),
797 fv::<V>(&[42.0, 0.0, 42.0, 0.0, 42.0, 0.0])
798 );
799 }
800
801 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
802 pub fn test_batched_get_index_panics<V: Vector>(ctx: V::C) {
803 assert!(ctx.nbatch() > 1);
804 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
805 let _val = v.get_index(0);
806 }
807
808 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
809 pub fn test_batched_fill<V: Vector>(ctx: V::C) {
810 assert_eq!(ctx.nbatch(), 2);
811 let mut v = V::zeros(3, ctx);
812 v.fill(f::<V>(7.0));
813 assert_eq!(v.clone_as_vec(), fv::<V>(&[7.0, 7.0, 7.0, 7.0, 7.0, 7.0]));
814 }
815
816 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
817 pub fn test_batched_component_mul<V: Vector>(ctx: V::C) {
818 assert_eq!(ctx.nbatch(), 2);
819 let mut a = V::from_vec(fv::<V>(&[2.0, 3.0, 4.0, 5.0]), ctx.clone());
820 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
821 a.component_mul_assign(&b);
822 assert_eq!(a.clone_as_vec(), fv::<V>(&[20.0, 60.0, 120.0, 200.0]));
823 }
824
825 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
826 pub fn test_batched_assign_at_indices<V: Vector>(ctx: V::C) {
827 assert_eq!(ctx.nbatch(), 2);
828 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]), ctx);
829 let indices = V::Index::from_vec(vec![0, 2], Default::default());
830 v.assign_at_indices(&indices, f::<V>(0.0));
831 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 2.0, 0.0, 0.0, 5.0, 0.0]));
832 }
833
834 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
835 pub fn test_batched_root_finding_consistent<V: Vector>(ctx: V::C) {
836 assert_eq!(ctx.nbatch(), 2);
837 let g0 = V::from_vec(fv::<V>(&[1.0, -1.0, 1.0, -1.0]), ctx.clone());
838 let g1 = V::from_vec(fv::<V>(&[-1.0, 1.0, -1.0, 1.0]), ctx);
839 let (found, _frac, idx) = g0.root_finding(&g1);
840 assert!(!found);
841 assert!(idx >= 0);
842 }
843
844 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
845 pub fn test_batched_root_finding_inconsistent<V: Vector>(ctx: V::C) {
846 assert_eq!(ctx.nbatch(), 2);
847 let g0 = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0, -1.0]), ctx.clone());
848 let g1 = V::from_vec(fv::<V>(&[-1.0, 1.0, 1.0, 1.0]), ctx);
849 let _result = g0.root_finding(&g1);
850 }
851
852 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
855 pub fn test_batched_axpy_broadcast<V: Vector>(ctx: V::C) {
856 assert_eq!(ctx.nbatch(), 2);
857 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
859 let x = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
860 y.axpy(f::<V>(2.0), &x, f::<V>(1.0));
861 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 16.0, 28.0]));
863 }
864
865 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
866 pub fn test_batched_copy_from_broadcast<V: Vector>(ctx: V::C) {
867 assert_eq!(ctx.nbatch(), 2);
868 let mut y = V::zeros(2, ctx);
869 let x = V::from_vec(fv::<V>(&[5.0, 7.0]), V::C::default());
870 y.copy_from(&x);
871 assert_eq!(y.clone_as_vec(), fv::<V>(&[5.0, 7.0, 5.0, 7.0]));
873 }
874
875 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
876 pub fn test_batched_component_div<V: Vector>(ctx: V::C) {
877 assert_eq!(ctx.nbatch(), 2);
878 let mut a = V::from_vec(fv::<V>(&[6.0, 8.0, 12.0, 20.0]), ctx.clone());
879 let b = V::from_vec(fv::<V>(&[2.0, 4.0, 3.0, 5.0]), ctx);
880 a.component_div_assign(&b);
881 assert_eq!(a.clone_as_vec(), fv::<V>(&[3.0, 2.0, 4.0, 4.0]));
882 }
883
884 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
885 pub fn test_batched_component_mul_broadcast<V: Vector>(ctx: V::C) {
886 assert_eq!(ctx.nbatch(), 2);
887 let mut a = V::from_vec(fv::<V>(&[2.0, 3.0, 4.0, 5.0]), ctx);
888 let b = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
889 a.component_mul_assign(&b);
890 assert_eq!(a.clone_as_vec(), fv::<V>(&[20.0, 60.0, 40.0, 100.0]));
892 }
893
894 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
895 pub fn test_batched_component_div_broadcast<V: Vector>(ctx: V::C) {
896 assert_eq!(ctx.nbatch(), 2);
897 let mut a = V::from_vec(fv::<V>(&[6.0, 8.0, 12.0, 20.0]), ctx);
898 let b = V::from_vec(fv::<V>(&[2.0, 4.0]), V::C::default());
899 a.component_div_assign(&b);
900 assert_eq!(a.clone_as_vec(), fv::<V>(&[3.0, 2.0, 6.0, 5.0]));
902 }
903
904 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
905 pub fn test_batched_add_assign_broadcast<V: Vector>(ctx: V::C) {
906 assert_eq!(ctx.nbatch(), 2);
907 let mut a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
908 let b = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
909 a += &b;
910 assert_eq!(a.clone_as_vec(), fv::<V>(&[11.0, 22.0, 13.0, 24.0]));
911 }
912
913 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
914 pub fn test_batched_sub_assign_broadcast<V: Vector>(ctx: V::C) {
915 assert_eq!(ctx.nbatch(), 2);
916 let mut a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
917 let b = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
918 a -= &b;
919 assert_eq!(a.clone_as_vec(), fv::<V>(&[9.0, 18.0, 29.0, 38.0]));
920 }
921
922 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
923 pub fn test_batched_sub<V: Vector>(ctx: V::C) {
924 assert_eq!(ctx.nbatch(), 2);
925 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx.clone());
926 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
927 let c = a - b;
928 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0, 36.0]));
929 }
930
931 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
932 pub fn test_batched_sub_assign<V: Vector>(ctx: V::C) {
933 assert_eq!(ctx.nbatch(), 2);
934 let mut a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx.clone());
935 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
936 a -= b;
937 assert_eq!(a.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0, 36.0]));
938 }
939
940 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
941 pub fn test_batched_from_slice<V: Vector>(ctx: V::C) {
942 assert_eq!(ctx.nbatch(), 2);
943 let slice = fv::<V>(&[1.0, 2.0, 3.0, 1.0, 2.0, 3.0]);
944 let v = V::from_slice(&slice, ctx);
945 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0, 1.0, 2.0, 3.0]));
946 }
947
948 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
949 pub fn test_batched_mul_scalar<V: Vector>(ctx: V::C) {
950 assert_eq!(ctx.nbatch(), 2);
951 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
952 let result = v * Scale(f::<V>(2.0));
953 assert_eq!(result.clone_as_vec(), fv::<V>(&[2.0, 4.0, 20.0, 40.0]));
954 }
955
956 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
957 pub fn test_batched_div_scalar<V: Vector>(ctx: V::C) {
958 assert_eq!(ctx.nbatch(), 2);
959 let v = V::from_vec(fv::<V>(&[2.0, 4.0, 20.0, 40.0]), ctx);
960 let result = v / Scale(f::<V>(2.0));
961 assert_eq!(result.clone_as_vec(), fv::<V>(&[1.0, 2.0, 10.0, 20.0]));
962 }
963
964 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
965 pub fn test_batched_copy_from_indices<V: Vector>(ctx: V::C) {
966 assert_eq!(ctx.nbatch(), 2);
967 let mut v1 = V::zeros(4, ctx.clone());
968 let v2 = V::from_vec(
969 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
970 ctx,
971 );
972 let indices = V::Index::from_vec(vec![0, 2, 3], Default::default());
973 v1.copy_from_indices(&v2, &indices);
974 assert_eq!(
975 v1.clone_as_vec(),
976 fv::<V>(&[10.0, 0.0, 30.0, 40.0, 50.0, 0.0, 70.0, 80.0])
977 );
978 }
979
980 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
981 pub fn test_batched_gather<V: Vector>(ctx: V::C) {
982 assert_eq!(ctx.nbatch(), 2);
983 let mut result = V::zeros(3, ctx.clone());
984 let v = V::from_vec(
985 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
986 ctx,
987 );
988 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
989 result.gather(&v, &indices);
990 assert_eq!(
991 result.clone_as_vec(),
992 fv::<V>(&[40.0, 10.0, 30.0, 80.0, 50.0, 70.0])
993 );
994 }
995
996 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
997 pub fn test_batched_scatter<V: Vector>(ctx: V::C) {
998 assert_eq!(ctx.nbatch(), 2);
999 let v = V::from_vec(fv::<V>(&[40.0, 10.0, 30.0, 80.0, 50.0, 70.0]), ctx.clone());
1000 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
1001 let mut result = V::zeros(4, ctx);
1002 v.scatter(&indices, &mut result);
1003 assert_eq!(
1004 result.clone_as_vec(),
1005 fv::<V>(&[10.0, 0.0, 30.0, 40.0, 50.0, 0.0, 70.0, 80.0])
1006 );
1007 }
1008
1009 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1010 pub fn test_batched_get_batch<V: Vector>(ctx: V::C) {
1011 assert_eq!(ctx.nbatch(), 2);
1012 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 10.0, 20.0, 30.0]), ctx);
1013 let batch0 = v.get_batch(0);
1014 assert_eq!(batch0.get_index(0), f::<V>(1.0));
1015 assert_eq!(batch0.get_index(1), f::<V>(2.0));
1016 assert_eq!(batch0.get_index(2), f::<V>(3.0));
1017 let batch1 = v.get_batch(1);
1018 assert_eq!(batch1.get_index(0), f::<V>(10.0));
1019 assert_eq!(batch1.get_index(1), f::<V>(20.0));
1020 assert_eq!(batch1.get_index(2), f::<V>(30.0));
1021 }
1022
1023 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1024 pub fn test_batched_get_batch_mut<V: Vector>(ctx: V::C) {
1025 assert_eq!(ctx.nbatch(), 2);
1026 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 10.0, 20.0, 30.0]), ctx);
1027 {
1028 let mut batch0 = v.get_batch_mut(0);
1029 batch0.set_index(1, f::<V>(99.0));
1030 }
1031 assert_eq!(
1032 v.clone_as_vec(),
1033 fv::<V>(&[1.0, 99.0, 3.0, 10.0, 20.0, 30.0])
1034 );
1035 }
1036
1037 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1038 pub fn test_batched_axpy_v<V: Vector>(ctx: V::C) {
1039 assert_eq!(ctx.nbatch(), 2);
1040 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1041 let x = V::from_vec(fv::<V>(&[3.0, 4.0, 30.0, 40.0]), ctx);
1042 let x_view = x.as_view();
1043 y.axpy_v(f::<V>(2.0), &x_view, f::<V>(1.0));
1044 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 70.0, 100.0]));
1045 }
1046
1047 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1048 pub fn test_batched_mul_assign_scalar<V: Vector>(ctx: V::C) {
1049 assert_eq!(ctx.nbatch(), 2);
1050 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
1051 v *= Scale(f::<V>(2.0));
1052 assert_eq!(v.clone_as_vec(), fv::<V>(&[2.0, 4.0, 20.0, 40.0]));
1053 }
1054
1055 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1056 pub fn test_batched_copy_from_view<V: Vector>(ctx: V::C) {
1057 assert_eq!(ctx.nbatch(), 2);
1058 let mut v1 = V::zeros(2, ctx);
1059 let v2 = V::from_vec(fv::<V>(&[5.0, 7.0]), V::C::default());
1060 let view = v2.as_view();
1061 v1.copy_from_view(&view);
1062 assert_eq!(v1.clone_as_vec(), fv::<V>(&[5.0, 7.0, 5.0, 7.0]));
1063 }
1064
1065 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1068 pub fn test_batched_axpy_new<V: Vector>(ctx: V::C) {
1069 assert_eq!(ctx.nbatch(), 2);
1070 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1071 let x = V::from_vec(fv::<V>(&[3.0, 4.0, 30.0, 40.0]), ctx);
1072 y.batched_axpy(&[f::<V>(2.0), f::<V>(0.5)], &x, f::<V>(1.0));
1073 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 25.0, 40.0]));
1076 }
1077
1078 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1079 pub fn test_batched_axpy_new_broadcast<V: Vector>(ctx: V::C) {
1080 assert_eq!(ctx.nbatch(), 2);
1081 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
1082 let x = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
1083 y.batched_axpy(&[f::<V>(2.0), f::<V>(0.5)], &x, f::<V>(1.0));
1084 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 11.5, 22.0]));
1088 }
1089
1090 #[allow(clippy::type_complexity)]
1091 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1092 pub fn test_batched_axpy_new_bad_length<V: Vector>(ctx: V::C) {
1093 assert_eq!(ctx.nbatch(), 2);
1094 let mut y = V::zeros(2, ctx);
1095 let x = V::zeros(2, V::C::default());
1096 y.batched_axpy(&[f::<V>(1.0)], &x, f::<V>(0.0));
1097 }
1098
1099 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1102 pub fn test_batched_axpy_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
1103 assert_eq!(ctx2.nbatch(), 2);
1104 assert_eq!(ctx3.nbatch(), 3);
1105 let mut y = V::zeros(2, ctx2);
1106 let x = V::zeros(2, ctx3);
1107 y.axpy(f::<V>(1.0), &x, f::<V>(1.0));
1108 }
1109
1110 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1111 pub fn test_batched_copy_from_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
1112 assert_eq!(ctx2.nbatch(), 2);
1113 assert_eq!(ctx3.nbatch(), 3);
1114 let mut y = V::zeros(2, ctx2);
1115 let x = V::zeros(2, ctx3);
1116 y.copy_from(&x);
1117 }
1118
1119 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1120 pub fn test_batched_add_assign_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
1121 assert_eq!(ctx2.nbatch(), 2);
1122 assert_eq!(ctx3.nbatch(), 3);
1123 let mut a = V::zeros(2, ctx2);
1124 let b = V::zeros(2, ctx3);
1125 a += &b;
1126 }
1127
1128 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1129 pub fn test_batched_component_mul_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
1130 assert_eq!(ctx2.nbatch(), 2);
1131 assert_eq!(ctx3.nbatch(), 3);
1132 let mut a = V::zeros(2, ctx2);
1133 let b = V::zeros(2, ctx3);
1134 a.component_mul_assign(&b);
1135 }
1136
1137 #[test]
1138 fn vector_common_for_references_and_default_helpers_work() {
1139 let mut v = NalgebraVec::from_vec(vec![1.0, 2.0], NalgebraContext::default());
1140 assert_eq!(<NalgebraVec<f64> as VectorCommon>::inner(&v).len(), 2);
1141 assert_eq!(<&NalgebraVec<f64> as VectorCommon>::inner(&&v).len(), 2);
1142 assert_eq!(
1143 <&mut NalgebraVec<f64> as VectorCommon>::inner(&&mut v).len(),
1144 2
1145 );
1146
1147 let empty = NalgebraVec::<f64>::zeros(0, NalgebraContext::default());
1148 assert!(empty.is_empty());
1149
1150 let non_empty = NalgebraVec::<f64>::zeros(2, NalgebraContext::default());
1151 assert!(!non_empty.is_empty());
1152 assert_eq!(non_empty.clone_as_vec(), vec![0.0, 0.0]);
1153 }
1154
1155 #[test]
1156 fn vector_assert_eq_panics_for_length_mismatch() {
1157 let left = NalgebraVec::from_vec(vec![1.0, 2.0], NalgebraContext::default());
1158 let right = NalgebraVec::from_vec(vec![1.0], NalgebraContext::default());
1159 let tol = NalgebraVec::from_vec(vec![0.0, 0.0], NalgebraContext::default());
1160 assert!(catch_unwind(AssertUnwindSafe(|| left.assert_eq(&right, &tol))).is_err());
1161 }
1162
1163 #[test]
1164 fn vector_assert_helpers_cover_success_and_failure_paths() {
1165 let left = NalgebraVec::from_vec(vec![1.0, 2.0, 3.0], NalgebraContext::default());
1166 let right = NalgebraVec::from_vec(vec![1.0, 2.0, 3.0], NalgebraContext::default());
1167 let tol = NalgebraVec::from_vec(vec![0.0, 0.0, 0.0], NalgebraContext::default());
1168 left.assert_eq(&right, &tol);
1169 left.assert_eq_st(&right, 0.0);
1170 left.assert_eq_norm(&right, &tol, 1e-6, 1.0);
1171
1172 let perturbed = NalgebraVec::from_vec(vec![1.1, 2.0, 3.0], NalgebraContext::default());
1173 assert!(catch_unwind(AssertUnwindSafe(
1174 || left.assert_eq_norm(&perturbed, &tol, 1e-6, 0.01)
1175 ))
1176 .is_err());
1177 }
1178
1179 #[test]
1180 fn vector_assert_eq_vec_panics_for_short_vector_mismatch() {
1181 assert!(catch_unwind(AssertUnwindSafe(|| {
1182 <NalgebraVec<f64> as Vector>::assert_eq_vec(
1183 vec![1.0, 2.0, 3.0],
1184 vec![0.0, 2.0, 3.0],
1185 vec![0.0, 0.0, 0.0],
1186 )
1187 }))
1188 .is_err());
1189 }
1190
1191 #[test]
1192 fn vector_assert_eq_vec_panics_for_first_middle_and_last_mismatch_in_long_vectors() {
1193 assert!(catch_unwind(AssertUnwindSafe(|| {
1194 <NalgebraVec<f64> as Vector>::assert_eq_vec(
1195 vec![1.0, 2.0, 3.0, 4.0],
1196 vec![0.0, 2.0, 3.0, 4.0],
1197 vec![0.0, 0.0, 0.0, 0.0],
1198 )
1199 }))
1200 .is_err());
1201 assert!(catch_unwind(AssertUnwindSafe(|| {
1202 <NalgebraVec<f64> as Vector>::assert_eq_vec(
1203 vec![1.0, 2.0, 3.0, 4.0, 5.0],
1204 vec![1.0, 2.0, 0.0, 4.0, 5.0],
1205 vec![0.0, 0.0, 0.0, 0.0, 0.0],
1206 )
1207 }))
1208 .is_err());
1209 assert!(catch_unwind(AssertUnwindSafe(|| {
1210 <NalgebraVec<f64> as Vector>::assert_eq_vec(
1211 vec![1.0, 2.0, 3.0, 4.0],
1212 vec![1.0, 2.0, 3.0, 0.0],
1213 vec![0.0, 0.0, 0.0, 0.0],
1214 )
1215 }))
1216 .is_err());
1217 }
1218
1219 use crate::matrix::DenseMatrix;
1220
1221 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1222 fn make_strided_test_matrix<M: DenseMatrix>(nbatch: usize) -> M {
1223 let ctx = M::C::default().clone_with_nbatch(nbatch).unwrap();
1224 let nrows = 3;
1225 let ncols = 4;
1226 let mut data = Vec::with_capacity(nrows * ncols * nbatch);
1227 for b in 0..nbatch {
1228 for col in 0..ncols {
1229 for row in 0..nrows {
1230 data.push(f::<M::V>(row as f64 + col as f64 * 10.0 + b as f64 * 100.0));
1231 }
1232 }
1233 }
1234 M::from_vec(nrows, ncols, data, ctx)
1235 }
1236
1237 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1238 pub fn test_strided_view_set_index<M: DenseMatrix>(ctx: M::C) {
1239 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1240 {
1241 let mut col1 = matrix.column_mut(1);
1242 col1.set_index(1, f::<M::V>(99.0));
1243 }
1244 let owned = matrix.column(1).into_owned();
1245 let b0 = owned.get_batch(0);
1246 let b1 = owned.get_batch(1);
1247 assert_eq!(b0.get_index(1), f::<M::V>(99.0));
1248 assert_eq!(b1.get_index(1), f::<M::V>(99.0));
1249 }
1250
1251 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1252 pub fn test_strided_view_mut_copy_from<M: DenseMatrix>(ctx: M::C) {
1253 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1254 let owned = M::V::from_vec(
1255 vec![f::<M::V>(50.0), f::<M::V>(51.0), f::<M::V>(52.0)],
1256 M::C::default(),
1257 );
1258 {
1259 let mut col1 = matrix.column_mut(1);
1260 col1.copy_from(&owned);
1261 }
1262 let owned_v = matrix.column(1).into_owned();
1263 let b0 = owned_v.get_batch(0);
1264 let b1 = owned_v.get_batch(1);
1265 assert_eq!(b0.get_index(0), f::<M::V>(50.0));
1266 assert_eq!(b0.get_index(1), f::<M::V>(51.0));
1267 assert_eq!(b0.get_index(2), f::<M::V>(52.0));
1268 assert_eq!(b1.get_index(0), f::<M::V>(50.0));
1269 assert_eq!(b1.get_index(1), f::<M::V>(51.0));
1270 assert_eq!(b1.get_index(2), f::<M::V>(52.0));
1271 }
1272
1273 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1274 pub fn test_strided_view_mut_axpy<M: DenseMatrix>(ctx: M::C) {
1275 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1276 let x = M::V::from_vec(
1277 vec![f::<M::V>(10.0), f::<M::V>(10.0), f::<M::V>(10.0)],
1278 M::C::default(),
1279 );
1280 {
1281 let mut col1 = matrix.column_mut(1);
1282 col1.axpy(f::<M::V>(2.0), &x, f::<M::V>(1.0));
1283 }
1284 let owned_v = matrix.column(1).into_owned();
1285 let b1 = owned_v.get_batch(1);
1286 assert_eq!(b1.get_index(0), f::<M::V>(130.0));
1287 assert_eq!(b1.get_index(1), f::<M::V>(131.0));
1288 assert_eq!(b1.get_index(2), f::<M::V>(132.0));
1289 }
1290
1291 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1292 pub fn test_strided_view_mut_mul_assign_scalar<M: DenseMatrix>(ctx: M::C) {
1293 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1294 {
1295 let mut col1 = matrix.column_mut(1);
1296 col1 *= Scale(f::<M::V>(2.0));
1297 }
1298 let owned_v = matrix.column(1).into_owned();
1299 let b0 = owned_v.get_batch(0);
1300 let b1 = owned_v.get_batch(1);
1301 assert_eq!(b0.get_index(0), f::<M::V>(20.0));
1302 assert_eq!(b1.get_index(0), f::<M::V>(220.0));
1303 }
1304
1305 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1306 pub fn test_strided_view_mut_add_assign<M: DenseMatrix>(ctx: M::C) {
1307 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1308 let rhs = M::V::from_vec(
1309 vec![
1310 f::<M::V>(5.0),
1311 f::<M::V>(5.0),
1312 f::<M::V>(5.0),
1313 f::<M::V>(10.0),
1314 f::<M::V>(10.0),
1315 f::<M::V>(10.0),
1316 ],
1317 ctx.clone(),
1318 );
1319 {
1320 let mut col1 = matrix.column_mut(1);
1321 col1 += &rhs;
1322 }
1323 let owned_v = matrix.column(1).into_owned();
1324 let b0 = owned_v.get_batch(0);
1325 let b1 = owned_v.get_batch(1);
1326 assert_eq!(b0.get_index(0), f::<M::V>(15.0));
1327 assert_eq!(b0.get_index(1), f::<M::V>(16.0));
1328 assert_eq!(b0.get_index(2), f::<M::V>(17.0));
1329 assert_eq!(b1.get_index(0), f::<M::V>(120.0));
1330 assert_eq!(b1.get_index(1), f::<M::V>(121.0));
1331 assert_eq!(b1.get_index(2), f::<M::V>(122.0));
1332 }
1333
1334 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1335 pub fn test_strided_view_mut_sub_assign<M: DenseMatrix>(ctx: M::C) {
1336 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1337 let rhs = M::V::from_vec(
1338 vec![
1339 f::<M::V>(1.0),
1340 f::<M::V>(1.0),
1341 f::<M::V>(1.0),
1342 f::<M::V>(1.0),
1343 f::<M::V>(1.0),
1344 f::<M::V>(1.0),
1345 ],
1346 ctx.clone(),
1347 );
1348 {
1349 let mut col1 = matrix.column_mut(1);
1350 col1 -= &rhs;
1351 }
1352 let owned_v = matrix.column(1).into_owned();
1353 let b0 = owned_v.get_batch(0);
1354 let b1 = owned_v.get_batch(1);
1355 assert_eq!(b0.get_index(0), f::<M::V>(9.0));
1356 assert_eq!(b1.get_index(0), f::<M::V>(109.0));
1357 }
1358
1359 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1360 pub fn test_strided_view_add_assign_broadcast<M: DenseMatrix>(ctx: M::C) {
1361 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1362 let rhs = M::V::from_vec(
1363 vec![f::<M::V>(5.0), f::<M::V>(5.0), f::<M::V>(5.0)],
1364 M::C::default(),
1365 );
1366 {
1367 let mut col1 = matrix.column_mut(1);
1368 col1 += &rhs;
1369 }
1370 let owned_v = matrix.column(1).into_owned();
1371 let b0 = owned_v.get_batch(0);
1372 let b1 = owned_v.get_batch(1);
1373 assert_eq!(b0.get_index(0), f::<M::V>(15.0));
1374 assert_eq!(b1.get_index(0), f::<M::V>(115.0));
1375 }
1376
1377 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1378 pub fn test_strided_view_add_owned<M: DenseMatrix>(ctx: M::C) {
1379 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1380 let nbatch = ctx.nbatch();
1381 let mut rhs_data = Vec::with_capacity(3 * nbatch);
1382 for _ in 0..nbatch {
1383 rhs_data.extend_from_slice(&[f::<M::V>(5.0), f::<M::V>(5.0), f::<M::V>(5.0)]);
1384 }
1385 let rhs = M::V::from_vec(rhs_data, ctx.clone());
1386 let col1 = matrix.column(1);
1387 let result = col1 + &rhs;
1388 let b0 = result.get_batch(0);
1389 let b1 = result.get_batch(1);
1390 assert_eq!(b0.get_index(0), f::<M::V>(15.0));
1391 assert_eq!(b1.get_index(0), f::<M::V>(115.0));
1392 }
1393
1394 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1395 pub fn test_strided_view_squared_norm<M: DenseMatrix>(ctx: M::C) {
1396 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1397 let nbatch = ctx.nbatch();
1398 let mut y_data = Vec::with_capacity(3 * nbatch);
1399 for _ in 0..nbatch {
1400 y_data.extend_from_slice(&[f::<M::V>(1.0), f::<M::V>(1.0), f::<M::V>(1.0)]);
1401 }
1402 let y = M::V::from_vec(y_data, ctx.clone());
1403 let atol = M::V::from_vec(
1404 vec![f::<M::V>(1e-3), f::<M::V>(1e-3), f::<M::V>(1e-3)],
1405 M::C::default(),
1406 );
1407 let col1 = matrix.column(1);
1408 let norm = col1.squared_norm(&y, &atol, f::<M::V>(1e-2));
1409 assert!(norm > f::<M::V>(0.0));
1410 }
1411
1412 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1413 pub fn test_strided_view_into_owned<M: DenseMatrix>(ctx: M::C) {
1414 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1415 let col1 = matrix.column(1);
1416 let owned = col1.into_owned();
1417 let b0 = owned.get_batch(0);
1418 let b1 = owned.get_batch(1);
1419 assert_eq!(b0.get_index(0), f::<M::V>(10.0));
1420 assert_eq!(b0.get_index(1), f::<M::V>(11.0));
1421 assert_eq!(b1.get_index(0), f::<M::V>(110.0));
1422 assert_eq!(b1.get_index(1), f::<M::V>(111.0));
1423 }
1424
1425 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1426 pub fn test_strided_view_component_mul<M: DenseMatrix>(ctx: M::C) {
1427 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1428 let rhs = M::V::from_vec(
1429 vec![f::<M::V>(10.0), f::<M::V>(1.0), f::<M::V>(0.0)],
1430 M::C::default(),
1431 );
1432 let col1 = matrix.column(1);
1433 let mut owned = col1.into_owned();
1434 owned.component_mul_assign(&rhs);
1435 let b0 = owned.get_batch(0);
1436 let b1 = owned.get_batch(1);
1437 assert_eq!(b0.get_index(0), f::<M::V>(100.0));
1438 assert_eq!(b0.get_index(1), f::<M::V>(11.0));
1439 assert_eq!(b1.get_index(0), f::<M::V>(1100.0));
1440 assert_eq!(b1.get_index(1), f::<M::V>(111.0));
1441 }
1442
1443 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1444 pub fn test_strided_view_component_div<M: DenseMatrix>(ctx: M::C) {
1445 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1446 let rhs = M::V::from_vec(
1447 vec![f::<M::V>(10.0), f::<M::V>(11.0), f::<M::V>(12.0)],
1448 M::C::default(),
1449 );
1450 let col1 = matrix.column(1);
1451 let mut owned = col1.into_owned();
1452 owned.component_div_assign(&rhs);
1453 let b0 = owned.get_batch(0);
1454 let b1 = owned.get_batch(1);
1455 assert_eq!(b0.get_index(0), f::<M::V>(1.0));
1456 assert_eq!(b1.get_index(0), f::<M::V>(11.0));
1457 }
1458
1459 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1460 pub fn test_strided_view_mul_scalar<M: DenseMatrix>(ctx: M::C) {
1461 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1462 let col1 = matrix.column(1);
1463 let result = col1 * Scale(f::<M::V>(2.0));
1464 let b0 = result.get_batch(0);
1465 let b1 = result.get_batch(1);
1466 assert_eq!(b0.get_index(0), f::<M::V>(20.0));
1467 assert_eq!(b1.get_index(0), f::<M::V>(220.0));
1468 }
1469
1470 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1471 pub fn test_strided_view_fill<M: DenseMatrix>(ctx: M::C) {
1472 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1473 let col1 = matrix.column(1);
1474 let mut owned = col1.into_owned();
1475 owned.fill(f::<M::V>(7.0));
1476 let b0 = owned.get_batch(0);
1477 let b1 = owned.get_batch(1);
1478 assert_eq!(b0.get_index(0), f::<M::V>(7.0));
1479 assert_eq!(b1.get_index(0), f::<M::V>(7.0));
1480 }
1481
1482 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1483 pub fn test_strided_view_assign_at_indices<M: DenseMatrix>(ctx: M::C) {
1484 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1485 let indices = <M::V as Vector>::Index::from_vec(vec![0, 2], M::C::default());
1486 let col1 = matrix.column(1);
1487 let mut owned = col1.into_owned();
1488 owned.assign_at_indices(&indices, f::<M::V>(0.0));
1489 let b0 = owned.get_batch(0);
1490 let b1 = owned.get_batch(1);
1491 assert_eq!(b0.get_index(0), f::<M::V>(0.0));
1492 assert_eq!(b1.get_index(0), f::<M::V>(0.0));
1493 }
1494
1495 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1496 pub fn test_strided_view_copy_from_indices<M: DenseMatrix>(ctx: M::C) {
1497 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1498 let nbatch = ctx.nbatch();
1499 let mut other_data = Vec::with_capacity(3 * nbatch);
1500 for _ in 0..nbatch {
1501 other_data.extend_from_slice(&[f::<M::V>(50.0), f::<M::V>(0.0), f::<M::V>(0.0)]);
1502 }
1503 let other = M::V::from_vec(other_data, ctx.clone());
1504 let indices = <M::V as Vector>::Index::from_vec(vec![0], M::C::default());
1505 let col1 = matrix.column(1);
1506 let mut owned = col1.into_owned();
1507 owned.copy_from_indices(&other, &indices);
1508 let b0 = owned.get_batch(0);
1509 let b1 = owned.get_batch(1);
1510 assert_eq!(b0.get_index(0), f::<M::V>(50.0));
1511 assert_eq!(b1.get_index(0), f::<M::V>(50.0));
1512 }
1513
1514 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1515 pub fn test_strided_view_gather<M: DenseMatrix>(ctx: M::C) {
1516 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1517 let nbatch = ctx.nbatch();
1518 let mut result = M::V::zeros(2, M::C::default().clone_with_nbatch(nbatch).unwrap());
1519 let indices = <M::V as Vector>::Index::from_vec(vec![0, 2], M::C::default());
1520 let col1 = matrix.column(1);
1521 let owned = col1.into_owned();
1522 result.gather(&owned, &indices);
1523 let b1 = result.get_batch(1);
1524 assert_eq!(b1.get_index(0), f::<M::V>(110.0));
1525 }
1526
1527 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1528 pub fn test_strided_view_scatter<M: DenseMatrix>(ctx: M::C) {
1529 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
1530 let nbatch = ctx.nbatch();
1531 let col1 = matrix.column(1);
1532 let owned = col1.into_owned();
1533 let indices = <M::V as Vector>::Index::from_vec(vec![0, 1, 2], M::C::default());
1534 let mut result = M::V::zeros(3, M::C::default().clone_with_nbatch(nbatch).unwrap());
1535 owned.scatter(&indices, &mut result);
1536 let b1 = result.get_batch(1);
1537 assert_eq!(b1.get_index(0), f::<M::V>(110.0));
1538 }
1539}
1540
1541#[cfg(test)]
1542macro_rules! generate_vector_tests_nonbatched {
1543 ($suffix:ident, $V:ty) => {
1544 paste::paste! {
1545 #[test]
1546 fn [<test_root_finding_ $suffix>]() {
1547 $crate::vector::tests::test_root_finding::<$V>();
1548 }
1549 #[test]
1550 fn [<test_from_slice_ $suffix>]() {
1551 $crate::vector::tests::test_from_slice::<$V>();
1552 }
1553 #[test]
1554 fn [<test_mul_scalar_ $suffix>]() {
1555 $crate::vector::tests::test_mul_scalar::<$V>();
1556 }
1557 #[test]
1558 fn [<test_div_scalar_ $suffix>]() {
1559 $crate::vector::tests::test_div_scalar::<$V>();
1560 }
1561 #[test]
1562 fn [<test_axpy_ $suffix>]() {
1563 $crate::vector::tests::test_axpy::<$V>();
1564 }
1565 #[test]
1566 fn [<test_copy_from_indices_ $suffix>]() {
1567 $crate::vector::tests::test_copy_from_indices::<$V>();
1568 }
1569 #[test]
1570 fn [<test_gather_ $suffix>]() {
1571 $crate::vector::tests::test_gather::<$V>();
1572 }
1573 #[test]
1574 fn [<test_scatter_ $suffix>]() {
1575 $crate::vector::tests::test_scatter::<$V>();
1576 }
1577 #[test]
1578 fn [<test_copy_from_via_view_mut_ $suffix>]() {
1579 $crate::vector::tests::test_copy_from_via_view_mut::<$V>();
1580 }
1581 #[test]
1582 fn [<test_set_index_ $suffix>]() {
1583 $crate::vector::tests::test_set_index::<$V>();
1584 }
1585 #[test]
1586 fn [<test_get_index_ $suffix>]() {
1587 $crate::vector::tests::test_get_index::<$V>();
1588 }
1589 #[test]
1590 fn [<test_norm_ $suffix>]() {
1591 $crate::vector::tests::test_norm::<$V>();
1592 }
1593 #[test]
1594 fn [<test_norm_l1_ $suffix>]() {
1595 $crate::vector::tests::test_norm_l1::<$V>();
1596 }
1597 #[test]
1598 fn [<test_squared_norm_ $suffix>]() {
1599 $crate::vector::tests::test_squared_norm::<$V>();
1600 }
1601 #[test]
1602 fn [<test_fill_ $suffix>]() {
1603 $crate::vector::tests::test_fill::<$V>();
1604 }
1605 #[test]
1606 fn [<test_from_element_ $suffix>]() {
1607 $crate::vector::tests::test_from_element::<$V>();
1608 }
1609 #[test]
1610 fn [<test_copy_from_ $suffix>]() {
1611 $crate::vector::tests::test_copy_from::<$V>();
1612 }
1613 #[test]
1614 fn [<test_from_vec_ $suffix>]() {
1615 $crate::vector::tests::test_from_vec::<$V>();
1616 }
1617 #[test]
1618 fn [<test_component_mul_assign_ $suffix>]() {
1619 $crate::vector::tests::test_component_mul_assign::<$V>();
1620 }
1621 #[test]
1622 fn [<test_component_div_assign_ $suffix>]() {
1623 $crate::vector::tests::test_component_div_assign::<$V>();
1624 }
1625 #[test]
1626 fn [<test_assign_at_indices_ $suffix>]() {
1627 $crate::vector::tests::test_assign_at_indices::<$V>();
1628 }
1629 #[test]
1630 fn [<test_add_ $suffix>]() {
1631 $crate::vector::tests::test_add::<$V>();
1632 }
1633 #[test]
1634 fn [<test_sub_ $suffix>]() {
1635 $crate::vector::tests::test_sub::<$V>();
1636 }
1637 #[test]
1638 fn [<test_add_assign_ $suffix>]() {
1639 $crate::vector::tests::test_add_assign::<$V>();
1640 }
1641 #[test]
1642 fn [<test_sub_assign_ $suffix>]() {
1643 $crate::vector::tests::test_sub_assign::<$V>();
1644 }
1645 #[test]
1646 fn [<test_axpy_v_ $suffix>]() {
1647 $crate::vector::tests::test_axpy_v::<$V>();
1648 }
1649 #[test]
1650 fn [<test_mul_assign_scalar_ $suffix>]() {
1651 $crate::vector::tests::test_mul_assign_scalar::<$V>();
1652 }
1653 #[test]
1654 fn [<test_copy_from_view_ $suffix>]() {
1655 $crate::vector::tests::test_copy_from_view::<$V>();
1656 }
1657 #[test]
1658 fn [<test_view_squared_norm_ $suffix>]() {
1659 $crate::vector::tests::test_view_squared_norm::<$V>();
1660 }
1661 #[test]
1662 fn [<test_view_into_owned_ $suffix>]() {
1663 $crate::vector::tests::test_view_into_owned::<$V>();
1664 }
1665 #[test]
1666 fn [<test_view_get_index_ $suffix>]() {
1667 $crate::vector::tests::test_view_get_index::<$V>();
1668 }
1669 #[test]
1670 fn [<test_view_mut_axpy_ $suffix>]() {
1671 $crate::vector::tests::test_view_mut_axpy::<$V>();
1672 }
1673 #[test]
1674 fn [<test_view_mut_set_index_ $suffix>]() {
1675 $crate::vector::tests::test_view_mut_set_index::<$V>();
1676 }
1677 #[test]
1678 fn [<test_view_mut_mul_assign_scalar_ $suffix>]() {
1679 $crate::vector::tests::test_view_mut_mul_assign_scalar::<$V>();
1680 }
1681 #[test]
1682 fn [<test_view_mut_copy_from_view_ $suffix>]() {
1683 $crate::vector::tests::test_view_mut_copy_from_view::<$V>();
1684 }
1685 }
1686 };
1687}
1688
1689#[cfg(test)]
1690#[cfg_attr(not(feature = "cuda"), allow(unused_macros))]
1691macro_rules! generate_vector_tests_batched {
1692 ($suffix:ident, $V:ty, $ctx2:expr, $ctx3:expr) => {
1693 paste::paste! {
1694 #[test]
1695 fn [<test_batched_len_and_total_len_ $suffix>]() {
1696 $crate::vector::tests::test_batched_len_and_total_len::<$V>($ctx3);
1697 }
1698 #[test]
1699 fn [<test_batched_from_vec_ $suffix>]() {
1700 $crate::vector::tests::test_batched_from_vec::<$V>($ctx2);
1701 }
1702 #[test]
1703 #[should_panic(expected = "divisible by nbatch")]
1704 fn [<test_batched_from_vec_bad_length_ $suffix>]() {
1705 $crate::vector::tests::test_batched_from_vec_bad_length::<$V>($ctx2);
1706 }
1707 #[test]
1708 fn [<test_batched_from_element_ $suffix>]() {
1709 $crate::vector::tests::test_batched_from_element::<$V>($ctx3);
1710 }
1711 #[test]
1712 fn [<test_batched_axpy_ $suffix>]() {
1713 $crate::vector::tests::test_batched_axpy::<$V>($ctx2);
1714 }
1715 #[test]
1716 fn [<test_batched_add_ $suffix>]() {
1717 $crate::vector::tests::test_batched_add::<$V>($ctx2);
1718 }
1719 #[test]
1720 fn [<test_batched_norm_max_across_batches_ $suffix>]() {
1721 $crate::vector::tests::test_batched_norm_max_across_batches::<$V>($ctx2);
1722 }
1723 #[test]
1724 fn [<test_batched_norm_l1_ $suffix>]() {
1725 $crate::vector::tests::test_batched_norm_l1::<$V>($ctx2);
1726 }
1727 #[test]
1728 fn [<test_batched_squared_norm_ $suffix>]() {
1729 $crate::vector::tests::test_batched_squared_norm::<$V>($ctx2);
1730 }
1731 #[test]
1732 fn [<test_batched_set_index_ $suffix>]() {
1733 $crate::vector::tests::test_batched_set_index::<$V>($ctx3);
1734 }
1735 #[test]
1736 #[should_panic(expected = "not supported for batched")]
1737 fn [<test_batched_get_index_panics_ $suffix>]() {
1738 $crate::vector::tests::test_batched_get_index_panics::<$V>($ctx2);
1739 }
1740 #[test]
1741 fn [<test_batched_fill_ $suffix>]() {
1742 $crate::vector::tests::test_batched_fill::<$V>($ctx2);
1743 }
1744 #[test]
1745 fn [<test_batched_component_mul_ $suffix>]() {
1746 $crate::vector::tests::test_batched_component_mul::<$V>($ctx2);
1747 }
1748 #[test]
1749 fn [<test_batched_assign_at_indices_ $suffix>]() {
1750 $crate::vector::tests::test_batched_assign_at_indices::<$V>($ctx2);
1751 }
1752 #[test]
1753 fn [<test_batched_root_finding_consistent_ $suffix>]() {
1754 $crate::vector::tests::test_batched_root_finding_consistent::<$V>($ctx2);
1755 }
1756 #[test]
1757 #[should_panic(expected = "differ across batches")]
1758 fn [<test_batched_root_finding_inconsistent_ $suffix>]() {
1759 $crate::vector::tests::test_batched_root_finding_inconsistent::<$V>($ctx2);
1760 }
1761 #[test]
1762 fn [<test_batched_axpy_broadcast_ $suffix>]() {
1763 $crate::vector::tests::test_batched_axpy_broadcast::<$V>($ctx2);
1764 }
1765 #[test]
1766 fn [<test_batched_copy_from_broadcast_ $suffix>]() {
1767 $crate::vector::tests::test_batched_copy_from_broadcast::<$V>($ctx2);
1768 }
1769 #[test]
1770 fn [<test_batched_component_div_ $suffix>]() {
1771 $crate::vector::tests::test_batched_component_div::<$V>($ctx2);
1772 }
1773 #[test]
1774 fn [<test_batched_component_mul_broadcast_ $suffix>]() {
1775 $crate::vector::tests::test_batched_component_mul_broadcast::<$V>($ctx2);
1776 }
1777 #[test]
1778 fn [<test_batched_component_div_broadcast_ $suffix>]() {
1779 $crate::vector::tests::test_batched_component_div_broadcast::<$V>($ctx2);
1780 }
1781 #[test]
1782 fn [<test_batched_add_assign_broadcast_ $suffix>]() {
1783 $crate::vector::tests::test_batched_add_assign_broadcast::<$V>($ctx2);
1784 }
1785 #[test]
1786 fn [<test_batched_sub_assign_broadcast_ $suffix>]() {
1787 $crate::vector::tests::test_batched_sub_assign_broadcast::<$V>($ctx2);
1788 }
1789 #[test]
1790 fn [<test_batched_sub_ $suffix>]() {
1791 $crate::vector::tests::test_batched_sub::<$V>($ctx2);
1792 }
1793 #[test]
1794 fn [<test_batched_sub_assign_ $suffix>]() {
1795 $crate::vector::tests::test_batched_sub_assign::<$V>($ctx2);
1796 }
1797 #[test]
1798 fn [<test_batched_from_slice_ $suffix>]() {
1799 $crate::vector::tests::test_batched_from_slice::<$V>($ctx2);
1800 }
1801 #[test]
1802 fn [<test_batched_mul_scalar_ $suffix>]() {
1803 $crate::vector::tests::test_batched_mul_scalar::<$V>($ctx2);
1804 }
1805 #[test]
1806 fn [<test_batched_div_scalar_ $suffix>]() {
1807 $crate::vector::tests::test_batched_div_scalar::<$V>($ctx2);
1808 }
1809 #[test]
1810 fn [<test_batched_copy_from_indices_ $suffix>]() {
1811 $crate::vector::tests::test_batched_copy_from_indices::<$V>($ctx2);
1812 }
1813 #[test]
1814 fn [<test_batched_gather_ $suffix>]() {
1815 $crate::vector::tests::test_batched_gather::<$V>($ctx2);
1816 }
1817 #[test]
1818 fn [<test_batched_scatter_ $suffix>]() {
1819 $crate::vector::tests::test_batched_scatter::<$V>($ctx2);
1820 }
1821 #[test]
1822 fn [<test_batched_get_batch_ $suffix>]() {
1823 $crate::vector::tests::test_batched_get_batch::<$V>($ctx2);
1824 }
1825 #[test]
1826 fn [<test_batched_get_batch_mut_ $suffix>]() {
1827 $crate::vector::tests::test_batched_get_batch_mut::<$V>($ctx2);
1828 }
1829 #[test]
1830 fn [<test_batched_axpy_v_ $suffix>]() {
1831 $crate::vector::tests::test_batched_axpy_v::<$V>($ctx2);
1832 }
1833 #[test]
1834 fn [<test_batched_mul_assign_scalar_ $suffix>]() {
1835 $crate::vector::tests::test_batched_mul_assign_scalar::<$V>($ctx2);
1836 }
1837 #[test]
1838 fn [<test_batched_copy_from_view_ $suffix>]() {
1839 $crate::vector::tests::test_batched_copy_from_view::<$V>($ctx2);
1840 }
1841 #[test]
1842 fn [<test_batched_axpy_new_ $suffix>]() {
1843 $crate::vector::tests::test_batched_axpy_new::<$V>($ctx2);
1844 }
1845 #[test]
1846 fn [<test_batched_axpy_new_broadcast_ $suffix>]() {
1847 $crate::vector::tests::test_batched_axpy_new_broadcast::<$V>($ctx2);
1848 }
1849 #[test]
1850 #[should_panic(expected = "alpha.len() must equal")]
1851 fn [<test_batched_axpy_new_bad_length_ $suffix>]() {
1852 $crate::vector::tests::test_batched_axpy_new_bad_length::<$V>($ctx2);
1853 }
1854 #[test]
1855 #[should_panic(expected = "incompatible nbatch")]
1856 fn [<test_batched_axpy_incompatible_ $suffix>]() {
1857 $crate::vector::tests::test_batched_axpy_incompatible::<$V>($ctx2, $ctx3);
1858 }
1859 #[test]
1860 #[should_panic(expected = "incompatible nbatch")]
1861 fn [<test_batched_copy_from_incompatible_ $suffix>]() {
1862 $crate::vector::tests::test_batched_copy_from_incompatible::<$V>($ctx2, $ctx3);
1863 }
1864 #[test]
1865 #[should_panic(expected = "incompatible nbatch")]
1866 fn [<test_batched_add_assign_incompatible_ $suffix>]() {
1867 $crate::vector::tests::test_batched_add_assign_incompatible::<$V>($ctx2, $ctx3);
1868 }
1869 #[test]
1870 #[should_panic(expected = "incompatible nbatch")]
1871 fn [<test_batched_component_mul_incompatible_ $suffix>]() {
1872 $crate::vector::tests::test_batched_component_mul_incompatible::<$V>($ctx2, $ctx3);
1873 }
1874
1875 #[test]
1877 fn [<test_strided_view_set_index_ $suffix>]() {
1878 $crate::vector::tests::test_strided_view_set_index::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1879 }
1880 #[test]
1881 fn [<test_strided_view_mut_copy_from_ $suffix>]() {
1882 $crate::vector::tests::test_strided_view_mut_copy_from::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1883 }
1884 #[test]
1885 fn [<test_strided_view_mut_axpy_ $suffix>]() {
1886 $crate::vector::tests::test_strided_view_mut_axpy::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1887 }
1888 #[test]
1889 fn [<test_strided_view_mut_mul_assign_scalar_ $suffix>]() {
1890 $crate::vector::tests::test_strided_view_mut_mul_assign_scalar::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1891 }
1892 #[test]
1893 fn [<test_strided_view_mut_add_assign_ $suffix>]() {
1894 $crate::vector::tests::test_strided_view_mut_add_assign::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1895 }
1896 #[test]
1897 fn [<test_strided_view_mut_sub_assign_ $suffix>]() {
1898 $crate::vector::tests::test_strided_view_mut_sub_assign::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1899 }
1900 #[test]
1901 fn [<test_strided_view_add_assign_broadcast_ $suffix>]() {
1902 $crate::vector::tests::test_strided_view_add_assign_broadcast::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1903 }
1904 #[test]
1905 fn [<test_strided_view_add_owned_ $suffix>]() {
1906 $crate::vector::tests::test_strided_view_add_owned::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1907 }
1908 #[test]
1909 fn [<test_strided_view_squared_norm_ $suffix>]() {
1910 $crate::vector::tests::test_strided_view_squared_norm::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1911 }
1912 #[test]
1913 fn [<test_strided_view_into_owned_ $suffix>]() {
1914 $crate::vector::tests::test_strided_view_into_owned::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1915 }
1916 #[test]
1917 fn [<test_strided_view_component_mul_ $suffix>]() {
1918 $crate::vector::tests::test_strided_view_component_mul::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1919 }
1920 #[test]
1921 fn [<test_strided_view_component_div_ $suffix>]() {
1922 $crate::vector::tests::test_strided_view_component_div::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1923 }
1924 #[test]
1925 fn [<test_strided_view_mul_scalar_ $suffix>]() {
1926 $crate::vector::tests::test_strided_view_mul_scalar::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1927 }
1928 #[test]
1929 fn [<test_strided_view_fill_ $suffix>]() {
1930 $crate::vector::tests::test_strided_view_fill::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1931 }
1932 #[test]
1933 fn [<test_strided_view_assign_at_indices_ $suffix>]() {
1934 $crate::vector::tests::test_strided_view_assign_at_indices::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1935 }
1936 #[test]
1937 fn [<test_strided_view_copy_from_indices_ $suffix>]() {
1938 $crate::vector::tests::test_strided_view_copy_from_indices::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1939 }
1940 #[test]
1941 fn [<test_strided_view_gather_ $suffix>]() {
1942 $crate::vector::tests::test_strided_view_gather::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1943 }
1944 #[test]
1945 fn [<test_strided_view_scatter_ $suffix>]() {
1946 $crate::vector::tests::test_strided_view_scatter::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1947 }
1948 }
1949 };
1950}
1951#[cfg(test)]
1952#[cfg_attr(not(feature = "cuda"), allow(unused_imports))]
1953pub(crate) use generate_vector_tests_batched;
1954#[cfg(test)]
1955pub(crate) use generate_vector_tests_nonbatched;