IVSparse  v1.0
A sparse matrix compression library.
VCSC_Operators.hpp
1 
9 #pragma once
10 
11 namespace IVSparse
12 {
13 
14  // Assignment Operator
15  template <typename T, typename indexT, bool columnMajor>
16  SparseMatrix<T, indexT, 2, columnMajor> &SparseMatrix<T, indexT, 2, columnMajor>::operator=(const IVSparse::SparseMatrix<T, indexT, 2, columnMajor> &other)
17  {
18 
19  // check if the matrices are the same
20  if (this != &other)
21  {
22 
23  // free the old data
24  if (values != nullptr)
25  {
26  for (uint32_t i = 0; i < outerDim; i++)
27  {
28  if (values[i] != nullptr)
29  free(values[i]);
30  }
31  free(values);
32  }
33  if (counts != nullptr)
34  {
35  for (uint32_t i = 0; i < outerDim; i++)
36  {
37  if (counts[i] != nullptr)
38  free(counts[i]);
39  }
40  free(counts);
41  }
42  if (indices != nullptr)
43  {
44  for (uint32_t i = 0; i < outerDim; i++)
45  {
46  if (indices[i] != nullptr)
47  free(indices[i]);
48  }
49  free(indices);
50  }
51  // free the metadata and size arrays
52  if (valueSizes != nullptr)
53  {
54  free(valueSizes);
55  }
56  if (indexSizes != nullptr)
57  {
58  free(indexSizes);
59  }
60  if (metadata != nullptr)
61  {
62  delete[] metadata;
63  }
64 
65  // set the dimensions
66  numRows = other.numRows;
67  numCols = other.numCols;
68  outerDim = other.outerDim;
69  innerDim = other.innerDim;
70  nnz = other.nnz;
71  compSize = other.compSize;
72 
73  // allocate the memory
74  try
75  {
76  values = (T **)malloc(outerDim * sizeof(T *));
77  counts = (indexT **)malloc(outerDim * sizeof(indexT *));
78  indices = (indexT **)malloc(outerDim * sizeof(indexT *));
79 
80  valueSizes = (indexT *)malloc(outerDim * sizeof(indexT));
81  indexSizes = (indexT *)malloc(outerDim * sizeof(indexT));
82 
83  metadata = new uint32_t[NUM_META_DATA];
84  }
85  catch (std::bad_alloc &e)
86  {
87  std::cerr << "Error: Could not allocate memory for IVSparse matrix" << std::endl;
88  exit(1);
89  }
90 
91  // copy the metadata
92  memcpy(metadata, other.metadata, sizeof(uint32_t) * NUM_META_DATA);
93 
94  // set the index and value types
95  encodeValueType();
96  index_t = other.index_t;
97 
98  // copy the data
99  for (uint32_t i = 0; i < outerDim; i++)
100  {
101  try
102  {
103  values[i] = (T *)malloc(other.valueSizes[i] * sizeof(T));
104  counts[i] = (indexT *)malloc(other.valueSizes[i] * sizeof(indexT));
105  indices[i] = (indexT *)malloc(other.indexSizes[i] * sizeof(indexT));
106  }
107  catch (std::bad_alloc &e)
108  {
109  std::cerr << "Error: Could not allocate memory for IVSparse matrix" << std::endl;
110  exit(1);
111  }
112 
113  // copy the data
114  memcpy(values[i], other.values[i], sizeof(T) * other.valueSizes[i]);
115  memcpy(counts[i], other.counts[i], sizeof(indexT) * other.valueSizes[i]);
116  memcpy(indices[i], other.indices[i], sizeof(indexT) * other.indexSizes[i]);
117 
118  valueSizes[i] = other.valueSizes[i];
119  indexSizes[i] = other.indexSizes[i];
120  }
121  }
122 
123  // return the new matrix
124  return *this;
125 
126  } // end assignment operator
127 
128  // Equality Operator
129  template <typename T, typename indexT, bool columnMajor>
130  bool SparseMatrix<T, indexT, 2, columnMajor>::operator==(const SparseMatrix<T, indexT, 2, columnMajor> &other)
131  {
132 
133  // first check the metadata using memcompare
134  if (memcmp(metadata, other.metadata, sizeof(uint32_t) * NUM_META_DATA) != 0)
135  {
136  return false;
137  }
138 
139  // check the value array
140  for (uint32_t i = 0; i < outerDim; i++)
141  {
142  if (memcmp(values[i], other.values[i], sizeof(T) * valueSizes[i]) != 0)
143  {
144  return false;
145  }
146  }
147 
148  // check the index array
149  for (uint32_t i = 0; i < outerDim; i++)
150  {
151  if (memcmp(indices[i], other.indices[i], sizeof(indexT) * indexSizes[i]) != 0)
152  {
153  return false;
154  }
155  }
156 
157  // check the count array
158  for (uint32_t i = 0; i < outerDim; i++)
159  {
160  if (memcmp(counts[i], other.counts[i], sizeof(indexT) * valueSizes[i]) != 0)
161  {
162  return false;
163  }
164  }
165 
166  // if all of the above checks pass then the matrices are equal
167  return true;
168  }
169 
170  // Inequality Operator
171  template <typename T, typename indexT, bool columnMajor>
172  bool SparseMatrix<T, indexT, 2, columnMajor>::operator!=(const SparseMatrix<T, indexT, 2, columnMajor> &other) { return !(*this == other); }
173 
174  // Coefficent Access Operator
175  template <typename T, typename indexT, bool columnMajor>
176  T SparseMatrix<T, indexT, 2, columnMajor>::operator()(uint32_t row, uint32_t col)
177  {
178  // check if the row and column are in bounds
179  if (row >= numRows || col >= numCols)
180  {
181  std::cerr << "Error: Index out of bounds" << std::endl;
182  exit(1);
183  }
184 
185  uint32_t vector = columnMajor ? col : row;
186  uint32_t index = columnMajor ? row : col;
187 
188  // get an iterator for the desired vector
189  for (typename SparseMatrix<T, indexT, 2, columnMajor>::InnerIterator it(*this, vector); it; ++it)
190  {
191  if (it.getIndex() == (indexT)index)
192  {
193  return it.value();
194  }
195  }
196 
197  // if the index is not found return 0
198  return 0;
199  }
200 
201  // Vector Access Operator
202  template <typename T, typename indexT, bool columnMajor>
203  typename SparseMatrix<T, indexT, 2, columnMajor>::Vector SparseMatrix<T, indexT, 2, columnMajor>::operator[](uint32_t vec)
204  {
205 
206  #ifdef CSF_DEBUG
207  // check if the vector is out of bounds
208  assert((vec < outerDim && vec >= 0) && "Vector index out of bounds");
209  #endif
210 
211  // return a IVSparse vector
212  typename IVSparse::SparseMatrix<T, indexT, 2, columnMajor>::Vector newVector(*this, vec);
213 
214  return newVector;
215  }
216 
217  // Outstream Operator
218  template <typename T, typename indexT, bool columnMajor>
219  std::ostream &operator<<(std::ostream &os, IVSparse::SparseMatrix<T, indexT, 2, columnMajor> &mat)
220  {
221  #ifndef CSF_DEBUG
222  if (mat.cols() > 110)
223  {
224  std::cout << "IVSparse matrix is too large to print" << std::endl;
225  return os;
226  }
227  #endif
228 
229  // create a matrix to store the full matrix representation of the IVSparse matrix
230  T **matrix = new T *[mat.rows()];
231  for (size_t i = 0; i < mat.rows(); i++)
232  {
233  matrix[i] = (T *)calloc(mat.cols(), sizeof(T));
234  }
235 
236  // Build the full matrix representation of the the IVSparse matrix
237  for (size_t i = 0; i < mat.cols(); i++)
238  {
239  for (typename IVSparse::SparseMatrix<T, indexT, 2, columnMajor>::InnerIterator it(mat, i); it; ++it)
240  {
241  // std::cout << "it.row(): " << it.row() << " col: " << it.col() << " value: " << it.value() << std::endl;
242  matrix[it.row()][it.col()] = it.value();
243  }
244  }
245 
246  // store all of matrix into the output stream
247  for (size_t i = 0; i < mat.rows(); i++)
248  {
249  for (size_t j = 0; j < mat.cols(); j++)
250  {
251  os << matrix[i][j] << " ";
252  }
253  os << std::endl;
254  }
255 
256  for (int i = 0; i < mat.rows(); i++)
257  {
258  free(matrix[i]);
259  }
260  delete[] matrix;
261 
262  return os;
263 
264  } // end outstream operator
265 
266  //* BLAS Operators *//
267 
268  // Scalar Multiplication
269  template <typename T, typename indexT, bool columnMajor>
270  IVSparse::SparseMatrix<T, indexT, 2, columnMajor> SparseMatrix<T, indexT, 2, columnMajor>::operator*(T scalar)
271  {
272  return scalarMultiply(scalar);
273  }
274 
275  // In place scalar multiplication
276  template <typename T, typename indexT, bool columnMajor>
277  void SparseMatrix<T, indexT, 2, columnMajor>::operator*=(T scalar)
278  {
279  return inPlaceScalarMultiply(scalar);
280  }
281 
282  // IVSparse Matrix * IVSparse Vector Multiplication
283  template <typename T, typename indexT, bool columnMajor>
284  Eigen::VectorXd SparseMatrix<T, indexT, 2, columnMajor>::operator*(SparseMatrix<T, indexT, 2, columnMajor>::Vector &vec)
285  {
286  return vectorMultiply(vec);
287  }
288 
289  // Matrix Vector Multiplication (IVSparse Eigen -> Eigen)
290  template <typename T, typename indexT, bool columnMajor>
291  Eigen::VectorXd SparseMatrix<T, indexT, 2, columnMajor>::operator*(Eigen::VectorXd &vec)
292  {
293  return vectorMultiply(vec);
294  }
295 
296  // Matrix Matrix Multiplication (IVSparse Eigen -> Eigen)
297  template <typename T, typename indexT, bool columnMajor>
298  Eigen::Matrix<T, -1, -1> SparseMatrix<T, indexT, 2, columnMajor>::operator*(Eigen::Matrix<T, -1, -1> mat)
299  {
300  return matrixMultiply(mat);
301  }
302 
303 } // end namespace IVSparse
Definition: VCSC_SparseMatrix.hpp:22
uint32_t cols() const
Definition: IVSparse_Base_Methods.hpp:25
uint32_t rows() const
Definition: IVSparse_Base_Methods.hpp:22
Definition: IVCSC_SparseMatrix.hpp:27