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