Toast++  1.0.2 (r.539)
Forward and inverse modelling in optical tomography
gsmatrix.h
1 // -*-C++-*-
2 // ==========================================================================
3 // Module mathlib
4 // File gsmatrix.h
5 // Declaration of template class TGenericSparseMatrix
6 // Base class for sparse matrix types
7 //
8 // The following typedefs for specific template types have been defined
9 // for convenience:
10 // RGenericSparseMatrix = TGenericSparseMatrix<double> ('real')
11 // FGenericSparseMatrix = TGenericSparseMatrix<float> ('float')
12 // CGenericSparseMatrix = TGenericSparseMatrix<complex> ('complex')
13 // IGenericSparseMatrix = TGenericSparseMatrix<int> ('integer')
14 // ==========================================================================
15 
16 #ifndef __GSMATRIX_H
17 #define __GSMATRIX_H
18 
19 #ifdef TOAST_PARALLEL
20 //#define CG_PARALLEL
21 #endif
22 
23 #ifdef DBG_TIMING
24 extern double cgtime;
25 #endif
26 
27 #include "matrix.h"
28 
29 const int BUFFER_CHUNK_SIZE = 256;
30 // allocation chunk size for dynamically growing matrices
31 
32 typedef enum {
33  ITMETHOD_CG,
34  ITMETHOD_BICG,
35  ITMETHOD_BICGSTAB,
36  ITMETHOD_GMRES,
37  ITMETHOD_GAUSSSEIDEL
38 } IterativeMethod;
39 
40 // ==========================================================================
41 // Nonmember declarations
42 
43 extern MATHLIB IterativeMethod itmethod_general;
44 extern MATHLIB IterativeMethod itmethod_complex;
45 extern MATHLIB int IterCount;
46 
47 template<class MT>class TGenericSparseMatrix;
48 template<class MT>class TPreconditioner;
49 
50 template<class MT>
51 int QRFactorize (TGenericSparseMatrix<MT> &A, TVector<MT> &c, TVector<MT> &d);
52 
53 template<class MT>
54 void RSolve (const TGenericSparseMatrix<MT> &A, const TVector<MT> &d,
55  TVector<MT> &b);
56 
57 template<class MT>
58 void QRSolve (const TGenericSparseMatrix<MT> &A, const TVector<MT> &c,
59  const TVector<MT> &d, const TVector<MT> &b, TVector<MT> &x);
60 
61 
62 template<class MT>
63 int IterativeSolve (const TGenericSparseMatrix<MT> &A, const TVector<MT> &b,
64  TVector<MT> &x, double &tol, TPreconditioner<MT> *precon = 0,
65  int maxit = 0);
66 
67 template<class MT>
68 void IterativeSolve (const TGenericSparseMatrix<MT> &A,
69  const TVector<MT> *b, TVector<MT> *x, int nrhs, double tol, int maxit = 0,
70  TPreconditioner<MT> *precon = 0, IterativeSolverResult *res = 0);
71 
72 template<class MT>
73 int CG (const TGenericSparseMatrix<MT> &A, const TVector<MT> &b,
74  TVector<MT> &x, double &tol, TPreconditioner<MT> *precon = 0,
75  int maxit = 0);
76 
77 template<class MT>
78 int BiCG (const TGenericSparseMatrix<MT> &A, const TVector<MT> &b,
79  TVector<MT> &x, double &tol, TPreconditioner<MT> *precon = 0,
80  int maxit = 0);
81 
82 template<class MT>
83 int ComplexBiCGSolve (const TGenericSparseMatrix<MT> &Are,
84  const TGenericSparseMatrix<MT> &Aim, const TVector<MT> &bre,
85  const TVector<MT> &bim, TVector<MT> &xre, TVector<MT> &xim,
86  double &tol, int maxit = 0);
87 
88 template<class MT>
89 int GaussSeidel (const TGenericSparseMatrix<MT> &A, const TVector<MT> &b,
90  TVector<MT> &x, double &tol, int maxit = 0);
91 
92 // ==========================================================================
93 // class TGenericSparseMatrix
94 // ==========================================================================
105 template<class MT> class TGenericSparseMatrix: public TMatrix<MT> {
106 
107 public:
112 
125  TGenericSparseMatrix (int rows, int cols, int nv=0, const MT *data=0);
126 
127  TGenericSparseMatrix (int rows, int cols, int nv, MT *data, CopyMode cmode=DEEP_COPY);
128 
133 
137  virtual ~TGenericSparseMatrix ();
138 
150  virtual void New (int nrows, int ncols);
151 
152  virtual MT Get (int r, int c) const = 0;
153  // derived classes (also sparse versions) return the value of matrix
154  // element (r,c). (Not reference because element might not be stored
155  // for some matrix types).
156 
164  virtual bool Exists (int r, int c) const = 0;
165 
166  virtual void Unlink ();
167  // deallocate data block
168 
169  void Initialise (int nv, const MT *data);
170  void Initialise (int nv, MT *data, CopyMode cmode);
171  // reallocates data vector of length nv and initialises it with 'data',
172  // if given, or zero otherwise
173 
174  void Zero ();
175  // Reset data to zero, but preserve sparse structure (no deallocation,
176  // keep index lists)
177 
178  inline int nVal() const { return nval; }
179 
180  inline MT &Val (int i)
181  { dASSERT(i >= 0 && i < nval, "Index out of range");
182  return val[i];
183  }
184  // return i-th value of data vector
185 
186  inline MT *ValPtr () { return val; }
187  inline const MT *ValPtr () const { return val; }
188 
189  virtual MT &operator() (int r, int c) = 0;
190  // element access
191 
192  virtual void Add (int r, int c, const MT &val)
193  { (*this)(r,c) += val; }
194 
195  virtual int Get_index (int r, int c) const = 0;
196  // returns offset into data array of entry for row r and column c
197  // returns -1 if entry does not exist
198 
199  virtual MT GetNext (int &r, int &c) const = 0;
200  // Iterator; Returns the next nonzero element, together with its row and
201  // column index. In the first call set r < 0 to retrieve first nonzero.
202  // In the following calls set r and c to the result of the previous call
203  // r < 0 on return indicates end of matrix.
204  // Note that elements are not necessarily returned in a particular order
205 
206  TGenericSparseMatrix &operator*= (const MT &sc);
207  // Multiply *this with scalar sc and return the result
208 
209  inline TVector<MT> operator* (const TVector<MT> &x) const
210  { TVector<MT> b(this->rows); Ax(x,b); return b; }
211  // Multiplies *this with x and returns the result
212 
213  virtual void Ax (const TVector<MT> &x, TVector<MT> &b) const = 0;
214  virtual void Ax (const TVector<MT> &x, TVector<MT> &b, int i1, int i2)
215  const = 0;
216  // Returns result of (*this) * x in b
217  // The second version processes only rows i1 <= i < i2 of A
218 
219  virtual void ATx (const TVector<MT> &x, TVector<MT> &b) const = 0;
220  // Returns result of transpose(*this) * x in b
221 
222  inline TVector<MT> ATx (const TVector<MT> &x) const
223  { return TMatrix<MT>::ATx (x); }
224 
225  inline double FillFraction () const
226  { return (nval ?
227  (double)nval/(double)(this->rows * this->cols) : 0.0); }
228  // Returns fractional matrix allocation size
229 
230  virtual void Display (std::ostream &os) const;
231  // pretty-print matrix in full format. Only advisable for small matrices
232 
233  virtual void PrintFillinGraph (const char *fname, int maxdim = 600,
234  bool binary = true, bool antialias = true);
235  // Generates a binary or ASCII PGM bitmap file 'fname' with the image of
236  // the fill-in graph of the matrix (NOT nozeros!)
237  // If the matrix dimensions are > maxdim and antialiasing is on
238  // then pixel values are interpolated
239 
255  virtual void ExportRCV (std::ostream &os) {}
256 
257  static void GlobalSelectIterativeSolver (IterativeMethod method);
258  static void GlobalSelectIterativeSolver_complex (IterativeMethod method);
259  static IterativeMethod GetGlobalIterativeSolver ();
260  static IterativeMethod GetGlobalIterativeSolver_complex ();
261 
262  friend int QRFactorize<> (TGenericSparseMatrix<MT> &A, TVector<MT> &c,
263  TVector<MT> &d);
264  // QR decomposition. Return value != 0 indicates singularity
265 
266  friend void RSolve<> (const TGenericSparseMatrix<MT> &A,
267  const TVector<MT> &d, TVector<MT> &b);
268  // Solves set of linear equations Rx=b where R is upper triangular matrix
269  // stored in A and d. On return b is overwritten by the result x.
270 
271  friend void QRSolve<> (const TGenericSparseMatrix<MT> &A,
272  const TVector<MT> &c, const TVector<MT> &d, const TVector<MT> &b,
273  TVector<MT> &x);
274  // Solves set of linear equations Ax=b, where A, c and d are the result of
275  // a preceeding call to QRFactorize
276 
277  friend int IterativeSolve<> (const TGenericSparseMatrix<MT> &A,
278  const TVector<MT> &b, TVector<MT> &x, double &tol,
279  TPreconditioner<MT> *precon, int maxit);
280  // Solves Ax=b using the previously selected iterative solver
281  // x contains initial guess on start, solution on exit
282  // tol is tolerance limit on start, and final error on exit
283  // maxit is iteration limit (0 = no limit)
284  // return value is iteration count
285 
286  friend void IterativeSolve<> (const TGenericSparseMatrix<MT> &A,
287  const TVector<MT> *b, TVector<MT> *x, int nrhs, double tol, int maxit,
289 
290  friend int CG<> (const TGenericSparseMatrix<MT> &A, const TVector<MT> &b,
291  TVector<MT> &x, double &tol, TPreconditioner<MT> *precon,
292  int maxit);
293  // preconditioned conjugate gradient method.
294 
295  friend int BiCG<> (const TGenericSparseMatrix<MT> &A, const TVector<MT> &b,
296  TVector<MT> &x, double &tol, TPreconditioner<MT> *precon,
297  int maxit);
298  // biconjugate gradient method.
299 
300  friend int ComplexBiCGSolve<> (const TGenericSparseMatrix<MT> &Are,
301  const TGenericSparseMatrix<MT> &Aim, const TVector<MT> &bre,
302  const TVector<MT> &bim, TVector<MT> &xre, TVector<MT> &xim,
303  double &tol, int maxit);
304  // Solves Ax = b for complex case using biconjugate gradient solver
305  // obsolete
306 
307  friend int GaussSeidel<> (const TGenericSparseMatrix<MT> &A,
308  const TVector<MT> &b, TVector<MT> &x, double &tol, int maxit);
309  // Solves Ax = b using Gauss-Seidel iteration
310 
311 protected:
312  void Append (MT v = 0);
313  // Adds an additional entry to the end of the data array, reallocating
314  // buffers as required. Used by derived classes which allow dynamic growth
315 
316  MT *val; // data block
317  int nbuf; // data block allocation size
318  int nval; // data block entry count (<= nbuf)
319 
320 #ifdef CG_PARALLEL
321  static void cg_loop1(void*,int,int);
322  static void cg_loop2(void*,int,int);
323  static void cg_loop3(void*,int,int);
324 #endif
325 
326 //private:
327 // static IterativeMethod itmethod_general;
328 // static IterativeMethod itmethod_complex;
329 };
330 
331 // ==========================================================================
332 // typedefs for specific instances of `TGenericSparseMatrix'
333 
339 
340 
341 // ==========================================================================
342 // ==========================================================================
343 // Member definitions
344 
345 //template<class MT>
346 //IterativeMethod TGenericSparseMatrix<MT>::itmethod_general = ITMETHOD_CG;
347 
348 //template<class MT>
349 //IterativeMethod TGenericSparseMatrix<MT>::itmethod_complex = ITMETHOD_BICGSTAB;
350 
351 // --------------------------------------------------------------------------
352 
353 template<class MT>
355 : TMatrix<MT> ()
356 {
357  nbuf = nval = 0;
358 }
359 
360 // --------------------------------------------------------------------------
361 
362 template<class MT>
364  int nv, const MT *data)
365 : TMatrix<MT> (rows, cols)
366 {
367  nbuf = nval = 0;
368  Initialise (nv, data);
369 }
370 
371 // --------------------------------------------------------------------------
372 
373 template<class MT>
375  int nv, MT *data, CopyMode cmode)
376 : TMatrix<MT> (rows, cols)
377 {
378  nbuf = nval = 0;
379  Initialise (nv, data, cmode);
380 }
381 
382 // --------------------------------------------------------------------------
383 
384 template<class MT>
386  &m)
387 : TMatrix<MT> (m)
388 {
389  nval = m.nval;
390  nbuf = m.nbuf;
391  int nsize = (nbuf > nval ? nbuf : nval);
392  if (nsize) {
393  val = new MT[nsize];
394  for (int i = 0; i < nval; i++) val[i] = m.val[i];
395  }
396 }
397 
398 // --------------------------------------------------------------------------
399 
400 template<class MT>
402 {
404 }
405 
406 // --------------------------------------------------------------------------
407 
408 template<class MT>
409 void TGenericSparseMatrix<MT>::New (int nrows, int ncols)
410 {
412  TMatrix<MT>::New (nrows, ncols);
413 }
414 
415 // --------------------------------------------------------------------------
416 
417 template<class MT>
419 {
420  if (nbuf) delete []val;
421  nbuf = nval = 0;
422 }
423 
424 // --------------------------------------------------------------------------
425 
426 template<class MT>
427 void TGenericSparseMatrix<MT>::Initialise (int nv, const MT *data)
428 {
429  int i;
430  if (nv != nval) {
431  if (nbuf) delete []val;
432  if ((nbuf = (nval = nv))) val = new MT[nv];
433  }
434  if (data) for (i = 0; i < nv; i++) val[i] = data[i];
435  else for (i = 0; i < nv; i++) val[i] = (MT)0;
436 }
437 
438 // --------------------------------------------------------------------------
439 
440 template<class MT>
441 void TGenericSparseMatrix<MT>::Initialise (int nv, MT *data, CopyMode cmode)
442 {
443  if (cmode == SHALLOW_COPY) {
444  dASSERT (data, "Nonzero data buffer reference required");
445  if (nbuf) {
446  delete []val;
447  nbuf = 0;
448  }
449  val = data;
450  nval = nv;
451  } else Initialise (nv, data);
452 }
453 
454 // --------------------------------------------------------------------------
455 
456 template<class MT>
458 {
459  for (int i = 0; i < nval; i++)
460  val[i] = (MT)0;
461 }
462 
463 // --------------------------------------------------------------------------
464 
465 template<class MT>
467 {
468  for (int i = 0; i < nval; i++)
469  val[i] *= sc;
470  return *this;
471 }
472 
473 // --------------------------------------------------------------------------
474 
475 template<class MT>
477 {
478  if (nval == nbuf) { // no slack buffer - reallocation required
479  MT *tmp_val = new MT[nbuf+BUFFER_CHUNK_SIZE];
480  for (int i = 0; i < nval; i++) tmp_val[i] = val[i];
481  if (nbuf) delete []val;
482  val = tmp_val;
483  nbuf += BUFFER_CHUNK_SIZE;
484  }
485  val[nval++] = v;
486 }
487 
488 // --------------------------------------------------------------------------
489 
490 template<class MT>
491 void TGenericSparseMatrix<MT>::Display (std::ostream &os) const
492 {
493  for (int r = 0; r < this->rows; r++)
494  for (int c = 0; c < this->cols; c++)
495  os << Get(r,c) << (c < this->cols-1 ? ' ' : '\n');
496 }
497 
498 // --------------------------------------------------------------------------
499 inline int scale (double x)
500 { return (int)(x*2.56e7+0.5); }
501 
502 template<class MT>
503 void TGenericSparseMatrix<MT>::PrintFillinGraph (const char *fname, int maxdim,
504  bool binary, bool antialias)
505 {
506  int i, v, nx, ny, c, r = -1, *img;
507 
508  if (this->cols <= maxdim && this->rows <= maxdim) {
509  nx = this->cols, ny = this->rows;
510  img = new int[nx*ny];
511  memset (img, 0, nx*ny*sizeof(int));
512  for (;;) {
513  GetNext (r, c);
514  if (r < 0) break; // finished
515  img[r*nx+c] = 255;
516  }
517  } else {
518  int ix, iy;
519  double d, x, y, rx, ry, wx0, wx1, wx2, wy0, wy1, wy2, dummy;
520  if (this->cols > this->rows)
521  nx = maxdim, ny = (maxdim*this->rows)/this->cols;
522  else
523  ny = maxdim, nx = (maxdim*this->cols)/this->rows;
524  d = 0.5*(double)nx/(double)this->cols;
525  img = new int[nx*ny];
526  memset (img, 0, nx*ny*sizeof(int));
527  for (;;) {
528  GetNext (r, c);
529  if (r < 0) break; // finished
530  x = (c+0.5)/(double)this->cols * (double)nx;
531  rx = modf (x, &dummy);
532  ix = (int)(dummy+0.5);
533  y = (r+0.5)/(double)this->rows * (double)ny;
534  ry = modf (y, &dummy);
535  iy = (int)(dummy+0.5);
536  if (!antialias) {
537  img[iy*nx+ix] = 255;
538  continue;
539  }
540  if (rx < d) {
541  wx0 = d-rx, wx1 = d+rx, wx2 = 0.0;
542  } else if (rx > 1.0-d) {
543  wx0 = 0.0, wx1 = d+1.0-rx, wx2 = d-1.0+rx;
544  } else {
545  wx0 = wx2 = 0.0, wx1 = d+d;
546  }
547  if (ry < d) {
548  wy0 = d-ry, wy1 = d+ry, wy2 = 0.0;
549  } else if (ry > 1.0-d) {
550  wy0 = 0.0, wy1 = d+1.0-ry, wy2 = d-1.0+ry;
551  } else {
552  wy0 = wy2 = 0.0, wy1 = d+d;
553  }
554  img[iy*nx+ix] += scale(wx1*wy1);
555  if (wx0 && ix) {
556  img[iy*nx+ix-1] += scale(wx0*wy1);
557  if (wy0 && iy) img[(iy-1)*nx+ix-1] += scale(wx0*wy0);
558  else if (wy2 && iy<ny-1) img[(iy+1)*nx+ix-1] += scale(wx0*wy2);
559  } else if (wx2 && ix<nx-1) {
560  img[iy*nx+ix+1] += scale(wx2*wy1);
561  if (wy0 && iy) img[(iy-1)*nx+ix+1] += scale(wx2*wy0);
562  else if (wy2 && iy<ny-1) img[(iy+1)*nx+ix+1] += scale(wx2*wy2);
563  }
564  if (wy0 && iy) {
565  img[(iy-1)*nx+ix] += scale(wx1*wy0);
566  } else if (wy2 && iy<ny-1) {
567  img[(iy+1)*nx+ix] += scale(wx1*wy2);
568  }
569  }
570  if (antialias)
571  for (i = 0; i < nx*ny; i++) // scale back down
572  if ((img[i] /= 100000) > 255) img[i] = 255;
573  }
574  std::ofstream ofs (fname);
575  ofs << (binary ? "P5" : "P2") << std::endl;
576  ofs << "# CREATOR: TOAST TGenericSparseMatrix::PrintFillinGraph" << std::endl;
577  ofs << nx << ' ' << ny << std::endl;
578  ofs << 255 << std::endl;
579  for (r = i = 0; r < ny; r++) {
580  for (c = 0; c < nx; c++) {
581  v = 255-img[r*nx+c];
582  if (binary) ofs << (unsigned char)v;
583  else ofs << v << (++i % 35 ? ' ' : '\n');
584  }
585  }
586  delete []img;
587 }
588 
589 // --------------------------------------------------------------------------
590 // select/return default iterative solver
591 
592 template<class MT>
594  (IterativeMethod method)
595 { itmethod_general = method; }
596 
597 template<class MT>
599  (IterativeMethod method)
600 { itmethod_complex = method; }
601 
602 template<class MT>
604 { return itmethod_general; }
605 
606 template<class MT>
608 { return itmethod_complex; }
609 
610 // --------------------------------------------------------------------------
611 
612 #ifdef CMAT2RMAT
613 /* add specific function for CGenericSparseMatrix */
614 RGenericSparseMatrix Re(const CGenericSparseMatrix &);
615 RGenericSparseMatrix Im(const CGenericSparseMatrix &);
616 #endif
617 
618 #endif // !__GSMATRIX_H
Virtual base class for sparse matrix types.
Definition: gsmatrix.h:47
virtual bool Exists(int r, int c) const =0
Checks allocation of a matrix element.
Definition: gsmatrix.h:48
virtual ~TGenericSparseMatrix()
Destructor.
Definition: gsmatrix.h:401
virtual void New(int nrows, int ncols)
Resize and reset the matrix.
Definition: matrix.h:462
virtual MT Get(int r, int c) const =0
Retrieve a matrix element.
TGenericSparseMatrix()
Create a sparse matrix of size 0 x 0.
Definition: gsmatrix.h:354
Virtual base class for all matrix types (dense and sparse)
Definition: matrix.h:43
virtual void New(int nrows, int ncols)
Reset the matrix dimensions.
Definition: gsmatrix.h:409
Definition: matrix.h:34
virtual void ExportRCV(std::ostream &os)
Write sparse matrix to ASCII output stream.
Definition: gsmatrix.h:255