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