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