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, 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#[cfg(feature = "cuda-oxide")]
17pub mod cuda_oxide;
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);
134 fn fill_index(&mut self, index: IndexType, value: Self::T);
136}
137
138pub trait VectorView<'a>:
144 VectorOpsByValue<Self, Self::Owned>
145 + VectorOpsByValue<Self::Owned, Self::Owned>
146 + for<'b> VectorOpsByValue<&'b Self::Owned, Self::Owned>
147 + for<'b> VectorOpsByValue<&'b Self, Self::Owned>
148 + Mul<Scale<Self::T>, Output = Self::Owned>
149{
150 type Owned;
151 fn get_index(&self, index: IndexType) -> Self::T;
153 fn squared_norm(&self, y: &Self::Owned, atol: &Self::Owned, rtol: Self::T) -> Self::T;
157 fn into_owned(self) -> Self::Owned;
159}
160
161pub trait Vector:
167 VectorOpsByValue<Self>
168 + for<'b> VectorOpsByValue<&'b Self>
169 + for<'a> VectorOpsByValue<Self::View<'a>>
170 + for<'a, 'b> VectorOpsByValue<&'b Self::View<'a>>
171 + Mul<Scale<Self::T>, Output = Self>
172 + Div<Scale<Self::T>, Output = Self>
173 + VectorMutOpsByValue<Self>
174 + for<'a> VectorMutOpsByValue<Self::View<'a>>
175 + for<'b> VectorMutOpsByValue<&'b Self>
176 + for<'a, 'b> VectorMutOpsByValue<&'b Self::View<'a>>
177 + MulAssign<Scale<Self::T>>
178 + Clone
179 + Send
180{
181 type View<'a>: VectorView<'a, T = Self::T, Owned = Self>
182 where
183 Self: 'a;
184 type ViewMut<'a>: VectorViewMut<'a, T = Self::T, Owned = Self, View = Self::View<'a>>
185 where
186 Self: 'a;
187 type Index: VectorIndex;
188
189 fn context(&self) -> &Self::C;
191
192 fn inner_mut(&mut self) -> &mut Self::Inner;
194
195 fn set_index(&mut self, index: IndexType, value: Self::T);
198
199 fn fill_index(&mut self, index: IndexType, value: Self::T);
204
205 fn get_index(&self, index: IndexType) -> Self::T;
208
209 fn norm(&self, k: i32) -> Self::T;
211
212 fn squared_norm(&self, y: &Self, atol: &Self, rtol: Self::T) -> Self::T;
216
217 fn len(&self) -> IndexType;
220
221 fn total_len(&self) -> IndexType {
224 self.len() * self.context().nbatch()
225 }
226
227 fn is_empty(&self) -> bool {
229 self.len() == 0
230 }
231
232 fn from_element(nstates: usize, value: Self::T, ctx: Self::C) -> Self;
234
235 fn zeros(nstates: usize, ctx: Self::C) -> Self {
237 Self::from_element(nstates, Self::T::zero(), ctx)
238 }
239
240 fn fill(&mut self, value: Self::T);
242
243 fn as_view(&self) -> Self::View<'_>;
245
246 fn as_view_mut(&mut self) -> Self::ViewMut<'_>;
248
249 fn get_batch(&self, batch: usize) -> Self::View<'_>;
251
252 fn get_batch_mut(&mut self, batch: usize) -> Self::ViewMut<'_>;
254
255 fn for_each_batch_mut_host<const M: usize, const N: usize>(
275 mut_args: [&mut Self; M],
276 args: [&Self; N],
277 f: impl FnMut([&mut [Self::T]; M], [&[Self::T]; N], usize),
278 );
279
280 fn for_each_batch_host<const N: usize>(
293 &mut self,
294 args: [&Self; N],
295 mut f: impl FnMut(&mut [Self::T], [&[Self::T]; N], usize),
296 ) {
297 Self::for_each_batch_mut_host([self], args, |[y], ins, lane| f(y, ins, lane));
298 }
299
300 fn for_each_batch_mut<const M: usize, const N: usize>(
311 mut_args: [&mut Self; M],
312 args: [&Self; N],
313 f: impl Fn([&mut [Self::T]; M], [&[Self::T]; N], usize) + Copy + Send,
314 ) {
315 Self::for_each_batch_mut_host(mut_args, args, f);
316 }
317
318 fn for_each_batch<const N: usize>(
331 &mut self,
332 args: [&Self; N],
333 f: impl Fn(&mut [Self::T], [&[Self::T]; N], usize) + Copy + Send,
334 ) {
335 Self::for_each_batch_mut([self], args, move |[y], ins, lane| f(y, ins, lane));
336 }
337
338 fn for_each_elem_mut<const M: usize, const N: usize>(
350 mut_args: [&mut Self; M],
351 args: [&Self; N],
352 f: impl Fn([&mut Self::T; M], [&[Self::T]; N], usize, usize) + Copy + Send,
353 ) {
354 Self::for_each_batch_mut_host(mut_args, args, |mut outs, ins, lane| {
355 let n = outs[0].len();
356 assert!(
357 outs.iter().all(|o| o.len() == n),
358 "for_each_elem_mut needs every mutable operand to have the same length"
359 );
360 for i in 0..n {
361 f(outs.each_mut().map(|o| &mut o[i]), ins, lane, i);
362 }
363 });
364 }
365
366 fn for_each_elem<const N: usize>(
379 &mut self,
380 args: [&Self; N],
381 f: impl Fn(&mut Self::T, [&[Self::T]; N], usize, usize) + Copy + Send,
382 ) {
383 Self::for_each_elem_mut([self], args, move |[y], ins, lane, elem| {
384 f(y, ins, lane, elem)
385 });
386 }
387
388 fn reduce_batch_host<const N: usize>(
407 dest: &mut Self,
408 args: [&Self; N],
409 init: Self::T,
410 mut map: impl FnMut([&[Self::T]; N], usize, usize) -> Self::T,
411 mut combine: impl FnMut(Self::T, Self::T) -> Self::T,
412 ) {
413 assert!(N > 0, "reduce_batch takes the lane count from args[0]");
414 assert_eq!(
415 dest.context().nbatch(),
416 1,
417 "reduce_batch removes the batch dimension, so dest must be unbatched"
418 );
419 dest.fill(init);
420 let mut lanes = Self::zeros(1, args[0].context().clone());
424 Self::for_each_batch_mut_host([&mut lanes, dest], args, |[_, d], ins, lane| {
425 for (i, d) in d.iter_mut().enumerate() {
426 *d = combine(*d, map(ins, lane, i));
427 }
428 });
429 }
430
431 fn reduce_batch<const N: usize>(
439 dest: &mut Self,
440 args: [&Self; N],
441 init: Self::T,
442 map: impl Fn([&[Self::T]; N], usize, usize) -> Self::T + Copy + Send,
443 combine: impl Fn(Self::T, Self::T) -> Self::T + Copy + Send,
444 ) {
445 Self::reduce_batch_host(dest, args, init, map, combine);
446 }
447
448 fn reduce_elem_host<const N: usize>(
467 dest: &mut Self,
468 args: [&Self; N],
469 init: Self::T,
470 mut map: impl FnMut([&[Self::T]; N], usize, usize) -> Self::T,
471 mut combine: impl FnMut(Self::T, Self::T) -> Self::T,
472 ) {
473 assert!(N > 0, "reduce_elem takes the element range from args[0]");
474 assert_eq!(
475 dest.len(),
476 1,
477 "reduce_elem removes the element dimension, so dest must be a batched scalar"
478 );
479 Self::for_each_batch_mut_host([dest], args, |[d], ins, lane| {
480 let mut acc = init;
481 for i in 0..ins[0].len() {
482 acc = combine(acc, map(ins, lane, i));
483 }
484 d[0] = acc;
485 });
486 }
487
488 fn reduce_elem<const N: usize>(
496 dest: &mut Self,
497 args: [&Self; N],
498 init: Self::T,
499 map: impl Fn([&[Self::T]; N], usize, usize) -> Self::T + Copy + Send,
500 combine: impl Fn(Self::T, Self::T) -> Self::T + Copy + Send,
501 ) {
502 Self::reduce_elem_host(dest, args, init, map, combine);
503 }
504
505 fn copy_from(&mut self, other: &Self);
507
508 fn copy_from_view(&mut self, other: &Self::View<'_>);
510
511 fn from_vec(vec: Vec<Self::T>, ctx: Self::C) -> Self;
514
515 fn from_slice(slice: &[Self::T], ctx: Self::C) -> Self;
517
518 fn clone_as_vec(&self) -> Vec<Self::T>;
521
522 fn axpy(&mut self, alpha: Self::T, x: &Self, beta: Self::T);
524
525 fn axpy_v(&mut self, alpha: Self::T, x: &Self::View<'_>, beta: Self::T);
527
528 fn batched_axpy(&mut self, alpha: &Self, x: &Self, beta: Self::T);
534
535 fn component_mul_assign(&mut self, other: &Self);
537
538 fn component_div_assign(&mut self, other: &Self);
540
541 fn root_finding(&self, g1: &Self) -> (bool, Self::T, i32);
548
549 fn assign_at_indices(&mut self, indices: &Self::Index, value: Self::T);
551
552 fn copy_from_indices(&mut self, other: &Self, indices: &Self::Index);
554
555 fn gather(&mut self, other: &Self, indices: &Self::Index);
557
558 fn scatter(&self, indices: &Self::Index, other: &mut Self);
560
561 fn assert_eq_st(&self, other: &Self, tol: Self::T) {
563 let tol = vec![tol; self.total_len()];
564 Self::assert_eq_vec(self.clone_as_vec(), other.clone_as_vec(), tol);
565 }
566
567 fn assert_eq_norm(&self, other: &Self, atol: &Self, rtol: Self::T, factor: Self::T) {
572 let error = self.clone() - other.clone();
573 let error_norm = error.squared_norm(other, atol, rtol).sqrt();
574 assert!(
575 error_norm < factor,
576 "error_norm: {error_norm}. self: {self:?}, other: {other:?}",
577 );
578 }
579
580 fn assert_eq(&self, other: &Self, tol: &Self) {
582 assert_eq!(
583 self.len(),
584 other.len(),
585 "Vector length mismatch: {} != {}",
586 self.len(),
587 other.len()
588 );
589 let s = self.clone_as_vec();
590 let other = other.clone_as_vec();
591 let tol = tol.clone_as_vec();
592 Self::assert_eq_vec(s, other, tol);
593 }
594
595 fn assert_eq_vec(s: Vec<Self::T>, other: Vec<Self::T>, tol: Vec<Self::T>) {
596 for i in 0..s.len() {
597 if num_traits::abs(s[i] - other[i]) > tol[i] {
598 eprintln!(
599 "Vector element mismatch at index {i}: {} != {}",
600 s[i], other[i]
601 );
602 if s.len() <= 3 {
603 eprintln!("left: {s:?}");
604 eprintln!("right: {other:?}");
605 } else if i == 0 {
606 eprintln!(
607 "left: [{}, {}, {}] != [{}, {}, {}]",
608 s[0], s[1], s[2], other[0], other[1], other[2]
609 );
610 } else if i == s.len() - 1 {
611 eprintln!(
612 "left: [..., {}, {}, {}] != [..., {}, {}, {}]",
613 s[i - 2],
614 s[i - 1],
615 s[i],
616 other[i - 2],
617 other[i - 1],
618 other[i]
619 );
620 } else {
621 eprintln!(
622 "left: [..., {}, {}, {}, ...] != [..., {}, {}, {}, ...]",
623 s[i - 1],
624 s[i],
625 s[i + 1],
626 other[i - 1],
627 other[i],
628 other[i + 1]
629 );
630 }
631 panic!(
632 "Vector element mismatch at index {}: {} != {}",
633 i, s[i], other[i]
634 );
635 }
636 }
637 }
638}
639
640pub trait DefaultDenseMatrix: Vector {
645 type M: DenseMatrix<V = Self, T = Self::T, C = Self::C>;
646}
647
648#[cfg(test)]
649macro_rules! generate_vector_tests_nonbatched {
650 ($suffix:ident, $V:ty) => {
651 paste::paste! {
652 #[test]
653 fn [<test_root_finding_ $suffix>]() {
654 $crate::vector::tests::test_root_finding::<$V>();
655 }
656 #[test]
657 fn [<test_from_slice_ $suffix>]() {
658 $crate::vector::tests::test_from_slice::<$V>();
659 }
660 #[test]
661 fn [<test_mul_scalar_ $suffix>]() {
662 $crate::vector::tests::test_mul_scalar::<$V>();
663 }
664 #[test]
665 fn [<test_div_scalar_ $suffix>]() {
666 $crate::vector::tests::test_div_scalar::<$V>();
667 }
668 #[test]
669 fn [<test_axpy_ $suffix>]() {
670 $crate::vector::tests::test_axpy::<$V>();
671 }
672 #[test]
673 fn [<test_copy_from_indices_ $suffix>]() {
674 $crate::vector::tests::test_copy_from_indices::<$V>();
675 }
676 #[test]
677 fn [<test_gather_ $suffix>]() {
678 $crate::vector::tests::test_gather::<$V>();
679 }
680 #[test]
681 fn [<test_scatter_ $suffix>]() {
682 $crate::vector::tests::test_scatter::<$V>();
683 }
684 #[test]
685 fn [<test_copy_from_via_view_mut_ $suffix>]() {
686 $crate::vector::tests::test_copy_from_via_view_mut::<$V>();
687 }
688 #[test]
689 fn [<test_for_each_batch_ $suffix>]() {
690 $crate::vector::tests::test_for_each_batch::<$V>();
691 }
692 #[test]
693 fn [<test_for_each_batch_index_ $suffix>]() {
694 $crate::vector::tests::test_for_each_batch_index::<$V>();
695 }
696 #[test]
697 fn [<test_for_each_batch_mut_ $suffix>]() {
698 $crate::vector::tests::test_for_each_batch_mut::<$V>();
699 }
700 #[test]
701 fn [<test_for_each_elem_mut_ $suffix>]() {
702 $crate::vector::tests::test_for_each_elem_mut::<$V>();
703 }
704 #[test]
705 fn [<test_reduce_unbatched_ $suffix>]() {
706 $crate::vector::tests::test_reduce_unbatched::<$V>();
707 }
708 #[test]
709 fn [<test_set_index_ $suffix>]() {
710 $crate::vector::tests::test_set_index::<$V>();
711 }
712 #[test]
713 fn [<test_get_index_ $suffix>]() {
714 $crate::vector::tests::test_get_index::<$V>();
715 }
716 #[test]
717 fn [<test_norm_ $suffix>]() {
718 $crate::vector::tests::test_norm::<$V>();
719 }
720 #[test]
721 fn [<test_norm_l1_ $suffix>]() {
722 $crate::vector::tests::test_norm_l1::<$V>();
723 }
724 #[test]
725 fn [<test_squared_norm_ $suffix>]() {
726 $crate::vector::tests::test_squared_norm::<$V>();
727 }
728 #[test]
729 fn [<test_fill_ $suffix>]() {
730 $crate::vector::tests::test_fill::<$V>();
731 }
732 #[test]
733 fn [<test_from_element_ $suffix>]() {
734 $crate::vector::tests::test_from_element::<$V>();
735 }
736 #[test]
737 fn [<test_copy_from_ $suffix>]() {
738 $crate::vector::tests::test_copy_from::<$V>();
739 }
740 #[test]
741 fn [<test_from_vec_ $suffix>]() {
742 $crate::vector::tests::test_from_vec::<$V>();
743 }
744 #[test]
745 fn [<test_component_mul_assign_ $suffix>]() {
746 $crate::vector::tests::test_component_mul_assign::<$V>();
747 }
748 #[test]
749 fn [<test_component_div_assign_ $suffix>]() {
750 $crate::vector::tests::test_component_div_assign::<$V>();
751 }
752 #[test]
753 fn [<test_assign_at_indices_ $suffix>]() {
754 $crate::vector::tests::test_assign_at_indices::<$V>();
755 }
756 #[test]
757 fn [<test_add_ $suffix>]() {
758 $crate::vector::tests::test_add::<$V>();
759 }
760 #[test]
761 fn [<test_sub_ $suffix>]() {
762 $crate::vector::tests::test_sub::<$V>();
763 }
764 #[test]
765 fn [<test_owned_rhs_ $suffix>]() {
766 $crate::vector::tests::test_owned_rhs::<$V>();
767 }
768 #[test]
769 fn [<test_add_assign_ $suffix>]() {
770 $crate::vector::tests::test_add_assign::<$V>();
771 }
772 #[test]
773 fn [<test_sub_assign_ $suffix>]() {
774 $crate::vector::tests::test_sub_assign::<$V>();
775 }
776 #[test]
777 fn [<test_axpy_v_ $suffix>]() {
778 $crate::vector::tests::test_axpy_v::<$V>();
779 }
780 #[test]
781 fn [<test_mul_assign_scalar_ $suffix>]() {
782 $crate::vector::tests::test_mul_assign_scalar::<$V>();
783 }
784 #[test]
785 fn [<test_copy_from_view_ $suffix>]() {
786 $crate::vector::tests::test_copy_from_view::<$V>();
787 }
788 #[test]
789 fn [<test_view_squared_norm_ $suffix>]() {
790 $crate::vector::tests::test_view_squared_norm::<$V>();
791 }
792 #[test]
793 fn [<test_view_into_owned_ $suffix>]() {
794 $crate::vector::tests::test_view_into_owned::<$V>();
795 }
796 #[test]
797 fn [<test_view_get_index_ $suffix>]() {
798 $crate::vector::tests::test_view_get_index::<$V>();
799 }
800 #[test]
801 fn [<test_view_mut_axpy_ $suffix>]() {
802 $crate::vector::tests::test_view_mut_axpy::<$V>();
803 }
804 #[test]
805 fn [<test_view_mut_set_index_ $suffix>]() {
806 $crate::vector::tests::test_view_mut_set_index::<$V>();
807 }
808 #[test]
809 fn [<test_view_mut_mul_assign_scalar_ $suffix>]() {
810 $crate::vector::tests::test_view_mut_mul_assign_scalar::<$V>();
811 }
812 #[test]
813 fn [<test_view_mut_copy_from_view_ $suffix>]() {
814 $crate::vector::tests::test_view_mut_copy_from_view::<$V>();
815 }
816 #[test]
817 fn [<test_view_add_sub_ $suffix>]() {
818 $crate::vector::tests::test_view_add_sub::<$V>();
819 }
820 #[test]
821 fn [<test_index_zeros_and_is_empty_ $suffix>]() {
822 $crate::vector::tests::test_index_zeros_and_is_empty::<$V>();
823 }
824 }
825 };
826}
827
828#[cfg(test)]
829#[cfg_attr(not(feature = "cuda"), allow(unused_macros))]
830macro_rules! generate_vector_tests_batched {
831 ($suffix:ident, $V:ty, $ctx2:expr, $ctx3:expr) => {
832 paste::paste! {
833 #[test]
834 fn [<test_batched_len_and_total_len_ $suffix>]() {
835 $crate::vector::tests::test_batched_len_and_total_len::<$V>($ctx3);
836 }
837 #[test]
838 fn [<test_batched_from_vec_ $suffix>]() {
839 $crate::vector::tests::test_batched_from_vec::<$V>($ctx2);
840 }
841 #[test]
842 #[should_panic(expected = "divisible by nbatch")]
843 fn [<test_batched_from_vec_bad_length_ $suffix>]() {
844 $crate::vector::tests::test_batched_from_vec_bad_length::<$V>($ctx2);
845 }
846 #[test]
847 fn [<test_batched_from_element_ $suffix>]() {
848 $crate::vector::tests::test_batched_from_element::<$V>($ctx3);
849 }
850 #[test]
851 fn [<test_batched_axpy_ $suffix>]() {
852 $crate::vector::tests::test_batched_axpy::<$V>($ctx2);
853 }
854 #[test]
855 fn [<test_batched_add_ $suffix>]() {
856 $crate::vector::tests::test_batched_add::<$V>($ctx2);
857 }
858 #[test]
859 fn [<test_batched_norm_max_across_batches_ $suffix>]() {
860 $crate::vector::tests::test_batched_norm_max_across_batches::<$V>($ctx2);
861 }
862 #[test]
863 fn [<test_batched_norm_l1_ $suffix>]() {
864 $crate::vector::tests::test_batched_norm_l1::<$V>($ctx2);
865 }
866 #[test]
867 fn [<test_batched_squared_norm_ $suffix>]() {
868 $crate::vector::tests::test_batched_squared_norm::<$V>($ctx2);
869 }
870 #[test]
871 fn [<test_batched_fill_index_ $suffix>]() {
872 $crate::vector::tests::test_batched_fill_index::<$V>($ctx3);
873 }
874 #[test]
875 #[should_panic(expected = "not supported for batched")]
876 fn [<test_batched_get_index_panics_ $suffix>]() {
877 $crate::vector::tests::test_batched_get_index_panics::<$V>($ctx2);
878 }
879 #[test]
880 #[should_panic(expected = "not supported for batched")]
881 fn [<test_batched_set_index_panics_ $suffix>]() {
882 $crate::vector::tests::test_batched_set_index_panics::<$V>($ctx2);
883 }
884 #[test]
885 fn [<test_batched_fill_ $suffix>]() {
886 $crate::vector::tests::test_batched_fill::<$V>($ctx2);
887 }
888 #[test]
889 fn [<test_batched_component_mul_ $suffix>]() {
890 $crate::vector::tests::test_batched_component_mul::<$V>($ctx2);
891 }
892 #[test]
893 fn [<test_batched_assign_at_indices_ $suffix>]() {
894 $crate::vector::tests::test_batched_assign_at_indices::<$V>($ctx2);
895 }
896 #[test]
897 fn [<test_batched_root_finding_consistent_ $suffix>]() {
898 $crate::vector::tests::test_batched_root_finding_consistent::<$V>($ctx2);
899 }
900 #[test]
901 #[should_panic(expected = "differ across batches")]
902 fn [<test_batched_root_finding_inconsistent_ $suffix>]() {
903 $crate::vector::tests::test_batched_root_finding_inconsistent::<$V>($ctx2);
904 }
905 #[test]
906 fn [<test_batched_for_each_batch_ $suffix>]() {
907 $crate::vector::tests::test_batched_for_each_batch::<$V>($ctx2);
908 }
909 #[test]
910 fn [<test_batched_for_each_batch_index_ $suffix>]() {
911 $crate::vector::tests::test_batched_for_each_batch_index::<$V>($ctx3);
912 }
913 #[test]
914 fn [<test_batched_for_each_batch_mut_ $suffix>]() {
915 $crate::vector::tests::test_batched_for_each_batch_mut::<$V>($ctx2);
916 }
917 #[test]
918 fn [<test_batched_for_each_elem_mut_ $suffix>]() {
919 $crate::vector::tests::test_batched_for_each_elem_mut::<$V>($ctx2);
920 }
921 #[test]
922 #[should_panic(expected = "for_each_batch")]
923 fn [<test_batched_for_each_batch_bad_nbatch_ $suffix>]() {
924 $crate::vector::tests::test_batched_for_each_batch_bad_nbatch::<$V>($ctx2);
925 }
926 #[test]
927 fn [<test_batched_reduce_batch_ $suffix>]() {
928 $crate::vector::tests::test_batched_reduce_batch::<$V>($ctx2);
929 }
930 #[test]
931 fn [<test_batched_reduce_elem_ $suffix>]() {
932 $crate::vector::tests::test_batched_reduce_elem::<$V>($ctx2);
933 }
934 #[test]
935 fn [<test_batched_reduce_broadcast_ $suffix>]() {
936 $crate::vector::tests::test_batched_reduce_broadcast::<$V>($ctx2);
937 }
938 #[test]
939 fn [<test_batched_reduce_host_stateful_ $suffix>]() {
940 $crate::vector::tests::test_batched_reduce_host_stateful::<$V>($ctx2);
941 }
942 #[test]
943 fn [<test_batched_reduce_long_lane_ $suffix>]() {
944 $crate::vector::tests::test_batched_reduce_long_lane::<$V>($ctx3);
945 }
946 #[test]
947 #[should_panic(expected = "dest must be unbatched")]
948 fn [<test_batched_reduce_batch_bad_dest_ $suffix>]() {
949 $crate::vector::tests::test_batched_reduce_batch_bad_dest::<$V>($ctx2);
950 }
951 #[test]
952 #[should_panic(expected = "batched scalar")]
953 fn [<test_batched_reduce_elem_bad_dest_ $suffix>]() {
954 $crate::vector::tests::test_batched_reduce_elem_bad_dest::<$V>($ctx2);
955 }
956 #[test]
957 fn [<test_batched_axpy_broadcast_ $suffix>]() {
958 $crate::vector::tests::test_batched_axpy_broadcast::<$V>($ctx2);
959 }
960 #[test]
961 fn [<test_batched_copy_from_broadcast_ $suffix>]() {
962 $crate::vector::tests::test_batched_copy_from_broadcast::<$V>($ctx2);
963 }
964 #[test]
965 fn [<test_batched_component_div_ $suffix>]() {
966 $crate::vector::tests::test_batched_component_div::<$V>($ctx2);
967 }
968 #[test]
969 fn [<test_batched_component_mul_broadcast_ $suffix>]() {
970 $crate::vector::tests::test_batched_component_mul_broadcast::<$V>($ctx2);
971 }
972 #[test]
973 fn [<test_batched_component_div_broadcast_ $suffix>]() {
974 $crate::vector::tests::test_batched_component_div_broadcast::<$V>($ctx2);
975 }
976 #[test]
977 fn [<test_batched_add_assign_broadcast_ $suffix>]() {
978 $crate::vector::tests::test_batched_add_assign_broadcast::<$V>($ctx2);
979 }
980 #[test]
981 fn [<test_batched_sub_assign_broadcast_ $suffix>]() {
982 $crate::vector::tests::test_batched_sub_assign_broadcast::<$V>($ctx2);
983 }
984 #[test]
985 fn [<test_batched_sub_ $suffix>]() {
986 $crate::vector::tests::test_batched_sub::<$V>($ctx2);
987 }
988 #[test]
989 fn [<test_batched_owned_rhs_broadcast_ $suffix>]() {
990 $crate::vector::tests::test_batched_owned_rhs_broadcast::<$V>($ctx2);
991 }
992 #[test]
993 fn [<test_batched_owned_lhs_broadcast_ $suffix>]() {
994 $crate::vector::tests::test_batched_owned_lhs_broadcast::<$V>($ctx2);
995 }
996 #[test]
997 fn [<test_batched_view_add_broadcast_ $suffix>]() {
998 $crate::vector::tests::test_batched_view_add_broadcast::<$V>($ctx2);
999 }
1000 #[test]
1001 fn [<test_batched_sub_assign_ $suffix>]() {
1002 $crate::vector::tests::test_batched_sub_assign::<$V>($ctx2);
1003 }
1004 #[test]
1005 fn [<test_batched_from_slice_ $suffix>]() {
1006 $crate::vector::tests::test_batched_from_slice::<$V>($ctx2);
1007 }
1008 #[test]
1009 fn [<test_batched_mul_scalar_ $suffix>]() {
1010 $crate::vector::tests::test_batched_mul_scalar::<$V>($ctx2);
1011 }
1012 #[test]
1013 fn [<test_batched_div_scalar_ $suffix>]() {
1014 $crate::vector::tests::test_batched_div_scalar::<$V>($ctx2);
1015 }
1016 #[test]
1017 fn [<test_batched_copy_from_indices_ $suffix>]() {
1018 $crate::vector::tests::test_batched_copy_from_indices::<$V>($ctx2);
1019 }
1020 #[test]
1021 fn [<test_batched_gather_ $suffix>]() {
1022 $crate::vector::tests::test_batched_gather::<$V>($ctx2);
1023 }
1024 #[test]
1025 fn [<test_batched_scatter_ $suffix>]() {
1026 $crate::vector::tests::test_batched_scatter::<$V>($ctx2);
1027 }
1028 #[test]
1029 fn [<test_batched_get_batch_ $suffix>]() {
1030 $crate::vector::tests::test_batched_get_batch::<$V>($ctx2);
1031 }
1032 #[test]
1033 fn [<test_batched_get_batch_mut_ $suffix>]() {
1034 $crate::vector::tests::test_batched_get_batch_mut::<$V>($ctx2);
1035 }
1036 #[test]
1037 fn [<test_batched_axpy_v_ $suffix>]() {
1038 $crate::vector::tests::test_batched_axpy_v::<$V>($ctx2);
1039 }
1040 #[test]
1041 fn [<test_batched_mul_assign_scalar_ $suffix>]() {
1042 $crate::vector::tests::test_batched_mul_assign_scalar::<$V>($ctx2);
1043 }
1044 #[test]
1045 fn [<test_batched_copy_from_view_ $suffix>]() {
1046 $crate::vector::tests::test_batched_copy_from_view::<$V>($ctx2);
1047 }
1048 #[test]
1049 fn [<test_batched_axpy_new_ $suffix>]() {
1050 $crate::vector::tests::test_batched_axpy_new::<$V>($ctx2);
1051 }
1052 #[test]
1053 fn [<test_batched_axpy_new_broadcast_ $suffix>]() {
1054 $crate::vector::tests::test_batched_axpy_new_broadcast::<$V>($ctx2);
1055 }
1056 #[test]
1057 #[should_panic(expected = "alpha must be a batched scalar")]
1058 fn [<test_batched_axpy_new_bad_length_ $suffix>]() {
1059 $crate::vector::tests::test_batched_axpy_new_bad_length::<$V>($ctx2);
1060 }
1061 #[test]
1062 #[should_panic(expected = "alpha nbatch must equal")]
1063 fn [<test_batched_axpy_new_bad_nbatch_ $suffix>]() {
1064 $crate::vector::tests::test_batched_axpy_new_bad_nbatch::<$V>($ctx2);
1065 }
1066 #[test]
1067 fn [<test_batched_empty_ $suffix>]() {
1068 $crate::vector::tests::test_batched_empty::<$V>($ctx2);
1069 }
1070 #[test]
1071 fn [<test_batched_binary_forms_broadcast_ $suffix>]() {
1072 $crate::vector::tests::test_batched_binary_forms_broadcast::<$V>($ctx2);
1073 }
1074
1075 #[test]
1077 #[should_panic(expected = "incompatible nbatch")]
1078 fn [<test_batched_owned_lhs_narrow_ $suffix>]() {
1079 $crate::vector::tests::test_batched_owned_lhs_narrow::<$V>($ctx2);
1080 }
1081 #[test]
1082 #[should_panic(expected = "incompatible nbatch")]
1083 fn [<test_batched_owned_rhs_narrow_ $suffix>]() {
1084 $crate::vector::tests::test_batched_owned_rhs_narrow::<$V>($ctx2);
1085 }
1086 #[test]
1087 #[should_panic(expected = "incompatible nbatch")]
1088 fn [<test_batched_view_add_narrow_ $suffix>]() {
1089 $crate::vector::tests::test_batched_view_add_narrow::<$V>($ctx2);
1090 }
1091 #[test]
1092 #[should_panic(expected = "incompatible nbatch")]
1093 fn [<test_grouped_add_narrow_lhs_ $suffix>]() {
1094 $crate::vector::tests::test_grouped_add_narrow_lhs::<$V>($ctx2);
1095 }
1096 #[test]
1097 #[should_panic(expected = "incompatible nbatch")]
1098 fn [<test_grouped_owned_lhs_narrow_ $suffix>]() {
1099 $crate::vector::tests::test_grouped_owned_lhs_narrow::<$V>($ctx2);
1100 }
1101
1102 #[test]
1104 #[should_panic(expected = "incompatible nbatch")]
1105 fn [<test_narrow_dest_copy_from_ $suffix>]() {
1106 $crate::vector::tests::test_narrow_dest_copy_from::<$V>($ctx2);
1107 }
1108 #[test]
1109 #[should_panic(expected = "incompatible nbatch")]
1110 fn [<test_narrow_dest_add_assign_ $suffix>]() {
1111 $crate::vector::tests::test_narrow_dest_add_assign::<$V>($ctx2);
1112 }
1113 #[test]
1114 #[should_panic(expected = "incompatible nbatch")]
1115 fn [<test_narrow_dest_axpy_ $suffix>]() {
1116 $crate::vector::tests::test_narrow_dest_axpy::<$V>($ctx2);
1117 }
1118 #[test]
1119 #[should_panic(expected = "incompatible nbatch")]
1120 fn [<test_narrow_dest_component_mul_ $suffix>]() {
1121 $crate::vector::tests::test_narrow_dest_component_mul::<$V>($ctx2);
1122 }
1123 #[test]
1124 #[should_panic(expected = "incompatible nbatch")]
1125 fn [<test_narrow_dest_gather_ $suffix>]() {
1126 $crate::vector::tests::test_narrow_dest_gather::<$V>($ctx2);
1127 }
1128 #[test]
1129 #[should_panic(expected = "incompatible nbatch")]
1130 fn [<test_narrow_dest_copy_from_indices_ $suffix>]() {
1131 $crate::vector::tests::test_narrow_dest_copy_from_indices::<$V>($ctx2);
1132 }
1133 #[test]
1134 #[should_panic(expected = "incompatible nbatch")]
1135 fn [<test_narrow_dest_scatter_ $suffix>]() {
1136 $crate::vector::tests::test_narrow_dest_scatter::<$V>($ctx2);
1137 }
1138 #[test]
1139 #[should_panic(expected = "incompatible nbatch")]
1140 fn [<test_narrow_dest_squared_norm_ $suffix>]() {
1141 $crate::vector::tests::test_narrow_dest_squared_norm::<$V>($ctx2);
1142 }
1143 #[test]
1144 #[should_panic(expected = "incompatible nbatch")]
1145 fn [<test_unbatched_dest_squared_norm_ $suffix>]() {
1146 $crate::vector::tests::test_unbatched_dest_squared_norm::<$V>($ctx2);
1147 }
1148
1149 #[test]
1151 fn [<test_grouped_owned_lhs_ref_rhs_ $suffix>]() {
1152 $crate::vector::tests::test_grouped_owned_lhs_ref_rhs::<$V>($ctx2);
1153 }
1154 #[test]
1155 fn [<test_grouped_axpy_ $suffix>]() {
1156 $crate::vector::tests::test_grouped_axpy::<$V>($ctx2);
1157 }
1158 #[test]
1159 fn [<test_grouped_add_assign_ $suffix>]() {
1160 $crate::vector::tests::test_grouped_add_assign::<$V>($ctx2);
1161 }
1162 #[test]
1163 fn [<test_grouped_add_ $suffix>]() {
1164 $crate::vector::tests::test_grouped_add::<$V>($ctx2);
1165 }
1166 #[test]
1167 fn [<test_grouped_copy_from_ $suffix>]() {
1168 $crate::vector::tests::test_grouped_copy_from::<$V>($ctx2);
1169 }
1170 #[test]
1171 fn [<test_grouped_component_mul_ $suffix>]() {
1172 $crate::vector::tests::test_grouped_component_mul::<$V>($ctx2);
1173 }
1174 #[test]
1175 fn [<test_grouped_squared_norm_ $suffix>]() {
1176 $crate::vector::tests::test_grouped_squared_norm::<$V>($ctx2);
1177 }
1178 #[test]
1179 fn [<test_grouped_gather_ $suffix>]() {
1180 $crate::vector::tests::test_grouped_gather::<$V>($ctx2);
1181 }
1182 #[test]
1183 #[should_panic(expected = "incompatible nbatch")]
1184 fn [<test_grouped_incompatible_ $suffix>]() {
1185 $crate::vector::tests::test_grouped_incompatible::<$V>($ctx3);
1186 }
1187 #[test]
1188 #[should_panic(expected = "incompatible nbatch")]
1189 fn [<test_batched_axpy_incompatible_ $suffix>]() {
1190 $crate::vector::tests::test_batched_axpy_incompatible::<$V>($ctx2, $ctx3);
1191 }
1192 #[test]
1193 #[should_panic(expected = "incompatible nbatch")]
1194 fn [<test_batched_copy_from_incompatible_ $suffix>]() {
1195 $crate::vector::tests::test_batched_copy_from_incompatible::<$V>($ctx2, $ctx3);
1196 }
1197 #[test]
1198 #[should_panic(expected = "incompatible nbatch")]
1199 fn [<test_batched_add_assign_incompatible_ $suffix>]() {
1200 $crate::vector::tests::test_batched_add_assign_incompatible::<$V>($ctx2, $ctx3);
1201 }
1202 #[test]
1203 #[should_panic(expected = "incompatible nbatch")]
1204 fn [<test_batched_component_mul_incompatible_ $suffix>]() {
1205 $crate::vector::tests::test_batched_component_mul_incompatible::<$V>($ctx2, $ctx3);
1206 }
1207
1208 #[test]
1210 fn [<test_strided_view_fill_index_ $suffix>]() {
1211 $crate::vector::tests::test_strided_view_fill_index::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1212 }
1213 #[test]
1214 #[should_panic(expected = "not supported for batched")]
1215 fn [<test_strided_view_set_index_panics_ $suffix>]() {
1216 $crate::vector::tests::test_strided_view_set_index_panics::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1217 }
1218 #[test]
1219 fn [<test_strided_view_mut_copy_from_ $suffix>]() {
1220 $crate::vector::tests::test_strided_view_mut_copy_from::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1221 }
1222 #[test]
1223 fn [<test_strided_view_mut_axpy_ $suffix>]() {
1224 $crate::vector::tests::test_strided_view_mut_axpy::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1225 }
1226 #[test]
1227 fn [<test_strided_view_mut_mul_assign_scalar_ $suffix>]() {
1228 $crate::vector::tests::test_strided_view_mut_mul_assign_scalar::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1229 }
1230 #[test]
1231 fn [<test_strided_view_mut_add_assign_ $suffix>]() {
1232 $crate::vector::tests::test_strided_view_mut_add_assign::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1233 }
1234 #[test]
1235 fn [<test_strided_view_mut_sub_assign_ $suffix>]() {
1236 $crate::vector::tests::test_strided_view_mut_sub_assign::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1237 }
1238 #[test]
1239 fn [<test_strided_view_add_assign_broadcast_ $suffix>]() {
1240 $crate::vector::tests::test_strided_view_add_assign_broadcast::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1241 }
1242 #[test]
1243 fn [<test_strided_view_add_owned_ $suffix>]() {
1244 $crate::vector::tests::test_strided_view_add_owned::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1245 }
1246 #[test]
1247 fn [<test_strided_view_squared_norm_ $suffix>]() {
1248 $crate::vector::tests::test_strided_view_squared_norm::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1249 }
1250 #[test]
1251 fn [<test_strided_view_into_owned_ $suffix>]() {
1252 $crate::vector::tests::test_strided_view_into_owned::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1253 }
1254 #[test]
1255 fn [<test_strided_view_component_mul_ $suffix>]() {
1256 $crate::vector::tests::test_strided_view_component_mul::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1257 }
1258 #[test]
1259 fn [<test_strided_view_component_div_ $suffix>]() {
1260 $crate::vector::tests::test_strided_view_component_div::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1261 }
1262 #[test]
1263 fn [<test_strided_view_mul_scalar_ $suffix>]() {
1264 $crate::vector::tests::test_strided_view_mul_scalar::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1265 }
1266 #[test]
1267 fn [<test_strided_view_fill_ $suffix>]() {
1268 $crate::vector::tests::test_strided_view_fill::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1269 }
1270 #[test]
1271 fn [<test_strided_view_assign_at_indices_ $suffix>]() {
1272 $crate::vector::tests::test_strided_view_assign_at_indices::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1273 }
1274 #[test]
1275 fn [<test_strided_view_copy_from_indices_ $suffix>]() {
1276 $crate::vector::tests::test_strided_view_copy_from_indices::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1277 }
1278 #[test]
1279 fn [<test_strided_view_gather_ $suffix>]() {
1280 $crate::vector::tests::test_strided_view_gather::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1281 }
1282 #[test]
1283 fn [<test_strided_view_scatter_ $suffix>]() {
1284 $crate::vector::tests::test_strided_view_scatter::<<$V as $crate::DefaultDenseMatrix>::M>($ctx2);
1285 }
1286 }
1287 };
1288}
1289#[cfg(test)]
1290#[cfg_attr(not(feature = "cuda"), allow(unused_imports))]
1291pub(crate) use generate_vector_tests_batched;
1292#[cfg(test)]
1293pub(crate) use generate_vector_tests_nonbatched;
1294
1295#[cfg(test)]
1296pub(crate) mod tests {
1297 use std::ops::{Add, Sub};
1298 use std::panic::{catch_unwind, AssertUnwindSafe};
1299
1300 use super::{Vector, VectorCommon, VectorIndex, VectorView, VectorViewMut};
1301 use crate::context::nalgebra::NalgebraContext;
1302 use crate::scalar::Scalar as _;
1303 use crate::scalar::Scale;
1304 use crate::vector::nalgebra_serial::NalgebraVec;
1305 use crate::Context;
1306 use crate::IndexType;
1307 use num_traits::FromPrimitive;
1308 use std::ops::{Index, IndexMut};
1309
1310 fn f<V: Vector>(x: f64) -> V::T {
1311 V::T::from_f64(x).unwrap()
1312 }
1313
1314 fn fv<V: Vector>(xs: &[f64]) -> Vec<V::T> {
1315 xs.iter().map(|&x| f::<V>(x)).collect()
1316 }
1317
1318 pub fn test_host_only<V>()
1321 where
1322 V: Vector + Index<IndexType, Output = V::T> + IndexMut<IndexType, Output = V::T>,
1323 {
1324 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1325 assert_eq!(v[0], f::<V>(1.0));
1326 v[1] = f::<V>(20.0);
1327 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 20.0, 3.0]));
1328 }
1329
1330 pub fn test_root_finding<V: Vector>() {
1331 let g0 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
1332 let g1 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1333 let (found_root, max_frac, max_frac_index) = g0.root_finding(&g1);
1334 assert!(!found_root);
1335 assert_eq!(max_frac, f::<V>(0.5));
1336 assert_eq!(max_frac_index, 1);
1337
1338 let g0 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
1339 let g1 = V::from_vec(fv::<V>(&[1.0, 2.0, 0.0]), Default::default());
1340 let (found_root, max_frac, max_frac_index) = g0.root_finding(&g1);
1341 assert!(found_root);
1342 assert_eq!(max_frac, f::<V>(0.5));
1343 assert_eq!(max_frac_index, 1);
1344
1345 let g0 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
1346 let g1 = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0]), Default::default());
1347 let (found_root, max_frac, max_frac_index) = g0.root_finding(&g1);
1348 assert!(!found_root);
1349 assert_eq!(max_frac, f::<V>(0.0));
1350 assert_eq!(max_frac_index, -1);
1351 }
1352
1353 pub fn test_from_slice<V: Vector>() {
1354 let slice = fv::<V>(&[1.0, 2.0, 3.0]);
1355 let v = V::from_slice(&slice, Default::default());
1356 assert_eq!(v.clone_as_vec(), slice);
1357 }
1358
1359 pub fn test_mul_scalar<V: Vector>() {
1360 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1361 let result = v * Scale(f::<V>(2.0));
1362 assert_eq!(result.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
1363 }
1364
1365 pub fn test_div_scalar<V: Vector>() {
1366 let v = V::from_vec(fv::<V>(&[2.0, 4.0, 6.0]), Default::default());
1367 let result = v / Scale(f::<V>(2.0));
1368 assert_eq!(result.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1369 }
1370
1371 pub fn test_axpy<V: Vector>() {
1372 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1373 let x = V::from_vec(fv::<V>(&[4.0, 5.0, 6.0]), Default::default());
1374 y.axpy(f::<V>(2.0), &x, f::<V>(1.0));
1375 assert_eq!(y.clone_as_vec(), fv::<V>(&[9.0, 12.0, 15.0]));
1376 y.axpy(f::<V>(2.0), &x, f::<V>(0.0));
1377 assert_eq!(y.clone_as_vec(), fv::<V>(&[8.0, 10.0, 12.0]));
1378 y.axpy(f::<V>(0.0), &x, f::<V>(1.0));
1379 assert_eq!(y.clone_as_vec(), fv::<V>(&[8.0, 10.0, 12.0]));
1380 }
1381
1382 pub fn test_copy_from_indices<V: Vector>() {
1383 let mut v1 = V::zeros(5, Default::default());
1384 let v2 = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0]), Default::default());
1385 let indices = V::Index::from_vec(vec![0, 2, 4], Default::default());
1386 v1.copy_from_indices(&v2, &indices);
1387 assert_eq!(v1.clone_as_vec(), fv::<V>(&[10.0, 0.0, 30.0, 0.0, 50.0]));
1388 }
1389
1390 pub fn test_gather<V: Vector>() {
1391 let mut result = V::zeros(3, Default::default());
1392 let v = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), Default::default());
1393 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
1394 result.gather(&v, &indices);
1395 assert_eq!(result.clone_as_vec(), fv::<V>(&[40.0, 10.0, 30.0]));
1396 }
1397
1398 pub fn test_scatter<V: Vector>() {
1399 let v = V::from_vec(fv::<V>(&[40.0, 10.0, 30.0]), Default::default());
1400 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
1401 let mut result = V::zeros(4, Default::default());
1402 v.scatter(&indices, &mut result);
1403 assert_eq!(result.clone_as_vec(), fv::<V>(&[10.0, 0.0, 30.0, 40.0]));
1404 }
1405
1406 pub fn test_copy_from_via_view_mut<V: Vector>() {
1407 let mut v1 = V::zeros(3, Default::default());
1408 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1409 v1.as_view_mut().copy_from(&v2);
1410 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1411 }
1412
1413 pub fn test_set_index<V: Vector>() {
1414 let mut v = V::zeros(3, Default::default());
1415 v.set_index(1, f::<V>(42.0));
1416 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 42.0, 0.0]));
1417 }
1418
1419 pub fn test_get_index<V: Vector>() {
1420 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1421 assert_eq!(v.get_index(0), f::<V>(1.0));
1422 assert_eq!(v.get_index(2), f::<V>(3.0));
1423 }
1424
1425 pub fn test_norm<V: Vector>() {
1426 let v = V::from_vec(fv::<V>(&[3.0, 4.0]), Default::default());
1427 let norm = v.norm(2);
1428 let diff = norm - f::<V>(5.0);
1429 assert!(num_traits::abs(diff) < f::<V>(1e-12));
1430 }
1431
1432 pub fn test_norm_l1<V: Vector>() {
1433 let v = V::from_vec(fv::<V>(&[3.0, -4.0]), Default::default());
1434 let norm = v.norm(1);
1435 let diff = norm - f::<V>(7.0);
1436 assert!(num_traits::abs(diff) < f::<V>(1e-12));
1437 }
1438
1439 pub fn test_squared_norm<V: Vector>() {
1440 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), Default::default());
1441 let y = V::from_vec(fv::<V>(&[1.0, 1.0]), Default::default());
1442 let atol = V::from_vec(fv::<V>(&[1e-3, 1e-3]), Default::default());
1443 let rtol = f::<V>(1e-2);
1444 let norm = x.squared_norm(&y, &atol, rtol);
1445 let denom = f::<V>(1.0) * rtol + f::<V>(1e-3);
1446 let err0 = f::<V>(1.0) / denom;
1447 let err1 = f::<V>(2.0) / denom;
1448 let expected = (err0 * err0 + err1 * err1) / f::<V>(2.0);
1449 assert!(num_traits::abs(norm - expected) < f::<V>(1e-12));
1450 }
1451
1452 pub fn test_fill<V: Vector>() {
1453 let mut v = V::zeros(3, Default::default());
1454 v.fill(f::<V>(7.0));
1455 assert_eq!(v.clone_as_vec(), fv::<V>(&[7.0, 7.0, 7.0]));
1456 }
1457
1458 pub fn test_from_element<V: Vector>() {
1459 let v = V::from_element(2, f::<V>(5.0), Default::default());
1460 assert_eq!(v.clone_as_vec(), fv::<V>(&[5.0, 5.0]));
1461 }
1462
1463 pub fn test_copy_from<V: Vector>() {
1464 let mut v1 = V::zeros(3, Default::default());
1465 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1466 v1.copy_from(&v2);
1467 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1468 }
1469
1470 pub fn test_from_vec<V: Vector>() {
1471 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1472 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1473 }
1474
1475 pub fn test_component_mul_assign<V: Vector>() {
1476 let mut a = V::from_vec(fv::<V>(&[2.0, 3.0]), Default::default());
1477 let b = V::from_vec(fv::<V>(&[10.0, 20.0]), Default::default());
1478 a.component_mul_assign(&b);
1479 assert_eq!(a.clone_as_vec(), fv::<V>(&[20.0, 60.0]));
1480 }
1481
1482 pub fn test_component_div_assign<V: Vector>() {
1483 let mut a = V::from_vec(fv::<V>(&[6.0, 12.0]), Default::default());
1484 let b = V::from_vec(fv::<V>(&[2.0, 3.0]), Default::default());
1485 a.component_div_assign(&b);
1486 assert_eq!(a.clone_as_vec(), fv::<V>(&[3.0, 4.0]));
1487 }
1488
1489 pub fn test_assign_at_indices<V: Vector>() {
1490 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1491 let indices = V::Index::from_vec(vec![0, 2], Default::default());
1492 v.assign_at_indices(&indices, f::<V>(0.0));
1493 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 2.0, 0.0]));
1494 }
1495
1496 pub fn test_add<V: Vector>() {
1497 let a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1498 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
1499 let c = a + b;
1500 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
1501 }
1502
1503 pub fn test_sub<V: Vector>() {
1504 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
1505 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1506 let c = a - b;
1507 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0]));
1508 }
1509
1510 pub fn test_owned_rhs<V: Vector>()
1513 where
1514 for<'a> &'a V: Add<V, Output = V> + Sub<V, Output = V>,
1515 {
1516 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
1517 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1518 let c = &a - b;
1519 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0]));
1520
1521 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1522 let c = &a + b;
1523 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
1524
1525 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1526 let c = a.as_view() - b;
1527 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0]));
1528
1529 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1530 let c = a.as_view() + b;
1531 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
1532 }
1533
1534 pub fn test_view_add_sub<V: Vector>() {
1537 let a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1538 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
1539 let c = a.as_view() + b.as_view();
1540 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
1541 let d = a.as_view() - b.as_view();
1542 assert_eq!(d.clone_as_vec(), fv::<V>(&[-9.0, -18.0, -27.0]));
1543 }
1544
1545 pub fn test_index_zeros_and_is_empty<V: Vector>() {
1548 let empty = V::Index::zeros(0, Default::default());
1549 assert!(empty.is_empty());
1550 let non_empty = V::Index::zeros(3, Default::default());
1551 assert!(!non_empty.is_empty());
1552 assert_eq!(non_empty.clone_as_vec(), vec![0; 3]);
1553 }
1554
1555 pub fn test_add_assign<V: Vector>() {
1556 let mut a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1557 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
1558 a += b;
1559 assert_eq!(a.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0]));
1560 }
1561
1562 pub fn test_sub_assign<V: Vector>() {
1563 let mut a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0]), Default::default());
1564 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1565 a -= b;
1566 assert_eq!(a.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0]));
1567 }
1568
1569 pub fn test_axpy_v<V: Vector>() {
1570 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1571 let x = V::from_vec(fv::<V>(&[4.0, 5.0, 6.0]), Default::default());
1572 let x_view = x.as_view();
1573 y.axpy_v(f::<V>(2.0), &x_view, f::<V>(1.0));
1574 assert_eq!(y.clone_as_vec(), fv::<V>(&[9.0, 12.0, 15.0]));
1575 }
1576
1577 pub fn test_mul_assign_scalar<V: Vector>() {
1578 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1579 v *= Scale(f::<V>(2.0));
1580 assert_eq!(v.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
1581 }
1582
1583 pub fn test_copy_from_view<V: Vector>() {
1584 let mut v1 = V::zeros(3, Default::default());
1585 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1586 let view = v2.as_view();
1587 v1.copy_from_view(&view);
1588 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1589 }
1590
1591 pub fn test_view_squared_norm<V: Vector>() {
1592 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), Default::default());
1593 let y = V::from_vec(fv::<V>(&[1.0, 1.0]), Default::default());
1594 let atol = V::from_vec(fv::<V>(&[1e-3, 1e-3]), Default::default());
1595 let rtol = f::<V>(1e-2);
1596 let view = x.as_view();
1597 let norm = VectorView::squared_norm(&view, &y, &atol, rtol);
1598 let denom = f::<V>(1.0) * rtol + f::<V>(1e-3);
1599 let err0 = f::<V>(1.0) / denom;
1600 let err1 = f::<V>(2.0) / denom;
1601 let expected = (err0 * err0 + err1 * err1) / f::<V>(2.0);
1602 assert!(num_traits::abs(norm - expected) < f::<V>(1e-12));
1603 }
1604
1605 pub fn test_view_into_owned<V: Vector>() {
1606 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1607 let view = v.as_view();
1608 let owned = view.into_owned();
1609 assert_eq!(owned.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1610 }
1611
1612 pub fn test_view_get_index<V: Vector>() {
1613 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1614 let view = v.as_view();
1615 assert_eq!(view.get_index(1), f::<V>(2.0));
1616 assert_eq!(view.get_index(2), f::<V>(3.0));
1617 }
1618
1619 pub fn test_view_mut_axpy<V: Vector>() {
1620 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1621 let x = V::from_vec(fv::<V>(&[4.0, 5.0, 6.0]), Default::default());
1622 {
1623 let mut y_view = y.as_view_mut();
1624 y_view.axpy(f::<V>(2.0), &x, f::<V>(1.0));
1625 }
1626 assert_eq!(y.clone_as_vec(), fv::<V>(&[9.0, 12.0, 15.0]));
1627 }
1628
1629 pub fn test_view_mut_set_index<V: Vector>() {
1630 let mut v = V::zeros(3, Default::default());
1631 {
1632 let mut view = v.as_view_mut();
1633 view.set_index(1, f::<V>(42.0));
1634 }
1635 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 42.0, 0.0]));
1636 }
1637
1638 pub fn test_view_mut_mul_assign_scalar<V: Vector>() {
1639 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1640 {
1641 let mut view = v.as_view_mut();
1642 view *= Scale(f::<V>(2.0));
1643 }
1644 assert_eq!(v.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
1645 }
1646
1647 pub fn test_view_mut_copy_from_view<V: Vector>() {
1648 let mut v1 = V::zeros(3, Default::default());
1649 let v2 = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), Default::default());
1650 {
1651 let v2_view = v2.as_view();
1652 let mut v1_view = v1.as_view_mut();
1653 v1_view.copy_from_view(&v2_view);
1654 }
1655 assert_eq!(v1.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0]));
1656 }
1657
1658 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1659 pub fn test_batched_len_and_total_len<V: Vector>(ctx: V::C) {
1660 let nbatch = ctx.nbatch();
1661 assert!(nbatch > 1);
1662 let v = V::zeros(4, ctx);
1663 assert_eq!(v.len(), 4);
1664 assert_eq!(v.total_len(), 4 * nbatch);
1665 }
1666
1667 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1668 pub fn test_batched_from_vec<V: Vector>(ctx: V::C) {
1669 assert_eq!(ctx.nbatch(), 2);
1670 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]), ctx);
1671 assert_eq!(v.len(), 3);
1672 assert_eq!(v.total_len(), 6);
1673 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]));
1674 }
1675
1676 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1677 pub fn test_batched_from_vec_bad_length<V: Vector>(ctx: V::C) {
1678 assert_eq!(ctx.nbatch(), 2);
1679 let _v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), ctx);
1680 }
1681
1682 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1683 pub fn test_batched_from_element<V: Vector>(ctx: V::C) {
1684 assert_eq!(ctx.nbatch(), 3);
1685 let v = V::from_element(2, f::<V>(5.0), ctx);
1686 assert_eq!(v.len(), 2);
1687 assert_eq!(v.clone_as_vec(), fv::<V>(&[5.0, 5.0, 5.0, 5.0, 5.0, 5.0]));
1688 }
1689
1690 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1691 pub fn test_batched_axpy<V: Vector>(ctx: V::C) {
1692 assert_eq!(ctx.nbatch(), 2);
1693 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1694 let x = V::from_vec(fv::<V>(&[3.0, 4.0, 30.0, 40.0]), ctx);
1695 y.axpy(f::<V>(2.0), &x, f::<V>(1.0));
1696 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 70.0, 100.0]));
1697 }
1698
1699 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1700 pub fn test_batched_add<V: Vector>(ctx: V::C) {
1701 assert_eq!(ctx.nbatch(), 2);
1702 let a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx.clone());
1703 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
1704 let c = a + b;
1705 assert_eq!(c.len(), 2);
1706 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 33.0, 44.0]));
1707 }
1708
1709 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1710 pub fn test_batched_norm_max_across_batches<V: Vector>(ctx: V::C) {
1711 assert_eq!(ctx.nbatch(), 2);
1712 let v = V::from_vec(fv::<V>(&[1.0, 0.0, 0.0, 3.0]), ctx);
1713 let norm = v.norm(2);
1714 let diff = norm - f::<V>(3.0);
1715 assert!(num_traits::abs(diff) < f::<V>(1e-12));
1716 }
1717
1718 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1719 pub fn test_batched_norm_l1<V: Vector>(ctx: V::C) {
1720 assert_eq!(ctx.nbatch(), 2);
1721 let v = V::from_vec(fv::<V>(&[1.0, -2.0, 3.0, 0.0]), ctx);
1722 let norm = v.norm(1);
1723 let diff = norm - f::<V>(3.0);
1725 assert!(num_traits::abs(diff) < f::<V>(1e-12));
1726 }
1727
1728 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1729 pub fn test_batched_squared_norm<V: Vector>(ctx: V::C) {
1730 assert_eq!(ctx.nbatch(), 2);
1731 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx.clone());
1732 let y = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0, 1.0]), ctx);
1733 let atol = V::from_vec(fv::<V>(&[1e-3, 1e-3]), V::C::default());
1734 let rtol = f::<V>(1e-2);
1735 let norm = x.squared_norm(&y, &atol, rtol);
1736 let denom = f::<V>(1.0) * rtol + f::<V>(1e-3);
1737 let err3 = f::<V>(3.0) / denom;
1738 let err4 = f::<V>(4.0) / denom;
1739 let batch1 = (err3 * err3 + err4 * err4) / f::<V>(2.0);
1740 let diff = norm - batch1;
1741 assert!(num_traits::abs(diff) < f::<V>(1e-12));
1742 }
1743
1744 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1745 pub fn test_batched_fill_index<V: Vector>(ctx: V::C) {
1746 assert_eq!(ctx.nbatch(), 3);
1747 let mut v = V::zeros(2, ctx);
1748 v.fill_index(0, f::<V>(42.0));
1749 assert_eq!(
1750 v.clone_as_vec(),
1751 fv::<V>(&[42.0, 0.0, 42.0, 0.0, 42.0, 0.0])
1752 );
1753 }
1754
1755 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1756 pub fn test_batched_get_index_panics<V: Vector>(ctx: V::C) {
1757 assert!(ctx.nbatch() > 1);
1758 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
1759 let _val = v.get_index(0);
1760 }
1761
1762 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1764 pub fn test_batched_set_index_panics<V: Vector>(ctx: V::C) {
1765 assert!(ctx.nbatch() > 1);
1766 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
1767 v.set_index(0, f::<V>(5.0));
1768 }
1769
1770 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1771 pub fn test_batched_fill<V: Vector>(ctx: V::C) {
1772 assert_eq!(ctx.nbatch(), 2);
1773 let mut v = V::zeros(3, ctx);
1774 v.fill(f::<V>(7.0));
1775 assert_eq!(v.clone_as_vec(), fv::<V>(&[7.0, 7.0, 7.0, 7.0, 7.0, 7.0]));
1776 }
1777
1778 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1779 pub fn test_batched_component_mul<V: Vector>(ctx: V::C) {
1780 assert_eq!(ctx.nbatch(), 2);
1781 let mut a = V::from_vec(fv::<V>(&[2.0, 3.0, 4.0, 5.0]), ctx.clone());
1782 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
1783 a.component_mul_assign(&b);
1784 assert_eq!(a.clone_as_vec(), fv::<V>(&[20.0, 60.0, 120.0, 200.0]));
1785 }
1786
1787 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1788 pub fn test_batched_assign_at_indices<V: Vector>(ctx: V::C) {
1789 assert_eq!(ctx.nbatch(), 2);
1790 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]), ctx);
1791 let indices = V::Index::from_vec(vec![0, 2], Default::default());
1792 v.assign_at_indices(&indices, f::<V>(0.0));
1793 assert_eq!(v.clone_as_vec(), fv::<V>(&[0.0, 2.0, 0.0, 0.0, 5.0, 0.0]));
1794 }
1795
1796 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1797 pub fn test_batched_root_finding_consistent<V: Vector>(ctx: V::C) {
1798 assert_eq!(ctx.nbatch(), 2);
1799 let g0 = V::from_vec(fv::<V>(&[1.0, -1.0, 1.0, -1.0]), ctx.clone());
1800 let g1 = V::from_vec(fv::<V>(&[-1.0, 1.0, -1.0, 1.0]), ctx);
1801 let (found, _frac, idx) = g0.root_finding(&g1);
1802 assert!(!found);
1803 assert!(idx >= 0);
1804 }
1805
1806 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
1807 pub fn test_batched_root_finding_inconsistent<V: Vector>(ctx: V::C) {
1808 assert_eq!(ctx.nbatch(), 2);
1809 let g0 = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0, -1.0]), ctx.clone());
1810 let g1 = V::from_vec(fv::<V>(&[-1.0, 1.0, 1.0, 1.0]), ctx);
1811 let _result = g0.root_finding(&g1);
1812 }
1813
1814 #[cfg_attr(not(any(feature = "cuda", feature = "cuda-oxide")), allow(dead_code))]
1817 pub fn test_for_each_batch<V: Vector>() {
1822 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
1823 let v = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
1824 let mut y = V::zeros(2, V::C::default());
1825 let mut y_host = V::zeros(2, V::C::default());
1826
1827 let set = |y: &mut [V::T], _: [&[V::T]; 0], _lane: usize| y[0] = f::<V>(7.0);
1828 y.for_each_batch([], set);
1829 y_host.for_each_batch_host([], set);
1830 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 0.0]));
1831 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
1832
1833 let take_second = |y: &mut [V::T], [x]: [&[V::T]; 1], _lane: usize| y[1] = x[1];
1834 y.for_each_batch([&x], take_second);
1835 y_host.for_each_batch_host([&x], take_second);
1836 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 2.0]));
1837 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
1838
1839 let combine = |y: &mut [V::T], [x, v]: [&[V::T]; 2], _lane: usize| {
1840 y[0] = x[0] * v[0] + x[1] * v[1];
1841 y[1] = x[0] - v[0];
1842 };
1843 y.for_each_batch([&x, &v], combine);
1844 y_host.for_each_batch_host([&x, &v], combine);
1845 assert_eq!(y.clone_as_vec(), fv::<V>(&[11.0, -2.0]));
1846 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
1847 }
1848
1849 pub fn test_batched_for_each_batch<V: Vector>(ctx: V::C) {
1851 assert_eq!(ctx.nbatch(), 2);
1852 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1854 let v = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
1856 let mut y = V::zeros(2, ctx.clone());
1857 let mut y_host = V::zeros(2, ctx.clone());
1858 let combine = |y: &mut [V::T], [x, v]: [&[V::T]; 2], _lane: usize| {
1859 y[0] = x[0] + v[0];
1860 y[1] = x[1] * v[1];
1861 };
1862 y.for_each_batch([&x, &v], combine);
1863 y_host.for_each_batch_host([&x, &v], combine);
1864 assert_eq!(y.clone_as_vec(), fv::<V>(&[4.0, 8.0, 13.0, 80.0]));
1865 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
1866
1867 let ctx4 = ctx.clone_with_nbatch(4).unwrap();
1869 let mut y4 = V::zeros(1, ctx4.clone());
1870 let mut y4_host = V::zeros(1, ctx4);
1871 let first = |y: &mut [V::T], [x]: [&[V::T]; 1], _lane: usize| y[0] = x[0];
1872 y4.for_each_batch([&x], first);
1873 y4_host.for_each_batch_host([&x], first);
1874 assert_eq!(y4.clone_as_vec(), fv::<V>(&[1.0, 1.0, 10.0, 10.0]));
1875 assert_eq!(y4_host.clone_as_vec(), y4.clone_as_vec());
1876
1877 let mut dot = V::zeros(1, ctx.clone());
1880 let mut dot_host = V::zeros(1, ctx);
1881 let reduce = |y: &mut [V::T], [x, v]: [&[V::T]; 2], _lane: usize| {
1882 y[0] = x
1883 .iter()
1884 .zip(v.iter())
1885 .fold(f::<V>(0.0), |acc, (x, v)| acc + *x * *v);
1886 };
1887 dot.for_each_batch([&x, &v], reduce);
1888 dot_host.for_each_batch_host([&x, &v], reduce);
1889 assert_eq!(dot.clone_as_vec(), fv::<V>(&[11.0, 110.0]));
1890 assert_eq!(dot_host.clone_as_vec(), dot.clone_as_vec());
1891 }
1892
1893 #[cfg_attr(not(any(feature = "cuda", feature = "cuda-oxide")), allow(dead_code))]
1894 pub fn test_reduce_unbatched<V: Vector>() {
1897 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), V::C::default());
1898 let sum = |a: V::T, b: V::T| a + b;
1899
1900 let mut dest = V::zeros(3, V::C::default());
1901 let mut dest_host = V::zeros(3, V::C::default());
1902 let double = |[x]: [&[V::T]; 1], _lane: usize, i: usize| x[i] + x[i];
1903 V::reduce_batch(&mut dest, [&x], f::<V>(0.0), double, sum);
1904 V::reduce_batch_host(&mut dest_host, [&x], f::<V>(0.0), double, sum);
1905 assert_eq!(dest.clone_as_vec(), fv::<V>(&[2.0, 4.0, 6.0]));
1906 assert_eq!(dest_host.clone_as_vec(), dest.clone_as_vec());
1907
1908 let mut total = V::zeros(1, V::C::default());
1909 let mut total_host = V::zeros(1, V::C::default());
1910 let pick = |[x]: [&[V::T]; 1], _lane: usize, i: usize| x[i];
1911 V::reduce_elem(&mut total, [&x], f::<V>(0.0), pick, sum);
1912 V::reduce_elem_host(&mut total_host, [&x], f::<V>(0.0), pick, sum);
1913 assert_eq!(total.clone_as_vec(), fv::<V>(&[6.0]));
1914 assert_eq!(total_host.clone_as_vec(), total.clone_as_vec());
1915 }
1916
1917 pub fn test_batched_reduce_batch<V: Vector>(ctx: V::C) {
1919 assert_eq!(ctx.nbatch(), 2);
1920 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1921 let pick = |[x]: [&[V::T]; 1], _lane: usize, i: usize| x[i];
1922
1923 let mut sum = V::zeros(2, V::C::default());
1924 let mut sum_host = V::zeros(2, V::C::default());
1925 V::reduce_batch(&mut sum, [&x], f::<V>(0.0), pick, |a, b| a + b);
1926 V::reduce_batch_host(&mut sum_host, [&x], f::<V>(0.0), pick, |a, b| a + b);
1927 assert_eq!(sum.clone_as_vec(), fv::<V>(&[11.0, 22.0]));
1928 assert_eq!(sum_host.clone_as_vec(), sum.clone_as_vec());
1929
1930 let mut max = V::zeros(2, V::C::default());
1931 let mut max_host = V::zeros(2, V::C::default());
1932 V::reduce_batch(&mut max, [&x], f::<V>(0.0), pick, |a, b| a.max(b));
1933 V::reduce_batch_host(&mut max_host, [&x], f::<V>(0.0), pick, |a, b| a.max(b));
1934 assert_eq!(max.clone_as_vec(), fv::<V>(&[10.0, 20.0]));
1935 assert_eq!(max_host.clone_as_vec(), max.clone_as_vec());
1936 }
1937
1938 pub fn test_batched_reduce_elem<V: Vector>(ctx: V::C) {
1943 assert_eq!(ctx.nbatch(), 2);
1944 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1945 let v = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
1946
1947 let mut dot = V::zeros(1, ctx.clone());
1948 let mut dot_host = V::zeros(1, ctx.clone());
1949 let prod = |[x, v]: [&[V::T]; 2], _lane: usize, i: usize| x[i] * v[i];
1950 V::reduce_elem(&mut dot, [&x, &v], f::<V>(0.0), prod, |a, b| a + b);
1951 V::reduce_elem_host(&mut dot_host, [&x, &v], f::<V>(0.0), prod, |a, b| a + b);
1952 assert_eq!(dot.clone_as_vec(), fv::<V>(&[11.0, 110.0]));
1953 assert_eq!(dot_host.clone_as_vec(), dot.clone_as_vec());
1954
1955 let mut max = V::zeros(1, ctx.clone());
1956 let mut max_host = V::zeros(1, ctx);
1957 let pick = |[x]: [&[V::T]; 1], _lane: usize, i: usize| x[i];
1958 V::reduce_elem(&mut max, [&x], f::<V>(0.0), pick, |a, b| a.max(b));
1959 V::reduce_elem_host(&mut max_host, [&x], f::<V>(0.0), pick, |a, b| a.max(b));
1960 assert_eq!(max.clone_as_vec(), fv::<V>(&[2.0, 20.0]));
1961 assert_eq!(max_host.clone_as_vec(), max.clone_as_vec());
1962 }
1963
1964 pub fn test_batched_reduce_broadcast<V: Vector>(ctx: V::C) {
1966 assert_eq!(ctx.nbatch(), 2);
1967 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
1968 let v = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
1969 let sum = |a: V::T, b: V::T| a + b;
1970 let add = |[x, v]: [&[V::T]; 2], _lane: usize, i: usize| x[i] + v[i];
1971
1972 let mut dest = V::zeros(2, V::C::default());
1974 let mut dest_host = V::zeros(2, V::C::default());
1975 V::reduce_batch(&mut dest, [&x, &v], f::<V>(0.0), add, sum);
1976 V::reduce_batch_host(&mut dest_host, [&x, &v], f::<V>(0.0), add, sum);
1977 assert_eq!(dest.clone_as_vec(), fv::<V>(&[17.0, 30.0]));
1978 assert_eq!(dest_host.clone_as_vec(), dest.clone_as_vec());
1979
1980 let mut lane = V::zeros(1, ctx.clone());
1982 let mut lane_host = V::zeros(1, ctx);
1983 V::reduce_elem(&mut lane, [&x, &v], f::<V>(0.0), add, sum);
1984 V::reduce_elem_host(&mut lane_host, [&x, &v], f::<V>(0.0), add, sum);
1985 assert_eq!(lane.clone_as_vec(), fv::<V>(&[10.0, 37.0]));
1986 assert_eq!(lane_host.clone_as_vec(), lane.clone_as_vec());
1987 }
1988
1989 pub fn test_batched_reduce_long_lane<V: Vector>(ctx: V::C) {
1991 let nbatch = ctx.nbatch();
1992 assert_eq!(nbatch, 3);
1993 let nstates = 13_000;
1997 let data: Vec<f64> = (0..nstates * nbatch).map(|i| (i % 97) as f64).collect();
1998 let x = V::from_vec(fv::<V>(&data), ctx.clone());
1999 let pick = |[x]: [&[V::T]; 1], _lane: usize, i: usize| x[i];
2000 let sum = |a: V::T, b: V::T| a + b;
2001
2002 let mut per_elem = V::zeros(nstates, V::C::default());
2003 let mut per_elem_host = V::zeros(nstates, V::C::default());
2004 V::reduce_batch(&mut per_elem, [&x], f::<V>(0.0), pick, sum);
2005 V::reduce_batch_host(&mut per_elem_host, [&x], f::<V>(0.0), pick, sum);
2006 assert_eq!(per_elem.clone_as_vec(), per_elem_host.clone_as_vec());
2007
2008 let mut per_lane = V::zeros(1, ctx.clone());
2009 let mut per_lane_host = V::zeros(1, ctx.clone());
2010 V::reduce_elem(&mut per_lane, [&x], f::<V>(0.0), pick, |a, b| a.max(b));
2012 V::reduce_elem_host(&mut per_lane_host, [&x], f::<V>(0.0), pick, |a, b| a.max(b));
2013 assert_eq!(per_lane.clone_as_vec(), per_lane_host.clone_as_vec());
2014
2015 let mut sums = V::zeros(1, ctx.clone());
2018 let mut sums_host = V::zeros(1, ctx);
2019 V::reduce_elem(&mut sums, [&x], f::<V>(0.0), pick, sum);
2020 V::reduce_elem_host(&mut sums_host, [&x], f::<V>(0.0), pick, sum);
2021 sums.assert_eq_st(&sums_host, f::<V>(1e-9));
2022 }
2023
2024 pub fn test_batched_reduce_host_stateful<V: Vector>(ctx: V::C) {
2029 assert_eq!(ctx.nbatch(), 2);
2030 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2031
2032 let mut calls = 0usize;
2033 let mut dest = V::zeros(1, ctx);
2034 V::reduce_elem_host(
2035 &mut dest,
2036 [&x],
2037 f::<V>(0.0),
2038 |[x], _lane, i| {
2039 calls += 1;
2040 x[i]
2041 },
2042 |a, b| a + b,
2043 );
2044 assert_eq!(dest.clone_as_vec(), fv::<V>(&[3.0, 30.0]));
2045 assert_eq!(calls, 4);
2047 }
2048
2049 pub fn test_batched_reduce_batch_bad_dest<V: Vector>(ctx: V::C) {
2051 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2052 let mut dest = V::zeros(2, ctx);
2053 V::reduce_batch(
2054 &mut dest,
2055 [&x],
2056 f::<V>(0.0),
2057 |[x], _lane, i| x[i],
2058 |a, b| a + b,
2059 );
2060 }
2061
2062 pub fn test_batched_reduce_elem_bad_dest<V: Vector>(ctx: V::C) {
2064 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2065 let mut dest = V::zeros(2, ctx);
2066 V::reduce_elem(
2067 &mut dest,
2068 [&x],
2069 f::<V>(0.0),
2070 |[x], _lane, i| x[i],
2071 |a, b| a + b,
2072 );
2073 }
2074
2075 #[cfg_attr(not(any(feature = "cuda", feature = "cuda-oxide")), allow(dead_code))]
2076 pub fn test_for_each_batch_mut<V: Vector>() {
2078 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2079 let mut y = V::zeros(2, V::C::default());
2080 let mut scratch = V::zeros(2, V::C::default());
2081 let mut y_host = V::zeros(2, V::C::default());
2082 let mut scratch_host = V::zeros(2, V::C::default());
2083
2084 let via_scratch = |[y, scratch]: [&mut [V::T]; 2], [x]: [&[V::T]; 1], _lane: usize| {
2085 scratch.copy_from_slice(x);
2086 scratch[0] += f::<V>(1.0);
2087 y[0] = scratch[0] * scratch[1];
2088 y[1] = scratch[1];
2089 };
2090 V::for_each_batch_mut([&mut y, &mut scratch], [&x], via_scratch);
2091 V::for_each_batch_mut_host([&mut y_host, &mut scratch_host], [&x], via_scratch);
2092 assert_eq!(y.clone_as_vec(), fv::<V>(&[4.0, 2.0]));
2093 assert_eq!(scratch.clone_as_vec(), fv::<V>(&[2.0, 2.0]));
2094 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
2095 assert_eq!(scratch_host.clone_as_vec(), scratch.clone_as_vec());
2096 }
2097
2098 #[cfg_attr(not(any(feature = "cuda", feature = "cuda-oxide")), allow(dead_code))]
2099 pub fn test_for_each_elem_mut<V: Vector>() {
2102 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0]), V::C::default());
2103 let mut y = V::zeros(3, V::C::default());
2104 let mut z = V::zeros(3, V::C::default());
2105 let mut y_host = V::zeros(3, V::C::default());
2106 let mut z_host = V::zeros(3, V::C::default());
2107
2108 let wrap = |[y, z]: [&mut V::T; 2], [x]: [&[V::T]; 1], _lane: usize, i: usize| {
2109 *y = x[i] + x[(i + 1) % x.len()];
2110 *z = *y * f::<V>(2.0);
2111 };
2112 V::for_each_elem_mut([&mut y, &mut z], [&x], wrap);
2113 V::for_each_batch_mut_host([&mut y_host, &mut z_host], [&x], |[y, z], [x], lane| {
2114 for i in 0..x.len() {
2115 wrap([&mut y[i], &mut z[i]], [x], lane, i);
2116 }
2117 });
2118 assert_eq!(y.clone_as_vec(), fv::<V>(&[3.0, 5.0, 4.0]));
2119 assert_eq!(z.clone_as_vec(), fv::<V>(&[6.0, 10.0, 8.0]));
2120 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
2121 assert_eq!(z_host.clone_as_vec(), z.clone_as_vec());
2122 }
2123
2124 pub fn test_batched_for_each_elem_mut<V: Vector>(ctx: V::C) {
2127 assert_eq!(ctx.nbatch(), 2);
2128 let x = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2129 let mut y = V::zeros(2, ctx.clone());
2130 let mut z = V::zeros(2, ctx);
2131
2132 V::for_each_elem_mut([&mut y, &mut z], [&x], |[y, z], [x], lane, i| {
2133 *y = x[i] + f::<V>(lane as f64 * 10.0);
2134 *z = x[(i + 1) % x.len()];
2135 });
2136 assert_eq!(y.clone_as_vec(), fv::<V>(&[1.0, 2.0, 11.0, 12.0]));
2137 assert_eq!(z.clone_as_vec(), fv::<V>(&[2.0, 1.0, 2.0, 1.0]));
2138 }
2139
2140 pub fn test_batched_for_each_batch_mut<V: Vector>(ctx: V::C) {
2146 assert_eq!(ctx.nbatch(), 2);
2147 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2148 let mut y = V::zeros(2, ctx);
2149 let mut scratch = V::zeros(2, V::C::default());
2150
2151 V::for_each_batch_mut_host([&mut y, &mut scratch], [&x], |[y, scratch], [x], lane| {
2152 scratch.copy_from_slice(x);
2153 scratch[1] += f::<V>(lane as f64);
2154 y[0] = scratch[0];
2155 y[1] = scratch[1];
2156 });
2157 assert_eq!(y.clone_as_vec(), fv::<V>(&[1.0, 2.0, 10.0, 21.0]));
2158 assert_eq!(scratch.clone_as_vec(), fv::<V>(&[10.0, 21.0]));
2160 }
2161
2162 pub fn test_for_each_batch_index<V: Vector>() {
2164 let mut y = V::zeros(1, V::C::default());
2165 let mut y_host = V::zeros(1, V::C::default());
2166 let write_lane = |y: &mut [V::T], _: [&[V::T]; 0], lane: usize| y[0] = f::<V>(lane as f64);
2167 y.for_each_batch([], write_lane);
2168 y_host.for_each_batch_host([], write_lane);
2169 assert_eq!(y.clone_as_vec(), fv::<V>(&[0.0]));
2170 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
2171 }
2172
2173 pub fn test_batched_for_each_batch_index<V: Vector>(ctx: V::C) {
2175 let nbatch = ctx.nbatch();
2176 assert!(nbatch > 1);
2177 let mut y = V::zeros(2, ctx.clone());
2178 let mut y_host = V::zeros(2, ctx);
2179 let write_lane = |y: &mut [V::T], _: [&[V::T]; 0], lane: usize| {
2180 y[0] = f::<V>(lane as f64);
2181 y[1] += f::<V>(1.0);
2182 };
2183 y.for_each_batch([], write_lane);
2184 y_host.for_each_batch_host([], write_lane);
2185 let expected: Vec<f64> = (0..nbatch).flat_map(|b| [b as f64, 1.0]).collect();
2186 assert_eq!(y.clone_as_vec(), fv::<V>(&expected));
2187 assert_eq!(y_host.clone_as_vec(), y.clone_as_vec());
2188 }
2189
2190 pub fn test_batched_for_each_batch_bad_nbatch<V: Vector>(ctx: V::C) {
2191 assert_eq!(ctx.nbatch(), 2);
2192 let ctx3 = ctx.clone_with_nbatch(3).unwrap();
2193 let x = V::zeros(1, ctx3);
2194 let mut y = V::zeros(1, ctx);
2195 y.for_each_batch([&x], |y: &mut [V::T], [x]: [&[V::T]; 1], _lane: usize| {
2196 y[0] = x[0]
2197 });
2198 }
2199
2200 pub fn test_batched_axpy_broadcast<V: Vector>(ctx: V::C) {
2201 assert_eq!(ctx.nbatch(), 2);
2202 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
2204 let x = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
2205 y.axpy(f::<V>(2.0), &x, f::<V>(1.0));
2206 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 16.0, 28.0]));
2208 }
2209
2210 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2211 pub fn test_batched_copy_from_broadcast<V: Vector>(ctx: V::C) {
2212 assert_eq!(ctx.nbatch(), 2);
2213 let mut y = V::zeros(2, ctx);
2214 let x = V::from_vec(fv::<V>(&[5.0, 7.0]), V::C::default());
2215 y.copy_from(&x);
2216 assert_eq!(y.clone_as_vec(), fv::<V>(&[5.0, 7.0, 5.0, 7.0]));
2218 }
2219
2220 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2221 pub fn test_batched_component_div<V: Vector>(ctx: V::C) {
2222 assert_eq!(ctx.nbatch(), 2);
2223 let mut a = V::from_vec(fv::<V>(&[6.0, 8.0, 12.0, 20.0]), ctx.clone());
2224 let b = V::from_vec(fv::<V>(&[2.0, 4.0, 3.0, 5.0]), ctx);
2225 a.component_div_assign(&b);
2226 assert_eq!(a.clone_as_vec(), fv::<V>(&[3.0, 2.0, 4.0, 4.0]));
2227 }
2228
2229 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2230 pub fn test_batched_component_mul_broadcast<V: Vector>(ctx: V::C) {
2231 assert_eq!(ctx.nbatch(), 2);
2232 let mut a = V::from_vec(fv::<V>(&[2.0, 3.0, 4.0, 5.0]), ctx);
2233 let b = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
2234 a.component_mul_assign(&b);
2235 assert_eq!(a.clone_as_vec(), fv::<V>(&[20.0, 60.0, 40.0, 100.0]));
2237 }
2238
2239 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2240 pub fn test_batched_component_div_broadcast<V: Vector>(ctx: V::C) {
2241 assert_eq!(ctx.nbatch(), 2);
2242 let mut a = V::from_vec(fv::<V>(&[6.0, 8.0, 12.0, 20.0]), ctx);
2243 let b = V::from_vec(fv::<V>(&[2.0, 4.0]), V::C::default());
2244 a.component_div_assign(&b);
2245 assert_eq!(a.clone_as_vec(), fv::<V>(&[3.0, 2.0, 6.0, 5.0]));
2247 }
2248
2249 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2250 pub fn test_batched_add_assign_broadcast<V: Vector>(ctx: V::C) {
2251 assert_eq!(ctx.nbatch(), 2);
2252 let mut a = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
2253 let b = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
2254 a += &b;
2255 assert_eq!(a.clone_as_vec(), fv::<V>(&[11.0, 22.0, 13.0, 24.0]));
2256 }
2257
2258 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2259 pub fn test_batched_sub_assign_broadcast<V: Vector>(ctx: V::C) {
2260 assert_eq!(ctx.nbatch(), 2);
2261 let mut a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
2262 let b = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2263 a -= &b;
2264 assert_eq!(a.clone_as_vec(), fv::<V>(&[9.0, 18.0, 29.0, 38.0]));
2265 }
2266
2267 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2270 pub fn test_batched_owned_rhs_broadcast<V: Vector>(ctx: V::C)
2271 where
2272 for<'a> &'a V: Sub<V, Output = V>,
2273 {
2274 assert_eq!(ctx.nbatch(), 2);
2275 let a = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
2277 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
2278 let c = &a - b;
2279 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 7.0, 16.0]));
2280 assert_eq!(c.context().nbatch(), 2);
2281 }
2282
2283 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2285 pub fn test_batched_owned_rhs_narrow<V: Vector>(ctx: V::C)
2286 where
2287 for<'a> &'a V: Sub<V, Output = V>,
2288 {
2289 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
2290 let b = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2291 let _ = &a - b;
2292 }
2293
2294 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2296 pub fn test_batched_owned_lhs_broadcast<V: Vector>(ctx: V::C) {
2297 assert_eq!(ctx.nbatch(), 2);
2298 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
2299 let b = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2300 let c = a - b;
2301 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 29.0, 38.0]));
2302 assert_eq!(c.context().nbatch(), 2);
2303 }
2304
2305 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2307 pub fn test_batched_owned_lhs_narrow<V: Vector>(ctx: V::C) {
2308 let a = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
2309 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
2310 let _ = a - b;
2311 }
2312
2313 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2317 pub fn test_batched_view_add_broadcast<V: Vector>(ctx: V::C) {
2318 assert_eq!(ctx.nbatch(), 2);
2319 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx);
2320 let b = V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2321 let c = a.as_view() + b.as_view();
2322 assert_eq!(c.clone_as_vec(), fv::<V>(&[11.0, 22.0, 31.0, 42.0]));
2323 assert_eq!(c.context().nbatch(), 2);
2324 }
2325
2326 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2329 pub fn test_batched_view_add_narrow<V: Vector>(ctx: V::C) {
2330 let a = V::from_vec(fv::<V>(&[10.0, 20.0]), V::C::default());
2331 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
2332 let _ = a.as_view() + b.as_view();
2333 }
2334
2335 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2336 pub fn test_batched_sub<V: Vector>(ctx: V::C) {
2337 assert_eq!(ctx.nbatch(), 2);
2338 let a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx.clone());
2339 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
2340 let c = a - b;
2341 assert_eq!(c.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0, 36.0]));
2342 }
2343
2344 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2345 pub fn test_batched_sub_assign<V: Vector>(ctx: V::C) {
2346 assert_eq!(ctx.nbatch(), 2);
2347 let mut a = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx.clone());
2348 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx);
2349 a -= b;
2350 assert_eq!(a.clone_as_vec(), fv::<V>(&[9.0, 18.0, 27.0, 36.0]));
2351 }
2352
2353 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2354 pub fn test_batched_from_slice<V: Vector>(ctx: V::C) {
2355 assert_eq!(ctx.nbatch(), 2);
2356 let slice = fv::<V>(&[1.0, 2.0, 3.0, 1.0, 2.0, 3.0]);
2357 let v = V::from_slice(&slice, ctx);
2358 assert_eq!(v.clone_as_vec(), fv::<V>(&[1.0, 2.0, 3.0, 1.0, 2.0, 3.0]));
2359 }
2360
2361 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2362 pub fn test_batched_mul_scalar<V: Vector>(ctx: V::C) {
2363 assert_eq!(ctx.nbatch(), 2);
2364 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
2365 let result = v * Scale(f::<V>(2.0));
2366 assert_eq!(result.clone_as_vec(), fv::<V>(&[2.0, 4.0, 20.0, 40.0]));
2367 }
2368
2369 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2370 pub fn test_batched_div_scalar<V: Vector>(ctx: V::C) {
2371 assert_eq!(ctx.nbatch(), 2);
2372 let v = V::from_vec(fv::<V>(&[2.0, 4.0, 20.0, 40.0]), ctx);
2373 let result = v / Scale(f::<V>(2.0));
2374 assert_eq!(result.clone_as_vec(), fv::<V>(&[1.0, 2.0, 10.0, 20.0]));
2375 }
2376
2377 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2378 pub fn test_batched_copy_from_indices<V: Vector>(ctx: V::C) {
2379 assert_eq!(ctx.nbatch(), 2);
2380 let mut v1 = V::zeros(4, ctx.clone());
2381 let v2 = V::from_vec(
2382 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2383 ctx,
2384 );
2385 let indices = V::Index::from_vec(vec![0, 2, 3], Default::default());
2386 v1.copy_from_indices(&v2, &indices);
2387 assert_eq!(
2388 v1.clone_as_vec(),
2389 fv::<V>(&[10.0, 0.0, 30.0, 40.0, 50.0, 0.0, 70.0, 80.0])
2390 );
2391 }
2392
2393 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2394 pub fn test_batched_gather<V: Vector>(ctx: V::C) {
2395 assert_eq!(ctx.nbatch(), 2);
2396 let mut result = V::zeros(3, ctx.clone());
2397 let v = V::from_vec(
2398 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2399 ctx,
2400 );
2401 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
2402 result.gather(&v, &indices);
2403 assert_eq!(
2404 result.clone_as_vec(),
2405 fv::<V>(&[40.0, 10.0, 30.0, 80.0, 50.0, 70.0])
2406 );
2407 }
2408
2409 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2410 pub fn test_batched_scatter<V: Vector>(ctx: V::C) {
2411 assert_eq!(ctx.nbatch(), 2);
2412 let v = V::from_vec(fv::<V>(&[40.0, 10.0, 30.0, 80.0, 50.0, 70.0]), ctx.clone());
2413 let indices = V::Index::from_vec(vec![3, 0, 2], Default::default());
2414 let mut result = V::zeros(4, ctx);
2415 v.scatter(&indices, &mut result);
2416 assert_eq!(
2417 result.clone_as_vec(),
2418 fv::<V>(&[10.0, 0.0, 30.0, 40.0, 50.0, 0.0, 70.0, 80.0])
2419 );
2420 }
2421
2422 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2423 pub fn test_batched_get_batch<V: Vector>(ctx: V::C) {
2424 assert_eq!(ctx.nbatch(), 2);
2425 let v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 10.0, 20.0, 30.0]), ctx);
2426 let batch0 = v.get_batch(0);
2427 assert_eq!(batch0.get_index(0), f::<V>(1.0));
2428 assert_eq!(batch0.get_index(1), f::<V>(2.0));
2429 assert_eq!(batch0.get_index(2), f::<V>(3.0));
2430 let batch1 = v.get_batch(1);
2431 assert_eq!(batch1.get_index(0), f::<V>(10.0));
2432 assert_eq!(batch1.get_index(1), f::<V>(20.0));
2433 assert_eq!(batch1.get_index(2), f::<V>(30.0));
2434 }
2435
2436 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2437 pub fn test_batched_get_batch_mut<V: Vector>(ctx: V::C) {
2438 assert_eq!(ctx.nbatch(), 2);
2439 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 10.0, 20.0, 30.0]), ctx);
2440 {
2441 let mut batch0 = v.get_batch_mut(0);
2442 batch0.set_index(1, f::<V>(99.0));
2443 }
2444 assert_eq!(
2445 v.clone_as_vec(),
2446 fv::<V>(&[1.0, 99.0, 3.0, 10.0, 20.0, 30.0])
2447 );
2448 }
2449
2450 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2451 pub fn test_batched_axpy_v<V: Vector>(ctx: V::C) {
2452 assert_eq!(ctx.nbatch(), 2);
2453 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2454 let x = V::from_vec(fv::<V>(&[3.0, 4.0, 30.0, 40.0]), ctx);
2455 let x_view = x.as_view();
2456 y.axpy_v(f::<V>(2.0), &x_view, f::<V>(1.0));
2457 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 70.0, 100.0]));
2458 }
2459
2460 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2461 pub fn test_batched_mul_assign_scalar<V: Vector>(ctx: V::C) {
2462 assert_eq!(ctx.nbatch(), 2);
2463 let mut v = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx);
2464 v *= Scale(f::<V>(2.0));
2465 assert_eq!(v.clone_as_vec(), fv::<V>(&[2.0, 4.0, 20.0, 40.0]));
2466 }
2467
2468 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2469 pub fn test_batched_copy_from_view<V: Vector>(ctx: V::C) {
2470 assert_eq!(ctx.nbatch(), 2);
2471 let mut v1 = V::zeros(2, ctx);
2472 let v2 = V::from_vec(fv::<V>(&[5.0, 7.0]), V::C::default());
2473 let view = v2.as_view();
2474 v1.copy_from_view(&view);
2475 assert_eq!(v1.clone_as_vec(), fv::<V>(&[5.0, 7.0, 5.0, 7.0]));
2476 }
2477
2478 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2481 pub fn test_batched_axpy_new<V: Vector>(ctx: V::C) {
2482 assert_eq!(ctx.nbatch(), 2);
2483 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2484 let x = V::from_vec(fv::<V>(&[3.0, 4.0, 30.0, 40.0]), ctx.clone());
2485 let alpha = V::from_vec(fv::<V>(&[2.0, 0.5]), ctx);
2487 y.batched_axpy(&alpha, &x, f::<V>(1.0));
2488 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 25.0, 40.0]));
2491 }
2492
2493 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2494 pub fn test_batched_axpy_new_broadcast<V: Vector>(ctx: V::C) {
2495 assert_eq!(ctx.nbatch(), 2);
2496 let mut y = V::from_vec(fv::<V>(&[1.0, 2.0, 10.0, 20.0]), ctx.clone());
2497 let x = V::from_vec(fv::<V>(&[3.0, 4.0]), V::C::default());
2498 let alpha = V::from_vec(fv::<V>(&[2.0, 0.5]), ctx);
2499 y.batched_axpy(&alpha, &x, f::<V>(1.0));
2500 assert_eq!(y.clone_as_vec(), fv::<V>(&[7.0, 10.0, 11.5, 22.0]));
2504 }
2505
2506 #[allow(clippy::type_complexity)]
2507 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2508 pub fn test_batched_axpy_new_bad_length<V: Vector>(ctx: V::C) {
2509 assert_eq!(ctx.nbatch(), 2);
2510 let mut y = V::zeros(2, ctx.clone());
2511 let x = V::zeros(2, V::C::default());
2512 let alpha = V::zeros(2, ctx);
2514 y.batched_axpy(&alpha, &x, f::<V>(0.0));
2515 }
2516
2517 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2520 pub fn test_batched_axpy_new_bad_nbatch<V: Vector>(ctx: V::C) {
2521 assert_eq!(ctx.nbatch(), 2);
2522 let mut y = V::zeros(2, ctx);
2523 let x = V::zeros(2, V::C::default());
2524 let alpha = V::from_vec(fv::<V>(&[2.0]), V::C::default());
2525 y.batched_axpy(&alpha, &x, f::<V>(0.0));
2526 }
2527
2528 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2534 pub fn test_batched_binary_forms_broadcast<V: Vector>(ctx: V::C)
2535 where
2536 for<'a> &'a V: Add<V, Output = V> + Sub<V, Output = V>,
2537 for<'a, 'b> &'a V: Add<&'b V, Output = V> + Sub<&'b V, Output = V>,
2538 for<'a, 'b> &'a V: Add<V::View<'b>, Output = V> + Sub<V::View<'b>, Output = V>,
2539 for<'a, 'b, 'c> &'a V: Add<&'b V::View<'c>, Output = V> + Sub<&'b V::View<'c>, Output = V>,
2540 for<'a> V::View<'a>: Add<V, Output = V> + Sub<V, Output = V>,
2541 for<'a, 'b> V::View<'a>: Add<&'b V, Output = V> + Sub<&'b V, Output = V>,
2542 for<'a, 'b> V::View<'a>: Add<V::View<'b>, Output = V> + Sub<V::View<'b>, Output = V>,
2543 for<'a, 'b, 'c> V::View<'a>:
2544 Add<&'b V::View<'c>, Output = V> + Sub<&'b V::View<'c>, Output = V>,
2545 {
2546 assert_eq!(ctx.nbatch(), 2);
2547 let wide = || V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx.clone());
2548 let narrow = || V::from_vec(fv::<V>(&[1.0, 2.0]), V::C::default());
2549 let (n, w) = (narrow(), wide());
2550 let ws = fv::<V>(&[9.0, 18.0, 29.0, 38.0]);
2552 let ns = fv::<V>(&[-9.0, -18.0, -29.0, -38.0]);
2553 let sum = fv::<V>(&[11.0, 22.0, 31.0, 42.0]);
2554
2555 assert_eq!((wide() - narrow()).clone_as_vec(), ws);
2557 assert_eq!((wide() - &narrow()).clone_as_vec(), ws);
2558 assert_eq!((wide() - n.as_view()).clone_as_vec(), ws);
2559 assert_eq!((wide() - &n.as_view()).clone_as_vec(), ws);
2560 assert_eq!((wide() + narrow()).clone_as_vec(), sum);
2561 assert_eq!((wide() + &narrow()).clone_as_vec(), sum);
2562 assert_eq!((wide() + n.as_view()).clone_as_vec(), sum);
2563 assert_eq!((wide() + &n.as_view()).clone_as_vec(), sum);
2564
2565 assert_eq!((&n - wide()).clone_as_vec(), ns);
2567 assert_eq!((n.as_view() - wide()).clone_as_vec(), ns);
2568 assert_eq!((&n + wide()).clone_as_vec(), sum);
2569 assert_eq!((n.as_view() + wide()).clone_as_vec(), sum);
2570
2571 assert_eq!((&w - &n).clone_as_vec(), ws);
2573 assert_eq!((&w - n.as_view()).clone_as_vec(), ws);
2574 assert_eq!((&w - &n.as_view()).clone_as_vec(), ws);
2575 assert_eq!((w.as_view() - &n).clone_as_vec(), ws);
2576 assert_eq!((w.as_view() - n.as_view()).clone_as_vec(), ws);
2577 assert_eq!((w.as_view() - &n.as_view()).clone_as_vec(), ws);
2578 assert_eq!((&w + &n).clone_as_vec(), sum);
2579 assert_eq!((&w + n.as_view()).clone_as_vec(), sum);
2580 assert_eq!((&w + &n.as_view()).clone_as_vec(), sum);
2581 assert_eq!((w.as_view() + &n).clone_as_vec(), sum);
2582 assert_eq!((w.as_view() + n.as_view()).clone_as_vec(), sum);
2583 assert_eq!((w.as_view() + &n.as_view()).clone_as_vec(), sum);
2584 }
2585
2586 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2589 pub fn test_batched_empty<V: Vector>(ctx: V::C)
2590 where
2591 for<'a, 'b> &'a V: Add<&'b V, Output = V>,
2592 {
2593 assert_eq!(ctx.nbatch(), 2);
2594 let empty = || V::from_vec(vec![], ctx.clone());
2595 let mut a = empty();
2596 let b = empty();
2597 assert_eq!(a.len(), 0);
2598 assert_eq!(a.total_len(), 0);
2599 a += &b;
2600 a -= &b;
2601 a.axpy(f::<V>(2.0), &b, f::<V>(1.0));
2602 a.axpy_v(f::<V>(2.0), &b.as_view(), f::<V>(1.0));
2603 a.component_mul_assign(&b);
2604 a.component_div_assign(&b);
2605 a.batched_axpy(
2606 &V::from_vec(fv::<V>(&[1.0, 1.0]), ctx.clone()),
2607 &b,
2608 f::<V>(1.0),
2609 );
2610 a.copy_from(&b);
2611 a.copy_from_view(&b.as_view());
2612 a.fill(f::<V>(1.0));
2613 a *= Scale(f::<V>(2.0));
2614 let c = empty() * Scale(f::<V>(2.0));
2615 let e = empty() + b.as_view();
2616 let g = &empty() + &b;
2617 assert!(g.clone_as_vec().is_empty());
2618 let idx = V::Index::from_vec(vec![], Default::default());
2619 a.gather(&b, &idx);
2620 a.scatter(&idx, &mut V::from_vec(vec![], ctx.clone()));
2621 a.assign_at_indices(&idx, f::<V>(1.0));
2622 a.copy_from_indices(&b, &idx);
2623 a.as_view_mut().copy_from_view(&b.as_view());
2624 a.as_view_mut().axpy(f::<V>(1.0), &b, f::<V>(1.0));
2625 assert!(a.clone_as_vec().is_empty());
2626 assert!(c.clone_as_vec().is_empty());
2627 assert!(e.clone_as_vec().is_empty());
2628 assert_eq!(a.norm(2), f::<V>(0.0));
2629 assert_eq!(a.squared_norm(&b, &empty(), f::<V>(1.0)), f::<V>(0.0));
2630 assert_eq!(a.root_finding(&b), (false, f::<V>(0.0), -1));
2631 }
2632
2633 fn ctx4<V: Vector>(ctx2: &V::C) -> V::C {
2640 assert_eq!(ctx2.nbatch(), 2);
2641 ctx2.clone_with_nbatch(4).unwrap()
2642 }
2643
2644 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2645 pub fn test_grouped_axpy<V: Vector>(ctx2: V::C) {
2646 let wide = ctx4::<V>(&ctx2);
2647 let mut y = V::from_vec(
2648 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2649 wide,
2650 );
2651 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2652 y.axpy(f::<V>(1.0), &x, f::<V>(1.0));
2653 assert_eq!(
2654 y.clone_as_vec(),
2655 fv::<V>(&[11.0, 22.0, 31.0, 42.0, 53.0, 64.0, 73.0, 84.0])
2656 );
2657 }
2658
2659 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2660 pub fn test_grouped_add_assign<V: Vector>(ctx2: V::C) {
2661 let wide = ctx4::<V>(&ctx2);
2662 let mut a = V::from_vec(
2663 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2664 wide,
2665 );
2666 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2667 a += &b;
2668 assert_eq!(
2669 a.clone_as_vec(),
2670 fv::<V>(&[11.0, 22.0, 31.0, 42.0, 53.0, 64.0, 73.0, 84.0])
2671 );
2672 }
2673
2674 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2676 pub fn test_grouped_add<V: Vector>(ctx2: V::C)
2677 where
2678 for<'b> &'b V: Add<&'b V, Output = V>,
2679 {
2680 let wide = ctx4::<V>(&ctx2);
2681 let a = V::from_vec(
2682 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2683 wide,
2684 );
2685 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2686 let expected = fv::<V>(&[11.0, 22.0, 31.0, 42.0, 53.0, 64.0, 73.0, 84.0]);
2688 assert_eq!((&a + &b).clone_as_vec(), expected);
2689 }
2690
2691 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2694 pub fn test_grouped_add_narrow_lhs<V: Vector>(ctx2: V::C)
2695 where
2696 for<'b> &'b V: Add<&'b V, Output = V>,
2697 {
2698 let wide = ctx4::<V>(&ctx2);
2699 let a = V::from_vec(
2700 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2701 wide,
2702 );
2703 let b = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2704 let _ = &b + &a;
2705 }
2706
2707 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2708 pub fn test_grouped_copy_from<V: Vector>(ctx2: V::C) {
2709 let wide = ctx4::<V>(&ctx2);
2710 let mut y = V::zeros(2, wide);
2711 let x = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2712 y.copy_from(&x);
2713 assert_eq!(
2714 y.clone_as_vec(),
2715 fv::<V>(&[1.0, 2.0, 1.0, 2.0, 3.0, 4.0, 3.0, 4.0])
2716 );
2717 }
2718
2719 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2720 pub fn test_grouped_component_mul<V: Vector>(ctx2: V::C) {
2721 let wide = ctx4::<V>(&ctx2);
2722 let mut a = V::from_vec(fv::<V>(&[1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 4.0, 4.0]), wide);
2723 let b = V::from_vec(fv::<V>(&[10.0, 20.0, 30.0, 40.0]), ctx2);
2724 a.component_mul_assign(&b);
2725 assert_eq!(
2726 a.clone_as_vec(),
2727 fv::<V>(&[10.0, 20.0, 20.0, 40.0, 90.0, 120.0, 120.0, 160.0])
2728 );
2729 }
2730
2731 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2733 pub fn test_grouped_squared_norm<V: Vector>(ctx2: V::C) {
2734 let wide = ctx4::<V>(&ctx2);
2735 let v = V::from_vec(
2736 fv::<V>(&[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]),
2737 wide.clone(),
2738 );
2739 let y = V::zeros(2, ctx2.clone());
2741 let atol = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0 / 3.0, 1.0 / 3.0]), ctx2.clone());
2742 let norm = v.squared_norm(&y, &atol, f::<V>(1.0));
2743 assert_eq!(norm, f::<V>(9.0));
2744 let narrow = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0, 1.0]), ctx2);
2746 assert_eq!(narrow.squared_norm(&y, &atol, f::<V>(1.0)), f::<V>(9.0));
2747 }
2748
2749 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2750 pub fn test_grouped_gather<V: Vector>(ctx2: V::C) {
2751 let wide = ctx4::<V>(&ctx2);
2752 let idx = V::Index::from_vec(vec![1, 0], Default::default());
2753 let o = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2754 let mut a = V::zeros(2, wide);
2755 a.gather(&o, &idx);
2756 assert_eq!(
2757 a.clone_as_vec(),
2758 fv::<V>(&[2.0, 1.0, 2.0, 1.0, 4.0, 3.0, 4.0, 3.0])
2759 );
2760 }
2761
2762 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2764 pub fn test_grouped_owned_lhs_ref_rhs<V: Vector>(ctx2: V::C) {
2765 let ctx = ctx4::<V>(&ctx2);
2766 let wide = || {
2767 V::from_vec(
2768 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2769 ctx.clone(),
2770 )
2771 };
2772 let narrow = || V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2.clone());
2773 let wide_lhs = fv::<V>(&[9.0, 18.0, 29.0, 38.0, 47.0, 56.0, 67.0, 76.0]);
2774 let n = narrow();
2775
2776 assert_eq!((wide() - &narrow()).clone_as_vec(), wide_lhs);
2778 assert_eq!((wide() - &n.as_view()).clone_as_vec(), wide_lhs);
2779 }
2780
2781 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2783 pub fn test_grouped_owned_lhs_narrow<V: Vector>(ctx2: V::C) {
2784 let ctx = ctx4::<V>(&ctx2);
2785 let wide = V::from_vec(
2786 fv::<V>(&[10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0]),
2787 ctx,
2788 );
2789 let narrow = V::from_vec(fv::<V>(&[1.0, 2.0, 3.0, 4.0]), ctx2);
2790 let _ = narrow - &wide;
2791 }
2792
2793 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2795 pub fn test_grouped_incompatible<V: Vector>(ctx3: V::C) {
2796 assert_eq!(ctx3.nbatch(), 3);
2797 let wide = ctx3.clone_with_nbatch(4).unwrap();
2798 let mut y = V::zeros(2, wide);
2799 let x = V::zeros(2, ctx3);
2800 y.axpy(f::<V>(1.0), &x, f::<V>(1.0));
2801 }
2802
2803 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2807 pub fn test_narrow_dest_copy_from<V: Vector>(ctx2: V::C) {
2808 let wide = ctx4::<V>(&ctx2);
2809 let mut y = V::zeros(2, ctx2);
2810 let x = V::zeros(2, wide);
2811 y.copy_from(&x);
2812 }
2813
2814 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2815 pub fn test_narrow_dest_add_assign<V: Vector>(ctx2: V::C) {
2816 let wide = ctx4::<V>(&ctx2);
2817 let mut y = V::zeros(2, ctx2);
2818 let x = V::zeros(2, wide);
2819 y += &x;
2820 }
2821
2822 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2823 pub fn test_narrow_dest_axpy<V: Vector>(ctx2: V::C) {
2824 let wide = ctx4::<V>(&ctx2);
2825 let mut y = V::zeros(2, ctx2);
2826 let x = V::zeros(2, wide);
2827 y.axpy(f::<V>(1.0), &x, f::<V>(1.0));
2828 }
2829
2830 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2831 pub fn test_narrow_dest_component_mul<V: Vector>(ctx2: V::C) {
2832 let wide = ctx4::<V>(&ctx2);
2833 let mut y = V::zeros(2, ctx2);
2834 let x = V::zeros(2, wide);
2835 y.component_mul_assign(&x);
2836 }
2837
2838 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2839 pub fn test_narrow_dest_gather<V: Vector>(ctx2: V::C) {
2840 let wide = ctx4::<V>(&ctx2);
2841 let idx = V::Index::from_vec(vec![1, 0], Default::default());
2842 let o = V::zeros(2, wide);
2843 let mut a = V::zeros(2, ctx2);
2844 a.gather(&o, &idx);
2845 }
2846
2847 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2848 pub fn test_narrow_dest_copy_from_indices<V: Vector>(ctx2: V::C) {
2849 let wide = ctx4::<V>(&ctx2);
2850 let idx = V::Index::from_vec(vec![1, 0], Default::default());
2851 let o = V::zeros(2, wide);
2852 let mut a = V::zeros(2, ctx2);
2853 a.copy_from_indices(&o, &idx);
2854 }
2855
2856 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2858 pub fn test_narrow_dest_scatter<V: Vector>(ctx2: V::C) {
2859 let wide = ctx4::<V>(&ctx2);
2860 let idx = V::Index::from_vec(vec![1, 0], Default::default());
2861 let source = V::zeros(2, wide);
2862 let mut dest = V::zeros(2, ctx2);
2863 source.scatter(&idx, &mut dest);
2864 }
2865
2866 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2868 pub fn test_unbatched_dest_squared_norm<V: Vector>(ctx2: V::C) {
2869 let ctx1 = ctx2.clone_with_nbatch(1).unwrap();
2870 let v = V::from_vec(fv::<V>(&[1.0, 1.0]), ctx1.clone());
2871 let y = V::zeros(2, ctx2);
2872 let atol = V::from_element(2, f::<V>(1.0), ctx1);
2873 v.squared_norm(&y, &atol, f::<V>(1.0));
2874 }
2875
2876 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2878 pub fn test_narrow_dest_squared_norm<V: Vector>(ctx2: V::C) {
2879 let wide = ctx4::<V>(&ctx2);
2880 let v = V::from_vec(fv::<V>(&[1.0, 1.0, 1.0, 1.0]), ctx2.clone());
2881 let y = V::zeros(2, wide);
2882 let atol = V::from_element(2, f::<V>(1.0), ctx2);
2883 v.squared_norm(&y, &atol, f::<V>(1.0));
2884 }
2885
2886 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2889 pub fn test_batched_axpy_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
2890 assert_eq!(ctx2.nbatch(), 2);
2891 assert_eq!(ctx3.nbatch(), 3);
2892 let mut y = V::zeros(2, ctx2);
2893 let x = V::zeros(2, ctx3);
2894 y.axpy(f::<V>(1.0), &x, f::<V>(1.0));
2895 }
2896
2897 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2898 pub fn test_batched_copy_from_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
2899 assert_eq!(ctx2.nbatch(), 2);
2900 assert_eq!(ctx3.nbatch(), 3);
2901 let mut y = V::zeros(2, ctx2);
2902 let x = V::zeros(2, ctx3);
2903 y.copy_from(&x);
2904 }
2905
2906 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2907 pub fn test_batched_add_assign_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
2908 assert_eq!(ctx2.nbatch(), 2);
2909 assert_eq!(ctx3.nbatch(), 3);
2910 let mut a = V::zeros(2, ctx2);
2911 let b = V::zeros(2, ctx3);
2912 a += &b;
2913 }
2914
2915 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
2916 pub fn test_batched_component_mul_incompatible<V: Vector>(ctx2: V::C, ctx3: V::C) {
2917 assert_eq!(ctx2.nbatch(), 2);
2918 assert_eq!(ctx3.nbatch(), 3);
2919 let mut a = V::zeros(2, ctx2);
2920 let b = V::zeros(2, ctx3);
2921 a.component_mul_assign(&b);
2922 }
2923
2924 #[test]
2925 fn vector_common_for_references_and_default_helpers_work() {
2926 let mut v = NalgebraVec::from_vec(vec![1.0, 2.0], NalgebraContext::default());
2927 assert_eq!(<NalgebraVec<f64> as VectorCommon>::inner(&v).nrows(), 2);
2928 assert_eq!(<NalgebraVec<f64> as VectorCommon>::inner(&v).ncols(), 1);
2929 assert_eq!(<&NalgebraVec<f64> as VectorCommon>::inner(&&v).nrows(), 2);
2930 assert_eq!(
2931 <&mut NalgebraVec<f64> as VectorCommon>::inner(&&mut v).ncols(),
2932 1
2933 );
2934
2935 let empty = NalgebraVec::<f64>::zeros(0, NalgebraContext::default());
2936 assert!(empty.is_empty());
2937
2938 let non_empty = NalgebraVec::<f64>::zeros(2, NalgebraContext::default());
2939 assert!(!non_empty.is_empty());
2940 assert_eq!(non_empty.clone_as_vec(), vec![0.0, 0.0]);
2941 }
2942
2943 #[test]
2944 fn vector_assert_eq_panics_for_length_mismatch() {
2945 let left = NalgebraVec::from_vec(vec![1.0, 2.0], NalgebraContext::default());
2946 let right = NalgebraVec::from_vec(vec![1.0], NalgebraContext::default());
2947 let tol = NalgebraVec::from_vec(vec![0.0, 0.0], NalgebraContext::default());
2948 assert!(catch_unwind(AssertUnwindSafe(|| left.assert_eq(&right, &tol))).is_err());
2949 }
2950
2951 #[test]
2952 fn vector_assert_helpers_cover_success_and_failure_paths() {
2953 let left = NalgebraVec::from_vec(vec![1.0, 2.0, 3.0], NalgebraContext::default());
2954 let right = NalgebraVec::from_vec(vec![1.0, 2.0, 3.0], NalgebraContext::default());
2955 let tol = NalgebraVec::from_vec(vec![0.0, 0.0, 0.0], NalgebraContext::default());
2956 left.assert_eq(&right, &tol);
2957 left.assert_eq_st(&right, 0.0);
2958 left.assert_eq_norm(&right, &tol, 1e-6, 1.0);
2959
2960 let perturbed = NalgebraVec::from_vec(vec![1.1, 2.0, 3.0], NalgebraContext::default());
2961 assert!(catch_unwind(AssertUnwindSafe(
2962 || left.assert_eq_norm(&perturbed, &tol, 1e-6, 0.01)
2963 ))
2964 .is_err());
2965 }
2966
2967 #[test]
2968 fn vector_assert_eq_vec_panics_for_short_vector_mismatch() {
2969 assert!(catch_unwind(AssertUnwindSafe(|| {
2970 <NalgebraVec<f64> as Vector>::assert_eq_vec(
2971 vec![1.0, 2.0, 3.0],
2972 vec![0.0, 2.0, 3.0],
2973 vec![0.0, 0.0, 0.0],
2974 )
2975 }))
2976 .is_err());
2977 }
2978
2979 #[test]
2980 fn vector_assert_eq_vec_panics_for_first_middle_and_last_mismatch_in_long_vectors() {
2981 assert!(catch_unwind(AssertUnwindSafe(|| {
2982 <NalgebraVec<f64> as Vector>::assert_eq_vec(
2983 vec![1.0, 2.0, 3.0, 4.0],
2984 vec![0.0, 2.0, 3.0, 4.0],
2985 vec![0.0, 0.0, 0.0, 0.0],
2986 )
2987 }))
2988 .is_err());
2989 assert!(catch_unwind(AssertUnwindSafe(|| {
2990 <NalgebraVec<f64> as Vector>::assert_eq_vec(
2991 vec![1.0, 2.0, 3.0, 4.0, 5.0],
2992 vec![1.0, 2.0, 0.0, 4.0, 5.0],
2993 vec![0.0, 0.0, 0.0, 0.0, 0.0],
2994 )
2995 }))
2996 .is_err());
2997 assert!(catch_unwind(AssertUnwindSafe(|| {
2998 <NalgebraVec<f64> as Vector>::assert_eq_vec(
2999 vec![1.0, 2.0, 3.0, 4.0],
3000 vec![1.0, 2.0, 3.0, 0.0],
3001 vec![0.0, 0.0, 0.0, 0.0],
3002 )
3003 }))
3004 .is_err());
3005 }
3006
3007 use crate::matrix::DenseMatrix;
3008
3009 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3010 fn make_strided_test_matrix<M: DenseMatrix>(nbatch: usize) -> M {
3011 let ctx = M::C::default().clone_with_nbatch(nbatch).unwrap();
3012 let nrows = 3;
3013 let ncols = 4;
3014 let mut data = Vec::with_capacity(nrows * ncols * nbatch);
3015 for b in 0..nbatch {
3016 for col in 0..ncols {
3017 for row in 0..nrows {
3018 data.push(f::<M::V>(row as f64 + col as f64 * 10.0 + b as f64 * 100.0));
3019 }
3020 }
3021 }
3022 M::from_vec(nrows, ncols, data, ctx)
3023 }
3024
3025 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3026 pub fn test_strided_view_fill_index<M: DenseMatrix>(ctx: M::C) {
3027 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3028 {
3029 let mut col1 = matrix.column_mut(1);
3030 col1.fill_index(1, f::<M::V>(99.0));
3031 }
3032 let owned = matrix.column(1).into_owned();
3033 let b0 = owned.get_batch(0);
3034 let b1 = owned.get_batch(1);
3035 assert_eq!(b0.get_index(1), f::<M::V>(99.0));
3036 assert_eq!(b1.get_index(1), f::<M::V>(99.0));
3037 }
3038
3039 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3041 pub fn test_strided_view_set_index_panics<M: DenseMatrix>(ctx: M::C) {
3042 assert!(ctx.nbatch() > 1);
3043 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3044 matrix.column_mut(1).set_index(1, f::<M::V>(99.0));
3045 }
3046
3047 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3048 pub fn test_strided_view_mut_copy_from<M: DenseMatrix>(ctx: M::C) {
3049 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3050 let owned = M::V::from_vec(
3051 vec![f::<M::V>(50.0), f::<M::V>(51.0), f::<M::V>(52.0)],
3052 M::C::default(),
3053 );
3054 {
3055 let mut col1 = matrix.column_mut(1);
3056 col1.copy_from(&owned);
3057 }
3058 let owned_v = matrix.column(1).into_owned();
3059 let b0 = owned_v.get_batch(0);
3060 let b1 = owned_v.get_batch(1);
3061 assert_eq!(b0.get_index(0), f::<M::V>(50.0));
3062 assert_eq!(b0.get_index(1), f::<M::V>(51.0));
3063 assert_eq!(b0.get_index(2), f::<M::V>(52.0));
3064 assert_eq!(b1.get_index(0), f::<M::V>(50.0));
3065 assert_eq!(b1.get_index(1), f::<M::V>(51.0));
3066 assert_eq!(b1.get_index(2), f::<M::V>(52.0));
3067 }
3068
3069 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3070 pub fn test_strided_view_mut_axpy<M: DenseMatrix>(ctx: M::C) {
3071 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3072 let x = M::V::from_vec(
3073 vec![f::<M::V>(10.0), f::<M::V>(10.0), f::<M::V>(10.0)],
3074 M::C::default(),
3075 );
3076 {
3077 let mut col1 = matrix.column_mut(1);
3078 col1.axpy(f::<M::V>(2.0), &x, f::<M::V>(1.0));
3079 }
3080 let owned_v = matrix.column(1).into_owned();
3081 let b1 = owned_v.get_batch(1);
3082 assert_eq!(b1.get_index(0), f::<M::V>(130.0));
3083 assert_eq!(b1.get_index(1), f::<M::V>(131.0));
3084 assert_eq!(b1.get_index(2), f::<M::V>(132.0));
3085 }
3086
3087 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3088 pub fn test_strided_view_mut_mul_assign_scalar<M: DenseMatrix>(ctx: M::C) {
3089 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3090 {
3091 let mut col1 = matrix.column_mut(1);
3092 col1 *= Scale(f::<M::V>(2.0));
3093 }
3094 let owned_v = matrix.column(1).into_owned();
3095 let b0 = owned_v.get_batch(0);
3096 let b1 = owned_v.get_batch(1);
3097 assert_eq!(b0.get_index(0), f::<M::V>(20.0));
3098 assert_eq!(b1.get_index(0), f::<M::V>(220.0));
3099 }
3100
3101 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3102 pub fn test_strided_view_mut_add_assign<M: DenseMatrix>(ctx: M::C) {
3103 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3104 let rhs = M::V::from_vec(
3105 vec![
3106 f::<M::V>(5.0),
3107 f::<M::V>(5.0),
3108 f::<M::V>(5.0),
3109 f::<M::V>(10.0),
3110 f::<M::V>(10.0),
3111 f::<M::V>(10.0),
3112 ],
3113 ctx.clone(),
3114 );
3115 {
3116 let mut col1 = matrix.column_mut(1);
3117 col1 += &rhs;
3118 }
3119 let owned_v = matrix.column(1).into_owned();
3120 let b0 = owned_v.get_batch(0);
3121 let b1 = owned_v.get_batch(1);
3122 assert_eq!(b0.get_index(0), f::<M::V>(15.0));
3123 assert_eq!(b0.get_index(1), f::<M::V>(16.0));
3124 assert_eq!(b0.get_index(2), f::<M::V>(17.0));
3125 assert_eq!(b1.get_index(0), f::<M::V>(120.0));
3126 assert_eq!(b1.get_index(1), f::<M::V>(121.0));
3127 assert_eq!(b1.get_index(2), f::<M::V>(122.0));
3128 }
3129
3130 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3131 pub fn test_strided_view_mut_sub_assign<M: DenseMatrix>(ctx: M::C) {
3132 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3133 let rhs = M::V::from_vec(
3134 vec![
3135 f::<M::V>(1.0),
3136 f::<M::V>(1.0),
3137 f::<M::V>(1.0),
3138 f::<M::V>(1.0),
3139 f::<M::V>(1.0),
3140 f::<M::V>(1.0),
3141 ],
3142 ctx.clone(),
3143 );
3144 {
3145 let mut col1 = matrix.column_mut(1);
3146 col1 -= &rhs;
3147 }
3148 let owned_v = matrix.column(1).into_owned();
3149 let b0 = owned_v.get_batch(0);
3150 let b1 = owned_v.get_batch(1);
3151 assert_eq!(b0.get_index(0), f::<M::V>(9.0));
3152 assert_eq!(b1.get_index(0), f::<M::V>(109.0));
3153 }
3154
3155 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3156 pub fn test_strided_view_add_assign_broadcast<M: DenseMatrix>(ctx: M::C) {
3157 let mut matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3158 let rhs = M::V::from_vec(
3159 vec![f::<M::V>(5.0), f::<M::V>(5.0), f::<M::V>(5.0)],
3160 M::C::default(),
3161 );
3162 {
3163 let mut col1 = matrix.column_mut(1);
3164 col1 += &rhs;
3165 }
3166 let owned_v = matrix.column(1).into_owned();
3167 let b0 = owned_v.get_batch(0);
3168 let b1 = owned_v.get_batch(1);
3169 assert_eq!(b0.get_index(0), f::<M::V>(15.0));
3170 assert_eq!(b1.get_index(0), f::<M::V>(115.0));
3171 }
3172
3173 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3174 pub fn test_strided_view_add_owned<M: DenseMatrix>(ctx: M::C) {
3175 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3176 let nbatch = ctx.nbatch();
3177 let mut rhs_data = Vec::with_capacity(3 * nbatch);
3178 for _ in 0..nbatch {
3179 rhs_data.extend_from_slice(&[f::<M::V>(5.0), f::<M::V>(5.0), f::<M::V>(5.0)]);
3180 }
3181 let rhs = M::V::from_vec(rhs_data, ctx.clone());
3182 let col1 = matrix.column(1);
3183 let result = col1 + &rhs;
3184 let b0 = result.get_batch(0);
3185 let b1 = result.get_batch(1);
3186 assert_eq!(b0.get_index(0), f::<M::V>(15.0));
3187 assert_eq!(b1.get_index(0), f::<M::V>(115.0));
3188 }
3189
3190 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3191 pub fn test_strided_view_squared_norm<M: DenseMatrix>(ctx: M::C) {
3192 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3193 let nbatch = ctx.nbatch();
3194 let mut y_data = Vec::with_capacity(3 * nbatch);
3195 for _ in 0..nbatch {
3196 y_data.extend_from_slice(&[f::<M::V>(1.0), f::<M::V>(1.0), f::<M::V>(1.0)]);
3197 }
3198 let y = M::V::from_vec(y_data, ctx.clone());
3199 let atol = M::V::from_vec(
3200 vec![f::<M::V>(1e-3), f::<M::V>(1e-3), f::<M::V>(1e-3)],
3201 M::C::default(),
3202 );
3203 let col1 = matrix.column(1);
3204 let norm = col1.squared_norm(&y, &atol, f::<M::V>(1e-2));
3205 assert!(norm > f::<M::V>(0.0));
3206 }
3207
3208 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3209 pub fn test_strided_view_into_owned<M: DenseMatrix>(ctx: M::C) {
3210 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3211 let col1 = matrix.column(1);
3212 let owned = col1.into_owned();
3213 let b0 = owned.get_batch(0);
3214 let b1 = owned.get_batch(1);
3215 assert_eq!(b0.get_index(0), f::<M::V>(10.0));
3216 assert_eq!(b0.get_index(1), f::<M::V>(11.0));
3217 assert_eq!(b1.get_index(0), f::<M::V>(110.0));
3218 assert_eq!(b1.get_index(1), f::<M::V>(111.0));
3219 }
3220
3221 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3222 pub fn test_strided_view_component_mul<M: DenseMatrix>(ctx: M::C) {
3223 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3224 let rhs = M::V::from_vec(
3225 vec![f::<M::V>(10.0), f::<M::V>(1.0), f::<M::V>(0.0)],
3226 M::C::default(),
3227 );
3228 let col1 = matrix.column(1);
3229 let mut owned = col1.into_owned();
3230 owned.component_mul_assign(&rhs);
3231 let b0 = owned.get_batch(0);
3232 let b1 = owned.get_batch(1);
3233 assert_eq!(b0.get_index(0), f::<M::V>(100.0));
3234 assert_eq!(b0.get_index(1), f::<M::V>(11.0));
3235 assert_eq!(b1.get_index(0), f::<M::V>(1100.0));
3236 assert_eq!(b1.get_index(1), f::<M::V>(111.0));
3237 }
3238
3239 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3240 pub fn test_strided_view_component_div<M: DenseMatrix>(ctx: M::C) {
3241 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3242 let rhs = M::V::from_vec(
3243 vec![f::<M::V>(10.0), f::<M::V>(11.0), f::<M::V>(12.0)],
3244 M::C::default(),
3245 );
3246 let col1 = matrix.column(1);
3247 let mut owned = col1.into_owned();
3248 owned.component_div_assign(&rhs);
3249 let b0 = owned.get_batch(0);
3250 let b1 = owned.get_batch(1);
3251 assert_eq!(b0.get_index(0), f::<M::V>(1.0));
3252 assert_eq!(b1.get_index(0), f::<M::V>(11.0));
3253 }
3254
3255 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3256 pub fn test_strided_view_mul_scalar<M: DenseMatrix>(ctx: M::C) {
3257 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3258 let col1 = matrix.column(1);
3259 let result = col1 * Scale(f::<M::V>(2.0));
3260 let b0 = result.get_batch(0);
3261 let b1 = result.get_batch(1);
3262 assert_eq!(b0.get_index(0), f::<M::V>(20.0));
3263 assert_eq!(b1.get_index(0), f::<M::V>(220.0));
3264 }
3265
3266 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3267 pub fn test_strided_view_fill<M: DenseMatrix>(ctx: M::C) {
3268 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3269 let col1 = matrix.column(1);
3270 let mut owned = col1.into_owned();
3271 owned.fill(f::<M::V>(7.0));
3272 let b0 = owned.get_batch(0);
3273 let b1 = owned.get_batch(1);
3274 assert_eq!(b0.get_index(0), f::<M::V>(7.0));
3275 assert_eq!(b1.get_index(0), f::<M::V>(7.0));
3276 }
3277
3278 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3279 pub fn test_strided_view_assign_at_indices<M: DenseMatrix>(ctx: M::C) {
3280 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3281 let indices = <M::V as Vector>::Index::from_vec(vec![0, 2], M::C::default());
3282 let col1 = matrix.column(1);
3283 let mut owned = col1.into_owned();
3284 owned.assign_at_indices(&indices, f::<M::V>(0.0));
3285 let b0 = owned.get_batch(0);
3286 let b1 = owned.get_batch(1);
3287 assert_eq!(b0.get_index(0), f::<M::V>(0.0));
3288 assert_eq!(b1.get_index(0), f::<M::V>(0.0));
3289 }
3290
3291 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3292 pub fn test_strided_view_copy_from_indices<M: DenseMatrix>(ctx: M::C) {
3293 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3294 let nbatch = ctx.nbatch();
3295 let mut other_data = Vec::with_capacity(3 * nbatch);
3296 for _ in 0..nbatch {
3297 other_data.extend_from_slice(&[f::<M::V>(50.0), f::<M::V>(0.0), f::<M::V>(0.0)]);
3298 }
3299 let other = M::V::from_vec(other_data, ctx.clone());
3300 let indices = <M::V as Vector>::Index::from_vec(vec![0], M::C::default());
3301 let col1 = matrix.column(1);
3302 let mut owned = col1.into_owned();
3303 owned.copy_from_indices(&other, &indices);
3304 let b0 = owned.get_batch(0);
3305 let b1 = owned.get_batch(1);
3306 assert_eq!(b0.get_index(0), f::<M::V>(50.0));
3307 assert_eq!(b1.get_index(0), f::<M::V>(50.0));
3308 }
3309
3310 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3311 pub fn test_strided_view_gather<M: DenseMatrix>(ctx: M::C) {
3312 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3313 let nbatch = ctx.nbatch();
3314 let mut result = M::V::zeros(2, M::C::default().clone_with_nbatch(nbatch).unwrap());
3315 let indices = <M::V as Vector>::Index::from_vec(vec![0, 2], M::C::default());
3316 let col1 = matrix.column(1);
3317 let owned = col1.into_owned();
3318 result.gather(&owned, &indices);
3319 let b1 = result.get_batch(1);
3320 assert_eq!(b1.get_index(0), f::<M::V>(110.0));
3321 }
3322
3323 #[cfg_attr(not(feature = "cuda"), allow(dead_code))]
3324 pub fn test_strided_view_scatter<M: DenseMatrix>(ctx: M::C) {
3325 let matrix = make_strided_test_matrix::<M>(ctx.nbatch());
3326 let nbatch = ctx.nbatch();
3327 let col1 = matrix.column(1);
3328 let owned = col1.into_owned();
3329 let indices = <M::V as Vector>::Index::from_vec(vec![0, 1, 2], M::C::default());
3330 let mut result = M::V::zeros(3, M::C::default().clone_with_nbatch(nbatch).unwrap());
3331 owned.scatter(&indices, &mut result);
3332 let b1 = result.get_batch(1);
3333 assert_eq!(b1.get_index(0), f::<M::V>(110.0));
3334 }
3335}