IVSparse  v1.0
A sparse matrix compression library.
IVCSC_Operators.hpp
1 
9 #pragma once
10 
11 namespace IVSparse {
12 
13  // Assignment Operator
14  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
15  SparseMatrix<T, indexT, compressionLevel, columnMajor> &SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator=(const IVSparse::SparseMatrix<T, indexT, compressionLevel, columnMajor> &other) {
16 
17  if (this != &other) {
18 
19  // free old data
20  if (data != nullptr) {
21  for (uint32_t i = 0; i < outerDim; i++) { if (data[i] != nullptr) {free(data[i]);} }
22  free(data);
23  }
24  if (endPointers != nullptr) { free(endPointers); }
25  if (metadata != nullptr) { delete[] metadata; }
26 
27  // set the dimensions
28  numRows = other.numRows;
29  numCols = other.numCols;
30  outerDim = other.outerDim;
31  innerDim = other.innerDim;
32  nnz = other.nnz;
33  compSize = other.compSize;
34 
35  // allocate the memory
36  try {
37  data = (void **)malloc(outerDim * sizeof(void *));
38  endPointers = (void **)malloc(outerDim * sizeof(void *));
39  metadata = new uint32_t[NUM_META_DATA];
40  } catch (std::bad_alloc &e) {
41  std::cerr << "Error: Could not allocate memory for IVSparse matrix" << std::endl;
42  exit(1);
43  }
44 
45  // copy the metadata
46  memcpy(metadata, other.metadata, sizeof(uint32_t) * NUM_META_DATA);
47 
48  // set the index and value types
49  encodeValueType();
50  index_t = other.index_t;
51 
52  // copy the data
53  for (uint32_t i = 0; i < outerDim; i++) {
54 
55  // if the vector is empty, set the data pointer to nullptr
56  if (other.data[i] == nullptr) {
57  data[i] = nullptr;
58  endPointers[i] = nullptr;
59  continue;
60  }
61 
62  try {
63  data[i] = malloc(other.getVectorSize(i));
64  } catch (std::bad_alloc &e) {
65  std::cerr << "Error: Could not allocate memory for IVSparse matrix" << std::endl;
66  exit(1);
67  }
68 
69  memcpy(data[i], other.data[i], other.getVectorSize(i));
70  endPointers[i] = (uint8_t *)data[i] + other.getVectorSize(i);
71  }
72  }
73  return *this;
74  }
75 
76  // Equality Operator
77  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
78  bool SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator==(const SparseMatrix<T, indexT, compressionLevel, columnMajor> &other) {
79  // check if the two matrices are equal
80 
81  // first check the metadata using memcompare
82  if (memcmp(metadata, other.metadata, sizeof(uint32_t) * NUM_META_DATA) != 0)
83  return false;
84 
85  // iterate through the data and compare each element
86  for (uint32_t i = 0; i < outerDim; i++) {
87 
88  if (memcmp(data[i], other.data[i], getVectorSize(i)) != 0)
89  return false;
90  }
91 
92  return true;
93  }
94 
95  // Inequality Operator
96  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
97  bool SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator!=(const SparseMatrix<T, indexT, compressionLevel, columnMajor> &other) {
98  return !(*this == other);
99  }
100 
101  // Coefficent Access Operator
102  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
103  T SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator()(uint32_t row, uint32_t col) {
104  // check if the row and column are in bounds
105  if (row >= numRows || col >= numCols) {
106  std::cerr << "Error: Index out of bounds" << std::endl;
107  exit(1);
108  }
109 
110  uint32_t vector = columnMajor ? col : row;
111  uint32_t index = columnMajor ? row : col;
112 
113  // if the vector is empty return 0
114  if (data[vector] == nullptr)
115  return 0;
116 
117  // get an iterator for the desired vector
118  for (typename SparseMatrix<T, indexT, compressionLevel, columnMajor>::InnerIterator it(*this, vector); it; ++it) {
119  if (it.getIndex() == (indexT)index) { return it.value(); }
120  }
121 
122  // if the index is not found return 0
123  return 0;
124  }
125 
126  // Vector Access Operator
127  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
128  typename SparseMatrix<T, indexT, compressionLevel, columnMajor>::Vector SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator[](uint32_t vec) {
129 
130  #ifdef CSF_DEBUG
131  // check if the vector is out of bounds
132  assert((vec < outerDim && vec >= 0) && "Vector index out of bounds");
133  #endif
134 
135  // return a IVSparse vector
137 
138  return newVector;
139  }
140 
141  // Outstream Operator
142  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
143  std::ostream &operator<<(std::ostream &os, IVSparse::SparseMatrix<T, indexT, compressionLevel, columnMajor> &mat) {
144  #ifndef CSF_DEBUG
145  if (mat.cols() > 110) {
146  std::cout << "IVSparse matrix is too large to print" << std::endl;
147  return os;
148  }
149  #endif
150 
151  // create a matrix to store the full matrix representation of the IVSparse matrix
152  T **matrix = new T *[mat.rows()];
153  for (size_t i = 0; i < mat.rows(); i++) { matrix[i] = (T *)calloc(mat.cols(), sizeof(T)); }
154 
155  // Build the full matrix representation of the the IVSparse matrix
156  for (size_t i = 0; i < mat.cols(); i++) {
158  // std::cout << "it.row(): " << it.row() << " col: " << it.col() << " value: " << it.value() << std::endl;
159  matrix[it.row()][it.col()] = it.value();
160  }
161  }
162 
163  // std::cout << "rows: " << mat.rows() << std::endl;
164  // std::cout << "cols: " << mat.cols() << std::endl;
165 
166  // store all of matrix into the output stream
167  for (size_t i = 0; i < mat.rows(); i++) {
168  for (size_t j = 0; j < mat.cols(); j++) {
169  os << matrix[i][j] << " ";
170  }
171  os << std::endl;
172  }
173 
174  for (int i = 0; i < mat.rows(); i++) { free(matrix[i]); }
175  delete[] matrix;
176 
177  return os;
178  }
179 
180  //* BLAS Operators *//
181 
182  // Scalar Multiplication
183  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
184  IVSparse::SparseMatrix<T, indexT, compressionLevel, columnMajor> SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator*(T scalar)
185  {
186  return scalarMultiply(scalar);
187  }
188 
189  // In place scalar multiplication
190  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
191  void SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator*=(T scalar)
192  {
193  return inPlaceScalarMultiply(scalar);
194  }
195 
196  // IVSparse Matrix * IVSparse Vector Multiplication
197  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
198  Eigen::VectorXd SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator*(SparseMatrix<T, indexT, compressionLevel, columnMajor>::Vector &vec)
199  {
200  return vectorMultiply(vec);
201  }
202 
203  // Matrix Vector Multiplication (IVSparse Eigen -> Eigen)
204  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
205  Eigen::VectorXd SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator*(Eigen::VectorXd &vec)
206  {
207  return vectorMultiply(vec);
208  }
209 
210  // Matrix Matrix Multiplication (IVSparse Eigen -> Eigen)
211  template <typename T, typename indexT, uint8_t compressionLevel, bool columnMajor>
212  Eigen::Matrix<T, -1, -1> SparseMatrix<T, indexT, compressionLevel, columnMajor>::operator*(Eigen::Matrix<T, -1, -1> mat)
213  {
214  return matrixMultiply(mat);
215  }
216 
217 } // namespace IVSparse
Definition: IVCSC_Iterator.hpp:25
Definition: IVCSC_Vector.hpp:27
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
size_t getVectorSize(uint32_t vec) const
Definition: IVCSC_Methods.hpp:33