sparse_bin_mat/
error.rs

1//! Error types for matrix and vector operations.
2//!
3//! This contains two kind of errors.
4//! [`InvalidPositions`](InvalidPositions) represents errors
5//! when building a vector or matrix with invalid positions.
6//! [`IncompatibleDimensions`](IncompatibleDimensions) represents errors
7//! when two objects have incompatible dimensions for a given operations
8//! such as addition or multiplication.
9
10use is_sorted::IsSorted;
11use itertools::Itertools;
12use std::fmt;
13
14/// An error to represent invalid positions in a vector or matrix.
15#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
16pub enum InvalidPositions {
17    Unsorted,
18    OutOfBound,
19    Duplicated,
20}
21
22impl fmt::Display for InvalidPositions {
23    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24        match self {
25            InvalidPositions::Unsorted => "some positions are not sorted".fmt(f),
26            InvalidPositions::OutOfBound => "some positions are out of bound".fmt(f),
27            InvalidPositions::Duplicated => "some positions are duplicated".fmt(f),
28        }
29    }
30}
31
32impl std::error::Error for InvalidPositions {}
33
34pub(crate) fn validate_positions(
35    length: usize,
36    positions: &[usize],
37) -> Result<(), InvalidPositions> {
38    for position in positions.iter() {
39        if *position >= length {
40            return Result::Err(InvalidPositions::OutOfBound);
41        }
42    }
43    if !IsSorted::is_sorted(&mut positions.iter()) {
44        return Result::Err(InvalidPositions::Unsorted);
45    }
46    if positions.iter().unique().count() != positions.len() {
47        return Result::Err(InvalidPositions::Duplicated);
48    }
49    Ok(())
50}
51
52/// An error to represent incompatible dimensions
53/// in matrix and vector operations.
54#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
55pub struct IncompatibleDimensions<DL, DR> {
56    left_dimensions: DL,
57    right_dimensions: DR,
58}
59
60impl<DL, DR> IncompatibleDimensions<DL, DR> {
61    pub fn new(left_dimensions: DL, right_dimensions: DR) -> Self {
62        Self {
63            left_dimensions,
64            right_dimensions,
65        }
66    }
67}
68
69pub type VecVecIncompatibleDimensions = IncompatibleDimensions<usize, usize>;
70pub type MatVecIncompatibleDimensions = IncompatibleDimensions<(usize, usize), usize>;
71pub type VecMatIncompatibleDimensions = IncompatibleDimensions<usize, (usize, usize)>;
72pub type MatMatIncompatibleDimensions = IncompatibleDimensions<(usize, usize), (usize, usize)>;
73
74macro_rules! impl_dim_error {
75    ($dl:ty, $dr:ty) => {
76        impl fmt::Display for IncompatibleDimensions<$dl, $dr> {
77            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78                format!(
79                    "incompatible dimensions {:?} and {:?}",
80                    self.left_dimensions, self.right_dimensions
81                )
82                .fmt(f)
83            }
84        }
85
86        impl std::error::Error for IncompatibleDimensions<$dl, $dr> {}
87    };
88}
89
90impl_dim_error!(usize, usize); // Vec - Vec
91impl_dim_error!((usize, usize), usize); // Mat - Vec
92impl_dim_error!(usize, (usize, usize)); // Vec - Mat
93impl_dim_error!((usize, usize), (usize, usize)); // Mat - Mat