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