sprs_rssn/sparse/
vec.rs

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;
9/// A sparse vector, which can be extracted from a sparse matrix
10///
11/// # Example
12/// ```rust
13/// use sprs::CsVec;
14/// let vec1 = CsVec::new(8, vec![0, 2, 5, 6], vec![1.; 4]);
15/// let vec2 = CsVec::new(8, vec![1, 3, 5], vec![2.; 3]);
16/// let res = &vec1 + &vec2;
17/// let mut iter = res.iter();
18/// assert_eq!(iter.next(), Some((0, &1.)));
19/// assert_eq!(iter.next(), Some((1, &2.)));
20/// assert_eq!(iter.next(), Some((2, &1.)));
21/// assert_eq!(iter.next(), Some((3, &2.)));
22/// assert_eq!(iter.next(), Some((5, &3.)));
23/// assert_eq!(iter.next(), Some((6, &1.)));
24/// assert_eq!(iter.next(), None);
25/// ```
26use 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)]
45/// Hold the index of a non-zero element in the compressed storage
46///
47/// An `NnzIndex` can be used to later access the non-zero element in constant
48/// time.
49pub struct NnzIndex(pub usize);
50
51/// A trait to represent types which can be interpreted as vectors
52/// of a given dimension.
53pub trait VecDim<N> {
54    /// The dimension of the vector
55    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/// An iterator over the non-zero elements of a sparse vector
76#[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
86/// An iterator over the mutable non-zero elements of a sparse vector
87pub 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    /// Iterate over non-zero elements of either of two vectors.
138    /// This is useful for implementing eg addition of vectors.
139    ///
140    /// # Example
141    ///
142    /// ```rust
143    /// use sprs::CsVec;
144    /// use sprs::vec::NnzEither;
145    /// use sprs::vec::SparseIterTools;
146    /// let v0 = CsVec::new(5, vec![0, 2, 4], vec![1., 2., 3.]);
147    /// let v1 = CsVec::new(5, vec![1, 2, 3], vec![-1., -2., -3.]);
148    /// let mut nnz_or_iter = v0.iter().nnz_or_zip(v1.iter());
149    /// assert_eq!(nnz_or_iter.next(), Some(NnzEither::Left((0, &1.))));
150    /// assert_eq!(nnz_or_iter.next(), Some(NnzEither::Right((1, &-1.))));
151    /// assert_eq!(nnz_or_iter.next(), Some(NnzEither::Both((2, &2., &-2.))));
152    /// assert_eq!(nnz_or_iter.next(), Some(NnzEither::Right((3, &-3.))));
153    /// assert_eq!(nnz_or_iter.next(), Some(NnzEither::Left((4, &3.))));
154    /// assert_eq!(nnz_or_iter.next(), None);
155    /// ```
156    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    /// Iterate over the matching non-zero elements of both vectors
172    /// Useful for vector dot product.
173    ///
174    /// # Example
175    ///
176    /// ```rust
177    /// use sprs::CsVec;
178    /// use sprs::vec::SparseIterTools;
179    /// let v0 = CsVec::new(5, vec![0, 2, 4], vec![1., 2., 3.]);
180    /// let v1 = CsVec::new(5, vec![1, 2, 3], vec![-1., -2., -3.]);
181    /// let mut nnz_zip = v0.iter().nnz_zip(v1.iter());
182    /// assert_eq!(nnz_zip.next(), Some((2, &2., &-2.)));
183    /// assert_eq!(nnz_zip.next(), None);
184    /// ```
185    #[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
210/// Trait for types that can be iterated as sparse vectors
211pub trait IntoSparseVecIter<'a, N: 'a> {
212    type IterType;
213
214    /// Transform self into an iterator that yields (usize, &N) tuples
215    /// where the usize is the index of the value in the sparse vector.
216    /// The indices should be sorted.
217    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    /// The dimension of the vector
225    fn dim(&self) -> usize;
226
227    /// Indicator to check whether the vector is actually dense
228    fn is_dense(&self) -> bool {
229        false
230    }
231
232    /// Random access to an element in the vector.
233    ///
234    /// # Panics
235    ///
236    /// - if the vector is not dense
237    /// - if the index is out of bounds
238    #[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    // FIXME we want
285    // type IterType = impl Iterator<Item=(usize, &'a N)>
286    #[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        // FIXME since it's not possible to have an existential type as an
295        // associated type yet, I'm using a trick to send the necessary
296        // context to a plain function, which enables specifying the type
297        // Needless to say, this needs to go when it's no longer necessary
298        #[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
326/// An iterator over the non zeros of either of two vector iterators, ordered,
327/// such that the sum of the vectors may be computed
328pub 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
406/// # Constructor methods
407impl<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    /// Create a sparse vector
413    ///
414    /// # Panics
415    ///
416    /// - if `indices` and `data` lengths differ
417    /// - if the vector contains out of bounds indices
418    /// - if indices are out of order
419    ///
420    /// # Examples
421    /// ```rust
422    /// # use sprs::*;
423    /// // Creating a sparse owned vector
424    /// let owned = CsVec::new(10, vec![0, 4], vec![-4, 2]);
425    /// // Creating a sparse borrowing vector with `I = u16`
426    /// let borrow = CsVecViewI::new(10, &[0_u16, 4], &[-4, 2]);
427    /// // Creating a general sparse vector with different storage types
428    /// let mixed = CsVecBase::new(10, &[0_u64, 4] as &[_], vec![-4, 2]);
429    /// ```
430    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    /// Try create a sparse vector from the given buffers
437    ///
438    /// Will return the buffers along with the error if
439    /// conversion is illegal
440    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    /// Internal version of `new_unchecked` where we guarantee the invariants
494    /// ourselves
495    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    /// Create a `CsVec` without checking the structure
508    ///
509    /// # Safety
510    ///
511    /// This is unsafe because algorithms are free to assume
512    /// that properties guaranteed by [`check_structure`](CsVecBase::check_structure) are enforced.
513    /// For instance, non out-of-bounds indices can be relied upon to
514    /// perform unchecked slice access.
515    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    /// Creates a sparse vector
534    ///
535    /// Will sort indices and data if necessary
536    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
560/// # Methods operating on owning sparse vectors
561impl<N, I: SpIndex> CsVecI<N, I> {
562    /// Create an empty `CsVec`, which can be used for incremental construction
563    pub fn empty(dim: usize) -> Self {
564        Self::new_trusted(dim, vec![], vec![])
565    }
566
567    /// Append an element to the sparse vector. Used for incremental
568    /// building of the `CsVec`. The append should preserve the structure
569    /// of the vector, ie the newly added index should be strictly greater
570    /// than the last element of indices.
571    ///
572    /// # Panics
573    ///
574    /// - Panics if `ind` is lower or equal to the last
575    ///   element of `self.indices()`
576    /// - Panics if `ind` is greater than `self.dim()`
577    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    /// Reserve `size` additional non-zero values.
590    pub fn reserve(&mut self, size: usize) {
591        self.indices.reserve(size);
592        self.data.reserve(size);
593    }
594
595    /// Reserve exactly `exact_size` non-zero values.
596    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    /// Clear the underlying storage
602    pub fn clear(&mut self) {
603        self.indices.clear();
604        self.data.clear();
605    }
606}
607
608/// # Common methods of sparse vectors
609impl<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    /// Get a view of this vector.
616    pub fn view(&self) -> CsVecViewI<'_, N, I> {
617        CsVecViewI::new_trusted(self.dim, &self.indices[..], &self.data)
618    }
619
620    /// Convert the sparse vector to a dense one
621    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    /// Iterate over the non zero values.
631    ///
632    /// # Example
633    ///
634    /// ```rust
635    /// use sprs::CsVec;
636    /// let v = CsVec::new(5, vec![0, 2, 4], vec![1., 2., 3.]);
637    /// let mut iter = v.iter();
638    /// assert_eq!(iter.next(), Some((0, &1.)));
639    /// assert_eq!(iter.next(), Some((2, &2.)));
640    /// assert_eq!(iter.next(), Some((4, &3.)));
641    /// assert_eq!(iter.next(), None);
642    /// ```
643    pub fn iter(&self) -> VectorIterator<'_, N, I> {
644        VectorIterator {
645            ind_data: self.indices.iter().zip(self.data.iter()),
646        }
647    }
648
649    /// Permuted iteration. Not finished
650    #[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    /// The underlying indices.
665    pub fn indices(&self) -> &[I] {
666        &self.indices
667    }
668
669    /// The underlying non zero values.
670    pub fn data(&self) -> &[N] {
671        &self.data
672    }
673
674    /// Destruct the vector object and recycle its storage containers.
675    pub fn into_raw_storage(self) -> (IStorage, DStorage) {
676        let Self { indices, data, .. } = self;
677        (indices, data)
678    }
679
680    /// The dimension of this vector.
681    pub fn dim(&self) -> usize {
682        self.dim
683    }
684
685    /// The non zero count of this vector.
686    pub fn nnz(&self) -> usize {
687        self.data.len()
688    }
689
690    /// Check the sparse structure, namely that:
691    /// - indices are sorted
692    /// - all indices are less than `dims()`
693    pub fn check_structure(&self) -> Result<(), StructureError> {
694        // Make sure indices can be converted to usize
695        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    /// Allocate a new vector equal to this one.
720    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    /// Clone the vector with another integer type for its indices
728    ///
729    /// # Panics
730    ///
731    /// If the indices cannot be represented by the requested integer type.
732    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    /// View this vector as a matrix with only one row.
747    pub fn row_view<Iptr: SpIndex>(&self) -> CsMatVecView_<'_, N, I, Iptr> {
748        // Safe because we're taking a view into a vector that has
749        // necessarily been checked
750        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    /// View this vector as a matrix with only one column.
767    pub fn col_view<Iptr: SpIndex>(&self) -> CsMatVecView_<'_, N, I, Iptr> {
768        // Safe because we're taking a view into a vector that has
769        // necessarily been checked
770        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    /// Access element at given index, with logarithmic complexity
787    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    /// Find the non-zero index of the requested dimension index,
795    /// returning None if no non-zero is present at the requested location.
796    ///
797    /// Looking for the `NnzIndex` is done with logarithmic complexity, but
798    /// once it is available, the `NnzIndex` enables retrieving the data with
799    /// O(1) complexity.
800    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    /// Sparse vector dot product. The right-hand-side can be any type
808    /// that can be interpreted as a sparse vector (hence sparse vectors, std
809    /// vectors and slices, and ndarray's dense vectors work).
810    ///
811    /// However, even if dense vectors work, it is more performant to use
812    /// the [`dot_dense`](struct.CsVecBase.html#method.dot_dense).
813    ///
814    /// # Panics
815    ///
816    /// If the dimension of the vectors do not match.
817    ///
818    /// # Example
819    ///
820    /// ```rust
821    /// use sprs::CsVec;
822    /// let v1 = CsVec::new(8, vec![1, 2, 4, 6], vec![1.; 4]);
823    /// let v2 = CsVec::new(8, vec![1, 3, 5, 7], vec![2.; 4]);
824    /// assert_eq!(2., v1.dot(&v2));
825    /// assert_eq!(4., v1.dot(&v1));
826    /// assert_eq!(16., v2.dot(&v2));
827    /// ```
828    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, // T is supposed to be a reference type
836    {
837        self.dot_acc(rhs)
838    }
839
840    /// Sparse vector dot product into accumulator.
841    ///
842    /// The right-hand-side can be any type
843    /// that can be interpreted as a sparse vector (hence sparse vectors, std
844    /// vectors and slices, and ndarray's dense vectors work).
845    /// The output type can be any type supporting `MulAcc`.
846    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, // T is supposed to be a reference type
854    {
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    /// Sparse-dense vector dot product. The right-hand-side can be any type
884    /// that can be interpreted as a dense vector (hence std vectors and
885    /// slices, and ndarray's dense vectors work).
886    ///
887    /// Since the `dot` method can work with the same performance on
888    /// dot vectors, the main interest of this method is to enforce at
889    /// compile time that the rhs is dense.
890    ///
891    /// # Panics
892    ///
893    /// If the dimension of the vectors do not match.
894    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    /// Compute the squared L2-norm.
907    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    /// Compute the L2-norm.
916    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    /// Compute the L1-norm.
925    pub fn l1_norm(&self) -> N
926    where
927        N: Signed + Sum,
928    {
929        self.data.iter().map(Signed::abs).sum()
930    }
931
932    /// Compute the vector norm for the given order p.
933    ///
934    /// The norm for vector v is defined as:
935    /// - If p = ∞: maxᵢ |vᵢ|
936    /// - If p = -∞: minᵢ |vᵢ|
937    /// - If p = 0: ∑ᵢ[vᵢ≠0]
938    /// - Otherwise: ᵖ√(∑ᵢ|vᵢ|ᵖ)
939    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    /// Fill a dense vector with our values
961    // FIXME I'm uneasy with this &mut V, can't I get rid of it with more
962    // trait magic? I would probably need to define what a mutable view is...
963    // But it's valuable. But I cannot find a way with the current trait system.
964    // Would probably require something link existential lifetimes.
965    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    /// Transform this vector into a set of (index, value) tuples
976    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    /// Apply a function to each non-zero element, yielding a new matrix
988    /// with the same sparsity structure.
989    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
1000/// # Methods on sparse vectors with mutable access to their data
1001impl<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    /// The underlying non zero values as a mutable slice.
1008    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    /// Access element at given index, with logarithmic complexity
1021    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    /// Apply a function to each non-zero element, mutating it
1030    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    /// Mutable iteration over the non-zero values of a sparse vector
1040    ///
1041    /// Only the values can be changed, the sparse structure is kept.
1042    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    /// Divides the vector by its own L2-norm.
1049    ///
1050    /// Zero vector is left unchanged.
1051    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
1064/// # Methods propagating the lifetime of a `CsVecViewI`.
1065impl<'a, N: 'a, I: 'a + SpIndex> CsVecViewI<'a, N, I> {
1066    /// Access element at given index, with logarithmic complexity
1067    ///
1068    /// Re-borrowing version of `at()`.
1069    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    /// Re-borrowing version of `iter()`. Namely, the iterator's lifetime
1075    /// will be bound to the lifetime of the underlying slices instead
1076    /// of being bound to the lifetime of the borrow.
1077    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")]
1335/// These traits requires the `alga` feature to be activated
1336mod 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; // this shouldn't move
1619        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        // Should work with both float and integer data
1694
1695        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)); // Here we choose the same behavior as Eigen
1754        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            // Zero sized vector
1991            let v2 = CsVec::new(0, vec![], vec![]);
1992            ::approx::assert_abs_diff_ne!(v1, v2);
1993        }
1994
1995        #[test]
1996        /// Testing if views can be compared
1997        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}