BandMatrix.cxx
1 // Copyright (C) 2014 INRIA
2 // Author(s): Marc DuruflĂ©
3 //
4 // This file is part of the linear-algebra library Seldon,
5 // http://seldon.sourceforge.net/.
6 //
7 // Seldon is free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 2.1 of the License, or (at your option)
10 // any later version.
11 //
12 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 // more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with Seldon. If not, see http://www.gnu.org/licenses/.
19 
20 #ifndef SELDON_FILE_BAND_MATRIX_CXX
21 
22 #include "BandMatrixInline.cxx"
23 
24 namespace Seldon
25 {
26 
27  /***************
28  * Matrix_Band *
29  ***************/
30 
31 
33  template <class T, class Prop, class Storage, class Allocator>
35  {
36  kl_ = 0;
37  ku_ = 0;
38  this->m_ = 0;
39  this->n_ = 0;
40  }
41 
42 
44  template <class T, class Prop, class Storage, class Allocator>
46  {
47  kl_ = 0;
48  ku_ = 0;
49  this->m_ = 0;
50  this->n_ = 0;
51  data_.Clear();
52  }
53 
54 
56  template <class T, class Prop, class Storage, class Allocator>
58  ::Reallocate(int m, int n, int kl, int ku)
59  {
60  this->m_ = m;
61  this->n_ = n;
62  kl_ = kl;
63  ku_ = ku;
64  data_.Reallocate(2*kl_+ku_+1, this->n_);
65  data_.Fill(0);
66  }
67 
68 
70  template <class T, class Prop, class Storage, class Allocator>
72  ::AddInteraction(int i, int j, const T& val)
73  {
74  int k = kl_ + ku_ + i - j;
75  if ((k >= kl_) && (k <= 2*kl_+ku_))
76  data_(k, j) += val;
77  else
78  {
79  cout << "Matrix not compatible " << endl;
80  abort();
81  }
82  }
83 
84 
86 
92  template <class T, class Prop, class Storage, class Allocator>
94  AddInteractionRow(int i, int n, const IVect& num, const Vector<T>& val,
95  bool sorted)
96  {
97  for (int j = 0; j < n; j++)
98  AddInteraction(i, num(j), val(j));
99  }
100 
101 
103 
106  template <class T, class Prop, class Storage, class Allocator>
108  {
109  T zero; SetComplexZero(zero);
110  for (int k = max(-i, -this->kl_); k <= min(this->ku_, this->n_-1-i); k++)
111  {
112  int j = i+k;
113  this->Get(i, j) = zero;
114  }
115  }
116 
117 
119  template <class T, class Prop, class Storage, class Allocator>
121  ::operator()(int i, int j) const
122  {
123  T zero; SetComplexZero(zero);
124  int k = kl_ + ku_ + i - j;
125  if ((k >= kl_) && (k <= 2*kl_+ku_))
126  return data_(k, j);
127 
128  return zero;
129  }
130 
131 
133  template <class T, class Prop, class Storage, class Allocator>
135  {
136  int k = kl_ + ku_ + i - j;
137  if ((k >= kl_) && (k <= 2*kl_+ku_))
138  return data_(k, j);
139  else
140  {
141  cout << "Element not accessible " << endl;
142  abort();
143  }
144  }
145 
146 
148  template <class T, class Prop, class Storage, class Allocator>
150  {
151  int k = kl_ + ku_ + i - j;
152  if ((k >= kl_) && (k <= 2*kl_+ku_))
153  return data_(k, j);
154  else
155  {
156  cout << "Element not accessible " << endl;
157  abort();
158  }
159  }
160 
161 
163  template <class T, class Prop, class Storage, class Allocator>
165  {
166  T zero, one; SetComplexZero(zero);
167  SetComplexOne(one);
168 
169  data_.Fill(zero);
170  for (int i = 0; i < this->n_; i++)
171  data_(kl_+ku_, i) = one;
172  }
173 
174 
176  template <class T, class Prop, class Storage, class Allocator>
177  template<class T0>
179  {
180  data_.Fill(x);
181 
182  T zero; SetComplexZero(zero);
183  for (int i = 0; i < this->n_; i++)
184  for (int j = 0; j < kl_; j++)
185  data_(j, i) = zero;
186  }
187 
188 
190  template <class T, class Prop, class Storage, class Allocator>
192  {
193  data_.FillRand();
194 
195  T zero; SetComplexZero(zero);
196  for (int i = 0; i < this->n_; i++)
197  for (int j = 0; j < kl_; j++)
198  data_(j, i) = zero;
199  }
200 
201 
203  template <class T, class Prop, class Storage, class Allocator>
206  {
207  Clear();
208 
209  // finding kl and ku
210  int kl = 0, ku = 0;
211  for (int i = 0; i < A.GetM(); i++)
212  for (int j = 0; j < A.GetRowSize(i); j++)
213  {
214  int col = A.Index(i, j);
215  if (col < i)
216  kl = max(kl, i-col);
217  else if (col > i)
218  ku = max(ku, col-i);
219  }
220 
221  Reallocate(A.GetM(), A.GetN(), kl, ku);
222  T zero; SetComplexZero(zero);
223  Fill(zero);
224 
225  // filling the matrix with values of A
226  for (int i = 0; i < A.GetM(); i++)
227  for (int j = 0; j < A.GetRowSize(i); j++)
228  AddInteraction(i, A.Index(i, j), A.Value(i, j));
229 
230  }
231 
232 
234  template <class T, class Prop, class Storage, class Allocator>
236  {
237  // position of the main diagonal
238  int d = kl_ + ku_;
239  T pivot, one;
240  SetComplexOne(one);
241  for (int j = 0; j < this->n_; j++)
242  {
243  // replacing diagonal element by its inverse
244  data_(d, j) = one/data_(d, j);
245  for (int p = 1; p <= min(this->m_ - 1 - j, kl_); p++)
246  {
247  pivot = data_(d+p, j)*data_(d, j);
248  data_(d+p, j) = pivot;
249  for (int k = 1; k <= min(this->n_ - 1 - j, ku_); k++)
250  data_(d+p-k, j+k) -= pivot*data_(d-k, j+k);
251  }
252  }
253  }
254 
255 
257  template <class T, class Prop, class Storage, class Allocator>
259  {
260  ipivot.Reallocate(this->m_);
261  // position of the main diagonal
262  int d = kl_ + ku_;
263  T pivot, one, tmp;
264  typename ClassComplexType<T>::Treal amax;
265  SetComplexOne(one);
266  for (int j = 0; j < this->n_; j++)
267  {
268  // searching pivot
269  int pmin = min(this->m_ - 1 - j, kl_);
270  amax = abs(data_(d, j));
271  int p0 = 0;
272  for (int p = 1; p <= pmin; p++)
273  if (abs(data_(d+p, j)) > amax)
274  {
275  p0 = p;
276  amax = abs(data_(d+p, j));
277  }
278 
279  ipivot(j) = j+p0;
280  if (p0 > 0)
281  {
282  // interchanging row j and j + p0
283  for (int j2 = j; j2 <= min(this->m_-1, kl_ + ku_ + j); j2++)
284  {
285  int k = kl_ + ku_ + j - j2;
286  tmp = data_(k, j2);
287  data_(k, j2) = data_(k+p0, j2);
288  data_(k+p0, j2) = tmp;
289  }
290  }
291 
292  // replacing diagonal element by its inverse
293  data_(d, j) = one/data_(d, j);
294 
295  // performing Gauss elimination on column j
296  for (int p = 1; p <= pmin; p++)
297  {
298  pivot = data_(d+p, j)*data_(d, j);
299  data_(d+p, j) = pivot;
300 
301  for (int k = 1; k <= min(this->n_ - 1 - j, kl_ + ku_); k++)
302  data_(d+p-k, j+k) -= pivot*data_(d-k, j+k);
303  }
304  }
305  }
306 
307 
309  template <class T, class Prop, class Storage, class Allocator>
310  template<class T0> void Matrix_Band<T, Prop, Storage, Allocator>
312  {
313  int kl = A.GetKL();
314  int ku = A.GetKU();
315  for (int i = 0; i < A.GetM(); i++)
316  for (int k = max(-i, -kl); k <= min(ku, this->n_-1-i); k++)
317  {
318  int j = i + k;
319  AddInteraction(i, j, alpha*A(i, j));
320  }
321  }
322 
323 
325  template <class T, class Prop, class Storage, class Allocator>
326  template<class T0, class T1>
328  ::MltAdd(const T0& alpha, const SeldonTranspose& trans,
329  const Vector<T1>& x, Vector<T1>& y) const
330  {
331  int d = kl_ + ku_; T1 val;
332  if (trans.NoTrans())
333  {
334  for (int j = 0; j < GetN(); j++)
335  {
336  int kmin = max(kl_, d - j), row;
337  int kmax = min(kl_ + d, this->m_ -1 + d - j);
338  val = alpha*x(j);
339  for (int k = kmin; k <= kmax; k++)
340  {
341  row = j + k - d;
342  y(row) = y(row) + data_(k, j)*val;
343  }
344  }
345  }
346  else if (trans.Trans())
347  {
348  for (int j = 0; j < GetN(); j++)
349  {
350  int kmin = max(kl_, d - j), row;
351  int kmax = min(kl_ + d, this->m_ -1 + d - j);
352  val = T1(0);
353  for (int k = kmin; k <= kmax; k++)
354  {
355  row = j + k - d;
356  val += data_(k, j)*x(row);
357  }
358 
359  y(j) += alpha*val;
360  }
361  }
362  else
363  {
364  for (int j = 0; j < GetN(); j++)
365  {
366  int kmin = max(kl_, d - j), row;
367  int kmax = min(kl_ + d, this->m_ -1 + d - j);
368  val = T1(0);
369  for (int k = kmin; k <= kmax; k++)
370  {
371  row = j + k - d;
372  val += conjugate(data_(k, j))*x(row);
373  }
374 
375  y(j) += alpha*val;
376  }
377  }
378  }
379 
380 
382  template <class T, class Prop, class Storage, class Allocator>
383  template<class T1>
385  {
386  int d = kl_ + ku_;
387  // resolution of L y = x
388  for (int j = 0; j < this->n_; j++)
389  for (int p = 1; p <= min(this->m_ - 1 - j, kl_); p++)
390  x(j+p) -= data_(d+p, j)*x(j);
391 
392  // resolution of U x = y
393  for (int j = this->n_-1; j >= 0; j--)
394  {
395  x(j) *= data_(d, j);
396  for (int p = 1; p <= min(j, ku_); p++)
397  x(j-p) -= data_(d-p, j)*x(j);
398  }
399  }
400 
401 
404  template <class T, class Prop, class Storage, class Allocator>
405  template<class T1> void Matrix_Band<T, Prop, Storage, Allocator>
406  ::Solve(const Vector<int>& ipivot, Vector<T1>& x) const
407  {
408  int d = kl_ + ku_;
409  T1 tmp;
410  // resolution of L y = x
411  for (int j = 0; j < this->n_; j++)
412  {
413  // applying row interchange if needed
414  if (ipivot(j) != j)
415  {
416  tmp = x(j);
417  x(j) = x(ipivot(j));
418  x(ipivot(j)) = tmp;
419  }
420 
421  for (int p = 1; p <= min(this->m_ - 1 - j, kl_); p++)
422  x(j+p) -= data_(d+p, j)*x(j);
423  }
424 
425  // resolution of U x = y
426  for (int j = this->n_-1; j >= 0; j--)
427  {
428  x(j) *= data_(d, j);
429  for (int p = 1; p <= min(j, kl_+ku_); p++)
430  x(j-p) -= data_(d-p, j)*x(j);
431  }
432  }
433 
434 
436  template <class T, class Prop, class Storage, class Allocator>
438  {
439  ofstream FileStream;
440  FileStream.open(FileName.c_str());
441 
442 #ifdef SELDON_CHECK_IO
443  // Checks if the file was opened.
444  if (!FileStream.is_open())
445  throw IOError("Matrix_Band::Write(string FileName)",
446  string("Unable to open file \"") + FileName + "\".");
447 #endif
448 
449  this->Write(FileStream);
450 
451  FileStream.close();
452  }
453 
454 
456  template <class T, class Prop, class Storage, class Allocator>
458  ::Write(ostream& FileStream) const
459  {
460  FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->m_)),
461  sizeof(int));
462  FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->n_)),
463  sizeof(int));
464  FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->kl_)),
465  sizeof(int));
466  FileStream.write(reinterpret_cast<char*>(const_cast<int*>(&this->ku_)),
467  sizeof(int));
468 
469  data_.Write(FileStream, false);
470  }
471 
472 
474  template <class T, class Prop, class Storage, class Allocator>
476  ::WriteText(string FileName) const
477  {
478  ofstream FileStream;
479  FileStream.precision(cout.precision());
480  FileStream.flags(cout.flags());
481  FileStream.open(FileName.c_str());
482 
483 #ifdef SELDON_CHECK_IO
484  // Checks if the file was opened.
485  if (!FileStream.is_open())
486  throw IOError("TinyBandMatrix::WriteText(string FileName)",
487  string("Unable to open file \"") + FileName + "\".");
488 #endif
489 
490  this->WriteText(FileStream);
491 
492  FileStream.close();
493  }
494 
495 
497  template <class T, class Prop, class Storage, class Allocator>
499  ::WriteText(ostream& FileStream) const
500  {
501  int d = kl_ + ku_;
502  for (int j = 0; j < GetN(); j++)
503  {
504  int kmin = max(kl_, d - j);
505  //int kmin = max(0, d-j);
506  int kmax = min(kl_ + d, this->m_ -1 + d - j);
507  for (int k = kmin; k <= kmax; k++)
508  {
509  int row = j + k - d;
510  FileStream
511  << row + 1 << " " << j+1 << " " << data_(k, j) << '\n';
512  }
513  }
514  }
515 
516 
517  /****************
518  * Matrix_Arrow *
519  ****************/
520 
521 
523  template <class T, class Prop, class Storage, class Allocator>
525  {
527 
528  last_rows_.Clear();
529  last_columns_.Clear();
530  last_block_.Clear();
531  }
532 
533 
535  template <class T, class Prop, class Storage, class Allocator>
537  {
538  this->data_.Zero();
539  last_rows_.Zero();
540  last_columns_.Zero();
541  last_block_.Zero();
542  }
543 
544 
546  template <class T, class Prop, class Storage, class Allocator>
548  Reallocate(int m, int n, int kl, int ku,
549  int nb_last_row, int nb_last_col)
550  {
552  Reallocate(m-nb_last_row, n-nb_last_col, kl, ku);
553 
554  last_rows_.Reallocate(nb_last_row, n-nb_last_col);
555  last_columns_.Reallocate(m-nb_last_row, nb_last_col);
556  last_block_.Reallocate(nb_last_row, nb_last_col);
557  }
558 
559 
561  template <class T, class Prop, class Storage, class Allocator>
563  ::AddInteraction(int i, int j, const T& val)
564  {
565  if (i >= this->m_)
566  {
567  if (j >= this->n_)
568  last_block_(i-this->m_, j-this->n_) += val;
569  else
570  last_rows_(i-this->m_, j) += val;
571  }
572  else
573  {
574  if (j >= this->n_)
575  last_columns_(i, j-this->n_) += val;
576  else
578  AddInteraction(i, j, val);
579  }
580  }
581 
582 
584 
590  template <class T, class Prop, class Storage, class Allocator>
592  AddInteractionRow(int i, int n, const IVect& num, const Vector<T>& val,
593  bool sorted)
594  {
595  for (int j = 0; j < n; j++)
596  AddInteraction(i, num(j), val(j));
597  }
598 
599 
601 
604  template <class T, class Prop, class Storage, class Allocator>
606  {
607  T zero; SetComplexZero(zero);
608  if (i < this->m_)
609  {
610  for (int k = max(-i, -this->kl_);
611  k <= min(this->ku_, this->n_-1-i); k++)
612  {
613  int j = i+k;
614  this->Get(i, j) = zero;
615  }
616 
617  for (int j = 0; j < last_columns_.GetN(); j++)
618  this->Get(i, this->n_+j) = zero;
619  }
620  else
621  {
622  for (int j = 0; j < this->n_+this->last_columns_.GetN(); j++)
623  this->Get(i, j) = zero;
624  }
625  }
626 
627 
629  template <class T, class Prop, class Storage, class Allocator>
631  ::operator()(int i, int j) const
632  {
633  if (i >= this->m_)
634  {
635  if (j >= this->n_)
636  return last_block_(i-this->m_, j-this->n_);
637 
638  return last_rows_(i-this->m_, j);
639  }
640 
641  if (j >= this->n_)
642  return last_columns_(i, j-this->n_);
643 
644  return static_cast<const Matrix_Band<T, Prop, Storage, Allocator>& >
645  (*this)(i, j);
646  }
647 
648 
650  template <class T, class Prop, class Storage, class Allocator>
653  {
654  this->data_ *= alpha;
655  last_rows_ *= alpha;
656  last_columns_ *= alpha;
657  last_block_ *= alpha;
658  return static_cast<Matrix<T, Prop, Storage, Allocator>& >(*this);
659  }
660 
661 
663  template <class T, class Prop, class Storage, class Allocator>
665  {
666  if (i >= this->m_)
667  {
668  if (j >= this->n_)
669  return last_block_(i-this->m_, j-this->n_);
670 
671  return last_rows_(i-this->m_, j);
672  }
673 
674  if (j >= this->n_)
675  return last_columns_(i, j-this->n_);
676 
678  }
679 
680 
682  template <class T, class Prop, class Storage, class Allocator>
684  {
685  if (i >= this->m_)
686  {
687  if (j >= this->n_)
688  return last_block_(i-this->m_, j-this->n_);
689 
690  return last_rows_(i-this->m_, j);
691  }
692 
693  if (j >= this->n_)
694  return last_columns_(i, j-this->n_);
695 
697  }
698 
699 
701  template <class T, class Prop, class Storage, class Allocator>
703  {
705 
706  T one, zero;
707  SetComplexZero(zero);
708  SetComplexOne(one);
709  last_rows_.Fill(zero);
710  last_columns_.Fill(zero);
711  last_block_.Fill(zero);
712  for (int i = min(this->m_, this->n_); i < this->GetM(); i++)
713  this->Get(i, i) = one;
714  }
715 
716 
718  template <class T, class Prop, class Storage, class Allocator>
719  template<class T0>
721  {
722  T x_;
723  SetComplexReal(x, x_);
724  this->data_.Fill(x_);
725  last_rows_.Fill(x_);
726  last_columns_.Fill(x_);
727  last_block_.Fill(x_);
728  }
729 
730 
732  template <class T, class Prop, class Storage, class Allocator>
734  {
735  this->data_.FillRand();
736  last_rows_.FillRand();
737  last_columns_.FillRand();
738  last_block_.FillRand();
739  }
740 
741 
743  template <class T, class Prop, class Storage, class Allocator>
745  {
746  // position of the main diagonal
747  int d = this->kl_ + this->ku_;
748 
749  // treating first columns
750  T pivot, diag;
751  int nb_last_row = last_rows_.GetM();
752  int nb_last_col = last_columns_.GetN();
753  T one; SetComplexOne(one);
754  for (int j = 0; j < this->n_; j++)
755  {
756  // replacing diagonal element by its inverse
757  if (j >= this->m_)
758  {
759  diag = one / this->last_rows_(j-this->m_, j);
760  this->last_rows_(j-this->m_, j) = diag;
761  }
762  else
763  {
764  this->data_(d, j) = one / this->data_(d, j);
765  diag = this->data_(d, j);
766  }
767 
768  // Gaussian elimination of rows below row j (part in the band)
769  for (int p = 1; p <= min(this->m_ - 1 - j, this->kl_); p++)
770  {
771  pivot = this->data_(d+p, j)*diag;
772  this->data_(d+p, j) = pivot;
773  // band
774  for (int k = 1; k <= min(this->n_ - 1 - j, this->ku_); k++)
775  this->data_(d+p-k, j+k) -= pivot*this->data_(d-k, j+k);
776 
777  // treating coefficients of the last columns
778  for (int k = 0; k < nb_last_col; k++)
779  last_columns_(j+p, k) -= pivot*last_columns_(j, k);
780  }
781 
782  // treating coefficients of the last rows
783  for (int p = max(0, j-this->m_+1); p < nb_last_row; p++)
784  {
785  pivot = last_rows_(p, j)*diag;
786  last_rows_(p, j) = pivot;
787  if (j >= this->m_)
788  {
789  for (int k = j+1; k < this->n_; k++)
790  last_rows_(p, k) -= pivot*this->last_rows_(j-this->m_, k);
791 
792  // treating coefficients of the last block
793  for (int k = 0; k < nb_last_col; k++)
794  last_block_(p, k) -= pivot*last_block_(j-this->m_, k);
795  }
796  else
797  {
798  for (int k = 1; k <= min(this->n_ - 1 - j, this->ku_); k++)
799  last_rows_(p, j+k) -= pivot*this->data_(d-k, j+k);
800 
801  // treating coefficients of the last block
802  for (int k = 0; k < nb_last_col; k++)
803  last_block_(p, k) -= pivot*last_columns_(j, k);
804  }
805  }
806  }
807 
808  // treating last columns
809  for (int j = this->n_; j < this->GetM(); j++)
810  {
811  if (j >= this->m_)
812  {
813  diag = one / last_block_(j-this->m_, j-this->n_);
814  last_block_(j-this->m_, j-this->n_) = diag;
815  }
816  else
817  {
818  diag = one / last_columns_(j, j-this->n_);
819  last_columns_(j, j-this->n_) = diag;
820 
821  // elimination in rows below but still located in last_columns
822  for (int i = j+1; i < this->m_; i++)
823  {
824  pivot = last_columns_(i, j-this->n_)*diag;
825  last_columns_(i, j-this->n_) = pivot;
826  for (int k = j+1; k < this->GetM(); k++)
827  last_columns_(i, k-this->n_)
828  -= pivot*last_columns_(j, k-this->n_);
829  }
830  }
831 
832  // now elimination of rows in last_block
833  for (int i = max(j+1,this->m_); i < this->GetM(); i++)
834  {
835  pivot = last_block_(i-this->m_, j-this->n_)*diag;
836  last_block_(i-this->m_, j-this->n_) = pivot;
837  if (j >= this->m_)
838  for (int k = j+1; k < this->GetM(); k++)
839  last_block_(i-this->m_, k-this->n_)
840  -= pivot*last_block_(j-this->m_, k-this->n_);
841  else
842  for (int k = j+1; k < this->GetM(); k++)
843  last_block_(i-this->m_, k-this->n_)
844  -= pivot*last_columns_(j, k-this->n_);
845  }
846  }
847  }
848 
849 
851  template <class T, class Prop, class Storage, class Allocator>
852  template<class T0>
855  {
856  // adding main band of A
857  int kl = A.GetKL();
858  int ku = A.GetKU();
859  int m = A.GetM() - A.GetNbLastRow();
860  int n = A.GetN() - A.GetNbLastCol();
861  for (int i = 0; i < m; i++)
862  for (int k = max(-i, -kl); k <= min(ku, n-1-i); k++)
863  {
864  int j = i + k;
865  AddInteraction(i, j, alpha*A(i, j));
866  }
867 
868  // then last rows
869  for (int i = 0; i < A.GetNbLastRow(); i++)
870  for (int j = 0; j < A.GetN(); j++)
871  AddInteraction(m+i, j, alpha*A(m+i, j));
872 
873  // and last columns
874  for (int j = 0; j < A.GetNbLastCol(); j++)
875  for (int i = 0; i < m; i++)
876  AddInteraction(i, n+j, alpha*A(i, n+j));
877  }
878 
879 
881  template <class T, class Prop, class Storage, class Allocator>
882  template<class T0, class T1>
884  MltAdd(const T0& alpha, const SeldonTranspose& trans,
885  const Vector<T1>& x, Vector<T1>& y) const
886  {
887  // banded part
889 
890  T1 val, zero; SetComplexZero(zero);
891  if (trans.NoTrans())
892  {
893  // last rows
894  for (int i = 0; i < last_rows_.GetM(); i++)
895  {
896  val = zero;
897  for (int j = 0; j < this->n_; j++)
898  val += last_rows_(i, j)*x(j);
899 
900  y(this->m_ + i) += alpha*val;
901  }
902 
903  // last columns
904  for (int j = 0; j < last_columns_.GetN(); j++)
905  {
906  val = alpha*x(this->n_+j);
907  for (int i = 0; i < this->m_; i++)
908  y(i) += last_columns_(i, j)*val;
909  }
910 
911  // last block
912  for (int i = 0; i < last_block_.GetM(); i++)
913  {
914  val = zero;
915  for (int j = 0; j < last_block_.GetN(); j++)
916  val += last_block_(i, j)*x(this->n_+j);
917 
918  y(this->m_+i) += alpha*val;
919  }
920  }
921  else if (trans.Trans())
922  {
923  // last rows
924  for (int i = 0; i < last_rows_.GetM(); i++)
925  {
926  val = alpha*x(this->m_ + i);
927  for (int j = 0; j < this->n_; j++)
928  y(j) += last_rows_(i, j)*val;
929  }
930 
931  // last columns
932  for (int j = 0; j < last_columns_.GetN(); j++)
933  {
934  val = zero;
935  for (int i = 0; i < this->m_; i++)
936  val += last_columns_(i, j)*x(i);
937 
938  y(this->n_+j) += alpha*val;
939  }
940 
941  // last block
942  for (int i = 0; i < last_block_.GetM(); i++)
943  {
944  val = alpha*x(this->m_+i);
945  for (int j = 0; j < last_block_.GetN(); j++)
946  y(this->n_+j) += last_block_(i, j)*val;
947  }
948  }
949  else
950  {
951  // last rows
952  for (int i = 0; i < last_rows_.GetM(); i++)
953  {
954  val = alpha*x(this->m_ + i);
955  for (int j = 0; j < this->n_; j++)
956  y(j) += conjugate(last_rows_(i, j))*val;
957  }
958 
959  // last columns
960  for (int j = 0; j < last_columns_.GetN(); j++)
961  {
962  val = zero;
963  for (int i = 0; i < this->m_; i++)
964  val += conjugate(last_columns_(i, j))*x(i);
965 
966  y(this->n_+j) += alpha*val;
967  }
968 
969  // last block
970  for (int i = 0; i < last_block_.GetM(); i++)
971  {
972  val = alpha*x(this->m_+i);
973  for (int j = 0; j < last_block_.GetN(); j++)
974  y(this->n_+j) += conjugate(last_block_(i, j))*val;
975  }
976  }
977  }
978 
979 
981  template <class T, class Prop, class Storage, class Allocator>
982  template<class T1>
984  {
985  int d = this->kl_ + this->ku_;
986  // resolution of L y = x
987 
988  // part due to band
989  for (int j = 0; j < min(this->m_, this->n_); j++)
990  for (int p = 1; p <= min(this->m_ - 1 - j, this->kl_); p++)
991  x(j+p) -= this->data_(d+p, j)*x(j);
992 
993  // part between the band and the last block
994  if (this->m_ > this->n_)
995  for (int j = this->n_; j < this->m_; j++)
996  for (int k = j+1; k < this->m_; k++)
997  x(k) -= last_columns_(k, j-this->n_)*x(j);
998  else
999  for (int j = this->m_; j < this->n_; j++)
1000  for (int k = 0; k < j; k++)
1001  x(j) -= last_rows_(j-this->m_, k)*x(k);
1002 
1003  // part due to the last block
1004  for (int i = max(this->m_, this->n_); i < this->GetM(); i++)
1005  {
1006  for (int j = 0; j < this->n_; j++)
1007  x(i) -= last_rows_(i-this->m_, j)*x(j);
1008 
1009  for (int j = this->n_; j < i; j++)
1010  x(i) -= last_block_(i-this->m_, j-this->n_)*x(j);
1011  }
1012 
1013  // resolution of U x = y
1014 
1015  // part due to the last block
1016  int N = this->GetM();
1017  for (int i = N-1; i >= max(this->m_, this->n_); i--)
1018  {
1019  x(i) *= last_block_(i-this->m_, i-this->n_);
1020  for (int j = this->m_; j < i; j++)
1021  x(j) -= last_block_(j-this->m_, i-this->n_)*x(i);
1022 
1023  for (int j = 0; j < this->m_; j++)
1024  x(j) -= last_columns_(j, i-this->n_)*x(i);
1025  }
1026 
1027  // part between band and the last block
1028  if (this->m_ > this->n_)
1029  for (int i = this->m_-1; i >= this->n_; i--)
1030  {
1031  x(i) *= last_columns_(i, i-this->n_);
1032  for (int j = 0; j < i; j++)
1033  x(j) -= last_columns_(j, i-this->n_)*x(i);
1034  }
1035  else
1036  for (int i = this->n_-1; i >= this->m_; i--)
1037  {
1038  for (int j = i+1; j < this->n_; j++)
1039  x(i) -= last_rows_(i-this->m_, j)*x(j);
1040 
1041  x(i) *= last_rows_(i-this->m_, i);
1042  }
1043 
1044  // part due to the band
1045  for (int j = this->n_-1; j >= 0; j--)
1046  {
1047  if (j < min(this->m_, this->n_))
1048  x(j) *= this->data_(d, j);
1049 
1050  for (int p = 1; p <= min(j, this->ku_); p++)
1051  if (j-p < this->m_)
1052  x(j-p) -= this->data_(d-p, j)*x(j);
1053  }
1054  }
1055 
1056 
1058  template <class T, class Prop, class Storage, class Allocator>
1060  ::Write(string FileName) const
1061  {
1062  ofstream FileStream;
1063  FileStream.open(FileName.c_str());
1064 
1065 #ifdef SELDON_CHECK_IO
1066  // Checks if the file was opened.
1067  if (!FileStream.is_open())
1068  throw IOError("Matrix_Arrow::Write(string FileName)",
1069  string("Unable to open file \"") + FileName + "\".");
1070 #endif
1071 
1072  this->Write(FileStream);
1073 
1074  FileStream.close();
1075  }
1076 
1077 
1079  template <class T, class Prop, class Storage, class Allocator>
1081  ::Write(ostream& FileStream) const
1082  {
1084 
1085  last_rows_.Write(FileStream);
1086  last_columns_.Write(FileStream);
1087  last_block_.Write(FileStream);
1088  }
1089 
1090 
1092  template <class T, class Prop, class Storage, class Allocator>
1094  ::WriteText(string FileName) const
1095  {
1096  ofstream FileStream;
1097  FileStream.precision(cout.precision());
1098  FileStream.flags(cout.flags());
1099  FileStream.open(FileName.c_str());
1100 
1101 #ifdef SELDON_CHECK_IO
1102  // Checks if the file was opened.
1103  if (!FileStream.is_open())
1104  throw IOError("TinyBandMatrix::WriteText(string FileName)",
1105  string("Unable to open file \"") + FileName + "\".");
1106 #endif
1107 
1108  this->WriteText(FileStream);
1109 
1110  FileStream.close();
1111  }
1112 
1113 
1115  template <class T, class Prop, class Storage, class Allocator>
1117  ::WriteText(ostream& FileStream) const
1118  {
1119  int d = this->kl_ + this->ku_;
1120  for (int j = 0; j < this->n_; j++)
1121  {
1122  int kmin = max(this->kl_, d - j);
1123  int kmax = min(this->kl_ + d, this->m_ -1 + d - j);
1124  for (int k = kmin; k <= kmax; k++)
1125  {
1126  int row = j + k - d;
1127  FileStream
1128  << row + 1 << " " << j+1 << " " << this->data_(k, j) << '\n';
1129  }
1130 
1131  for (int k = 0; k < last_rows_.GetM(); k++)
1132  {
1133  int row = this->m_ + k;
1134  FileStream
1135  << row + 1 << " " << j+1 << " " << last_rows_(k, j) << '\n';
1136  }
1137  }
1138 
1139  for (int j = 0; j < last_columns_.GetN(); j++)
1140  {
1141  for (int i = 0; i < this->m_; i++)
1142  FileStream << i+1 << " " << this->n_+j+1 << " "
1143  << last_columns_(i, j) << '\n';
1144 
1145  for (int i = 0; i < last_block_.GetM(); i++)
1146  FileStream << this->m_+i+1 << " " << this->n_+j+1
1147  << " " << last_block_(i, j) << '\n';
1148  }
1149  }
1150 
1151 
1152  /*************
1153  * Functions *
1154  *************/
1155 
1156 
1158  template<class T, class Allocator>
1161  bool keep_matrix)
1162  {
1163  mat_lu = A;
1164  if (!keep_matrix)
1165  A.Clear();
1166 
1167  mat_lu.Factorize();
1168  }
1169 
1170 
1172  template<class T, class Allocator>
1174  {
1175  A.Factorize();
1176  }
1177 
1178 
1180  template<class Allocator>
1182  Vector<int>& ipivot, LapackInfo& info)
1183  {
1184 #ifdef SELDON_WITH_LAPACK
1185  int m = A.GetM();
1186  int n = A.GetN();
1187 #ifdef SELDON_CHECK_BOUNDS
1188  if ((m <= 0)||(n <= 0))
1189  throw WrongDim("GetLU", "Provide a non-empty matrix");
1190 #endif
1191 
1192  ipivot.Reallocate(m);
1193  int kl = A.GetKL();
1194  int ku = A.GetKU();
1195  int lda = 2*kl + ku + 1;
1196  dgbtrf_(&m, &n, &kl, &ku, A.GetData(), &lda,
1197  ipivot.GetData(), &info.GetInfoRef());
1198 
1199 #ifdef SELDON_LAPACK_CHECK_INFO
1200  if (info.GetInfo() != 0)
1201  throw LapackError(info.GetInfo(), "GetLU",
1202  "An error occured during the factorization.");
1203 #endif
1204 
1205 #else
1206 
1207  A.Factorize(ipivot);
1208 
1209 #endif
1210  }
1211 
1212 
1214  template<class Allocator>
1216  const Vector<int>& ipivot, Vector<double>& b,
1217  LapackInfo& info)
1218  {
1219 #ifdef SELDON_WITH_LAPACK
1220  int n = A.GetM();
1221  int kl = A.GetKL();
1222  int ku = A.GetKU();
1223  int nrhs = 1;
1224  int lda = 2*kl + ku + 1;
1225  int ldb = n;
1226  char trans('N');
1227  dgbtrs_(&trans, &n, &kl, &ku, &nrhs, A.GetData(), &lda,
1228  ipivot.GetData(), b.GetData(), &ldb, &info.GetInfoRef());
1229 #else
1230 
1231  A.Solve(ipivot, b);
1232 #endif
1233 
1234  }
1235 
1236 
1238  template<class Allocator>
1240  const Vector<int>& ipivot, Vector<complex<double> >& b,
1241  LapackInfo& info)
1242  {
1243 #ifdef SELDON_WITH_LAPACK
1244  int n = A.GetM();
1245  int kl = A.GetKL();
1246  int ku = A.GetKU();
1247  int nrhs = 2;
1248  int lda = 2*kl + ku + 1;
1249  int ldb = n;
1250  char trans('N');
1251 
1253  for (int i = 0; i < n; i++)
1254  {
1255  brhs(i, 0) = real(b(i));
1256  brhs(i, 1) = imag(b(i));
1257  }
1258 
1259  dgbtrs_(&trans, &n, &kl, &ku, &nrhs, A.GetData(), &lda,
1260  ipivot.GetData(), brhs.GetData(), &ldb, &info.GetInfoRef());
1261 
1262  for (int i = 0; i < n; i++)
1263  b(i) = complex<double>(brhs(i, 0), brhs(i, 1));
1264 
1265 #else
1266 
1267  A.Solve(ipivot, b);
1268 #endif
1269 
1270  }
1271 
1272 
1274  template<class Allocator>
1275  void GetLU(Matrix<complex<double>, General, BandedCol, Allocator>& A,
1276  Vector<int>& ipivot, LapackInfo& info)
1277  {
1278 #ifdef SELDON_WITH_LAPACK
1279  int m = A.GetM();
1280  int n = A.GetN();
1281 #ifdef SELDON_CHECK_BOUNDS
1282  if ((m <= 0)||(n <= 0))
1283  throw WrongDim("GetLU", "Provide a non-empty matrix");
1284 #endif
1285 
1286  ipivot.Reallocate(m);
1287  int kl = A.GetKL();
1288  int ku = A.GetKU();
1289  int lda = 2*kl + ku + 1;
1290  zgbtrf_(&m, &n, &kl, &ku, A.GetData(), &lda,
1291  ipivot.GetData(), &info.GetInfoRef());
1292 
1293 #ifdef SELDON_LAPACK_CHECK_INFO
1294  if (info.GetInfo() != 0)
1295  throw LapackError(info.GetInfo(), "GetLU",
1296  "An error occured during the factorization.");
1297 #endif
1298 
1299 #else
1300 
1301  A.Factorize(ipivot);
1302 #endif
1303 
1304  }
1305 
1306 
1308  template<class Allocator>
1309  void SolveLU(const Matrix<complex<double>,
1310  General, BandedCol, Allocator>& A,
1311  const Vector<int>& ipivot, Vector<complex<double> >& b,
1312  LapackInfo& info)
1313  {
1314 #ifdef SELDON_WITH_LAPACK
1315  int n = A.GetM();
1316  int kl = A.GetKL();
1317  int ku = A.GetKU();
1318  int nrhs = 1;
1319  int lda = 2*kl + ku + 1;
1320  int ldb = n;
1321  char trans('N');
1322  zgbtrs_(&trans, &n, &kl, &ku, &nrhs, A.GetData(), &lda,
1323  ipivot.GetData(), b.GetDataVoid(), &ldb, &info.GetInfoRef());
1324 #else
1325 
1326  A.Solve(ipivot, b);
1327 #endif
1328 
1329  }
1330 
1331 
1333  template<class T, class Allocator>
1335  Vector<int>& ipivot, LapackInfo& info)
1336  {
1337  A.Factorize(ipivot);
1338  }
1339 
1340 
1342  template<class T, class Allocator>
1344  const Vector<int>& ipivot, Vector<T>& b, LapackInfo& info)
1345  {
1346  A.Solve(ipivot, b);
1347  }
1348 
1349 
1351  template<class T, class Allocator>
1353  const Vector<int>& ipivot, Vector<complex<T> >& b, LapackInfo& info)
1354  {
1355  A.Solve(ipivot, b);
1356  }
1357 
1358 
1360 
1365  template<class T, class Prop, class Allocator,
1366  class T1, class Allocator1, class T2, class Allocator2>
1370  {
1371  int kl = A.GetKL(), ku = A.GetKU(), n = A.GetM();
1372  for (int i = 0; i < A.GetM(); i++)
1373  for (int j = max(0, i-kl); j < min(n, i+ku+1); j++)
1374  A.Get(i, j) *= Drow(i)*Dcol(j);
1375  }
1376 
1377 }
1378 
1379 #define SELDON_FILE_BAND_MATRIX_CXX
1380 #endif
Seldon::Matrix_Band
base class for a banded-matrix
Definition: BandMatrix.hxx:36
Seldon::Matrix_Band::Add_
void Add_(const T0 &alpha, const Matrix< T, General, BandedCol, Allocator > &A)
performs the operation *this = *this + alpha A
Definition: BandMatrix.cxx:311
Seldon::Matrix_Arrow::AddInteraction
void AddInteraction(int i, int j, const T &val)
performs the operation A(i, j) = A(i, j) + val
Definition: BandMatrix.cxx:563
Seldon::SeldonTranspose
Definition: MatrixFlag.hxx:32
Seldon::Matrix_Arrow::Fill
void Fill(const T0 &x)
sets all non-zero entries to a same value
Definition: BandMatrix.cxx:720
Seldon::LapackInfo
Definition: Errors.hxx:243
Seldon::Matrix_Arrow::Add_
void Add_(const T0 &alpha, const Matrix< T, General, ArrowCol, Allocator > &A)
performs the operation *this = *this + alpha A
Definition: BandMatrix.cxx:854
Seldon::Matrix_Band::MltAdd
void MltAdd(const T0 &alpha, const SeldonTranspose &trans, const Vector< T1 > &x, Vector< T1 > &y) const
performs matrix-vector product y = y + alpha A x
Definition: BandMatrix.cxx:328
Seldon::Matrix_Band::Factorize
void Factorize()
performs LU factorisation without pivoting
Definition: BandMatrix.cxx:235
Seldon::Matrix_Arrow::FillRand
void FillRand()
sets all non-zero entries to random values
Definition: BandMatrix.cxx:733
Seldon::Matrix_Arrow::AddInteractionRow
void AddInteractionRow(int i, int n, const IVect &num, const Vector< T > &val, bool sorted=false)
adds severals values on a single row of the matrix
Definition: BandMatrix.cxx:592
Seldon::Matrix_Band::Solve
void Solve(Vector< T1 > &x) const
solves A x = b, assuming that Factorize has been previously called
Definition: BandMatrix.cxx:384
Seldon::Matrix< T, General, ArrowCol, Allocator >
arrow matrix stored by columns
Definition: BandMatrix.hxx:253
Seldon::Vector< int, VectFull >
Seldon::Matrix_Band::Copy
void Copy(const Matrix< T, General, ArrayRowSparse > &A)
conversion from a CSR matrix
Definition: BandMatrix.cxx:205
Seldon::Matrix_Arrow::SetIdentity
void SetIdentity()
sets the matrix to the identity matrix
Definition: BandMatrix.cxx:702
Seldon::Matrix
Definition: SeldonHeader.hxx:226
Seldon::Matrix_Band::GetM
int GetM() const
returns the number of rows
Definition: BandMatrixInline.cxx:34
Seldon::Matrix_Band::operator()
const T operator()(int i, int j) const
returns entry (i, j) of the matrix
Definition: BandMatrix.cxx:121
Seldon::Matrix_Band::Matrix_Band
Matrix_Band()
default constructor
Definition: BandMatrix.cxx:34
Seldon::Matrix_Arrow::operator()
const T operator()(int i, int j) const
returns entry (i, j) of the matrix
Definition: BandMatrix.cxx:631
Seldon::Matrix_Arrow::Solve
void Solve(Vector< T1 > &x) const
solves A x = b, assuming that Factorize has been previously called
Definition: BandMatrix.cxx:983
Seldon::Matrix< T, General, BandedCol, Allocator >
banded matrix stored by columns (Lapack format)
Definition: BandMatrix.hxx:161
Seldon::Matrix_Arrow::operator*=
Matrix< T, Prop, Storage, Allocator > & operator*=(const T &alpha)
multiplication by a scalar
Definition: BandMatrix.cxx:652
Seldon::Matrix_Band::AddInteractionRow
void AddInteractionRow(int i, int n, const IVect &num, const Vector< T > &val, bool sorted=false)
adds severals values on a single row of the matrix
Definition: BandMatrix.cxx:94
Seldon::Matrix_Arrow::GetN
int GetN() const
returns the number of columns
Definition: BandMatrixInline.cxx:288
Seldon::Matrix_Arrow::Reallocate
void Reallocate(int m, int n)
changes the size of the matrix
Definition: BandMatrixInline.cxx:338
Seldon::Matrix_Band::Clear
void Clear()
clears the matrix
Definition: BandMatrix.cxx:45
Seldon::Matrix_Arrow::Clear
void Clear()
clears the matrix
Definition: BandMatrix.cxx:524
Seldon::Matrix_Arrow::GetNbLastCol
int GetNbLastCol() const
returns the number of dense columns placed at the end of the matrix
Definition: BandMatrixInline.cxx:304
Seldon::Matrix_Band::Get
T & Get(int i, int j)
returns a reference to A(i, j)
Definition: BandMatrix.cxx:134
Seldon::Matrix_Arrow::ClearRow
void ClearRow(int i)
clears row i, fills it with 0
Definition: BandMatrix.cxx:605
Seldon::Matrix_Arrow::GetNbLastRow
int GetNbLastRow() const
returns the number of dense rows placed at the end of the matrix
Definition: BandMatrixInline.cxx:296
Seldon::Matrix_Band::ClearRow
void ClearRow(int i)
clears row i, fills it with 0
Definition: BandMatrix.cxx:107
Seldon::General
Definition: Properties.hxx:26
Seldon::BandedCol
Definition: BandMatrix.hxx:24
Seldon::Matrix_Arrow::Write
void Write(string FileName) const
writes the matrix in a file in binary format
Definition: BandMatrix.cxx:1060
Seldon::GetLU
void GetLU(Matrix< T0, Prop0, Storage0, Allocator0 > &A)
Returns the LU factorization of a matrix.
Definition: Functions_Matrix.cxx:2073
Seldon::Matrix_Band::AddInteraction
void AddInteraction(int i, int j, const T &val)
sets A(i, j) = A(i, j) + val
Definition: BandMatrix.cxx:72
Seldon::Matrix_Arrow::Get
T & Get(int i, int j)
returns a reference to A(i, j)
Definition: BandMatrix.cxx:664
Seldon::Matrix_Band::Write
void Write(string FileName) const
writes the matrix in a file in binary format
Definition: BandMatrix.cxx:437
Seldon::Matrix_Band::GetKU
int GetKU() const
returns the number of extra-diagonals in upper part of the matrix
Definition: BandMatrixInline.cxx:50
Seldon::Matrix_Band::Fill
void Fill(const T0 &x)
sets all non-zero entries to a same value
Definition: BandMatrix.cxx:178
Seldon::Matrix_Arrow::GetM
int GetM() const
returns the number of rows
Definition: BandMatrixInline.cxx:280
Seldon::Matrix_Band::FillRand
void FillRand()
sets all non-zero entries to random values
Definition: BandMatrix.cxx:191
Seldon::Matrix_Band::Reallocate
void Reallocate(int m, int n)
changes the size of the matrix, previous entries are lost
Definition: BandMatrixInline.cxx:98
Seldon::WrongDim
Definition: Errors.hxx:102
Seldon::Matrix_Arrow::Zero
void Zero()
sets all non-zero entries to 0
Definition: BandMatrix.cxx:536
Seldon::Matrix_Band::SetIdentity
void SetIdentity()
sets the matrix to the identity matrix
Definition: BandMatrix.cxx:164
Seldon
Seldon namespace.
Definition: Array.cxx:24
Seldon::IOError
Definition: Errors.hxx:150
Seldon::Matrix_Arrow::WriteText
void WriteText(string FileName) const
writes the matrix in a file in text format
Definition: BandMatrix.cxx:1094
Seldon::LapackError
Definition: Errors.hxx:225
Seldon::Matrix_Arrow::Factorize
void Factorize()
performs LU factorisation without pivoting
Definition: BandMatrix.cxx:744
Seldon::Matrix_Band::WriteText
void WriteText(string FileName) const
writes the matrix in a file in text format
Definition: BandMatrix.cxx:476
Seldon::Matrix_Band::GetKL
int GetKL() const
returns the number of extra-diagonals in lower part of the matrix
Definition: BandMatrixInline.cxx:42
Seldon::Matrix_Arrow::MltAdd
void MltAdd(const T0 &alpha, const SeldonTranspose &trans, const Vector< T1 > &x, Vector< T1 > &y) const
performs matrix-vector product y = y + alpha A x
Definition: BandMatrix.cxx:884
Seldon::SetComplexReal
void SetComplexReal(int n, std::complex< T > &number)
Sets a complex number to (n, 0).
Definition: CommonInline.cxx:234