IVSparse  v1.0
A sparse matrix compression library.
VCSC_Vector_Methods.hpp
1 
9 #pragma once
10 
11 namespace IVSparse
12 {
13 
14  //* Constructors and Destructor *//
15 
16  // Destructor
17  template <typename T, typename indexT, bool columnMajor>
19  {
20  if (values != nullptr)
21  {
22  free(values);
23  }
24  if (counts != nullptr)
25  {
26  free(counts);
27  }
28  if (indices != nullptr)
29  {
30  free(indices);
31  }
32  }
33 
34  // IVSparse Matrix Constructor
35  template <typename T, typename indexT, bool columnMajor>
37  {
38 
39 #ifdef CSF_DEBUG
40  // make sure the vector is in bounds
41  assert((vec >= 0 && vec < mat.outerSize()) && "Vector index out of bounds");
42 
43  // make sure the matrix is not empty
44  assert((mat.outerSize() > 0 && mat.innerSize() > 0) && "Matrix is empty");
45 #endif
46 
47  // check if the vector is empty
48  if (mat.getNumUniqueVals(vec) == 0)
49  {
50  size = 0;
51  valuesSize = 0;
52  indexSize = 0;
53 
54  values = nullptr;
55  counts = nullptr;
56  indices = nullptr;
57 
58  length = mat.innerSize();
59 
60  return;
61  }
62 
63  length = mat.innerSize();
64  valuesSize = mat.getNumUniqueVals(vec);
65  indexSize = mat.getNumIndices(vec);
66  nnz = mat.getNumIndices(vec);
67 
68  try
69  {
70  values = (T *)malloc(valuesSize * sizeof(T));
71  counts = (indexT *)malloc(valuesSize * sizeof(indexT));
72  indices = (indexT *)malloc(indexSize * sizeof(indexT));
73  }
74  catch (std::bad_alloc &e)
75  {
76  std::cerr << e.what() << '\n';
77  }
78 
79  // copy the data
80  memcpy(values, mat.getValues(vec), valuesSize * sizeof(T));
81  memcpy(counts, mat.getCounts(vec), valuesSize * sizeof(indexT));
82  memcpy(indices, mat.getIndices(vec), indexSize * sizeof(indexT));
83 
84  calculateCompSize();
85  }
86 
87  // Deep copy constructor
88  template <typename T, typename indexT, bool columnMajor>
90  {
91 
92  // set the variables
93  length = vec.length;
94  size = vec.size;
95  nnz = vec.nnz;
96  indexWidth = vec.indexWidth;
97 
98  if (size == 0)
99  {
100  values = nullptr;
101  counts = nullptr;
102  indices = nullptr;
103  return;
104  }
105 
106  valuesSize = vec.valuesSize;
107  indexSize = vec.indexSize;
108 
109  // allocate the memory
110  try
111  {
112  values = (T *)malloc(valuesSize * sizeof(T));
113  counts = (indexT *)malloc(valuesSize * sizeof(indexT));
114  indices = (indexT *)malloc(indexSize * sizeof(indexT));
115  }
116  catch (std::bad_alloc &e)
117  {
118  std::cerr << e.what() << '\n';
119  }
120 
121  // copy the data
122  memcpy(values, vec.values, valuesSize * sizeof(T));
123  memcpy(counts, vec.counts, valuesSize * sizeof(indexT));
124  memcpy(indices, vec.indices, indexSize * sizeof(indexT));
125 
126 // user checks
127 #ifdef CSF_DEBUG
128  userChecks();
129 #endif
130  }
131 
132  //* Private Class Methods *//
133 
134  // User checks to confirm a valid vector
135  template <typename T, typename indexT, bool columnMajor>
137  {
138  assert(std::is_floating_point<indexT>::value == false && "The index type must be a non-floating point type");
139  assert((std::is_arithmetic<T>::value && std::is_arithmetic<indexT>::value) && "The value and index types must be numeric types");
140  assert((std::is_same<indexT, bool>::value == false) && "The index type must not be bool");
141  }
142 
143  // Calculates the size of the vector in bytes
144  template <typename T, typename indexT, bool columnMajor>
146  {
147  size = 0;
148 
149  // calculate the size of the vector
150  size += sizeof(T) * valuesSize;
151  size += sizeof(indexT) * valuesSize;
152  size += sizeof(indexT) * indexSize;
153  }
154 
155  //* Getters *//
156 
157  // Get the inner size of the vector
158  template <typename T, typename indexT, bool columnMajor>
160 
161  // Get the outer size of the vector
162  template <typename T, typename indexT, bool columnMajor>
164 
165  // Get the number of non-zero elements in the vector
166  template <typename T, typename indexT, bool columnMajor>
168 
169  // Get the byte size of the vector
170  template <typename T, typename indexT, bool columnMajor>
172 
173  // Get the value at the given index
174  template <typename T, typename indexT, bool columnMajor>
175  T SparseMatrix<T, indexT, 2, columnMajor>::Vector::coeff(uint32_t index) { return (*this)[index]; }
176 
177  // Get the length of the vector
178  template <typename T, typename indexT, bool columnMajor>
180 
181  // Get a pointer to the values of the vector
182  template <typename T, typename indexT, bool columnMajor>
184 
185  // Get a pointer to the counts of the vector
186  template <typename T, typename indexT, bool columnMajor>
188 
189  // Get a pointer to the indices of the vector
190  template <typename T, typename indexT, bool columnMajor>
192 
193  // Get the number of unique values in the vector
194  template <typename T, typename indexT, bool columnMajor>
196 
197  //* Utility Methods *//
198 
199  // Print the vector to console
200  template <typename T, typename indexT, bool columnMajor>
202  {
203 
204  // if length is larger than 100 then print then don't print
205  if (length > 100)
206  {
207  std::cout << "Vector is too large to print" << std::endl;
208  return;
209  }
210 
211  std::cout << "Vector: ";
212  std::cout << std::endl;
213 
214  // print a dense vector
215  for (uint32_t i = 0; i < length; i++)
216  {
217  std::cout << (*this)[i] << " ";
218  }
219 
220  std::cout << std::endl;
221  }
222 
223  //* Calculation Methods *//
224 
225  // Calculate the norm of the vector
226  template <typename T, typename indexT, bool columnMajor>
228  {
229  double norm = 0;
230 #pragma omp parallel for schedule(dynamic)
231  for (int i = 0; i < valueSizes; i++)
232  {
233  norm += values[i] * values[i] * counts[i];
234  }
235  return sqrt(norm);
236  }
237 
238  // Calculate the sum of the vector
239  template <typename T, typename indexT, bool columnMajor>
241  {
242  double sum = 0;
243 #pragma omp parallel for schedule(dynamic)
244  for (int i = 0; i < valueSizes; i++)
245  {
246  sum += values[i] * counts[i];
247  }
248  return sum;
249  }
250 
251  // Calculate the dot product with an Eigen dense vector
252  template <typename T, typename indexT, bool columnMajor>
253  double SparseMatrix<T, indexT, 2, columnMajor>::Vector::dot(Eigen::Vector<T, -1> &other)
254  {
255 
256  double dot = 0;
257 
258  for (typename SparseMatrix<T, indexT, 2, columnMajor>::InnerIterator it(*this); it; ++it)
259  {
260  dot += it.value() * other.coeff(it.row());
261  }
262 
263  return dot;
264  }
265 
266  // Calculate the dot product with an Eigen sparse vector
267  template <typename T, typename indexT, bool columnMajor>
268  double SparseMatrix<T, indexT, 2, columnMajor>::Vector::dot(Eigen::SparseVector<T, -1> &other)
269  {
270 
271  double dot = 0;
272 
273  for (typename SparseMatrix<T, indexT, 2, columnMajor>::InnerIterator it(*this); it; ++it)
274  {
275  dot += it.value() * other.coeff(it.row());
276  }
277 
278  return dot;
279  }
280 
281  //* Operator Overloads *//
282 
283  template <typename T, typename indexT, bool columnMajor>
285  {
286  // check if the vector is the same
287  if (this == &other)
288  {
289  return *this;
290  }
291 
292  // free the old data if not null
293  if (values != nullptr)
294  {
295  delete[] values;
296  }
297  if (counts != nullptr)
298  {
299  delete[] counts;
300  }
301  if (indices != nullptr)
302  {
303  delete[] indices;
304  }
305 
306  // set the variables
307  length = other.length;
308  size = other.size;
309  nnz = other.nnz;
310  indexWidth = other.indexWidth;
311 
312  if (size == 0)
313  {
314  values = nullptr;
315  counts = nullptr;
316  indices = nullptr;
317  return *this;
318  }
319 
320  valuesSize = other.valuesSize;
321  indexSize = other.indexSize;
322 
323  // allocate the memory
324  try
325  {
326  values = (T *)malloc(valuesSize * sizeof(T));
327  counts = (indexT *)malloc(valuesSize * sizeof(indexT));
328  indices = (indexT *)malloc(indexSize * sizeof(indexT));
329  }
330  catch (std::bad_alloc &e)
331  {
332  std::cerr << e.what() << '\n';
333  }
334 
335  // copy the data
336  memcpy(values, other.values, valuesSize * sizeof(T));
337  memcpy(counts, other.counts, valuesSize * sizeof(indexT));
338  memcpy(indices, other.indices, indexSize * sizeof(indexT));
339 
340 // user checks
341 #ifdef CSF_DEBUG
342  userChecks();
343 #endif
344 
345  // return this
346  return *this;
347  }
348 
349  // equality operator
350  template <typename T, typename indexT, bool columnMajor>
351  bool SparseMatrix<T, indexT, 2, columnMajor>::Vector::operator==(typename SparseMatrix<T, indexT, 2, columnMajor>::Vector &other)
352  {
353 
354  // check if the lengths are the same
355  if (length != other.length)
356  {
357  return false;
358  }
359 
360  // check if the nnz are the same
361  if (nnz != other.nnz)
362  {
363  return false;
364  }
365 
366  // check if the values are the same
367  for (uint32_t i = 0; i < valuesSize; i++)
368  {
369  if (values[i] != other.values[i])
370  {
371  return false;
372  }
373  }
374 
375  // check if the counts are the same
376  for (uint32_t i = 0; i < valuesSize; i++)
377  {
378  if (counts[i] != other.counts[i])
379  {
380  return false;
381  }
382  }
383 
384  // check if the indices are the same
385  for (uint32_t i = 0; i < indexSize; i++)
386  {
387  if (indices[i] != other.indices[i])
388  {
389  return false;
390  }
391  }
392 
393  // return true if all checks pass
394  return true;
395  }
396 
397  // inequality operator
398  template <typename T, typename indexT, bool columnMajor>
399  bool SparseMatrix<T, indexT, 2, columnMajor>::Vector::operator!=(typename SparseMatrix<T, indexT, 2, columnMajor>::Vector &other)
400  {
401  return !(*this == other);
402  }
403 
404  // coefficient access operator
405  template <typename T, typename indexT, bool columnMajor>
406  T SparseMatrix<T, indexT, 2, columnMajor>::Vector::operator[](uint32_t index)
407  {
408 
409 #ifdef CSF_DEBUG
410  // check if the index is out of bounds
411  assert(index < length && "The index is out of bounds");
412 #endif
413 
414  // make an iterator for the vector
416 
417  // iterate through the vector until the index is found
418  while (it)
419  {
420  if (it.getIndex() == (indexT)index)
421  {
422  return it.value();
423  }
424  ++it;
425  }
426 
427  // if the index is not found then return 0
428  return 0;
429  }
430 
431  // Scalar multiplication operator
432  template <typename T, typename indexT, bool columnMajor>
433  void SparseMatrix<T, indexT, 2, columnMajor>::Vector::operator*=(T scalar)
434  {
435 #pragma omp parallel for schedule(dynamic)
436  for (int i = 0; i < valueSizes; i++)
437  {
438  values[i] *= scalar;
439  }
440  }
441 
442  // Scalar multiplication operator (returns a new vector)
443  template <typename T, typename indexT, bool columnMajor>
444  typename IVSparse::SparseMatrix<T, indexT, 2, columnMajor>::Vector SparseMatrix<T, indexT, 2, columnMajor>::Vector::operator*(T scalar)
445  {
446 
448 
449 #pragma omp parallel for schedule(dynamic)
450  for (int i = 0; i < outerDim; i++)
451  {
452  for (int j = 0; j < valueSizes; j++)
453  {
454  newVector.values[i][j] *= scalar;
455  }
456  }
457 
458  return newVector;
459  }
460 
461 } // end IVSparse namespace
Definition: IVCSC_Iterator.hpp:25
Definition: IVCSC_Vector.hpp:27
uint32_t getLength()
Definition: IVCSC_Vector_Methods.hpp:183
T coeff(uint32_t index)
Definition: IVCSC_Vector_Methods.hpp:179
void print()
Definition: IVCSC_Vector_Methods.hpp:189
uint32_t innerSize()
Definition: IVCSC_Vector_Methods.hpp:155
T sum()
Definition: IVCSC_Vector_Methods.hpp:227
size_t byteSize()
Definition: IVCSC_Vector_Methods.hpp:175
Vector()
Definition: IVCSC_Vector.hpp:61
double norm()
Definition: IVCSC_Vector_Methods.hpp:215
uint32_t nonZeros()
Definition: IVCSC_Vector_Methods.hpp:163
uint32_t outerSize()
Definition: IVCSC_Vector_Methods.hpp:159
~Vector()
Definition: IVCSC_Vector_Methods.hpp:18
double dot(Eigen::Vector< T, -1 > &other)
Definition: IVCSC_Vector_Methods.hpp:239
Definition: VCSC_SparseMatrix.hpp:22
indexT getNumUniqueVals(uint32_t vec) const
Definition: VCSC_Methods.hpp:38
indexT * getCounts(uint32_t vec) const
Definition: VCSC_Methods.hpp:30
indexT getNumIndices(uint32_t vec) const
Definition: VCSC_Methods.hpp:46
indexT * getIndices(uint32_t vec) const
Definition: VCSC_Methods.hpp:34
T * getValues(uint32_t vec) const
Definition: VCSC_Methods.hpp:26
uint32_t innerSize() const
Definition: IVSparse_Base_Methods.hpp:28
uint32_t outerSize() const
Definition: IVSparse_Base_Methods.hpp:31
Definition: IVCSC_SparseMatrix.hpp:27