ug4
sparsematrix_impl.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3  * Author: Martin Rupp
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG__CPU_ALGEBRA__SPARSEMATRIX_IMPL__
34 #define __H__UG__CPU_ALGEBRA__SPARSEMATRIX_IMPL__
35 
36 // creation etc
37 
38 #include <fstream>
39 #include <cstring>
40 
43 #include "sparsematrix.h"
44 #include <vector>
45 #include <algorithm>
46 
47 
48 
49 namespace ug{
50 
51 // defined in C99, and sometimes part of <math.h>, <cmath>
52 template <class __T> inline bool
53 iszero (__T __val)
54 {
55  return __val == 0;
56 }
57 
58 template<typename T>
60 {
61  PROFILE_SPMATRIX(SparseMatrix_constructor);
62  bNeedsValues = true;
63  iIterators=0;
64  nnz = 0;
65  m_numCols = 0;
66  maxValues = 0;
67  cols.resize(32);
68  if(bNeedsValues) values.resize(32);
69 }
70 
71 template<typename T>
73 {
74  std::vector<int>().swap(rowStart);
75  std::vector<int>().swap(rowMax);
76  std::vector<int>().swap(rowEnd);
77  m_numCols = 0;
78  nnz = 0;
79 
80  std::vector<int>().swap(cols);
81  std::vector<value_type>().swap(values);
82  maxValues = 0;
83 
84 #ifdef CHECK_ROW_ITERATORS
85  std::vector<int>().swap(nrOfRowIterators);
86 #endif
87 }
88 
89 
90 template<typename T>
91 void SparseMatrix<T>::resize_and_clear(size_t newRows, size_t newCols)
92 {
93  PROFILE_SPMATRIX(SparseMatrix_resize_and_clear);
94  rowStart.clear(); rowStart.resize(newRows+1, -1);
95  rowMax.clear(); rowMax.resize(newRows);
96  rowEnd.clear(); rowEnd.resize(newRows, -1);
97  m_numCols = newCols;
98  nnz = 0;
99 
100  cols.clear(); cols.resize(newRows);
101  values.clear();
102  if(bNeedsValues) values.resize(newRows);
103  maxValues = 0;
104 
105 #ifdef CHECK_ROW_ITERATORS
106  nrOfRowIterators.clear();
107  nrOfRowIterators.resize(newRows, 0);
108 #endif
109 }
110 
111 template<typename T>
112 void SparseMatrix<T>::resize_and_keep_values(size_t newRows, size_t newCols)
113 {
114  PROFILE_SPMATRIX(SparseMatrix_resize_and_keep_values);
115  //UG_LOG("SparseMatrix resize " << newRows << "x" << newCols << "\n");
116  if(newRows == 0 && newCols == 0)
117  return resize_and_clear(0,0);
118 
119  if(newRows != num_rows())
120  {
121  size_t oldrows = num_rows();
122  rowStart.resize(newRows+1, -1);
123  rowMax.resize(newRows);
124  rowEnd.resize(newRows, -1);
125 #ifdef CHECK_ROW_ITERATORS
126  nrOfRowIterators.resize(newRows, 0);
127 #endif
128  for(size_t i=oldrows; i<newRows; i++)
129  {
130  rowStart[i] = -1;
131  rowEnd[i] = -1;
132  }
133  }
134  if((int)newCols < m_numCols)
135  copyToNewSize(get_nnz_max_cols(newCols), newCols);
136 
137  m_numCols = newCols;
138 }
139 
140 
141 template<typename T>
143 {
144  std::fill(values.begin(), values.end(), value_type(0));
145 }
146 
147 
148 template<typename T>
150 {
151  PROFILE_SPMATRIX(SparseMatrix_set_as_transpose_of);
152  resize_and_clear(B.num_cols(), B.num_rows());
153  /*rowStart.resize(B.num_cols(), 0);
154  rowMax.resize(B.num_cols(), 0);
155  rowEnd.resize(B.num_cols(), 0);
156  nnz = B.nnz;
157  bNeedsValues = B.bNeedsValues;
158  if(bNeedsValues) values.resize(nnz);
159  cols.resize(nnz);
160  maxValues = B.maxValues;
161  fragmented = 0;
162  m_numCols = B.num_rows();
163  size_t r, c;
164  for(r=0; r<num_rows(); r++)
165  for(const_row_iterator it = B.begin_row(r); it != B.end_row(r); ++it)
166  rowMax[it.index()]++;
167  rowEnd[0] = rowMax[0];
168  rowEnd[0] = 0;
169  for(c=1; c<B.num_cols(); c++)
170  {
171  rowStart[c] = rowMax[c-1];
172  rowMax[c] = rowStart[c]+rowMax[c];
173  rowEnd[c] = rowStart[c];
174  }*/
175 
176  for(size_t r=0; r<B.num_rows(); r++)
177  {
178  const_row_iterator itEnd = B.end_row(r);
179  for(const_row_iterator it = B.begin_row(r); it != itEnd; ++it)
180  operator()(it.index(), r) = MatrixTranspose(scale*it.value());
181  }
182  // todo: sort rows
183 }
184 
185 template<typename T>
187 {
188  PROFILE_SPMATRIX(SparseMatrix_set_as_transpose_of2);
189  resize_and_clear(B.num_cols(), B.num_rows());
190  assert(num_cols() == B.num_rows());
191  assert(num_rows() == B.num_cols());
192  size_t r, c;
193 
194  for(r=0; r<num_rows(); ++r){
195  assert(rowMax[r] == 0);
196  }
197 
198  std::vector<int> rowsize(num_rows());
199  nnz = 0;
200  bNeedsValues = B.bNeedsValues; // allocate value array
201 
202  maxValues = B.maxValues;
203  fragmented = 0;
204 
205  for(r=0; r<num_cols(); r++){
206  for(const_row_iterator it = B.begin_row(r); it != B.end_row(r); ++it){
207  if(iszero(it.value())){
208  }else{
209  ++nnz;
210  ++rowMax[it.index()];
211  }
212  }
213  }
214 
215  rowStart[0] = 0;
216  rowEnd[0] = 0;
217  for(c=1; c<num_rows(); ++c) {
218  rowStart[c] = rowMax[c-1];
219  rowMax[c] = rowStart[c]+rowMax[c];
220  rowEnd[c] = rowStart[c];
221  }
222 
223  cols.resize(nnz);
224  if(bNeedsValues){
225  values.resize(nnz);
226  }else{
227  }
228 
229  for(r=0; r<num_cols(); ++r){
230  for(const_row_iterator it = B.begin_row(r); it != B.end_row(r); ++it){
231  if(iszero(it.value())){
232  }else{
233  int idx = rowEnd[it.index()]++;
234  if(bNeedsValues){
235  values[idx] = scale * it.value();
236  }else{
237  }
238  cols[idx] = r;
239  }
240  }
241  }
242 
243 #ifndef NDEBUG
244  for(r=0; r<num_rows(); ++r){
245  assert(rowMax[r] == rowEnd[r]);
246  }
247 
248  assert(nnz <= B.nnz);
249 
250  for(r=1; r<num_rows(); ++r) {
251  assert(rowEnd[r] == rowMax[r]);
252  }
253 #endif
254 
255 }
256 
257 template<typename T>
258 template<typename vector_t>
259 inline void SparseMatrix<T>::mat_mult_add_row(size_t row, typename vector_t::value_type &dest, double alpha, const vector_t &v) const
260 {
261 
262  size_t itEnd=rowEnd[row];
263  for(size_t rowIt=rowStart[row]; rowIt != itEnd; ++rowIt)
264  MatMultAdd(dest, 1.0, dest, alpha, values[rowIt], v[cols[rowIt]]);
265 
266  //for(const_row_iterator conn = begin_row(row); conn != end_row(row); ++conn)
267  //MatMultAdd(dest, 1.0, dest, alpha, conn.value(), v[conn.index()]);
268 }
269 
270 
271 template<typename T>
272 template<typename vector_t>
274  const number &beta1, const vector_t &w1) const
275 {
276  for(size_t i=0; i < num_rows(); i++)
277  {
278  size_t rowIt=rowStart[i];
279  size_t itEnd=rowEnd[i];
280  if(rowIt == itEnd)
281  continue;
282 
283  MatMult(dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
284  for(++rowIt; rowIt != itEnd; ++rowIt)
285  // res[i] += conn.value() * x[conn.index()];
286  MatMultAdd(dest[i], 1.0, dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
287  }
288 }
289 
290 
291 // calculate dest = alpha1*v1 + beta1*A*w1 (A = this matrix)
292 template<typename T>
293 template<typename vector_t>
294 void SparseMatrix<T>::axpy(vector_t &dest,
295  const number &alpha1, const vector_t &v1,
296  const number &beta1, const vector_t &w1) const
297 {
298  PROFILE_SPMATRIX(SparseMatrix_axpy);
299  check_fragmentation();
300  if(alpha1 == 0.0)
301  {
302  for(size_t i=0; i < num_rows(); i++)
303  {
304  size_t rowIt=rowStart[i];
305  size_t itEnd=rowEnd[i];
306  if(rowIt == itEnd)
307  {
308  dest[i] = 0.0;
309  continue;
310  }
311  MatMult(dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
312  for(++rowIt; rowIt != itEnd; ++rowIt)
313  // res[i] += conn.value() * x[conn.index()];
314  MatMultAdd(dest[i], 1.0, dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
315  }
316  }
317  else if(&dest == &v1)
318  {
319  if(alpha1 != 1.0) {
320  for(size_t i=0; i < num_rows(); i++)
321  {
322  dest[i] *= alpha1;
323  mat_mult_add_row(i, dest[i], beta1, w1);
324  }
325  }
326  else
327  for(size_t i=0; i < num_rows(); i++)
328  mat_mult_add_row(i, dest[i], beta1, w1);
329 
330  }
331  else
332  {
333  for(size_t i=0; i < num_rows(); i++)
334  {
335  VecScaleAssign(dest[i], alpha1, v1[i]);
336  mat_mult_add_row(i, dest[i], beta1, w1);
337  }
338  }
339 }
340 
341 // calculate dest = alpha1*v1 + beta1*A^T*w1 (A = this matrix)
342 template<typename T>
343 template<typename vector_t>
345  const number &alpha1, const vector_t &v1,
346  const number &beta1, const vector_t &w1) const
347 {
348  PROFILE_SPMATRIX(SparseMatrix_axpy_transposed);
349  check_fragmentation();
350  if(&dest == &v1) {
351  if(alpha1 == 0.0)
352  dest.set(0.0);
353  else if(alpha1 != 1.0)
354  dest *= alpha1;
355  }
356  else if(alpha1 == 0.0)
357  dest.set(0.0);
358  else
359  VecScaleAssign(dest, alpha1, v1);
360 
361  for(size_t i=0; i<num_rows(); i++)
362  {
363 
364  size_t itEnd=rowEnd[i];
365  for(size_t rowIt=rowStart[i]; rowIt != itEnd; ++rowIt)
366  // dest[conn.index()] += beta1 * conn.value() * w1[i];
367  if(values[rowIt] != 0.0)
368  MatMultTransposedAdd(dest[cols[rowIt]], 1.0, dest[cols[rowIt]], beta1, values[rowIt], w1[i]);
369  }
370 }
371 
372 
373 template<typename T>
374 template<typename vector_t>
376  const number &beta1, const vector_t &w1) const
377 {
378  for(size_t i=0; i<num_rows(); i++)
379  {
380  row_iterator itEnd = end_row(i);
381  for(const_row_iterator conn = begin_row(i); conn != itEnd; ++conn)
382  dest[conn.index()] = 0.0;
383  }
384 
385  for(size_t i=0; i<num_rows(); i++)
386  {
387  size_t itEnd=rowEnd[i];
388  for(size_t rowIt=rowStart[i]; rowIt != itEnd; ++rowIt)
389  // dest[conn.index()] += beta1 * conn.value() * w1[i];
390  if(values[rowIt] != 0.0)
391  MatMultTransposedAdd(dest[cols[rowIt]], 1.0, dest[cols[rowIt]], beta1, values[rowIt], w1[i]);
392  }
393 }
394 
395 
396 template<typename T>
397 void SparseMatrix<T>::set(double a)
398 {
399  PROFILE_SPMATRIX(SparseMatrix_set);
400  check_fragmentation();
401  for(size_t row=0; row<num_rows(); row++)
402  {
403  row_iterator itEnd = end_row(row);
404  for(row_iterator it = begin_row(row); it != itEnd; ++it)
405  {
406  if(it.index() == row)
407  it.value() = a;
408  else
409  it.value() = 0.0;
410  }
411  }
412 }
413 
414 
415 template<typename T>
416 inline bool SparseMatrix<T>::is_isolated(size_t i) const
417 {
418  UG_ASSERT(i < num_rows() && i >= 0, *this << ": " << i << " out of bounds.");
419 
420  const_row_iterator itEnd = end_row(i);
421  for(const_row_iterator it = begin_row(i); it != itEnd; ++it)
422  if(it.index() != i && it.value() != 0.0)
423  return false;
424  return true;
425 }
426 
427 
428 template<typename T>
429 void SparseMatrix<T>::set_matrix_row(size_t row, connection *c, size_t nr)
430 {
431  /*PROFILE_SPMATRIX(SparseMatrix_set_matrix_row);
432  bool bSorted=false;
433  for(size_t i=0; bSorted && i+1 < nr; i++)
434  bSorted = c[i].iIndex < c[i+1].iIndex;
435  if(bSorted)
436  {
437  int start;
438  if(rowStart[row] == -1 || rowMax[row] - rowStart[row] < (int)nr)
439  {
440  assureValuesSize(maxValues+nr);
441  start = maxValues;
442  rowMax[row] = start+nr;
443  rowStart[row] = start;
444  maxValues+=nr;
445  }
446  else
447  start = rowStart[row];
448  rowEnd[row] = start+nr;
449  for(size_t i=0; i<nr; i++)
450  {
451  cols[start+i] = c[i].iIndex;
452  values[start+i] = c[i].dValue;
453  }
454  }
455  else*/
456  {
457  for(size_t i=0; i<nr; i++)
458  operator()(row, c[i].iIndex) = c[i].dValue;
459  }
460 }
461 
462 template<typename T>
463 void SparseMatrix<T>::add_matrix_row(size_t row, connection *c, size_t nr)
464 {
465  //PROFILE_SPMATRIX(SparseMatrix_add_matrix_row);
466  for(size_t i=0; i<nr; i++)
467  operator()(row, c[i].iIndex) += c[i].dValue;
468 }
469 
470 
471 template<typename T>
473 {
474  //PROFILE_SPMATRIX(SparseMatrix_set_as_copy_of);
475  resize_and_clear(B.num_rows(), B.num_cols());
476  for(size_t i=0; i < B.num_rows(); i++)
477  {
478  const_row_iterator itEnd = B.end_row(i);
479  for(const_row_iterator it = B.begin_row(i); it != itEnd; ++it)
480  operator()(i, it.index()) = scale*it.value();
481  }
482 }
483 
484 
485 
486 template<typename T>
488 {
489  //PROFILE_SPMATRIX(SparseMatrix_scale);
490  for(size_t i=0; i < num_rows(); i++)
491  {
492  row_iterator itEnd = end_row(i);
493  for(row_iterator it = begin_row(i); it != itEnd; ++it)
494  it.value() *= d;
495  }
496 }
497 
498 
499 
500 
501 
502 //======================================================================================================
503 // submatrix set/get
504 
505 template<typename T>
506 template<typename M>
507 void SparseMatrix<T>::add(const M &mat)
508 {
509  for(size_t i=0; i < mat.num_rows(); i++)
510  {
511  int r = mat.row_index(i);
512  for(size_t j=0; j < mat.num_cols(); j++)
513  {
514  int c = mat.col_index(j);
515  (*this)(r,c) += mat(i,j);
516  }
517  }
518 }
519 
520 
521 template<typename T>
522 template<typename M>
523 void SparseMatrix<T>::set(const M &mat)
524 {
525  for(size_t i=0; i < mat.num_rows(); i++)
526  {
527  int r = mat.row_index(i);
528  for(size_t j=0; j < mat.num_cols(); j++)
529  {
530  int c = mat.col_index(j);
531  (*this)(r,c) = mat(i,j);
532  }
533  }
534 }
535 
536 template<typename T>
537 template<typename M>
538 void SparseMatrix<T>::get(M &mat) const
539 {
540  for(size_t i=0; i < mat.num_rows(); i++)
541  {
542  int r = mat.row_index(i);
543  for(size_t j=0; j < mat.num_cols(); j++)
544  {
545  int c = mat.col_index(j);
546  mat(i,j) = (*this)(r,c);
547  }
548  }
549 }
550 
551 
552 template<typename T>
553 int SparseMatrix<T>::get_index_internal(size_t row, int col) const
554 {
555 // PROFILE_SPMATRIX(SP_get_index_internal);
556  assert(rowStart[row] != -1);
557  int l = rowStart[row];
558  int r = rowEnd[row];
559  int mid=0;
560  while(l < r)
561  {
562  mid = (l+r)/2;
563  if(cols[mid] < col)
564  l = mid+1;
565  else if(cols[mid] > col)
566  r = mid-1;
567  else
568  return mid;
569  }
570  mid = (l+r)/2;
571  int ret;
572  if(mid < rowStart[row])
573  ret = rowStart[row];
574  else if(mid == rowEnd[row] || col <= cols[mid])
575  ret = mid;
576  else ret = mid+1;
577  UG_ASSERT(ret <= rowEnd[row] && ret >= rowStart[row], "row iterator row " << row << " pos " << ret << " out of bounds [" << rowStart[row] << ", " << rowEnd[row] << "]");
578  return ret;
579 }
580 
581 
582 
583 template<typename T>
584 int SparseMatrix<T>::get_index_const(int r, int c) const
585 {
586  if(rowStart[r] == -1 || rowStart[r] == rowEnd[r]) return -1;
587  int index=get_index_internal(r, c);
588  if(index >= rowStart[r] && index < rowEnd[r] && cols[index] == c)
589  return index;
590  else
591  return -1;
592 }
593 
594 
595 template<typename T>
596 int SparseMatrix<T>::get_index(int r, int c)
597 {
598 // UG_LOG("get_index " << r << ", " << c << "\n");
599 // UG_LOG(rowStart[r] << " - " << rowMax[r] << " - " << rowEnd[r] << " - " << cols.size() << " - " << maxValues << "\n");
600  if(rowStart[r] == -1 || rowStart[r] == rowEnd[r])
601  {
602 // UG_LOG("new row\n");
603  // row did not start, start new row at the end of cols array
604  assureValuesSize(maxValues+1);
605  rowStart[r] = maxValues;
606  rowEnd[r] = maxValues+1;
607  rowMax[r] = maxValues+1;
608  if(bNeedsValues) values[maxValues] = 0.0;
609  cols[maxValues] = c;
610  maxValues++;
611  nnz++;
612  return maxValues-1;
613  }
614 
615  /* for(int i=rowStart[r]; i<rowEnd[r]; i++)
616  if(cols[i] == c)
617  return i;*/
618 
619  // get the index where (r,c) _should_ be
620  int index=get_index_internal(r, c);
621 
622  if(index < rowEnd[r]
623  && cols[index] == c)
624  {
625 // UG_LOG("found\n");
626  return index; // we found it
627  }
628 
629  // we did not find it, so we have to add it
630 
631  check_row_modifiable(r);
632 
633 #ifndef NDEBUG
634  assert(index == rowEnd[r] || cols[index] > c);
635  assert(index == rowStart[r] || cols[index-1] < c);
636  for(int i=rowStart[r]+1; i<rowEnd[r]; i++)
637  assert(cols[i] > cols[i-1]);
638 #endif
639  if(rowEnd[r] == rowMax[r] && rowEnd[r] == maxValues
640  && maxValues < (int)cols.size())
641  {
642 // UG_LOG("at end\n");
643  // this row is stored at the end, so we can easily make more room
644  rowMax[r]++;
645  maxValues++;
646  }
647 
648  if(rowEnd[r] == rowMax[r])
649  {
650 // UG_LOG("renew\n");
651  // row is full, we need to copy it to another place
652  int newSize = (rowEnd[r]-rowStart[r])*2;
653  if(maxValues+newSize > (int)cols.size())
654  {
655 // UG_LOG("ass\n");
656  assureValuesSize(maxValues+newSize);
657  index=get_index_internal(r, c);
658  }
659  // copy it to the end and insert index
660  fragmented += rowEnd[r]-rowStart[r];
661  index = index-rowStart[r]+maxValues;
662  int j=rowEnd[r]-rowStart[r]+maxValues;
663  if(rowEnd[r] != 0)
664  for(int i=rowEnd[r]-1; i>=rowStart[r]; i--, j--)
665  {
666  if(j==index) j--;
667  if(bNeedsValues) values[j] = values[i];
668  cols[j] = cols[i];
669  if(i==rowStart[r]) break;
670  }
671  rowEnd[r] = maxValues+rowEnd[r]-rowStart[r]+1;
672  rowStart[r] = maxValues;
673  rowMax[r] = maxValues+newSize;
674  maxValues += newSize;
675  }
676  else
677  {
678 // UG_LOG("enlength\n");
679  // move part > index so we can insert the index
680  if(rowEnd[r] != 0)
681  for(int i=rowEnd[r]-1; i>=index; i--)
682  {
683  if(bNeedsValues) values[i+1] = values[i];
684  cols[i+1] = cols[i];
685  if(i==index) break;
686  }
687  rowEnd[r]++;
688  }
689  if(bNeedsValues) values[index] = 0.0;
690  cols[index] = c;
691 
692  nnz++;
693 #ifndef NDEBUG
694  assert(index >= rowStart[r] && index < rowEnd[r]);
695  for(int i=rowStart[r]+1; i<rowEnd[r]; i++)
696  assert(cols[i] > cols[i-1]);
697 #endif
698  return index;
699 
700 }
701 
702 template<typename T>
703 void SparseMatrix<T>::copyToNewSize(size_t newSize, size_t maxCol)
704 {
705  PROFILE_SPMATRIX(SparseMatrix_copyToNewSize);
706  /*UG_LOG("copyToNewSize: from " << values.size() << " to " << newSize << "\n");
707  UG_LOG("sizes are " << cols.size() << " and " << values.size() << ", ");
708  UG_LOG(reset_floats << "capacities are " << cols.capacity() << " and " << values.capacity() << ", NNZ = " << nnz << ", fragmentation = " <<
709  (1-((double)nnz)/cols.size())*100.0 << "%\n");
710  if(newSize == nnz) { UG_LOG("Defragmenting to NNZ."); }*/
711  if( (iIterators > 0)
712  || (newSize > values.size() && (100.0*nnz)/newSize < 20 && newSize <= cols.capacity()) )
713  {
714  UG_ASSERT(newSize > values.size(), "no nnz-defragmenting while using iterators.");
715  //UG_LOG("copyToNew not defragmenting because of iterators or low fragmentation.\n");}
716  cols.resize(newSize);
717  cols.resize(cols.capacity());
718  if(bNeedsValues) { values.resize(newSize); values.resize(cols.size()); }
719  return;
720  }
721 
722  std::vector<value_type> v(newSize);
723  std::vector<int> c(newSize);
724  size_t j=0;
725  for(size_t r=0; r<num_rows(); r++)
726  {
727  if(rowStart[r] == -1)
728  rowStart[r] = rowEnd[r] = rowMax[r] = j;
729  else
730  {
731  size_t start=j;
732  for(int k=rowStart[r]; k<rowEnd[r]; k++)
733  {
734  if(cols[k] < (int)maxCol)
735  {
736  if(bNeedsValues) v[j] = values[k];
737  c[j] = cols[k];
738  j++;
739  }
740  }
741  rowStart[r] = start;
742  rowEnd[r] = rowMax[r] = j;
743  }
744  }
745  rowStart[num_rows()] = rowEnd[num_rows()-1];
746  fragmented = 0;
747  maxValues = j;
748  if(bNeedsValues) values.swap(v);
749  cols.swap(c);
750 }
751 
752 template<typename T>
754 {
755  if((double)nnz/(double)maxValues < 0.9)
756  defragment();
757 }
758 
759 template<typename T>
761 {
762  if(s <= cols.size()) return;
763  size_t newSize = nnz*2;
764  if(newSize < s) newSize = s;
765  copyToNewSize(newSize);
766 
767 }
768 
769 template<typename T>
771 {
772  int j=0;
773  for(size_t r=0; r<num_rows(); r++)
774  {
775  if(rowStart[r] == -1) continue;
776  for(int k=rowStart[r]; k<rowEnd[r]; k++)
777  if(cols[k] < (int)maxCols)
778  j++;
779  }
780  return j;
781 }
782 
783 } // namespace ug
784 
785 #endif
786 
parameterString s
bool MatMultAdd(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const matrix_t &A1, const vector_t &w1)
calculates dest = alpha1*v1 + beta1 * A1 *w1;
bool MatMult(vector_t &dest, const matrix_t &A1, const vector_t &w1)
calculates dest = A1 * w1;
Definition: connection.h:40
size_t iIndex
Definition: connection.h:42
Definition: sparsematrix.h:421
Definition: sparsematrix.h:366
sparse matrix for big, variable sparse matrices.
Definition: sparsematrix.h:99
size_t nnz
Definition: sparsematrix.h:742
TValueType value_type
Definition: sparsematrix.h:101
size_t num_rows() const
returns number of rows
Definition: sparsematrix.h:342
int maxValues
Definition: sparsematrix.h:746
SparseMatrix()
constructor for empty SparseMatrix
Definition: sparsematrix_impl.h:59
row_iterator end_row(size_t r)
Definition: sparsematrix.h:485
size_t num_cols() const
returns the number of cols
Definition: sparsematrix.h:345
row_iterator begin_row(size_t r)
Definition: sparsematrix.h:484
bool bNeedsValues
Definition: sparsematrix.h:743
function util fill(N, c)
DenseMatrix< TStorage > MatrixTranspose(const DenseMatrix< TStorage > &A)
Definition: densematrix.h:240
number alpha
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
double number
Definition: types.h:124
SM_edge_weight_map< typename T::value_type, ug::BidirectionalMatrix< T > > get(edge_weight_t, ug::BidirectionalMatrix< T > const &g)
Definition: bidirectional_boost.h:157
the ug namespace
bool iszero(__T __val)
Definition: sparsematrix_impl.h:53
bool MatMultTransposedAdd(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const matrix_t &A1, const vector_t &w1)
calculates dest = alpha1*v1 + beta1 * A1 *w1;
Definition: operations_mat.h:121
void VecScaleAssign(double &dest, double alpha1, const double &v1)
calculates dest = alpha1*v1. for doubles
Definition: operations_vec.h:49
#define PROFILE_SPMATRIX(name)
Definition: sparsematrix.h:47
T value_type
Definition: sparsematrix_interface.h:2
size_t num_rows() const
Definition: sparsematrix_interface.h:38
const_row_iterator end_row(size_t row) const
value_type & operator()(size_t r, size_t c)
void defragment()
const_row_iterator begin_row(size_t row) const
size_t num_cols() const
Definition: sparsematrix_interface.h:39