1use crate::dense_vector::{DenseVector, DenseVectorMut};
2use crate::sparse::to_dense::assign_vector_to_dense;
3use crate::Ix1;
4use ndarray::Array;
5use std::cmp;
6use std::collections::HashSet;
7use std::convert::AsRef;
8use std::hash::Hash;
9use std::iter::{Enumerate, FilterMap, IntoIterator, Peekable, Sum, Zip};
27use std::marker::PhantomData;
28use std::ops::{
29 Add, Deref, DerefMut, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub,
30};
31use std::slice::{Iter, IterMut};
32
33use num_traits::{Float, Signed, Zero};
34
35use crate::array_backend::Array2;
36use crate::errors::StructureError;
37use crate::indexing::SpIndex;
38use crate::sparse::csmat::CompressedStorage::{CSC, CSR};
39use crate::sparse::permutation::PermViewI;
40use crate::sparse::prelude::*;
41use crate::sparse::utils;
42use crate::sparse::{binop, prod};
43
44#[derive(Clone, Copy, PartialEq, Eq, Debug)]
45pub struct NnzIndex(pub usize);
50
51pub trait VecDim<N> {
54 fn dim(&self) -> usize;
56}
57
58impl<N, I: SpIndex, IS: Deref<Target = [I]>, DS: Deref<Target = [N]>> VecDim<N>
59 for CsVecBase<IS, DS, N, I>
60{
61 fn dim(&self) -> usize {
62 self.dim
63 }
64}
65
66impl<N, T: ?Sized> VecDim<N> for T
67where
68 T: AsRef<[N]>,
69{
70 fn dim(&self) -> usize {
71 self.as_ref().len()
72 }
73}
74
75#[derive(Clone)]
77pub struct VectorIterator<'a, N: 'a, I: 'a> {
78 ind_data: Zip<Iter<'a, I>, Iter<'a, N>>,
79}
80
81pub struct VectorIteratorPerm<'a, N: 'a, I: 'a> {
82 ind_data: Zip<Iter<'a, I>, Iter<'a, N>>,
83 perm: PermViewI<'a, I>,
84}
85
86pub struct VectorIteratorMut<'a, N: 'a, I: 'a> {
88 ind_data: Zip<Iter<'a, I>, IterMut<'a, N>>,
89}
90
91impl<'a, N: 'a, I: 'a + SpIndex> Iterator for VectorIterator<'a, N, I> {
92 type Item = (usize, &'a N);
93
94 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
95 self.ind_data
96 .next()
97 .map(|(inner_ind, data)| (inner_ind.index_unchecked(), data))
98 }
99
100 fn size_hint(&self) -> (usize, Option<usize>) {
101 self.ind_data.size_hint()
102 }
103}
104
105impl<'a, N: 'a, I: 'a + SpIndex> Iterator for VectorIteratorPerm<'a, N, I> {
106 type Item = (usize, &'a N);
107
108 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
109 match self.ind_data.next() {
110 None => None,
111 Some((inner_ind, data)) => {
112 Some((self.perm.at(inner_ind.index_unchecked()), data))
113 }
114 }
115 }
116
117 fn size_hint(&self) -> (usize, Option<usize>) {
118 self.ind_data.size_hint()
119 }
120}
121
122impl<'a, N: 'a, I: 'a + SpIndex> Iterator for VectorIteratorMut<'a, N, I> {
123 type Item = (usize, &'a mut N);
124
125 fn next(&mut self) -> Option<<Self as Iterator>::Item> {
126 self.ind_data
127 .next()
128 .map(|(inner_ind, data)| (inner_ind.index_unchecked(), data))
129 }
130
131 fn size_hint(&self) -> (usize, Option<usize>) {
132 self.ind_data.size_hint()
133 }
134}
135
136pub trait SparseIterTools: Iterator {
137 fn nnz_or_zip<'a, I, N1, N2>(
157 self,
158 other: I,
159 ) -> NnzOrZip<'a, Self, I::IntoIter, N1, N2>
160 where
161 Self: Iterator<Item = (usize, &'a N1)> + Sized,
162 I: IntoIterator<Item = (usize, &'a N2)>,
163 {
164 NnzOrZip {
165 left: self.peekable(),
166 right: other.into_iter().peekable(),
167 life: PhantomData,
168 }
169 }
170
171 #[allow(clippy::type_complexity)]
186 fn nnz_zip<'a, I, N1, N2>(
187 self,
188 other: I,
189 ) -> FilterMap<
190 NnzOrZip<'a, Self, I::IntoIter, N1, N2>,
191 fn(NnzEither<'a, N1, N2>) -> Option<(usize, &'a N1, &'a N2)>,
192 >
193 where
194 Self: Iterator<Item = (usize, &'a N1)> + Sized,
195 I: IntoIterator<Item = (usize, &'a N2)>,
196 {
197 let nnz_or_iter = NnzOrZip {
198 left: self.peekable(),
199 right: other.into_iter().peekable(),
200 life: PhantomData,
201 };
202 nnz_or_iter.filter_map(filter_both_nnz)
203 }
204}
205
206impl<T: Iterator> SparseIterTools for Enumerate<T> {}
207
208impl<'a, N: 'a, I: 'a + SpIndex> SparseIterTools for VectorIterator<'a, N, I> {}
209
210pub trait IntoSparseVecIter<'a, N: 'a> {
212 type IterType;
213
214 fn into_sparse_vec_iter(
218 self,
219 ) -> <Self as IntoSparseVecIter<'a, N>>::IterType
220 where
221 <Self as IntoSparseVecIter<'a, N>>::IterType:
222 Iterator<Item = (usize, &'a N)>;
223
224 fn dim(&self) -> usize;
226
227 fn is_dense(&self) -> bool {
229 false
230 }
231
232 #[allow(unused_variables)]
239 fn index(self, idx: usize) -> &'a N
240 where
241 Self: Sized,
242 {
243 panic!("cannot be called on a vector that is not dense");
244 }
245}
246
247impl<'a, N: 'a, I: 'a> IntoSparseVecIter<'a, N> for CsVecViewI<'a, N, I>
248where
249 I: SpIndex,
250{
251 type IterType = VectorIterator<'a, N, I>;
252
253 fn dim(&self) -> usize {
254 self.dim()
255 }
256
257 fn into_sparse_vec_iter(self) -> VectorIterator<'a, N, I> {
258 self.iter_rbr()
259 }
260}
261
262impl<'a, N: 'a, I: 'a, IS, DS> IntoSparseVecIter<'a, N>
263 for &'a CsVecBase<IS, DS, N, I>
264where
265 I: SpIndex,
266 IS: Deref<Target = [I]>,
267 DS: Deref<Target = [N]>,
268{
269 type IterType = VectorIterator<'a, N, I>;
270
271 fn dim(&self) -> usize {
272 (*self).dim()
273 }
274
275 fn into_sparse_vec_iter(self) -> VectorIterator<'a, N, I> {
276 self.iter()
277 }
278}
279
280impl<'a, N: 'a, V: ?Sized> IntoSparseVecIter<'a, N> for &'a V
281where
282 V: DenseVector<Scalar = N>,
283{
284 #[allow(clippy::type_complexity)]
287 type IterType = std::iter::Map<
288 std::iter::Zip<std::iter::Repeat<Self>, std::ops::Range<usize>>,
289 fn((&'a V, usize)) -> (usize, &'a N),
290 >;
291
292 #[inline(always)]
293 fn into_sparse_vec_iter(self) -> Self::IterType {
294 #[inline(always)]
299 fn hack_instead_of_closure<N, V>(vi: (&V, usize)) -> (usize, &N)
300 where
301 V: ?Sized,
302 V: DenseVector<Scalar = N>,
303 {
304 (vi.1, vi.0.index(vi.1))
305 }
306 let n = DenseVector::dim(self);
307 std::iter::repeat(self)
308 .zip(0..n)
309 .map(hack_instead_of_closure)
310 }
311
312 fn dim(&self) -> usize {
313 DenseVector::dim(*self)
314 }
315
316 fn is_dense(&self) -> bool {
317 true
318 }
319
320 #[inline(always)]
321 fn index(self, idx: usize) -> &'a N {
322 DenseVector::index(self, idx)
323 }
324}
325
326pub struct NnzOrZip<'a, Ite1, Ite2, N1: 'a, N2: 'a>
329where
330 Ite1: Iterator<Item = (usize, &'a N1)>,
331 Ite2: Iterator<Item = (usize, &'a N2)>,
332{
333 left: Peekable<Ite1>,
334 right: Peekable<Ite2>,
335 life: PhantomData<(&'a N1, &'a N2)>,
336}
337
338#[derive(PartialEq, Eq, Debug)]
339pub enum NnzEither<'a, N1: 'a, N2: 'a> {
340 Both((usize, &'a N1, &'a N2)),
341 Left((usize, &'a N1)),
342 Right((usize, &'a N2)),
343}
344
345fn filter_both_nnz<'a, N: 'a, M: 'a>(
346 elem: NnzEither<'a, N, M>,
347) -> Option<(usize, &'a N, &'a M)> {
348 match elem {
349 NnzEither::Both((ind, lval, rval)) => Some((ind, lval, rval)),
350 _ => None,
351 }
352}
353
354impl<'a, Ite1, Ite2, N1: 'a, N2: 'a> Iterator
355 for NnzOrZip<'a, Ite1, Ite2, N1, N2>
356where
357 Ite1: Iterator<Item = (usize, &'a N1)>,
358 Ite2: Iterator<Item = (usize, &'a N2)>,
359{
360 type Item = NnzEither<'a, N1, N2>;
361
362 fn next(&mut self) -> Option<NnzEither<'a, N1, N2>> {
363 use NnzEither::{Both, Left, Right};
364 match (self.left.peek(), self.right.peek()) {
365 (None, Some(&(_, _))) => {
366 let (rind, rval) = self.right.next().unwrap();
367 Some(Right((rind, rval)))
368 }
369 (Some(&(_, _)), None) => {
370 let (lind, lval) = self.left.next().unwrap();
371 Some(Left((lind, lval)))
372 }
373 (None, None) => None,
374 (Some(&(lind, _)), Some(&(rind, _))) => match lind.cmp(&rind) {
375 std::cmp::Ordering::Less => {
376 let (lind, lval) = self.left.next().unwrap();
377 Some(Left((lind, lval)))
378 }
379 std::cmp::Ordering::Greater => {
380 let (rind, rval) = self.right.next().unwrap();
381 Some(Right((rind, rval)))
382 }
383 std::cmp::Ordering::Equal => {
384 let (lind, lval) = self.left.next().unwrap();
385 let (_, rval) = self.right.next().unwrap();
386 Some(Both((lind, lval, rval)))
387 }
388 },
389 }
390 }
391
392 #[inline]
393 fn size_hint(&self) -> (usize, Option<usize>) {
394 let (left_lower, left_upper) = self.left.size_hint();
395 let (right_lower, right_upper) = self.right.size_hint();
396 let upper = match (left_upper, right_upper) {
397 (Some(x), Some(y)) => Some(x + y),
398 (Some(x), None) => Some(x),
399 (None, Some(y)) => Some(y),
400 (None, None) => None,
401 };
402 (cmp::max(left_lower, right_lower), upper)
403 }
404}
405
406impl<N, I: SpIndex, DStorage, IStorage> CsVecBase<IStorage, DStorage, N, I>
408where
409 DStorage: std::ops::Deref<Target = [N]>,
410 IStorage: std::ops::Deref<Target = [I]>,
411{
412 pub fn new(n: usize, indices: IStorage, data: DStorage) -> Self {
431 Self::try_new(n, indices, data)
432 .map_err(|(_, _, e)| e)
433 .unwrap()
434 }
435
436 pub fn try_new(
441 n: usize,
442 indices: IStorage,
443 data: DStorage,
444 ) -> Result<Self, (IStorage, DStorage, StructureError)> {
445 if I::from(n).is_none() {
446 return Err((
447 indices,
448 data,
449 StructureError::OutOfRange("Index size is too small"),
450 ));
451 }
452 if indices.len() != data.len() {
453 return Err((
454 indices,
455 data,
456 StructureError::SizeMismatch(
457 "indices and data do not have compatible lengths",
458 ),
459 ));
460 }
461 for i in indices.iter() {
462 if i.to_usize().is_none() {
463 return Err((
464 indices,
465 data,
466 StructureError::OutOfRange(
467 "index can not be converted to usize",
468 ),
469 ));
470 }
471 }
472 if !utils::sorted_indices(indices.as_ref()) {
473 return Err((
474 indices,
475 data,
476 StructureError::Unsorted("Unsorted indices"),
477 ));
478 }
479 if let Some(i) = indices.last() {
480 if i.to_usize().unwrap() >= n {
481 return Err((
482 indices,
483 data,
484 StructureError::SizeMismatch(
485 "indices larger than vector size",
486 ),
487 ));
488 }
489 }
490 Ok(Self::new_trusted(n, indices, data))
491 }
492
493 pub(crate) fn new_trusted(
496 n: usize,
497 indices: IStorage,
498 data: DStorage,
499 ) -> Self {
500 Self {
501 dim: n,
502 indices,
503 data,
504 }
505 }
506
507 pub unsafe fn new_uncheked(
516 n: usize,
517 indices: IStorage,
518 data: DStorage,
519 ) -> Self {
520 Self {
521 dim: n,
522 indices,
523 data,
524 }
525 }
526}
527
528impl<N, I: SpIndex, DStorage, IStorage> CsVecBase<IStorage, DStorage, N, I>
529where
530 DStorage: std::ops::DerefMut<Target = [N]>,
531 IStorage: std::ops::DerefMut<Target = [I]>,
532{
533 pub fn new_from_unsorted(
537 n: usize,
538 indices: IStorage,
539 data: DStorage,
540 ) -> Result<Self, (IStorage, DStorage, StructureError)>
541 where
542 N: Clone,
543 {
544 let v = Self::try_new(n, indices, data);
545 match v {
546 Err((mut indices, mut data, StructureError::Unsorted(_))) => {
547 let mut buf = Vec::with_capacity(indices.len());
548 utils::sort_indices_data_slices(
549 &mut indices[..],
550 &mut data[..],
551 &mut buf,
552 );
553 Self::try_new(n, indices, data)
554 }
555 v => v,
556 }
557 }
558}
559
560impl<N, I: SpIndex> CsVecI<N, I> {
562 pub fn empty(dim: usize) -> Self {
564 Self::new_trusted(dim, vec![], vec![])
565 }
566
567 pub fn append(&mut self, ind: usize, val: N) {
578 match self.indices.last() {
579 None => (),
580 Some(&last_ind) => {
581 assert!(ind > last_ind.index_unchecked(), "unsorted append");
582 }
583 }
584 assert!(ind <= self.dim, "out of bounds index");
585 self.indices.push(I::from_usize(ind));
586 self.data.push(val);
587 }
588
589 pub fn reserve(&mut self, size: usize) {
591 self.indices.reserve(size);
592 self.data.reserve(size);
593 }
594
595 pub fn reserve_exact(&mut self, exact_size: usize) {
597 self.indices.reserve_exact(exact_size);
598 self.data.reserve_exact(exact_size);
599 }
600
601 pub fn clear(&mut self) {
603 self.indices.clear();
604 self.data.clear();
605 }
606}
607
608impl<N, I, IStorage, DStorage> CsVecBase<IStorage, DStorage, N, I>
610where
611 I: SpIndex,
612 IStorage: Deref<Target = [I]>,
613 DStorage: Deref<Target = [N]>,
614{
615 pub fn view(&self) -> CsVecViewI<'_, N, I> {
617 CsVecViewI::new_trusted(self.dim, &self.indices[..], &self.data)
618 }
619
620 pub fn to_dense(&self) -> Array<N, Ix1>
622 where
623 N: Clone + Zero,
624 {
625 let mut res = Array::zeros(self.dim());
626 assign_vector_to_dense(res.view_mut(), self.view());
627 res
628 }
629
630 pub fn iter(&self) -> VectorIterator<'_, N, I> {
644 VectorIterator {
645 ind_data: self.indices.iter().zip(self.data.iter()),
646 }
647 }
648
649 #[doc(hidden)]
651 pub fn iter_perm<'a, 'perm: 'a>(
652 &'a self,
653 perm: PermViewI<'perm, I>,
654 ) -> VectorIteratorPerm<'a, N, I>
655 where
656 N: 'a,
657 {
658 VectorIteratorPerm {
659 ind_data: self.indices.iter().zip(self.data.iter()),
660 perm,
661 }
662 }
663
664 pub fn indices(&self) -> &[I] {
666 &self.indices
667 }
668
669 pub fn data(&self) -> &[N] {
671 &self.data
672 }
673
674 pub fn into_raw_storage(self) -> (IStorage, DStorage) {
676 let Self { indices, data, .. } = self;
677 (indices, data)
678 }
679
680 pub fn dim(&self) -> usize {
682 self.dim
683 }
684
685 pub fn nnz(&self) -> usize {
687 self.data.len()
688 }
689
690 pub fn check_structure(&self) -> Result<(), StructureError> {
694 for i in self.indices.iter() {
696 i.index();
697 }
698 if !utils::sorted_indices(&self.indices) {
699 return Err(StructureError::Unsorted("Unsorted indices"));
700 }
701
702 if self.dim == 0 && self.indices.len() == 0 && self.data.len() == 0 {
703 return Ok(());
704 }
705
706 let max_ind = self
707 .indices
708 .iter()
709 .max()
710 .unwrap_or(&I::zero())
711 .index_unchecked();
712 if max_ind >= self.dim {
713 return Err(StructureError::OutOfRange("Out of bounds index"));
714 }
715
716 Ok(())
717 }
718
719 pub fn to_owned(&self) -> CsVecI<N, I>
721 where
722 N: Clone,
723 {
724 CsVecI::new_trusted(self.dim, self.indices.to_vec(), self.data.to_vec())
725 }
726
727 pub fn to_other_types<I2>(&self) -> CsVecI<N, I2>
733 where
734 N: Clone,
735 I2: SpIndex,
736 {
737 let indices = self
738 .indices
739 .iter()
740 .map(|i| I2::from_usize(i.index_unchecked()))
741 .collect();
742 let data = self.data.iter().cloned().collect();
743 CsVecI::new_trusted(self.dim, indices, data)
744 }
745
746 pub fn row_view<Iptr: SpIndex>(&self) -> CsMatVecView_<'_, N, I, Iptr> {
748 let indptr = Array2 {
751 data: [
752 Iptr::zero(),
753 Iptr::from_usize_unchecked(self.indices.len()),
754 ],
755 };
756 CsMatBase {
757 storage: CSR,
758 nrows: 1,
759 ncols: self.dim,
760 indptr: crate::IndPtrBase::new_trusted(indptr),
761 indices: &self.indices[..],
762 data: &self.data[..],
763 }
764 }
765
766 pub fn col_view<Iptr: SpIndex>(&self) -> CsMatVecView_<'_, N, I, Iptr> {
768 let indptr = Array2 {
771 data: [
772 Iptr::zero(),
773 Iptr::from_usize_unchecked(self.indices.len()),
774 ],
775 };
776 CsMatBase {
777 storage: CSC,
778 nrows: self.dim,
779 ncols: 1,
780 indptr: crate::IndPtrBase::new_trusted(indptr),
781 indices: &self.indices[..],
782 data: &self.data[..],
783 }
784 }
785
786 pub fn get<'a>(&'a self, index: usize) -> Option<&'a N>
788 where
789 I: 'a,
790 {
791 self.view().get_rbr(index)
792 }
793
794 pub fn nnz_index(&self, index: usize) -> Option<NnzIndex> {
801 self.indices
802 .binary_search(&I::from_usize(index))
803 .map(|i| NnzIndex(i.index_unchecked()))
804 .ok()
805 }
806
807 pub fn dot<'b, T>(&'b self, rhs: T) -> N
829 where
830 N: 'b + crate::MulAcc + num_traits::Zero,
831 I: 'b,
832 T: IntoSparseVecIter<'b, N>,
833 <T as IntoSparseVecIter<'b, N>>::IterType:
834 Iterator<Item = (usize, &'b N)>,
835 T: Copy, {
837 self.dot_acc(rhs)
838 }
839
840 pub fn dot_acc<'b, T, M, Acc>(&'b self, rhs: T) -> Acc
847 where
848 Acc: 'b + crate::MulAcc<N, M> + num_traits::Zero,
849 M: 'b,
850 T: IntoSparseVecIter<'b, M>,
851 <T as IntoSparseVecIter<'b, M>>::IterType:
852 Iterator<Item = (usize, &'b M)>,
853 T: Copy, {
855 assert_eq!(self.dim(), rhs.dim());
856 let mut sum = Acc::zero();
857 if rhs.is_dense() {
858 self.iter().for_each(|(idx, val)| {
859 sum.mul_acc(val, rhs.index(idx.index_unchecked()));
860 });
861 } else {
862 let mut lhs_iter = self.iter();
863 let mut rhs_iter = rhs.into_sparse_vec_iter();
864 let mut left_nnz = lhs_iter.next();
865 let mut right_nnz = rhs_iter.next();
866 while left_nnz.is_some() && right_nnz.is_some() {
867 let (left_ind, left_val) = left_nnz.unwrap();
868 let (right_ind, right_val) = right_nnz.unwrap();
869 if left_ind == right_ind {
870 sum.mul_acc(left_val, right_val);
871 }
872 if left_ind <= right_ind {
873 left_nnz = lhs_iter.next();
874 }
875 if left_ind >= right_ind {
876 right_nnz = rhs_iter.next();
877 }
878 }
879 }
880 sum
881 }
882
883 pub fn dot_dense<V>(&self, rhs: V) -> N
895 where
896 V: DenseVector<Scalar = N>,
897 N: Sum,
898 for<'r> &'r N: Mul<&'r N, Output = N>,
899 {
900 assert_eq!(self.dim(), rhs.dim());
901 self.iter()
902 .map(|(idx, val)| val * rhs.index(idx.index_unchecked()))
903 .sum()
904 }
905
906 pub fn squared_l2_norm(&self) -> N
908 where
909 N: Sum,
910 for<'r> &'r N: Mul<&'r N, Output = N>,
911 {
912 self.data.iter().map(|x| x * x).sum()
913 }
914
915 pub fn l2_norm(&self) -> N
917 where
918 N: Float + Sum,
919 for<'r> &'r N: Mul<&'r N, Output = N>,
920 {
921 self.squared_l2_norm().sqrt()
922 }
923
924 pub fn l1_norm(&self) -> N
926 where
927 N: Signed + Sum,
928 {
929 self.data.iter().map(Signed::abs).sum()
930 }
931
932 pub fn norm(&self, p: N) -> N
940 where
941 N: Float + Sum,
942 {
943 let abs_val_iter = self.data.iter().map(|x| x.abs());
944 if p.is_infinite() {
945 if self.data.is_empty() {
946 N::zero()
947 } else if p.is_sign_positive() {
948 abs_val_iter.fold(N::neg_infinity(), N::max)
949 } else {
950 abs_val_iter.fold(N::infinity(), N::min)
951 }
952 } else if p.is_zero() {
953 N::from(abs_val_iter.filter(|x| !x.is_zero()).count())
954 .expect("Conversion from usize to a Float type should not fail")
955 } else {
956 abs_val_iter.map(|x| x.powf(p)).sum::<N>().powf(p.powi(-1))
957 }
958 }
959
960 pub fn scatter<V>(&self, out: &mut V)
966 where
967 N: Clone,
968 V: DenseVectorMut<Scalar = N> + ?Sized,
969 {
970 for (ind, val) in self.iter() {
971 *out.index_mut(ind) = val.clone();
972 }
973 }
974
975 pub fn to_set(&self) -> HashSet<(usize, N)>
977 where
978 N: Hash + Eq + Clone,
979 {
980 self.indices()
981 .iter()
982 .map(|i| i.index_unchecked())
983 .zip(self.data.iter().cloned())
984 .collect()
985 }
986
987 pub fn map<F>(&self, f: F) -> CsVecI<N, I>
990 where
991 F: FnMut(&N) -> N,
992 N: Clone,
993 {
994 let mut res = self.to_owned();
995 res.map_inplace(f);
996 res
997 }
998}
999
1000impl<N, I, IStorage, DStorage> CsVecBase<IStorage, DStorage, N, I>
1002where
1003 I: SpIndex,
1004 IStorage: Deref<Target = [I]>,
1005 DStorage: DerefMut<Target = [N]>,
1006{
1007 fn data_mut(&mut self) -> &mut [N] {
1009 &mut self.data[..]
1010 }
1011
1012 pub fn view_mut(&mut self) -> CsVecViewMutI<'_, N, I> {
1013 CsVecViewMutI::new_trusted(
1014 self.dim,
1015 &self.indices[..],
1016 &mut self.data[..],
1017 )
1018 }
1019
1020 pub fn get_mut(&mut self, index: usize) -> Option<&mut N> {
1022 if let Some(NnzIndex(position)) = self.nnz_index(index) {
1023 Some(&mut self.data[position])
1024 } else {
1025 None
1026 }
1027 }
1028
1029 pub fn map_inplace<F>(&mut self, mut f: F)
1031 where
1032 F: FnMut(&N) -> N,
1033 {
1034 for val in &mut self.data[..] {
1035 *val = f(val);
1036 }
1037 }
1038
1039 pub fn iter_mut(&mut self) -> VectorIteratorMut<'_, N, I> {
1043 VectorIteratorMut {
1044 ind_data: self.indices.iter().zip(self.data.iter_mut()),
1045 }
1046 }
1047
1048 pub fn unit_normalize(&mut self)
1052 where
1053 N: Float + Sum,
1054 for<'r> &'r N: Mul<&'r N, Output = N>,
1055 {
1056 let norm_sq = self.squared_l2_norm();
1057 if norm_sq > N::zero() {
1058 let norm = norm_sq.sqrt();
1059 self.map_inplace(|x| *x / norm);
1060 }
1061 }
1062}
1063
1064impl<'a, N: 'a, I: 'a + SpIndex> CsVecViewI<'a, N, I> {
1066 pub fn get_rbr(&self, index: usize) -> Option<&'a N> {
1070 self.nnz_index(index)
1071 .map(|NnzIndex(position)| &self.data[position])
1072 }
1073
1074 fn iter_rbr(&self) -> VectorIterator<'a, N, I> {
1078 VectorIterator {
1079 ind_data: self.indices.iter().zip(self.data.iter()),
1080 }
1081 }
1082}
1083
1084impl<'a, 'b, N, I, Iptr, IS1, DS1, IpS2, IS2, DS2>
1085 Mul<&'b CsMatBase<N, I, IpS2, IS2, DS2, Iptr>>
1086 for &'a CsVecBase<IS1, DS1, N, I>
1087where
1088 N: 'a + Clone + crate::MulAcc + num_traits::Zero + Default + Send + Sync,
1089 I: 'a + SpIndex,
1090 Iptr: 'a + SpIndex,
1091 IS1: 'a + Deref<Target = [I]>,
1092 DS1: 'a + Deref<Target = [N]>,
1093 IpS2: 'b + Deref<Target = [Iptr]>,
1094 IS2: 'b + Deref<Target = [I]>,
1095 DS2: 'b + Deref<Target = [N]>,
1096{
1097 type Output = CsVecI<N, I>;
1098
1099 fn mul(self, rhs: &CsMatBase<N, I, IpS2, IS2, DS2, Iptr>) -> Self::Output {
1100 (&self.row_view() * rhs).outer_view(0).unwrap().to_owned()
1101 }
1102}
1103
1104impl<N, I, Iptr, IpS1, IS1, DS1, IS2, DS2> Mul<&CsVecBase<IS2, DS2, N, I>>
1105 for &CsMatBase<N, I, IpS1, IS1, DS1, Iptr>
1106where
1107 N: Clone
1108 + crate::MulAcc
1109 + num_traits::Zero
1110 + PartialEq
1111 + Default
1112 + Send
1113 + Sync,
1114 I: SpIndex,
1115 Iptr: SpIndex,
1116 IpS1: Deref<Target = [Iptr]>,
1117 IS1: Deref<Target = [I]>,
1118 DS1: Deref<Target = [N]>,
1119 IS2: Deref<Target = [I]>,
1120 DS2: Deref<Target = [N]>,
1121{
1122 type Output = CsVecI<N, I>;
1123
1124 fn mul(self, rhs: &CsVecBase<IS2, DS2, N, I>) -> Self::Output {
1125 if self.is_csr() {
1126 prod::csr_mul_csvec(self.view(), rhs.view())
1127 } else {
1128 self.mul(&rhs.col_view()).outer_view(0).unwrap().to_owned()
1129 }
1130 }
1131}
1132
1133impl<Lhs, Rhs, Res, I, IS1, DS1, IS2, DS2> Add<CsVecBase<IS2, DS2, Rhs, I>>
1134 for CsVecBase<IS1, DS1, Lhs, I>
1135where
1136 Lhs: Zero,
1137 Rhs: Zero,
1138 for<'r> &'r Lhs: Add<&'r Rhs, Output = Res>,
1139 I: SpIndex,
1140 IS1: Deref<Target = [I]>,
1141 DS1: Deref<Target = [Lhs]>,
1142 IS2: Deref<Target = [I]>,
1143 DS2: Deref<Target = [Rhs]>,
1144{
1145 type Output = CsVecI<Res, I>;
1146
1147 fn add(self, rhs: CsVecBase<IS2, DS2, Rhs, I>) -> Self::Output {
1148 &self + &rhs
1149 }
1150}
1151
1152impl<Lhs, Rhs, Res, I, IS1, DS1, IS2, DS2> Add<&CsVecBase<IS2, DS2, Rhs, I>>
1153 for CsVecBase<IS1, DS1, Lhs, I>
1154where
1155 Lhs: Zero,
1156 Rhs: Zero,
1157 for<'r> &'r Lhs: Add<&'r Rhs, Output = Res>,
1158 I: SpIndex,
1159 IS1: Deref<Target = [I]>,
1160 DS1: Deref<Target = [Lhs]>,
1161 IS2: Deref<Target = [I]>,
1162 DS2: Deref<Target = [Rhs]>,
1163{
1164 type Output = CsVecI<Res, I>;
1165
1166 fn add(self, rhs: &CsVecBase<IS2, DS2, Rhs, I>) -> Self::Output {
1167 &self + rhs
1168 }
1169}
1170
1171impl<Lhs, Rhs, Res, I, IS1, DS1, IS2, DS2> Add<CsVecBase<IS2, DS2, Rhs, I>>
1172 for &CsVecBase<IS1, DS1, Lhs, I>
1173where
1174 Lhs: Zero,
1175 Rhs: Zero,
1176 for<'r> &'r Lhs: Add<&'r Rhs, Output = Res>,
1177 I: SpIndex,
1178 IS1: Deref<Target = [I]>,
1179 DS1: Deref<Target = [Lhs]>,
1180 IS2: Deref<Target = [I]>,
1181 DS2: Deref<Target = [Rhs]>,
1182{
1183 type Output = CsVecI<Res, I>;
1184
1185 fn add(self, rhs: CsVecBase<IS2, DS2, Rhs, I>) -> Self::Output {
1186 self + &rhs
1187 }
1188}
1189
1190impl<Lhs, Rhs, Res, I, IS1, DS1, IS2, DS2> Add<&CsVecBase<IS2, DS2, Rhs, I>>
1191 for &CsVecBase<IS1, DS1, Lhs, I>
1192where
1193 Lhs: Zero,
1194 Rhs: Zero,
1195 for<'r> &'r Lhs: Add<&'r Rhs, Output = Res>,
1196 I: SpIndex,
1197 IS1: Deref<Target = [I]>,
1198 DS1: Deref<Target = [Lhs]>,
1199 IS2: Deref<Target = [I]>,
1200 DS2: Deref<Target = [Rhs]>,
1201{
1202 type Output = CsVecI<Res, I>;
1203
1204 fn add(self, rhs: &CsVecBase<IS2, DS2, Rhs, I>) -> Self::Output {
1205 binop::csvec_binop(self.view(), rhs.view(), |x, y| x + y).unwrap()
1206 }
1207}
1208
1209impl<Lhs, Rhs, Res, I, IS1, DS1, IS2, DS2> Sub<&CsVecBase<IS2, DS2, Rhs, I>>
1210 for &CsVecBase<IS1, DS1, Lhs, I>
1211where
1212 Lhs: Zero,
1213 Rhs: Zero,
1214 for<'r> &'r Lhs: Sub<&'r Rhs, Output = Res>,
1215 I: SpIndex,
1216 IS1: Deref<Target = [I]>,
1217 DS1: Deref<Target = [Lhs]>,
1218 IS2: Deref<Target = [I]>,
1219 DS2: Deref<Target = [Rhs]>,
1220{
1221 type Output = CsVecI<Res, I>;
1222
1223 fn sub(self, rhs: &CsVecBase<IS2, DS2, Rhs, I>) -> Self::Output {
1224 binop::csvec_binop(self.view(), rhs.view(), |x, y| x - y).unwrap()
1225 }
1226}
1227
1228impl<N, I> Neg for CsVecI<N, I>
1229where
1230 N: Clone + Neg<Output = N>,
1231 I: SpIndex,
1232{
1233 type Output = Self;
1234
1235 fn neg(mut self) -> Self::Output {
1236 for value in &mut self.data {
1237 *value = -value.clone();
1238 }
1239 self
1240 }
1241}
1242
1243impl<N, I, IStorage, DStorage> MulAssign<N>
1244 for CsVecBase<IStorage, DStorage, N, I>
1245where
1246 N: Clone + MulAssign<N>,
1247 I: SpIndex,
1248 IStorage: Deref<Target = [I]>,
1249 DStorage: DerefMut<Target = [N]>,
1250{
1251 fn mul_assign(&mut self, rhs: N) {
1252 self.data_mut()
1253 .iter_mut()
1254 .for_each(|v| v.mul_assign(rhs.clone()));
1255 }
1256}
1257
1258impl<N, I, IStorage, DStorage> DivAssign<N>
1259 for CsVecBase<IStorage, DStorage, N, I>
1260where
1261 N: Clone + DivAssign<N>,
1262 I: SpIndex,
1263 IStorage: Deref<Target = [I]>,
1264 DStorage: DerefMut<Target = [N]>,
1265{
1266 fn div_assign(&mut self, rhs: N) {
1267 self.data_mut()
1268 .iter_mut()
1269 .for_each(|v| v.div_assign(rhs.clone()));
1270 }
1271}
1272
1273impl<N, IS, DS> Index<usize> for CsVecBase<IS, DS, N>
1274where
1275 IS: Deref<Target = [usize]>,
1276 DS: Deref<Target = [N]>,
1277{
1278 type Output = N;
1279
1280 fn index(&self, index: usize) -> &N {
1281 self.get(index).unwrap()
1282 }
1283}
1284
1285impl<N, IS, DS> IndexMut<usize> for CsVecBase<IS, DS, N>
1286where
1287 IS: Deref<Target = [usize]>,
1288 DS: DerefMut<Target = [N]>,
1289{
1290 fn index_mut(&mut self, index: usize) -> &mut N {
1291 self.get_mut(index).unwrap()
1292 }
1293}
1294
1295impl<N, IS, DS> Index<NnzIndex> for CsVecBase<IS, DS, N>
1296where
1297 IS: Deref<Target = [usize]>,
1298 DS: Deref<Target = [N]>,
1299{
1300 type Output = N;
1301
1302 fn index(&self, index: NnzIndex) -> &N {
1303 let NnzIndex(i) = index;
1304 self.data().get(i).unwrap()
1305 }
1306}
1307
1308impl<N, IS, DS> IndexMut<NnzIndex> for CsVecBase<IS, DS, N>
1309where
1310 IS: Deref<Target = [usize]>,
1311 DS: DerefMut<Target = [N]>,
1312{
1313 fn index_mut(&mut self, index: NnzIndex) -> &mut N {
1314 let NnzIndex(i) = index;
1315 self.data_mut().get_mut(i).unwrap()
1316 }
1317}
1318
1319impl<N, I> Zero for CsVecI<N, I>
1320where
1321 N: Zero + Clone,
1322 for<'r> &'r N: Add<Output = N>,
1323 I: SpIndex,
1324{
1325 fn zero() -> Self {
1326 Self::new(0, vec![], vec![])
1327 }
1328
1329 fn is_zero(&self) -> bool {
1330 self.data.iter().all(Zero::is_zero)
1331 }
1332}
1333
1334#[cfg(feature = "alga")]
1335mod alga_impls {
1337 use super::*;
1338 use alga::general::*;
1339 use num_traits::Num;
1340
1341 impl<N, I> AbstractMagma<Additive> for CsVecI<N, I>
1342 where
1343 N: Num + Clone,
1344 for<'r> &'r N: Add<Output = N>,
1345 I: SpIndex,
1346 {
1347 fn operate(&self, right: &Self) -> Self {
1348 self + right
1349 }
1350 }
1351
1352 impl<N, I> Identity<Additive> for CsVecI<N, I>
1353 where
1354 N: Num + Clone,
1355 for<'r> &'r N: Add<Output = N>,
1356 I: SpIndex,
1357 {
1358 fn identity() -> Self {
1359 Self::zero()
1360 }
1361 }
1362
1363 impl<N, I> AbstractSemigroup<Additive> for CsVecI<N, I>
1364 where
1365 N: Num + Clone,
1366 for<'r> &'r N: Add<Output = N>,
1367 I: SpIndex,
1368 {
1369 }
1370
1371 impl<N, I> AbstractMonoid<Additive> for CsVecI<N, I>
1372 where
1373 N: Num + Copy,
1374 for<'r> &'r N: Add<Output = N>,
1375 I: SpIndex,
1376 {
1377 }
1378
1379 impl<N, I> TwoSidedInverse<Additive> for CsVecI<N, I>
1380 where
1381 N: Clone + Neg<Output = N> + Num,
1382 I: SpIndex,
1383 {
1384 fn two_sided_inverse(&self) -> Self {
1385 Self::new_trusted(
1386 self.dim,
1387 self.indices.clone(),
1388 self.data.iter().map(|x| -x.clone()).collect(),
1389 )
1390 }
1391 }
1392
1393 impl<N, I> AbstractQuasigroup<Additive> for CsVecI<N, I>
1394 where
1395 N: Num + Clone + Neg<Output = N>,
1396 for<'r> &'r N: Add<Output = N>,
1397 I: SpIndex,
1398 {
1399 }
1400
1401 impl<N, I> AbstractLoop<Additive> for CsVecI<N, I>
1402 where
1403 N: Num + Copy + Neg<Output = N>,
1404 for<'r> &'r N: Add<Output = N>,
1405 I: SpIndex,
1406 {
1407 }
1408
1409 impl<N, I> AbstractGroup<Additive> for CsVecI<N, I>
1410 where
1411 N: Num + Copy + Neg<Output = N>,
1412 for<'r> &'r N: Add<Output = N>,
1413 I: SpIndex,
1414 {
1415 }
1416
1417 impl<N, I> AbstractGroupAbelian<Additive> for CsVecI<N, I>
1418 where
1419 N: Num + Copy + Neg<Output = N>,
1420 for<'r> &'r N: Add<Output = N>,
1421 I: SpIndex,
1422 {
1423 }
1424
1425 #[cfg(test)]
1426 mod test {
1427 use super::*;
1428
1429 #[test]
1430 fn additive_operator_is_addition() {
1431 let a = CsVec::new(2, vec![0], vec![2.]);
1432 let b = CsVec::new(2, vec![0], vec![3.]);
1433 assert_eq!(AbstractMagma::<Additive>::operate(&a, &b), &a + &b);
1434 }
1435
1436 #[test]
1437 fn additive_identity_is_zero() {
1438 assert_eq!(CsVec::<f64>::zero(), Identity::<Additive>::identity());
1439 }
1440
1441 #[test]
1442 fn additive_inverse_is_negated() {
1443 let vector = CsVec::new(2, vec![0], vec![2.]);
1444 assert_eq!(
1445 -vector.clone(),
1446 TwoSidedInverse::<Additive>::two_sided_inverse(&vector)
1447 );
1448 }
1449 }
1450}
1451
1452#[cfg(feature = "approx")]
1453mod approx_impls {
1454 use super::*;
1455 use approx::*;
1456
1457 impl<N, I, IS1, DS1, IS2, DS2> AbsDiffEq<CsVecBase<IS2, DS2, N, I>>
1458 for CsVecBase<IS1, DS1, N, I>
1459 where
1460 I: SpIndex,
1461 CsVecBase<IS1, DS1, N, I>:
1462 std::cmp::PartialEq<CsVecBase<IS2, DS2, N, I>>,
1463 IS1: Deref<Target = [I]>,
1464 IS2: Deref<Target = [I]>,
1465 DS1: Deref<Target = [N]>,
1466 DS2: Deref<Target = [N]>,
1467 N: AbsDiffEq,
1468 N::Epsilon: Clone,
1469 N: num_traits::Zero,
1470 {
1471 type Epsilon = N::Epsilon;
1472 fn default_epsilon() -> N::Epsilon {
1473 N::default_epsilon()
1474 }
1475
1476 fn abs_diff_eq(
1477 &self,
1478 other: &CsVecBase<IS2, DS2, N, I>,
1479 epsilon: N::Epsilon,
1480 ) -> bool {
1481 match (self.dim(), other.dim()) {
1482 (0, _) | (_, 0) => {}
1483 (nx, ny) => {
1484 if nx != ny {
1485 return false;
1486 }
1487 }
1488 }
1489 let zero = N::zero();
1490 self.iter()
1491 .nnz_or_zip(other.iter())
1492 .map(|either| match either {
1493 NnzEither::Both((_, l, r)) => (l, r),
1494 NnzEither::Left((_, l)) => (l, &zero),
1495 NnzEither::Right((_, r)) => (&zero, r),
1496 })
1497 .all(|(v0, v1)| v0.abs_diff_eq(v1, epsilon.clone()))
1498 }
1499 }
1500
1501 impl<N, I, IS1, DS1, IS2, DS2> UlpsEq<CsVecBase<IS2, DS2, N, I>>
1502 for CsVecBase<IS1, DS1, N, I>
1503 where
1504 I: SpIndex,
1505 CsVecBase<IS1, DS1, N, I>:
1506 std::cmp::PartialEq<CsVecBase<IS2, DS2, N, I>>,
1507 IS1: Deref<Target = [I]>,
1508 IS2: Deref<Target = [I]>,
1509 DS1: Deref<Target = [N]>,
1510 DS2: Deref<Target = [N]>,
1511 N: UlpsEq,
1512 N::Epsilon: Clone,
1513 N: num_traits::Zero,
1514 {
1515 fn default_max_ulps() -> u32 {
1516 N::default_max_ulps()
1517 }
1518
1519 fn ulps_eq(
1520 &self,
1521 other: &CsVecBase<IS2, DS2, N, I>,
1522 epsilon: N::Epsilon,
1523 max_ulps: u32,
1524 ) -> bool {
1525 match (self.dim(), other.dim()) {
1526 (0, _) | (_, 0) => {}
1527 (nx, ny) => {
1528 if nx != ny {
1529 return false;
1530 }
1531 }
1532 }
1533 let zero = N::zero();
1534 self.iter()
1535 .nnz_or_zip(other.iter())
1536 .map(|either| match either {
1537 NnzEither::Both((_, l, r)) => (l, r),
1538 NnzEither::Left((_, l)) => (l, &zero),
1539 NnzEither::Right((_, r)) => (&zero, r),
1540 })
1541 .all(|(v0, v1)| v0.ulps_eq(v1, epsilon.clone(), max_ulps))
1542 }
1543 }
1544 impl<N, I, IS1, DS1, IS2, DS2> RelativeEq<CsVecBase<IS2, DS2, N, I>>
1545 for CsVecBase<IS1, DS1, N, I>
1546 where
1547 I: SpIndex,
1548 CsVecBase<IS1, DS1, N, I>:
1549 std::cmp::PartialEq<CsVecBase<IS2, DS2, N, I>>,
1550 IS1: Deref<Target = [I]>,
1551 IS2: Deref<Target = [I]>,
1552 DS1: Deref<Target = [N]>,
1553 DS2: Deref<Target = [N]>,
1554 N: RelativeEq,
1555 N::Epsilon: Clone,
1556 N: num_traits::Zero,
1557 {
1558 fn default_max_relative() -> N::Epsilon {
1559 N::default_max_relative()
1560 }
1561
1562 fn relative_eq(
1563 &self,
1564 other: &CsVecBase<IS2, DS2, N, I>,
1565 epsilon: N::Epsilon,
1566 max_relative: Self::Epsilon,
1567 ) -> bool {
1568 match (self.dim(), other.dim()) {
1569 (0, _) | (_, 0) => {}
1570 (nx, ny) => {
1571 if nx != ny {
1572 return false;
1573 }
1574 }
1575 }
1576 let zero = N::zero();
1577 self.iter()
1578 .nnz_or_zip(other.iter())
1579 .map(|either| match either {
1580 NnzEither::Both((_, l, r)) => (l, r),
1581 NnzEither::Left((_, l)) => (l, &zero),
1582 NnzEither::Right((_, r)) => (&zero, r),
1583 })
1584 .all(|(v0, v1)| {
1585 v0.relative_eq(v1, epsilon.clone(), max_relative.clone())
1586 })
1587 }
1588 }
1589}
1590
1591#[cfg(test)]
1592mod test {
1593 use super::SparseIterTools;
1594 use crate::sparse::{CsVec, CsVecI};
1595 use ndarray::Array;
1596 use num_traits::Zero;
1597
1598 fn test_vec1() -> CsVec<f64> {
1599 let n = 8;
1600 let indices = vec![0, 1, 4, 5, 7];
1601 let data = vec![0., 1., 4., 5., 7.];
1602
1603 return CsVec::new(n, indices, data);
1604 }
1605
1606 fn test_vec2() -> CsVecI<f64, usize> {
1607 let n = 8;
1608 let indices = vec![0, 2, 4, 6, 7];
1609 let data = vec![0.5, 2.5, 4.5, 6.5, 7.5];
1610
1611 return CsVecI::new(n, indices, data);
1612 }
1613
1614 #[test]
1615 fn test_copy() {
1616 let v = test_vec1();
1617 let view1 = v.view();
1618 let view2 = view1; assert_eq!(view1, view2);
1620 }
1621
1622 #[test]
1623 fn test_nnz_zip_iter() {
1624 let vec1 = test_vec1();
1625 let vec2 = test_vec2();
1626 let mut iter = vec1.iter().nnz_zip(vec2.iter());
1627 assert_eq!(iter.next().unwrap(), (0, &0., &0.5));
1628 assert_eq!(iter.next().unwrap(), (4, &4., &4.5));
1629 assert_eq!(iter.next().unwrap(), (7, &7., &7.5));
1630 assert!(iter.next().is_none());
1631 }
1632
1633 #[test]
1634 fn test_nnz_or_zip_iter() {
1635 use super::NnzEither::*;
1636 let vec1 = test_vec1();
1637 let vec2 = test_vec2();
1638 let mut iter = vec1.iter().nnz_or_zip(vec2.iter());
1639 assert_eq!(iter.next().unwrap(), Both((0, &0., &0.5)));
1640 assert_eq!(iter.next().unwrap(), Left((1, &1.)));
1641 assert_eq!(iter.next().unwrap(), Right((2, &2.5)));
1642 assert_eq!(iter.next().unwrap(), Both((4, &4., &4.5)));
1643 assert_eq!(iter.next().unwrap(), Left((5, &5.)));
1644 assert_eq!(iter.next().unwrap(), Right((6, &6.5)));
1645 assert_eq!(iter.next().unwrap(), Both((7, &7., &7.5)));
1646 }
1647
1648 #[test]
1649 fn dot_product() {
1650 let vec1 = CsVec::new(8, vec![0, 2, 4, 6], vec![1.; 4]);
1651 let vec2 = CsVec::new(8, vec![1, 3, 5, 7], vec![2.; 4]);
1652 let vec3 = CsVec::new(8, vec![1, 2, 5, 6], vec![3.; 4]);
1653
1654 assert_eq!(0., vec1.dot(&vec2));
1655 assert_eq!(4., vec1.dot(&vec1));
1656 assert_eq!(16., vec2.dot(&vec2));
1657 assert_eq!(6., vec1.dot(&vec3));
1658 assert_eq!(12., vec2.dot(vec3.view()));
1659
1660 let dense_vec = vec![1., 2., 3., 4., 5., 6., 7., 8.];
1661 {
1662 let slice = &dense_vec[..];
1663 assert_eq!(16., vec1.dot(&dense_vec));
1664 assert_eq!(16., vec1.dot(slice));
1665 assert_eq!(16., vec1.dot_dense(slice));
1666 assert_eq!(16., vec1.dot_dense(&dense_vec));
1667 }
1668 assert_eq!(16., vec1.dot_dense(dense_vec));
1669
1670 let ndarray_vec = Array::linspace(1., 8., 8);
1671 assert_eq!(16., vec1.dot(&ndarray_vec));
1672 assert_eq!(16., vec1.dot_dense(ndarray_vec.view()));
1673 }
1674
1675 #[test]
1676 #[should_panic]
1677 fn dot_product_panics() {
1678 let vec1 = CsVec::new(8, vec![0, 2, 4, 6], vec![1.; 4]);
1679 let vec2 = CsVec::new(9, vec![1, 3, 5, 7], vec![2.; 4]);
1680 vec1.dot(&vec2);
1681 }
1682
1683 #[test]
1684 #[should_panic]
1685 fn dot_product_panics2() {
1686 let vec1 = CsVec::new(8, vec![0, 2, 4, 6], vec![1.; 4]);
1687 let dense_vec = vec![0., 1., 2., 3., 4., 5., 6., 7., 8.];
1688 vec1.dot(&dense_vec);
1689 }
1690
1691 #[test]
1692 fn squared_l2_norm() {
1693 let v = CsVec::new(0, Vec::<usize>::new(), Vec::<i32>::new());
1696 assert_eq!(0, v.squared_l2_norm());
1697
1698 let v = CsVec::new(0, Vec::<usize>::new(), Vec::<f32>::new());
1699 assert_eq!(0., v.squared_l2_norm());
1700
1701 let v = CsVec::new(8, vec![0, 1, 4, 5, 7], vec![0, 1, 4, 5, 7]);
1702 assert_eq!(v.dot(&v), v.squared_l2_norm());
1703
1704 let v = CsVec::new(8, vec![0, 1, 4, 5, 7], vec![0., 1., 4., 5., 7.]);
1705 assert_eq!(v.dot(&v), v.squared_l2_norm());
1706 }
1707
1708 #[test]
1709 fn l2_norm() {
1710 let v = CsVec::new(0, Vec::<usize>::new(), Vec::<f32>::new());
1711 assert_eq!(0., v.l2_norm());
1712
1713 let v = test_vec1();
1714 assert_eq!(v.dot(&v).sqrt(), v.l2_norm());
1715 }
1716
1717 #[test]
1718 fn unit_normalize() {
1719 let mut v = CsVec::new(0, Vec::<usize>::new(), Vec::<f32>::new());
1720 v.unit_normalize();
1721 assert_eq!(0, v.nnz());
1722 assert!(v.indices.is_empty());
1723 assert!(v.data.is_empty());
1724
1725 let mut v = CsVec::new(8, vec![1, 3, 5], vec![0., 0., 0.]);
1726 v.unit_normalize();
1727 assert_eq!(3, v.nnz());
1728 assert!(v.data.iter().all(|x| x.is_zero()));
1729
1730 let mut v =
1731 CsVec::new(8, vec![0, 1, 4, 5, 7], vec![0., 1., 4., 5., 7.]);
1732 v.unit_normalize();
1733 let norm = (1f32 + 4. * 4. + 5. * 5. + 7. * 7.).sqrt();
1734 assert_eq!(
1735 vec![0., 1. / norm, 4. / norm, 5. / norm, 7. / norm],
1736 v.data
1737 );
1738 assert!((v.l2_norm() - 1.).abs() < 1e-5);
1739 }
1740
1741 #[test]
1742 fn l1_norm() {
1743 let v = CsVec::new(0, Vec::<usize>::new(), Vec::<f32>::new());
1744 assert_eq!(0., v.l1_norm());
1745
1746 let v = CsVec::new(8, vec![0, 1, 4, 5, 7], vec![0, -1, 4, -5, 7]);
1747 assert_eq!(1 + 4 + 5 + 7, v.l1_norm());
1748 }
1749
1750 #[test]
1751 fn norm() {
1752 let v = CsVec::new(0, Vec::<usize>::new(), Vec::<f32>::new());
1753 assert_eq!(0., v.norm(std::f32::INFINITY)); assert_eq!(0., v.norm(0.));
1755 assert_eq!(0., v.norm(5.));
1756
1757 let v = CsVec::new(8, vec![0, 1, 4, 5, 7], vec![0., 1., -4., 5., -7.]);
1758 assert_eq!(7., v.norm(std::f32::INFINITY));
1759 assert_eq!(0., v.norm(std::f32::NEG_INFINITY));
1760 assert_eq!(4., v.norm(0.));
1761
1762 let diff = v.l1_norm() - v.norm(1.0);
1763 assert!(diff.abs() < 1e-4);
1764 let diff = v.l2_norm() - v.norm(2.0);
1765 assert!(diff.abs() < 1e-4);
1766 }
1767
1768 #[test]
1769 fn nnz_index() {
1770 let vec = CsVec::new(8, vec![0, 2, 4, 6], vec![1.; 4]);
1771 assert_eq!(vec.nnz_index(1), None);
1772 assert_eq!(vec.nnz_index(9), None);
1773 assert_eq!(vec.nnz_index(0), Some(super::NnzIndex(0)));
1774 assert_eq!(vec.nnz_index(4), Some(super::NnzIndex(2)));
1775
1776 let index = vec.nnz_index(2).unwrap();
1777
1778 assert_eq!(vec[index], 1.);
1779 let mut vec = vec;
1780 vec[index] = 2.;
1781 assert_eq!(vec[index], 2.);
1782 }
1783
1784 #[test]
1785 fn get_mut() {
1786 let mut vec = CsVec::new(8, vec![0, 2, 4, 6], vec![1.; 4]);
1787
1788 *vec.get_mut(4).unwrap() = 2.;
1789
1790 let expected = CsVec::new(8, vec![0, 2, 4, 6], vec![1., 1., 2., 1.]);
1791
1792 assert_eq!(vec, expected);
1793
1794 vec[6] = 3.;
1795
1796 let expected = CsVec::new(8, vec![0, 2, 4, 6], vec![1., 1., 2., 3.]);
1797
1798 assert_eq!(vec, expected);
1799 }
1800
1801 #[test]
1802 fn indexing() {
1803 let vec = CsVec::new(8, vec![0, 2, 4, 6], vec![1., 2., 3., 4.]);
1804 assert_eq!(vec[0], 1.);
1805 assert_eq!(vec[2], 2.);
1806 assert_eq!(vec[4], 3.);
1807 assert_eq!(vec[6], 4.);
1808 }
1809
1810 #[test]
1811 fn map_inplace() {
1812 let mut vec = CsVec::new(8, vec![0, 2, 4, 6], vec![1., 2., 3., 4.]);
1813 vec.map_inplace(|&x| x + 1.);
1814 let expected = CsVec::new(8, vec![0, 2, 4, 6], vec![2., 3., 4., 5.]);
1815 assert_eq!(vec, expected);
1816 }
1817
1818 #[test]
1819 fn map() {
1820 let vec = CsVec::new(8, vec![0, 2, 4, 6], vec![1., 2., 3., 4.]);
1821 let res = vec.map(|&x| x * 2.);
1822 let expected = CsVec::new(8, vec![0, 2, 4, 6], vec![2., 4., 6., 8.]);
1823 assert_eq!(res, expected);
1824 }
1825
1826 #[test]
1827 fn iter_mut() {
1828 let mut vec = CsVec::new(8, vec![0, 2, 4, 6], vec![1., 2., 3., 4.]);
1829 for (ind, val) in vec.iter_mut() {
1830 if ind == 2 {
1831 *val += 1.;
1832 } else {
1833 *val *= 2.;
1834 }
1835 }
1836 let expected = CsVec::new(8, vec![0, 2, 4, 6], vec![2., 3., 6., 8.]);
1837 assert_eq!(vec, expected);
1838 }
1839
1840 #[test]
1841 fn adds_vectors_by_value() {
1842 let (a, b, expected_sum) = addition_sample();
1843 assert_eq!(expected_sum, a + b);
1844 }
1845
1846 #[test]
1847 fn adds_vectors_by_left_value_and_right_reference() {
1848 let (a, b, expected_sum) = addition_sample();
1849 assert_eq!(expected_sum, a + &b);
1850 }
1851
1852 #[test]
1853 fn adds_vectors_by_left_reference_and_right_value() {
1854 let (a, b, expected_sum) = addition_sample();
1855 assert_eq!(expected_sum, &a + b);
1856 }
1857
1858 #[test]
1859 fn adds_vectors_by_reference() {
1860 let (a, b, expected_sum) = addition_sample();
1861 assert_eq!(expected_sum, &a + &b);
1862 }
1863
1864 fn addition_sample() -> (CsVec<f64>, CsVec<f64>, CsVec<f64>) {
1865 let dim = 8;
1866 let a = CsVec::new(dim, vec![0, 3, 5, 7], vec![2., -3., 7., -1.]);
1867 let b = CsVec::new(dim, vec![1, 3, 4, 5], vec![4., 2., -3., 1.]);
1868 let expected_sum = CsVec::new(
1869 dim,
1870 vec![0, 1, 3, 4, 5, 7],
1871 vec![2., 4., -1., -3., 8., -1.],
1872 );
1873 (a, b, expected_sum)
1874 }
1875
1876 #[test]
1877 fn negates_vectors() {
1878 let vector = CsVec::new(4, vec![0, 3], vec![2., -3.]);
1879 let negated = CsVec::new(4, vec![0, 3], vec![-2., 3.]);
1880 assert_eq!(-vector, negated);
1881 }
1882
1883 #[test]
1884 fn can_construct_zero_sized_vectors() {
1885 CsVec::<f64>::new(0, vec![], vec![]);
1886 }
1887
1888 #[test]
1889 fn zero_element_vanishes_when_added() {
1890 let zero = CsVec::<f64>::zero();
1891 let vector = CsVec::new(3, vec![0, 2], vec![1., 2.]);
1892 assert_eq!(&vector + &zero, vector);
1893 }
1894
1895 #[test]
1896 fn zero_element_is_identified_as_zero() {
1897 assert!(CsVec::<f32>::zero().is_zero());
1898 }
1899
1900 #[test]
1901 fn larger_zero_vector_is_identified_as_zero() {
1902 let vector = CsVec::new(3, vec![1, 2], vec![0., 0.]);
1903 assert!(vector.is_zero());
1904 }
1905
1906 #[test]
1907 fn mul_assign() {
1908 let mut vector = CsVec::new(4, vec![1, 2, 3], vec![1_i32, 3, 4]);
1909 vector *= 2;
1910 assert_eq!(vector, CsVec::new(4, vec![1, 2, 3], vec![2_i32, 6, 8]));
1911 }
1912
1913 #[test]
1914 fn div_assign() {
1915 let mut vector = CsVec::new(4, vec![1, 2, 3], vec![1_i32, 3, 4]);
1916 vector /= 2;
1917 assert_eq!(vector, CsVec::new(4, vec![1, 2, 3], vec![0_i32, 1, 2]));
1918 }
1919
1920 #[test]
1921 fn scatter() {
1922 let vector = CsVec::new(4, vec![1, 2, 3], vec![1_i32, 3, 4]);
1923 let mut res = vec![0; 4];
1924 vector.scatter(&mut res);
1925 assert_eq!(res, &[0, 1, 3, 4]);
1926 let mut res = Array::zeros(4);
1927 vector.scatter(&mut res);
1928 assert_eq!(res, ndarray::arr1(&[0, 1, 3, 4]));
1929 let res: &mut [i32] = &mut [0; 4];
1930 vector.scatter(res);
1931 assert_eq!(res, &[0, 1, 3, 4]);
1932 }
1933
1934 #[test]
1935 fn add_sub_complex() {
1936 use num_complex::Complex32;
1937 let vector = CsVec::new(
1938 4,
1939 vec![1, 2, 3],
1940 vec![
1941 Complex32::new(0., 1.),
1942 Complex32::new(3., 1.),
1943 Complex32::new(4., 0.),
1944 ],
1945 );
1946 let doubled = &vector + &vector;
1947 let expected = CsVec::new(
1948 4,
1949 vec![1, 2, 3],
1950 vec![
1951 Complex32::new(0., 2.),
1952 Complex32::new(6., 2.),
1953 Complex32::new(8., 0.),
1954 ],
1955 );
1956 assert_eq!(doubled, expected);
1957 let subtracted = &doubled - &vector;
1958 assert_eq!(subtracted, vector);
1959 }
1960
1961 #[cfg(feature = "approx")]
1962 mod approx {
1963 use crate::*;
1964
1965 #[test]
1966 fn approx_abs_diff_eq() {
1967 let v1 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 3]);
1968 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 3]);
1969 ::approx::assert_abs_diff_eq!(v1, v2);
1970
1971 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 4]);
1972 ::approx::assert_abs_diff_eq!(v1, v2, epsilon = 1);
1973 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 4]);
1974 ::approx::assert_abs_diff_ne!(v1, v2, epsilon = 0);
1975
1976 let v1 = CsVec::new(5, vec![0, 2, 4], vec![1.0_f32, 2.0, 3.0]);
1977 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1.0_f32, 2.0, 3.0]);
1978 ::approx::assert_abs_diff_eq!(v1, v2);
1979 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1.0_f32, 2.0, 3.1]);
1980 ::approx::assert_abs_diff_ne!(v1, v2);
1981
1982 let v1 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 3]);
1983 let v2 = CsVec::new(5, vec![0, 3, 4], vec![1_u8, 2, 3]);
1984 ::approx::assert_abs_diff_ne!(v1, v2);
1985
1986 let v1 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 3]);
1987 let v2 = CsVec::new(6, vec![0, 2, 4], vec![1_u8, 2, 3]);
1988 ::approx::assert_abs_diff_ne!(v1, v2);
1989
1990 let v2 = CsVec::new(0, vec![], vec![]);
1992 ::approx::assert_abs_diff_ne!(v1, v2);
1993 }
1994
1995 #[test]
1996 fn approx_view() {
1998 let v1 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 3]);
1999 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1_u8, 2, 3]);
2000 ::approx::assert_abs_diff_eq!(v1, v2);
2001 ::approx::assert_abs_diff_eq!(v1.view(), v2.view());
2002
2003 let v1 = CsVec::new(5, vec![0, 2, 4], vec![1.0_f32, 2.0, 3.0]);
2004 let v2 = CsVec::new(5, vec![0, 2, 4], vec![1.0_f32, 2.0, 3.0]);
2005 ::approx::assert_abs_diff_eq!(v1, v2);
2006 ::approx::assert_abs_diff_eq!(v1.view(), v2.view());
2007 }
2008 }
2009}