sparsemat/
sparsemat_par.rs

1use std::cmp::min;
2use std::cmp::max;
3//use std::thread;
4//use std::sync::Arc;
5//use std::sync::mpsc;
6//use crate::vector::Vector;
7//use crate::types::{IndexType, ValueType};
8use crate::sparsematrix::SparseMatrix;
9
10// A sparse matrix implementation used for parallel operations
11#[derive(Clone, Debug)]
12pub struct SparseMatPar<M> {
13    n_rows_sub_matrix: usize,
14    n_blocks: usize,
15    sub_matrices: Vec<M>,
16}
17 
18impl<'a, M> SparseMatPar<M>
19where M: SparseMatrix<'a> {
20    pub fn with_sub_matrices(n_blocks: usize, max_n_rows: usize) -> Self {
21        let n_rows_sub_matrix = max_n_rows / n_blocks;
22        let sub_matrices = vec![M::with_capacity(n_rows_sub_matrix); n_blocks];
23        Self {
24            n_rows_sub_matrix: n_rows_sub_matrix,
25            n_blocks: n_blocks,
26            sub_matrices: sub_matrices,
27        }
28    }
29
30    // Returns the index of the submatrix and the actual row index
31    fn get_block_and_row_id(&self, row: usize) -> (usize, usize) {
32        let block_id = min(row / self.n_rows_sub_matrix, self.n_blocks);
33        let row_id = row - block_id * self.n_rows_sub_matrix;
34        (block_id, row_id)
35    }
36
37    // TODO
38    /*
39    pub fn mvp_par<V>(&'a self, rhs: &V) -> V
40    where V: Vector<'a, Value = M::Value> + Send + Sync,
41          M: Send + Sync {
42        let arc = Arc::new(rhs);
43        let (tx, rx) = mpsc::channel();
44        for b in 0..self.n_blocks {
45            let rhs = arc.clone();
46            let mat = &self.sub_matrices[b];
47            let tx = tx.clone();
48            let mut v = V::with_capacity(self.n_rows_sub_matrix);
49            thread::spawn(move || {
50                for i in 0..mat.n_rows() {
51                    let mut sum = M::Value::zero();
52                    for (&col, &val) in mat.iter_row(i) {
53                        let j = col.as_usize();
54                        sum += rhs.get(j) * val;
55                    }
56                    v.set(i, sum);
57                }
58                tx.send((b, v)).unwrap();
59            });
60        }
61        let mut ret = V::with_capacity(self.n_rows());
62        for _ in 0..self.n_blocks {
63            let (b, v) = rx.recv().unwrap();
64            let offset = b * self.n_rows_sub_matrix;
65        }
66        ret
67    }
68    */
69}
70
71impl<'a, M> SparseMatrix<'a> for SparseMatPar<M>
72where M: 'a + SparseMatrix<'a> {
73    type Value = M::Value;
74    type Index = M::Index;
75    //type Iter = Iter<'a, M>;
76    type IterRow = M::IterRow;
77
78    //fn iter(&'a self) -> Self::Iter {
79    //    Iter {
80    //        mat: &self,
81    //        block_id: 0,
82    //        iter: self.sub_matrices[0].iter(),
83    //    }
84    //}
85
86    fn iter_row(&'a self, row: usize) -> Self::IterRow {
87        let (block_id, row_id) = self.get_block_and_row_id(row);
88        self.sub_matrices[block_id].iter_row(row_id)
89    }
90    
91    fn with_capacity(cap: usize) -> Self {
92        Self::with_sub_matrices(4, cap)
93    }
94
95    fn n_rows(&self) -> usize {
96        let mut last = 0;
97        // Find the last non-empty sub matrix
98        for b in 0..self.sub_matrices.len() {
99            if self.sub_matrices[b].empty() {
100                break;
101            }
102            last = b;
103        }
104        // The number of rows equals the number of rows in the last non-empty sub matrix
105        // plus the number of rows of all preceding sub matrices
106        last * self.n_rows_sub_matrix + self.sub_matrices[last].n_rows()
107    }
108
109    fn n_cols(&self) -> usize {
110        let mut ret = 0;
111        for mat in &self.sub_matrices {
112            ret = max(mat.n_cols(), ret);
113        }
114        ret
115    }
116    
117    fn n_non_zero_entries(&self) -> usize {
118        let mut ret = 0;
119        for mat in &self.sub_matrices {
120            ret += mat.n_non_zero_entries();
121        }
122        ret
123    }
124
125    fn get(&self, i: usize, j: usize) -> Self::Value {
126        let (block_id, row_id) = self.get_block_and_row_id(i);
127        self.sub_matrices[block_id].get(row_id, j)
128    }
129
130    fn get_mut(&mut self, i: usize, j: usize) -> &mut Self::Value {
131        let (block_id, row_id) = self.get_block_and_row_id(i);
132        self.sub_matrices[block_id].get_mut(row_id, j)
133    }
134
135    fn scale(&mut self, rhs: Self::Value) {
136        for mat in &mut self.sub_matrices {
137            mat.scale(rhs);
138        }
139    }
140}