TBTK
SparseMatrix.h
Go to the documentation of this file.
1 /* Copyright 2017 Kristofer Bj√∂rnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
23 #ifndef COM_DAFER45_TBTK_SPARSE_MATRIX
24 #define COM_DAFER45_TBTK_SPARSE_MATRIX
25 
26 #include "TBTK/TBTKMacros.h"
27 
28 #include <algorithm>
29 #include <tuple>
30 #include <vector>
31 
32 namespace TBTK{
33 
34 template<typename DataType>
36 public:
38  enum class StorageFormat {CSR, CSC};
39 
42 
44  SparseMatrix(const SparseMatrix &sparseMatrix);
45 
47  SparseMatrix(SparseMatrix &&sparseMatrix);
48 
51  StorageFormat storageFormat,
52  unsigned int numRows,
53  unsigned int numCols
54  );
55 
57  SparseMatrix& operator=(const SparseMatrix &sparseMatrix);
58 
60  SparseMatrix& operator=(SparseMatrix &&sparseMatrix);
61 
63  ~SparseMatrix();
64 
66  void add(unsigned int row, unsigned int col, const DataType &value);
67 
69  void setStorageFormat(StorageFormat storageFormat);
70 
72  unsigned int getNumRows() const;
73 
75  unsigned int getNumColumns() const;
76 
78  unsigned int getCSRNumMatrixElements() const;
79 
81  unsigned int getCSCNumMatrixElements() const;
82 
84  const unsigned int* getCSRRowPointers() const;
85 
87  const unsigned int* getCSCColumnPointers() const;
88 
90  const unsigned int* getCSRColumns() const;
91 
93  const unsigned int* getCSCRows() const;
94 
96  const DataType* getCSRValues() const;
97 
99  const DataType* getCSCValues() const;
100 
102  void print() const;
103 private:
106  std::vector<
107  std::tuple<unsigned int, unsigned int, DataType>
108  > dictionaryOfKeys;
109 
111  int numRows, numCols;
112 
115  bool allowDynamicDimensions;
116 
118  StorageFormat storageFormat;
119 
122  unsigned int *csxXPointers;
123 
125  unsigned int *csxY;
126 
128  DataType *csxValues;
129 
132  int csxNumMatrixElements;
133 public:
135  std::vector<
136  std::vector<std::tuple<unsigned int, DataType>>
137  > constructLIL();
138 
140  void sortLIL(
141  std::vector<
142  std::vector<std::tuple<unsigned int, DataType>>
143  > &listOfLists
144  ) const;
145 
148  void mergeLIL(
149  std::vector<
150  std::vector<std::tuple<unsigned int, DataType>>
151  > &listOfLists
152  ) const;
153 
155  void constructCSX();
156 
161  void convertCSXToLIL();
162 };
163 
164 template<typename DataType>
166  this->storageFormat = storageFormat;
167 
168  numRows = -1;
169  numCols = -1;
170  allowDynamicDimensions = true;
171 
172  csxXPointers = nullptr;
173  csxY = nullptr;
174  csxValues = nullptr;
175  csxNumMatrixElements = -1;
176 }
177 
178 template<typename DataType>
180  StorageFormat storageFormat,
181  unsigned int numRows,
182  unsigned int numCols
183 ){
184  this->storageFormat = storageFormat;
185 
186  this->numRows = numRows;
187  this->numCols = numCols;
188  allowDynamicDimensions = false;
189 
190  csxXPointers = nullptr;
191  csxY = nullptr;
192  csxValues = nullptr;
193  csxNumMatrixElements = -1;
194 }
195 
196 template<typename DataType>
198  const SparseMatrix &sparseMatrix
199 ){
200  storageFormat = sparseMatrix.storageFormat;
201 
202  numRows = sparseMatrix.numRows;
203  numCols = sparseMatrix.numCols;
204  allowDynamicDimensions = sparseMatrix.allowDynamicDimensions;
205 
206  csxNumMatrixElements = sparseMatrix.csxNumMatrixElements;
207  if(csxNumMatrixElements == -1){
208  TBTKAssert(
209  sparseMatrix.csxXPointers == nullptr
210  && sparseMatrix.csxY == nullptr
211  && sparseMatrix.csxValues == nullptr,
212  "SparseMatrix::SparseMatrix()",
213  "Invalid pointers in the original SparseMatrix.",
214  "This should never happen, contact the developer."
215  );
216 
217  csxXPointers = nullptr;
218  csxY = nullptr;
219  csxValues = nullptr;
220  }
221  else{
222  TBTKAssert(
223  sparseMatrix.csxXPointers != nullptr
224  && sparseMatrix.csxY != nullptr
225  && sparseMatrix.csxValues != nullptr,
226  "SparseMatrix::SparseMatrix()",
227  "Invalid pointers in the original SparseMatrix.",
228  "This should never happen, contact the developer."
229  );
230 
231  switch(storageFormat){
232  case StorageFormat::CSR:
233  csxXPointers = new unsigned int[numRows+1];
234  for(int row = 0; row < numRows+1; row++){
235  csxXPointers[row]
236  = sparseMatrix.csxXPointers[row];
237  }
238  break;
239  case StorageFormat::CSC:
240  csxXPointers = new unsigned int[numCols+1];
241  for(int col = 0; col < numCols+1; col++){
242  csxXPointers[col]
243  = sparseMatrix.csxXPointers[col];
244  }
245  break;
246  default:
247  TBTKExit(
248  "SparseMatrix::SparseMatrix()",
249  "Unknow StorageFormat.",
250  "This should never happen, contact the"
251  << " developer."
252  );
253  }
254 
255  csxY = new unsigned int[csxNumMatrixElements];
256  csxValues = new DataType[csxNumMatrixElements];
257  for(int n = 0; n < csxNumMatrixElements; n++){
258  csxY[n] = sparseMatrix.csxY[n];
259  csxValues[n] = sparseMatrix.csxValues[n];
260  }
261  }
262 }
263 
264 template<typename DataType>
266  SparseMatrix &&sparseMatrix
267 ){
268  storageFormat = sparseMatrix.storageFormat;
269 
270  numRows = sparseMatrix.numRows;
271  numCols = sparseMatrix.numCols;
272  allowDynamicDimensions = sparseMatrix.allowDynamicDimensions;
273 
274  csxNumMatrixElements = sparseMatrix.csxNumMatrixElements;
275  if(csxNumMatrixElements == -1){
276  TBTKAssert(
277  sparseMatrix.csxXPointers == nullptr
278  && sparseMatrix.csxY == nullptr
279  && sparseMatrix.csxValues == nullptr,
280  "SparseMatrix::SparseMatrix()",
281  "Invalid pointers in the original SparseMatrix.",
282  "This should never happen, contact the developer."
283  );
284 
285  csxXPointers = nullptr;
286  csxY = nullptr;
287  csxValues = nullptr;
288  }
289  else{
290  TBTKAssert(
291  sparseMatrix.csxXPointers != nullptr
292  && sparseMatrix.csxY != nullptr
293  && sparseMatrix.csxValues != nullptr,
294  "SparseMatrix::SparseMatrix()",
295  "Invalid pointers in the original SparseMatrix.",
296  "This should never happen, contact the developer."
297  );
298 
299  csxXPointers = sparseMatrix.csxXPointers;
300  sparseMatrix.csxXPointers = nullptr;
301 
302  csxY = sparseMatrix.csxY;
303  sparseMatrix.csxY = nullptr;
304 
305  csxValues = sparseMatrix.csxValues;
306  sparseMatrix.csxValues = nullptr;
307  }
308 }
309 
310 template<typename DataType>
312  if(csxXPointers != nullptr)
313  delete [] csxXPointers;
314  if(csxY != nullptr)
315  delete [] csxY;
316  if(csxValues != nullptr)
317  delete [] csxValues;
318 }
319 
320 template<typename DataType>
322  const SparseMatrix &rhs
323 ){
324  if(this != &rhs){
325  storageFormat = rhs.storageFormat;
326 
327  numRows = rhs.numRows;
328  numCols = rhs.numCols;
329  allowDynamicDimensions = rhs.allowDynamicDimensions;
330 
331  if(csxXPointers != nullptr)
332  delete [] csxXPointers;
333  if(csxY != nullptr)
334  delete [] csxY;
335  if(csxValues != nullptr)
336  delete [] csxValues;
337 
338  csxNumMatrixElements = rhs.csxNumMatrixElements;
339  if(csxNumMatrixElements == -1){
340  TBTKAssert(
341  rhs.csxXPointers == nullptr
342  && rhs.csxY == nullptr
343  && rhs.csxValues == nullptr,
344  "SparseMatrix::operator=()",
345  "Invalid pointers in the original SparseMatrix.",
346  "This should never happen, contact the developer."
347  );
348 
349  csxXPointers = nullptr;
350  csxY = nullptr;
351  csxValues = nullptr;
352  }
353  else{
354  TBTKAssert(
355  rhs.csxXPointers != nullptr
356  && rhs.csxY != nullptr
357  && rhs.csxValues != nullptr,
358  "SparseMatrix::SparseMatrix()",
359  "Invalid pointers in the original SparseMatrix.",
360  "This should never happen, contact the developer."
361  );
362 
363  switch(storageFormat){
364  case StorageFormat::CSR:
365  csxXPointers = new unsigned int[numRows+1];
366  for(unsigned int row = 0; row < numRows+1; row++){
367  csxXPointers[row]
368  = rhs.csxXPointers[row];
369  }
370  break;
371  case StorageFormat::CSC:
372  csxXPointers = new unsigned int[numCols+1];
373  for(unsigned int col = 0; col < numCols+1; col++){
374  csxXPointers[col]
375  = rhs.csxXPointers[col];
376  }
377  break;
378  default:
379  TBTKExit(
380  "SparseMatrix::SparseMatrix()",
381  "Unknow StorageFormat.",
382  "This should never happen, contact the"
383  << " developer."
384  );
385  }
386 
387  csxY = new unsigned int[csxNumMatrixElements];
388  csxValues = new DataType[csxNumMatrixElements];
389  for(unsigned int n = 0; n < csxNumMatrixElements; n++){
390  csxY[n] = rhs.csxY[n];
391  csxValues[n] = rhs.csxValues[n];
392  }
393  }
394  }
395 
396  return *this;
397 }
398 
399 template<typename DataType>
401  SparseMatrix &&rhs
402 ){
403  if(this != &rhs){
404  Streams::out << "Move assignment\n";
405  storageFormat = rhs.storageFormat;
406 
407  numRows = rhs.numRows;
408  numCols = rhs.numCols;
409  allowDynamicDimensions = rhs.allowDynamicDimensions;
410 
411  if(csxXPointers != nullptr)
412  delete [] csxXPointers;
413  if(csxY != nullptr)
414  delete [] csxY;
415  if(csxValues != nullptr)
416  delete [] csxValues;
417 
418  csxNumMatrixElements = rhs.csxNumMatrixElements;
419  if(csxNumMatrixElements == -1){
420  TBTKAssert(
421  rhs.csxXPointers == nullptr
422  && rhs.csxY == nullptr
423  && rhs.csxValues == nullptr,
424  "SparseMatrix::operator=()",
425  "Invalid pointers in the original SparseMatrix.",
426  "This should never happen, contact the developer."
427  );
428 
429  csxXPointers = nullptr;
430  csxY = nullptr;
431  csxValues = nullptr;
432  }
433  else{
434  TBTKAssert(
435  rhs.csxXPointers != nullptr
436  && rhs.csxY != nullptr
437  && rhs.csxValues != nullptr,
438  "SparseMatrix::SparseMatrix()",
439  "Invalid pointers in the original SparseMatrix.",
440  "This should never happen, contact the developer."
441  );
442 
443  csxXPointers = rhs.csxXPointers;
444  rhs.csxXPointers = nullptr;
445 
446  csxY = rhs.csxY;
447  rhs.csxY = nullptr;
448 
449  csxValues = rhs.csxValues;
450  rhs.csxValues = nullptr;
451  }
452  }
453 
454  return *this;
455 }
456 
457 template<typename DataType>
459  unsigned int row,
460  unsigned int col,
461  const DataType &value
462 ){
463  if(!allowDynamicDimensions){
464  TBTKAssert(
465  (int)row < numRows && (int)col < numCols,
466  "SparseMatrix::add()",
467  "Invalid matrix entry. The matrix was constructed"
468  " specifiying that the matrix dimension is '"
469  << numRows << "x" << numCols << " but tried to add"
470  << " matrix element with index '(" << row << ", "
471  << col << ")'",
472  "Ensure that the matrix elements are in range, or use"
473  << " a constructor which does not fix the matrix"
474  << " dimension."
475  );
476  }
477 
478  dictionaryOfKeys.push_back(std::make_tuple(row, col, value));
479 }
480 
481 template<typename DataType>
483  StorageFormat storageFormat
484 ){
485  if(this->storageFormat != storageFormat){
486  convertCSXToLIL();
487  this->storageFormat = storageFormat;
488  constructCSX();
489  }
490 }
491 
492 template<typename DataType>
493 inline unsigned int SparseMatrix<DataType>::getNumRows() const{
494  TBTKAssert(
495  numRows != -1,
496  "SparseMatrix::getNumRows()",
497  "Number of rows not yet determined.",
498  ""
499  );
500 
501  return (unsigned int)numRows;
502 }
503 
504 template<typename DataType>
505 inline unsigned int SparseMatrix<DataType>::getNumColumns() const{
506  TBTKAssert(
507  numRows != -1,
508  "SparseMatrix::getNumRows()",
509  "Number of rows not yet determined.",
510  ""
511  );
512 
513  return (unsigned int)numCols;
514 }
515 
516 template<typename DataType>
518  TBTKAssert(
519  storageFormat == StorageFormat::CSR,
520  "SparseMatrix::getCSRNumMatrixElements()",
521  "Tried to access CSR number of matrix elements, but the matrix"
522  " is not on the CSR storage format.",
523  "Use SparseMatrix::setFormat() to change the storage format."
524  );
525 
526  if(csxNumMatrixElements == -1)
527  return 0;
528  else
529  return (unsigned int)csxNumMatrixElements;
530 }
531 
532 template<typename DataType>
534  TBTKAssert(
535  storageFormat == StorageFormat::CSC,
536  "SparseMatrix::getCSCNumMatrixElements()",
537  "Tried to access CSC number of matrix elements, but the matrix"
538  " is not on the CSC storage format.",
539  "Use SparseMatrix::setFormat() to change the storage format."
540  );
541 
542  if(csxNumMatrixElements == -1)
543  return 0;
544  else
545  return (unsigned int)csxNumMatrixElements;
546 }
547 
548 template<typename DataType>
549 inline const unsigned int* SparseMatrix<DataType>::getCSRRowPointers() const{
550  TBTKAssert(
551  storageFormat == StorageFormat::CSR,
552  "SparseMatrix::getCSRRowPointers()",
553  "Tried to access CSR row pointers, but the matrix is not on"
554  " the CSR storage format.",
555  "Use SparseMatrix::setFormat() to change the storage format."
556  );
557 
558  TBTKAssert(
559  csxXPointers != nullptr,
560  "SparseMatrix::getCSRRowPointers()",
561  "Tried to access CSR row pointers, but row pointers have not"
562  << " been constructed yet.",
563  ""
564  );
565 
566  return csxXPointers;
567 }
568 
569 template<typename DataType>
570 inline const unsigned int* SparseMatrix<DataType>::getCSCColumnPointers() const{
571  TBTKAssert(
572  storageFormat == StorageFormat::CSC,
573  "SparseMatrix::getCSCColumnPointers()",
574  "Tried to access CSC row pointers, but the matrix is not on"
575  " the CSC storage format.",
576  "Use SparseMatrix::setFormat() to change the storage format."
577  );
578 
579  TBTKAssert(
580  csxXPointers != nullptr,
581  "SparseMatrix::getCSCColumnPointers()",
582  "Tried to access CSC column pointers, but column pointers have"
583  << " not been constructed yet.",
584  ""
585  );
586 
587  return csxXPointers;
588 }
589 
590 template<typename DataType>
591 inline const unsigned int* SparseMatrix<DataType>::getCSRColumns() const{
592  TBTKAssert(
593  storageFormat == StorageFormat::CSR,
594  "SparseMatrix::getCSRColumns()",
595  "Tried to access CSR columns, but the matrix is not on the CSR"
596  << " storage format.",
597  "Use SparseMatrix::setFormat() to change the storage format."
598  );
599 
600  TBTKAssert(
601  csxY != nullptr,
602  "SparseMatrix::getCSRColumns()",
603  "Tried to access CSR columns, but columns have not been"
604  << " constructed yet.",
605  ""
606  );
607 
608  return csxY;
609 }
610 
611 template<typename DataType>
612 inline const unsigned int* SparseMatrix<DataType>::getCSCRows() const{
613  TBTKAssert(
614  storageFormat == StorageFormat::CSC,
615  "SparseMatrix::getCSCRows()",
616  "Tried to access CSC rows, but the matrix is not on the CSC"
617  << " storage format.",
618  "Use SparseMatrix::setFormat() to change the storage format."
619  );
620 
621  TBTKAssert(
622  csxY != nullptr,
623  "SparseMatrix::getCSCRows()",
624  "Tried to access CSC rows, but rows have not been constructed"
625  << " yet.",
626  ""
627  );
628 
629  return csxY;
630 }
631 
632 template<typename DataType>
633 inline const DataType* SparseMatrix<DataType>::getCSRValues() const{
634  TBTKAssert(
635  storageFormat == StorageFormat::CSR,
636  "SparseMatrix::getCSRValues()",
637  "Tried to access CSR values, but the matrix is not on the CSR"
638  << " storage format.",
639  "Use SparseMatrix::setFormat() to change the storage format."
640  );
641 
642  TBTKAssert(
643  csxValues != nullptr,
644  "SparseMatrix::getCSRValues()",
645  "Tried to access CSR values, but values have not been"
646  << " constructed yet.",
647  ""
648  );
649 
650  return csxValues;
651 }
652 
653 template<typename DataType>
654 inline const DataType* SparseMatrix<DataType>::getCSCValues() const{
655  TBTKAssert(
656  storageFormat == StorageFormat::CSC,
657  "SparseMatrix::getCSCValues()",
658  "Tried to access CSC values, but the matrix is not on the CSC"
659  << " storage format.",
660  "Use SparseMatrix::setFormat() to change the storage format."
661  );
662 
663  TBTKAssert(
664  csxValues != nullptr,
665  "SparseMatrix::getCSCValues()",
666  "Tried to access CSC values, but values have not been"
667  << " constructed yet.",
668  ""
669  );
670 
671  return csxValues;
672 }
673 
674 template<typename DataType>
675 inline void SparseMatrix<DataType>::print() const{
676  Streams::out << "### Dictionary of Keys (DOK) ###\n";
677  if(dictionaryOfKeys.size() == 0)
678  Streams::out << "-\n";
679  for(unsigned int n = 0; n < dictionaryOfKeys.size(); n++){
680  unsigned int row = std::get<0>(dictionaryOfKeys[n]);
681  unsigned int col = std::get<1>(dictionaryOfKeys[n]);
682  const DataType &value = std::get<2>(dictionaryOfKeys[n]);
683  Streams::out << "(" << row << ", " << col << ", " << value << ")\n";
684  }
685 
686  Streams::out << "\n";
687  switch(storageFormat){
688  case StorageFormat::CSR:
689  Streams::out << "### Compressed sparse row (CSR) ###\n";
690  if(csxNumMatrixElements == -1){
691  Streams::out << "-\n";
692  }
693  else{
694  Streams::out << "Row pointers:\n";
695  for(int row = 0; row < numRows+1; row++)
696  Streams::out << csxXPointers[row] << "\t";
697  Streams::out << "\nColumns:\n";
698  for(int n = 0; n < csxNumMatrixElements; n++)
699  Streams::out << csxY[n] << "\t";
700  Streams::out << "\nValues:\n";
701  for(int n = 0; n < csxNumMatrixElements; n++)
702  Streams::out << csxValues[n] << "\t";
703  Streams::out << "\n";
704  }
705  break;
706  case StorageFormat::CSC:
707  Streams::out << "### Compressed sparse column (CSC) ###\n";
708  if(csxNumMatrixElements == -1){
709  Streams::out << "-\n";
710  }
711  else{
712  Streams::out << "Column pointers:\n";
713  for(int col = 0; col < numCols+1; col++)
714  Streams::out << csxXPointers[col] << "\t";
715  Streams::out << "\nRows:\n";
716  for(int n = 0; n < csxNumMatrixElements; n++)
717  Streams::out << csxY[n] << "\t";
718  Streams::out << "\nValues:\n";
719  for(int n = 0; n < csxNumMatrixElements; n++)
720  Streams::out << csxValues[n] << "\t";
721  Streams::out << "\n";
722  }
723  break;
724  default:
725  TBTKExit(
726  "SparseMatrix::print()",
727  "Unknow StorageFormat.",
728  "This should never happen, contact the developer."
729  );
730  }
731 }
732 
733 template<typename DataType>
734 inline std::vector<
735  std::vector<std::tuple<unsigned int, DataType>>
737  unsigned int numRows = 0;
738  unsigned int numCols = 0;
739  for(unsigned int n = 0; n < dictionaryOfKeys.size(); n++){
740  unsigned int row = std::get<0>(dictionaryOfKeys[n]);
741  unsigned int col = std::get<1>(dictionaryOfKeys[n]);
742  if(row >= numRows)
743  numRows = row+1;
744  if(col >= numCols)
745  numCols = col+1;
746  }
747 
748  std::vector<
749  std::vector<std::tuple<unsigned int, DataType>>
750  > listOfLists;
751 
752  switch(storageFormat){
753  case StorageFormat::CSR:
754  listOfLists.reserve(numRows);
755  for(unsigned int row = 0; row < numRows; row++){
756  listOfLists.push_back(
757  std::vector<std::tuple<unsigned int, DataType>>()
758  );
759  }
760 
761  for(unsigned int n = 0; n < dictionaryOfKeys.size(); n++){
762  unsigned int row = std::get<0>(dictionaryOfKeys[n]);
763  unsigned int col = std::get<1>(dictionaryOfKeys[n]);
764  const DataType &value = std::get<2>(dictionaryOfKeys[n]);
765 
766  listOfLists[row].push_back(std::make_tuple(col, value));
767  }
768  break;
769  case StorageFormat::CSC:
770  listOfLists.reserve(numCols);
771  for(unsigned int col = 0; col < numCols; col++){
772  listOfLists.push_back(
773  std::vector<std::tuple<unsigned int, DataType>>()
774  );
775  }
776 
777  for(unsigned int n = 0; n < dictionaryOfKeys.size(); n++){
778  unsigned int row = std::get<0>(dictionaryOfKeys[n]);
779  unsigned int col = std::get<1>(dictionaryOfKeys[n]);
780  const DataType &value = std::get<2>(dictionaryOfKeys[n]);
781 
782  listOfLists[col].push_back(std::make_tuple(row, value));
783  }
784  break;
785  default:
786  TBTKExit(
787  "SparseMatrix::constructLIL()",
788  "Unknow StorageFormat.",
789  "This should never happen, contact the developer."
790  );
791  }
792 
793  sortLIL(listOfLists);
794  mergeLIL(listOfLists);
795 
796  dictionaryOfKeys.clear();
797 
798  return listOfLists;
799 }
800 
801 template<typename DataType>
803  std::vector<
804  std::vector<std::tuple<unsigned int, DataType>>
805  > &listOfLists
806 ) const{
807  for(unsigned int x = 0; x < listOfLists.size(); x++){
808  std::sort(
809  listOfLists[x].begin(),
810  listOfLists[x].end(),
811  [](
812  const std::tuple<unsigned int, DataType> &t1,
813  const std::tuple<unsigned int, DataType> &t2
814  ){
815  return std::get<0>(t1) < std::get<0>(t2);
816  }
817  );
818  }
819 }
820 
821 template<typename DataType>
823  std::vector<
824  std::vector<std::tuple<unsigned int, DataType>>
825  > &listOfLists
826 ) const{
827  for(unsigned int x = 0; x < listOfLists.size(); x++){
828  for(int y = listOfLists[x].size()-1; y > 0; y--){
829  unsigned int y1 = std::get<0>(listOfLists[x][y]);
830  unsigned int y2 = std::get<0>(listOfLists[x][y-1]);
831 
832  if(y1 == y2){
833  std::get<1>(listOfLists[x][y-1])
834  += std::get<1>(listOfLists[x][y]);
835  listOfLists[x].erase(
836  listOfLists[x].begin() + y
837  );
838  }
839  }
840  }
841 }
842 
843 template<typename DataType>
845  convertCSXToLIL();
846 
847  if(dictionaryOfKeys.size() != 0){
848  std::vector<
849  std::vector<std::tuple<unsigned int, DataType>>
850  > listOfLists = constructLIL();
851 
852  if(allowDynamicDimensions){
853  switch(storageFormat){
854  case StorageFormat::CSR:
855  numRows = listOfLists.size();
856  numCols = 0;
857  for(
858  unsigned int row = 0;
859  row < listOfLists.size();
860  row++
861  ){
862  if(listOfLists[row].size() == 0)
863  continue;
864 
865  unsigned int maxCol = std::get<0>(
866  listOfLists[row].back()
867  );
868  if((int)maxCol+1 > numCols)
869  numCols = maxCol + 1;
870  }
871  break;
872  case StorageFormat::CSC:
873  numCols = listOfLists.size();
874  numRows = 0;
875  for(
876  unsigned int col = 0;
877  col < listOfLists.size();
878  col++
879  ){
880  if(listOfLists[col].size() == 0)
881  continue;
882 
883  unsigned int maxRow = std::get<0>(
884  listOfLists[col].back()
885  );
886  if((int)maxRow+1 > numRows)
887  numRows = maxRow + 1;
888  }
889  break;
890  default:
891  TBTKExit(
892  "SparseMatrix::constructCSX()",
893  "Unknow StorageFormat.",
894  "This should never happen, contact the"
895  << " developer."
896  );
897  }
898  }
899 
900  csxNumMatrixElements = 0;
901  for(unsigned int x = 0; x < listOfLists.size(); x++)
902  csxNumMatrixElements += listOfLists[x].size();
903 
904  switch(storageFormat){
905  case StorageFormat::CSR:
906  csxXPointers = new unsigned int[numRows+1];
907  break;
908  case StorageFormat::CSC:
909  csxXPointers = new unsigned int[numCols+1];
910  break;
911  default:
912  TBTKExit(
913  "SparseMatrix::constructCSX()",
914  "Unknow StorageFormat.",
915  "This should never happen, contact the"
916  << " developer."
917  );
918  }
919  csxY = new unsigned int[csxNumMatrixElements];
920  csxValues = new DataType[csxNumMatrixElements];
921 
922  csxXPointers[0] = 0;
923  unsigned int currentMatrixElement = 0;
924  for(unsigned int x = 0; x < listOfLists.size(); x++){
925  csxXPointers[x+1]
926  = csxXPointers[x]
927  + listOfLists[x].size();
928 
929  for(
930  unsigned int y = 0;
931  y < listOfLists[x].size();
932  y++
933  ){
934  csxY[currentMatrixElement]
935  = std::get<0>(listOfLists[x][y]);
936  csxValues[currentMatrixElement]
937  = std::get<1>(listOfLists[x][y]);
938 
939  currentMatrixElement++;
940  }
941  }
942 
943  switch(storageFormat){
944  case StorageFormat::CSR:
945  for(
946  int row = listOfLists.size();
947  row < numRows;
948  row++
949  ){
950  csxXPointers[row+1] = csxXPointers[row];
951  }
952  break;
953  case StorageFormat::CSC:
954  for(
955  int col = listOfLists.size();
956  col < numCols;
957  col++
958  ){
959  csxXPointers[col+1] = csxXPointers[col];
960  }
961  break;
962  default:
963  TBTKExit(
964  "SparseMatrix::constructCSX()",
965  "Unknow StorageFormat.",
966  "This should never happen, contact the"
967  << " developer."
968  );
969  }
970 
971  TBTKAssert(
972  csxNumMatrixElements == (int)currentMatrixElement,
973  "SparseMatrix::constructCSX()",
974  "Invalid number of matrix elements.",
975  "This should never happen, contact the developer."
976  );
977  }
978 }
979 
980 template<typename DataType>
982  if(csxNumMatrixElements != -1){
983  TBTKAssert(
984  csxXPointers != nullptr
985  && csxY != nullptr
986  && csxValues != nullptr,
987  "SparseMatrix::convertCSXToLIL()",
988  "'csxNumMatrixElements' is not -1, but a csx-pointer"
989  << " is a nullptr.",
990  "This should never happen, contact the developer."
991  );
992 
993  switch(storageFormat){
994  case StorageFormat::CSR:
995  {
996  unsigned int row = 0;
997  for(int n = 0; n < csxNumMatrixElements; n++){
998  if((int)csxXPointers[row+1] == n){
999  for(
1000  int r = row+1;
1001  r < numRows+1;
1002  r++
1003  ){
1004  row++;
1005  if((int)csxXPointers[r+1] > n)
1006  break;
1007  }
1008  }
1009 
1010  add(row, csxY[n], csxValues[n]);
1011  }
1012 
1013  break;
1014  }
1015  case StorageFormat::CSC:
1016  {
1017  unsigned int col = 0;
1018  for(int n = 0; n < csxNumMatrixElements; n++){
1019  if((int)csxXPointers[col+1] == n){
1020  for(
1021  int c = col+1;
1022  c < numCols+1;
1023  c++
1024  ){
1025  col++;
1026  if((int)csxXPointers[c+1] > n)
1027  break;
1028  }
1029  }
1030 
1031  add(csxY[n], col, csxValues[n]);
1032  }
1033 
1034  break;
1035  }
1036  default:
1037  TBTKExit(
1038  "SparseMatrix::convertCSXToLIL()",
1039  "Unknow StorageFormat.",
1040  "This should never happen, contact the"
1041  << " developer."
1042  );
1043  }
1044 
1045  delete [] csxXPointers;
1046  delete [] csxY;
1047  delete [] csxValues;
1048  csxNumMatrixElements = -1;
1049  }
1050 }
1051 
1052 }; //End of namesapce TBTK
1053 
1054 #endif
const DataType * getCSCValues() const
Definition: SparseMatrix.h:654
Precompiler macros.
void mergeLIL(std::vector< std::vector< std::tuple< unsigned int, DataType >> > &listOfLists) const
Definition: SparseMatrix.h:822
void convertCSXToLIL()
Definition: SparseMatrix.h:981
SparseMatrix(StorageFormat)
Definition: SparseMatrix.h:165
void print() const
Definition: SparseMatrix.h:675
void constructCSX()
Definition: SparseMatrix.h:844
const DataType * getCSRValues() const
Definition: SparseMatrix.h:633
const unsigned int * getCSRColumns() const
Definition: SparseMatrix.h:591
unsigned int getNumColumns() const
Definition: SparseMatrix.h:505
void setStorageFormat(StorageFormat storageFormat)
Definition: SparseMatrix.h:482
std::vector< std::vector< std::tuple< unsigned int, DataType > > > constructLIL()
static std::ostream out
Definition: Streams.h:36
unsigned int getNumRows() const
Definition: SparseMatrix.h:493
~SparseMatrix()
Definition: SparseMatrix.h:311
const unsigned int * getCSRRowPointers() const
Definition: SparseMatrix.h:549
Definition: ModelFactory.h:35
Definition: SparseMatrix.h:35
SparseMatrix & operator=(const SparseMatrix &sparseMatrix)
Definition: SparseMatrix.h:321
void sortLIL(std::vector< std::vector< std::tuple< unsigned int, DataType >> > &listOfLists) const
Definition: SparseMatrix.h:802
unsigned int getCSCNumMatrixElements() const
Definition: SparseMatrix.h:533
const unsigned int * getCSCRows() const
Definition: SparseMatrix.h:612
void add(unsigned int row, unsigned int col, const DataType &value)
Definition: SparseMatrix.h:458
unsigned int getCSRNumMatrixElements() const
Definition: SparseMatrix.h:517
const unsigned int * getCSCColumnPointers() const
Definition: SparseMatrix.h:570
StorageFormat
Definition: SparseMatrix.h:38