Free Electron
SparseMatrix.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __solve_SparseMatrix_h__
8 #define __solve_SparseMatrix_h__
9 
10 namespace fe
11 {
12 namespace ext
13 {
14 /**************************************************************************//**
15  @brief Dense array of sparse rows
16 
17  @ingroup solve
18 
19  SparseMatrix has some similar functionality to Matrix through
20  overloaded non-member operations.
21 
22  Only a small number of operations are implemented for SparseMatrix.
23  Others may be added as needed.
24 *//***************************************************************************/
25 template< class T,class ROW=SparseArray<T> >
26 class SparseMatrix
27 {
28  public:
29  SparseMatrix(void);
30  SparseMatrix(U32 rows,U32 columns);
31  SparseMatrix(const SparseMatrix<T,ROW>& rhs);
32  ~SparseMatrix(void);
33 
34  SparseMatrix<T,ROW>& operator=(const SparseMatrix<T,ROW>& rhs);
35 
36  T operator()(U32 i, U32 j) const;
37  T& operator()(U32 i, U32 j);
38 
39  void reset(U32 rows,U32 columns);
40  void clear(void);
41  U32 rows(void) const { return m_rows; }
42  U32 columns(void) const { return m_columns; }
43 
44  void setTranspose(const SparseMatrix<T,ROW>& rhs);
45  void setSum(const SparseMatrix<T,ROW> &rhs);
46  void setDifference(const SparseMatrix<T,ROW> &rhs);
47  void setProduct(
48  const SparseMatrix<T,ROW> &lhs,
49  const SparseMatrix<T,ROW> &rhs);
50 
51  void premultiplyDiagonal(
52  const SparseMatrix<T,ROW> &diag,
53  SparseMatrix<T,ROW> &b) const;
54  void premultiplyDiagonal(
55  const DenseVector<T> &diag,
56  SparseMatrix<T,ROW> &b) const;
57  void premultiplyInverseDiagonal(
58  const SparseMatrix<T,ROW> &diag,
59  SparseMatrix<T,ROW> &b) const;
60  void premultiplyInverseDiagonal(
61  const DenseVector<T> &diag,
62  SparseMatrix<T,ROW> &b) const;
63  void postmultiplyDiagonal(
64  const DenseVector<T> &diag,
65  SparseMatrix<T,ROW> &b) const;
66  void postmultiplyInverseDiagonal(
67  const SparseMatrix<T,ROW> &diag,
68  SparseMatrix<T,ROW> &b) const;
69  void postmultiplyInverseDiagonal(
70  const DenseVector<T> &diag,
71  SparseMatrix<T,ROW> &b) const;
72 
73  void scale(const F32 scalar);
74  void scale(const F32 scalar,
75  SparseMatrix<T,ROW>& result) const;
76 
77  void transform(const DenseVector<T> &x,
78  DenseVector<T> &b) const;
79  void transposeTransform(const DenseVector<T> &x,
80  DenseVector<T> &b) const;
81 
82  protected:
83  U32 m_rows;
84  U32 m_columns;
85 
86  ROW* m_pRow;
87 };
88 
89 template<class T,class ROW>
90 inline SparseMatrix<T,ROW>::SparseMatrix(void):
91  m_rows(1),
92  m_columns(1)
93 {
94  m_pRow=new ROW[m_rows];
95 }
96 
97 template<class T,class ROW>
98 inline SparseMatrix<T,ROW>::SparseMatrix(U32 rows,U32 columns):
99  m_rows(rows),
100  m_columns(columns)
101 {
102  m_pRow=new ROW[m_rows];
103 }
104 
105 template<class T,class ROW>
106 inline SparseMatrix<T,ROW>::SparseMatrix(const SparseMatrix<T,ROW>& rhs):
107  m_rows(rhs.m_rows),
108  m_columns(rhs.m_columns)
109 {
110  m_pRow=new ROW[m_rows];
111  operator=(rhs);
112 }
113 
114 template<class T,class ROW>
115 inline SparseMatrix<T,ROW>::~SparseMatrix(void)
116 {
117  delete[] m_pRow;
118 }
119 
120 template<class T,class ROW>
121 inline void SparseMatrix<T,ROW>::reset(U32 rows,U32 columns)
122 {
123  delete[] m_pRow;
124  m_rows=rows;
125  m_columns=columns;
126  m_pRow=new ROW[m_rows];
127 }
128 template<class T,class ROW>
129 inline void SparseMatrix<T,ROW>::clear(void)
130 {
131  for(U32 i=0;i<m_rows;i++)
132  {
133  m_pRow[i].clear();
134  }
135 }
136 
137 template<class T,class ROW>
138 inline T SparseMatrix<T,ROW>::operator()(U32 i, U32 j) const
139 {
140 #if FE_BOUNDSCHECK
141  if(i >= m_rows || j >= m_columns) { feX(e_invalidRange); }
142 #endif
143 
144  const ROW& row=m_pRow[i];
145  return row[j];
146 }
147 
148 template<class T,class ROW>
149 inline T& SparseMatrix<T,ROW>::operator()(U32 i, U32 j)
150 {
151 #if FE_BOUNDSCHECK
152  if(i >= m_rows || j >= m_columns) { feX(e_invalidRange); }
153 #endif
154 
155  return m_pRow[i][j];
156 }
157 
158 /** Copy existing matrix
159  @relates SparseMatrix
160  */
161 template<class T,class ROW>
162 inline SparseMatrix<T,ROW>& SparseMatrix<T,ROW>::operator=(
163  const SparseMatrix<T,ROW>& rhs)
164 {
165  if(this != &rhs)
166  {
167  if(m_rows==rhs.m_rows)
168  {
169  m_columns=rhs.m_columns;
170  clear();
171  }
172  else
173  {
174  reset(rhs.m_rows,rhs.m_columns);
175  }
176 
177  for(U32 i=0;i<m_rows;i++)
178  {
179  const ROW& row=rhs.m_pRow[i];
180  m_pRow[i]=row;
181  }
182  }
183  return *this;
184 }
185 
186 /** set as transpose of argument
187  @relates SparseMatrix
188  */
189 template<class T,class ROW>
190 inline void SparseMatrix<T,ROW>::setTranspose(const SparseMatrix<T,ROW> &rhs)
191 {
192  if(this != &rhs)
193  {
194  if(m_rows==rhs.m_rows)
195  {
196  m_columns=rhs.m_columns;
197  clear();
198  }
199  else
200  {
201  reset(rhs.m_rows,rhs.m_columns);
202  }
203 
204  for(U32 i=0;i<m_rows;i++)
205  {
206  const ROW& row=rhs.m_pRow[i];
207  U32 entries=row.entries();
208  for(U32 loc=0; loc<entries; loc++)
209  {
210  //* effectively this(j,i) = rhs(i,j)
211  operator()(row.index(loc),i)=row.entry(loc);
212  }
213  }
214  }
215 }
216 
217 /** add to SparseMatrix in place
218  @relates SparseMatrix
219  */
220 template<class T,class ROW>
221 inline void SparseMatrix<T,ROW>::setSum(const SparseMatrix<T,ROW> &rhs)
222 {
223  for(U32 i=0; i<m_rows; i++)
224  {
225  const ROW& row=rhs.m_pRow[i];
226  U32 entries=row.entries();
227  for(U32 loc=0; loc<entries; loc++)
228  {
229  //* effectively this(i,j) += rhs(i,j)
230  operator()(i,row.index(loc))+=row.entry(loc);
231  }
232  }
233 }
234 
235 /** subtract from SparseMatrix in place
236  @relates SparseMatrix
237  */
238 template<class T,class ROW>
239 inline void SparseMatrix<T,ROW>::setDifference(const SparseMatrix<T,ROW> &rhs)
240 {
241  for(U32 i=0; i<m_rows; i++)
242  {
243  const ROW& row=rhs.m_pRow[i];
244  U32 entries=row.entries();
245  for(U32 loc=0; loc<entries; loc++)
246  {
247  //* effectively this(i,j) -= rhs(i,j)
248  operator()(i,row.index(loc))-=row.entry(loc);
249  }
250  }
251 }
252 
253 /** SparseMatrix-SparseMatrix multiply
254  @relates SparseMatrix
255 
256  Very slow. For testing only.
257  */
258 template<class T,class ROW>
259 inline void SparseMatrix<T,ROW>::setProduct(
260  const SparseMatrix<T,ROW> &lhs,
261  const SparseMatrix<T,ROW> &rhs)
262 {
263  FEASSERT(lhs.m_columns==rhs.m_rows);
264 
265  if(m_rows==lhs.m_rows)
266  {
267  m_columns=rhs.m_columns;
268  clear();
269  }
270  else
271  {
272  reset(lhs.m_rows,rhs.m_columns);
273  }
274 
275  for(U32 i=0; i<m_rows; i++)
276  {
277  for(U32 j=0; j<m_columns; j++)
278  {
279  T sum=T(0);
280  for(U32 k=0; k<lhs.m_columns; k++)
281  {
282  sum += lhs(i,k)*rhs(k,j);
283  }
284  if(sum!=0.0)
285  {
286  operator()(i,j)=sum;
287  }
288  }
289  }
290 }
291 
292 /** SparseMatrix-Scalar multiply in place
293  @relates SparseMatrix
294  */
295 template<class T,class ROW>
296 inline void SparseMatrix<T,ROW>::scale(const F32 scalar)
297 {
298  for(U32 i=0; i<m_rows; i++)
299  {
300  ROW& row=m_pRow[i];
301  U32 entries=row.entries();
302  for(U32 loc=0; loc<entries; loc++)
303  {
304  //* effectively this(i,j) *= scalar
305  row.entry(loc)*=scalar;
306  }
307  }
308 }
309 
310 /** SparseMatrix-Scalar multiply
311  @relates SparseMatrix
312  */
313 template<class T,class ROW>
314 inline void SparseMatrix<T,ROW>::scale(const F32 scalar,
315  SparseMatrix<T,ROW> &result) const
316 {
317  for(U32 i=0; i<m_rows; i++)
318  {
319  const ROW& row=m_pRow[i];
320  U32 entries=row.entries();
321  for(U32 loc=0; loc<entries; loc++)
322  {
323  //* effectively result(i,j) = this(i,j) * scalar
324  result(i,row.index(loc))=row.entry(loc)*scalar;
325  }
326  }
327 }
328 
329 /** SparseMatrix-Vector multiply
330  @relates SparseMatrix
331  */
332 template<class T,class ROW>
333 inline void SparseMatrix<T,ROW>::transform(const DenseVector<T> &x,
334  DenseVector<T> &b) const
335 {
336  for(U32 i=0; i<m_rows; i++)
337  {
338  const ROW& row=m_pRow[i];
339  U32 entries=row.entries();
340 
341  T sum=T(0);
342  for(U32 loc=0; loc<entries; loc++)
343  {
344  //* effectively b[i] += this(i,j) * x[j]
345  sum+=row.entry(loc) * x[row.index(loc)];
346  }
347  setAt(b,i,sum);
348  }
349 }
350 
351 /** SparseMatrix-Vector multiply with matrix transposed
352  @relates SparseMatrix
353  */
354 template<class T,class ROW>
355 inline void SparseMatrix<T,ROW>::transposeTransform(const DenseVector<T> &x,
356  DenseVector<T> &b) const
357 {
358  set(b);
359 
360  for(U32 i=0; i<m_rows; i++)
361  {
362  const ROW& row=m_pRow[i];
363  U32 entries=row.entries();
364 
365  for(U32 loc=0; loc<entries; loc++)
366  {
367  //* effectively b[j] += this(i,j) * x[i]
368  b[row.index(loc)]+=row.entry(loc) * x[i];
369  }
370  }
371 }
372 
373 /** Diagonal-SparseMatrix multiply
374  @relates SparseMatrix
375 
376  This amounts to a scale of each row by the corresponding diagonal element.
377  */
378 template<class T,class ROW>
379 inline void SparseMatrix<T,ROW>::premultiplyDiagonal(
380  const SparseMatrix<T,ROW> &diag,SparseMatrix<T,ROW> &result) const
381 {
382  if(result.rows()!=m_rows || result.columns()!=m_columns)
383  {
384  result.reset(m_rows,m_columns);
385  }
386  for(U32 i=0; i<m_rows; i++)
387  {
388  const ROW& row=m_pRow[i];
389  U32 entries=row.entries();
390 
391  T d=diag(i,i);
392  for(U32 loc=0; loc<entries; loc++)
393  {
394  //* effectively result(i,j) = this(i,j) * diag(i,i)
395  result(i,row.index(loc))=row.entry(loc)*d;
396  }
397  }
398 }
399 
400 /** Diagonal-SparseMatrix multiply
401  @relates SparseMatrix
402 
403  The diagonal matrix is represented as a vector.
404 
405  This amounts to a scale of each row by the corresponding diagonal element.
406  */
407 template<class T,class ROW>
408 inline void SparseMatrix<T,ROW>::premultiplyDiagonal(
409  const DenseVector<T> &diag,SparseMatrix<T,ROW> &result) const
410 {
411  if(result.rows()!=m_rows || result.columns()!=m_columns)
412  {
413  result.reset(m_rows,m_columns);
414  }
415  for(U32 i=0; i<m_rows; i++)
416  {
417  const ROW& row=m_pRow[i];
418  U32 entries=row.entries();
419 
420  T d=diag[i];
421  for(U32 loc=0; loc<entries; loc++)
422  {
423  //* effectively result(i,j) = this(i,j) * diag(i,i)
424  result(i,row.index(loc))=row.entry(loc)*d;
425  }
426  }
427 }
428 
429 /** Inverse_Diagonal-SparseMatrix multiply
430  @relates SparseMatrix
431 
432  This amounts to a scale of each row by the reciprical of the
433  corresponding diagonal element.
434  */
435 template<class T,class ROW>
436 inline void SparseMatrix<T,ROW>::premultiplyInverseDiagonal(
437  const SparseMatrix<T,ROW> &diag,SparseMatrix<T,ROW> &result) const
438 {
439  if(result.rows()!=m_rows || result.columns()!=m_columns)
440  {
441  result.reset(m_rows,m_columns);
442  }
443  for(U32 i=0; i<m_rows; i++)
444  {
445  const ROW& row=m_pRow[i];
446  U32 entries=row.entries();
447 
448  T d=T(1)/diag(i,i);
449  for(U32 loc=0; loc<entries; loc++)
450  {
451  //* effectively result(i,j) = this(i,j) * diag(i,i)
452  result(i,row.index(loc))=row.entry(loc)*d;
453  }
454  }
455 }
456 
457 /** Inverse_Diagonal-SparseMatrix multiply
458  @relates SparseMatrix
459 
460  The diagonal matrix is represented as a vector.
461 
462  This amounts to a scale of each row by the reciprical of the
463  corresponding diagonal element.
464  */
465 template<class T,class ROW>
466 inline void SparseMatrix<T,ROW>::premultiplyInverseDiagonal(
467  const DenseVector<T> &diag,SparseMatrix<T,ROW> &result) const
468 {
469  if(result.rows()!=m_rows || result.columns()!=m_columns)
470  {
471  result.reset(m_rows,m_columns);
472  }
473  for(U32 i=0; i<m_rows; i++)
474  {
475  const ROW& row=m_pRow[i];
476  U32 entries=row.entries();
477 
478  T d=T(1)/diag[i];
479  for(U32 loc=0; loc<entries; loc++)
480  {
481  //* effectively result(i,j) = this(i,j) * diag(i)
482  result(i,row.index(loc))=row.entry(loc)*d;
483  }
484  }
485 }
486 
487 /** Diagonal-SparseMatrix multiply
488  @relates SparseMatrix
489 
490  The diagonal matrix is represented as a vector.
491 
492  This amounts to a scale of each column by the corresponding
493  diagonal element.
494  */
495 template<class T,class ROW>
496 inline void SparseMatrix<T,ROW>::postmultiplyDiagonal(
497  const DenseVector<T> &diag,SparseMatrix<T,ROW> &result) const
498 {
499  if(result.rows()!=m_rows || result.columns()!=m_columns)
500  {
501  result.reset(m_rows,m_columns);
502  }
503  for(U32 i=0; i<m_rows; i++)
504  {
505  const ROW& row=m_pRow[i];
506  U32 entries=row.entries();
507 
508  for(U32 loc=0; loc<entries; loc++)
509  {
510  //* effectively result(i,j) = this(i,j) * diag(j,j)
511  const U32 j=row.index(loc);
512  result(i,j)=row.entry(loc)*diag[j];
513  }
514  }
515 }
516 
517 /** SparseMatrix-Inverse_Diagonal multiply
518  @relates SparseMatrix
519 
520  This amounts to a scale of each column by the reciprical of the
521  corresponding diagonal element.
522  */
523 template<class T,class ROW>
524 inline void SparseMatrix<T,ROW>::postmultiplyInverseDiagonal(
525  const SparseMatrix<T,ROW> &diag,SparseMatrix<T,ROW> &result) const
526 {
527  if(result.rows()!=m_rows || result.columns()!=m_columns)
528  {
529  result.reset(m_rows,m_columns);
530  }
531  T scale[m_rows];
532  for(U32 i=0; i<m_rows; i++)
533  {
534  scale[i]=T(1)/diag(i,i);
535  }
536  for(U32 i=0; i<m_rows; i++)
537  {
538  const ROW& row=m_pRow[i];
539  U32 entries=row.entries();
540 
541  for(U32 loc=0; loc<entries; loc++)
542  {
543  //* effectively result(i,j) = this(i,j) * diag(j,j)
544  const U32 j=row.index(loc);
545  result(i,row.index(loc))=row.entry(loc)*scale[j];
546  }
547  }
548 }
549 
550 /** SparseMatrix-Inverse_Diagonal multiply
551  @relates SparseMatrix
552 
553  The diagonal matrix is represented as a vector.
554 
555  This amounts to a scale of each column by the reciprical of the
556  corresponding diagonal element.
557  */
558 template<class T,class ROW>
559 inline void SparseMatrix<T,ROW>::postmultiplyInverseDiagonal(
560  const DenseVector<T> &diag,SparseMatrix<T,ROW> &result) const
561 {
562  if(result.rows()!=m_rows || result.columns()!=m_columns)
563  {
564  result.reset(m_rows,m_columns);
565  }
566  T scale[m_rows];
567  for(U32 i=0; i<m_rows; i++)
568  {
569  scale[i]=T(1)/diag(i);
570  }
571  for(U32 i=0; i<m_rows; i++)
572  {
573  const ROW& row=m_pRow[i];
574  U32 entries=row.entries();
575 
576  for(U32 loc=0; loc<entries; loc++)
577  {
578  //* effectively result(i,j) = this(i,j) * diag(j)
579  const U32 j=row.index(loc);
580  result(i,row.index(loc))=row.entry(loc)*scale[j];
581  }
582  }
583 }
584 
585 /* non member operations */
586 
587 /** Return the horizonatal dimension
588  @relates SparseMatrix
589 */
590 template<class T,class ROW>
591 inline U32 width(const SparseMatrix<T,ROW>& matrix)
592 {
593  return matrix.rows();
594 }
595 
596 /** Return the vertical dimension
597  @relates SparseMatrix
598 */
599 template<class T,class ROW>
600 inline U32 height(const SparseMatrix<T,ROW>& matrix)
601 {
602  return matrix.columns();
603 }
604 
605 /** @brief Compute the per-element product of the vector and the
606  diagonal entries
607 
608  @relates SparseMatrix
609 
610  Only the diagonal elements are used. The non-diagonal values are
611  not read and treated as zero.
612 */
613 template<class T,class ROW>
615  DenseVector<T>& result,
616  const SparseMatrix<T,ROW>& diagonal,
617  const DenseVector<T>& vector)
618 {
619  //* result[i] = vector[i] / diag[i][i]
620 
621  const U32 size=vector.size();
622  if(result.size()!=size)
623  {
624  result.reset(size);
625  }
626  for(U32 m=0;m<size;m++)
627  {
628  result[m]=vector[m]*diagonal(m,m);
629  }
630 }
631 
632 /** @brief Compute the per-element product of the vector and the
633  inverse diagonal entries
634 
635  @relates SparseMatrix
636 
637  Only the diagonal elements are used. The non-diagonal values are
638  not read and treated as zero.
639 */
640 template<class T,class ROW>
642  DenseVector<T>& result,
643  const SparseMatrix<T,ROW>& diagonal,
644  const DenseVector<T>& vector)
645 {
646  //* result[i] = vector[i] / diag[i][i]
647 
648  const U32 size=vector.size();
649  if(result.size()!=size)
650  {
651  result.reset(size);
652  }
653  for(U32 m=0;m<size;m++)
654  {
655  result[m]=vector[m]/diagonal(m,m);
656  }
657 }
658 
659 template<class T,class ROW>
660 inline SparseMatrix<T,ROW>& set(SparseMatrix<T,ROW> &matrix)
661 {
662  matrix.clear();
663  return matrix;
664 }
665 
666 /** @brief Return true is matrix is square, otherwise return false.
667  @relates SparseMatrix
668  */
669 template<class T,class ROW>
670 inline BWORD isSquare(const SparseMatrix<T,ROW> &matrix)
671 {
672  return(matrix.rows()==matrix.columns());
673 }
674 
675 /** Set matrix to identity matrix
676  @relates SparseMatrix
677  */
678 template<class T,class ROW>
680 {
681  U32 limit=minimum(matrix.columns(),matrix.rows());
682  matrix.clear();
683  for(U32 i = 0;i < limit;i++)
684  matrix(i,i) = T(1);
685  return matrix;
686 }
687 
688 /** Return transpose of matrix
689  @relates SparseMatrix
690  */
691 template<class T,class ROW>
693 {
694  SparseMatrix<T,ROW> A(matrix.rows(),matrix.columns());
695  A.setTranspose(matrix);
696 
697  return A;
698 }
699 
700 /** SparseMatrix add
701  @relates SparseMatrix
702  */
703 template<class T,class ROW>
705  const SparseMatrix<T,ROW> &rhs)
706 {
707  SparseMatrix<T,ROW> result=lhs;
708  result.setSum(rhs);
709  return result;
710 }
711 
712 /** SparseMatrix subtract
713  @relates SparseMatrix
714  */
715 template<class T,class ROW>
717  const SparseMatrix<T,ROW> &rhs)
718 {
719  SparseMatrix<T,ROW> result=lhs;
720  result.setDifference(rhs);
721  return result;
722 }
723 
724 /** SparseMatrix add in place
725  @relates SparseMatrix
726  */
727 template<class T,class ROW>
729  const SparseMatrix<T,ROW> &rhs)
730 {
731  lhs.setSum(rhs);
732  return lhs;
733 }
734 
735 /** SparseMatrix subtract in place
736  @relates SparseMatrix
737  */
738 template<class T,class ROW>
740  const SparseMatrix<T,ROW> &rhs)
741 {
742  lhs.setDifference(rhs);
743  return lhs;
744 }
745 
746 /** SparseMatrix-SparseMatrix multiply where first matrix is presumed diagonal
747  @relates SparseMatrix
748 
749  The diagonal matrix is represented as a vector.
750 
751  The result argument can be used to avoid the expensive allocation of
752  a temporary. The same object is returned by reference for efficient
753  operation in a compound expression.
754  */
755 template<class T,class ROW>
757  const DenseVector<T> &lhs,const SparseMatrix<T,ROW> &rhs)
758 {
759  result.clear();
760  rhs.premultiplyDiagonal(lhs,result);
761  return result;
762 }
763 
764 /** SparseMatrix-SparseMatrix multiply where first matrix is presumed diagonal
765  @relates SparseMatrix
766 
767  Non-diagonal elements of the first matrix are ignored and treated as zero.
768 
769  The result argument can be used to avoid the expensive allocation of
770  a temporary. The same object is returned by reference for efficient
771  operation in a compound expression.
772  */
773 template<class T,class ROW>
775  const SparseMatrix<T,ROW> &lhs,const SparseMatrix<T,ROW> &rhs)
776 {
777  result.clear();
778  rhs.premultiplyDiagonal(lhs,result);
779  return result;
780 }
781 
782 /** SparseMatrix-SparseMatrix multiply where first matrix is presumed diagonal
783  @relates SparseMatrix
784 
785  Diagonal elements of the first matrix are inverted during the multiply.
786  Non-diagonal elements of the first matrix are ignored and treated as zero.
787 
788  The result argument can be used to avoid the expensive allocation of
789  a temporary. The same object is returned by reference for efficient
790  operation in a compound expression.
791  */
792 template<class T,class ROW>
794  SparseMatrix<T,ROW> &result,
795  const SparseMatrix<T,ROW> &lhs,const SparseMatrix<T,ROW> &rhs)
796 {
797  result.clear();
798  rhs.premultiplyInverseDiagonal(lhs,result);
799  return result;
800 }
801 
802 /** SparseMatrix-SparseMatrix multiply where first matrix is a diagonal
803  represented with a vector
804 
805  @relates SparseMatrix
806 
807  Diagonal elements of the first matrix are inverted during the multiply.
808  Non-diagonal elements of the first matrix are ignored and treated as zero.
809 
810  The result argument can be used to avoid the expensive allocation of
811  a temporary. The same object is returned by reference for efficient
812  operation in a compound expression.
813  */
814 template<class T,class ROW>
816  SparseMatrix<T,ROW> &result,
817  const DenseVector<T> &lhs,const SparseMatrix<T,ROW> &rhs)
818 {
819  result.clear();
820  rhs.premultiplyInverseDiagonal(lhs,result);
821  return result;
822 }
823 
824 /** SparseMatrix-SparseMatrix multiply where second matrix is a diagonal
825  @relates SparseMatrix
826 
827  The diagonal matrix is represented as a vector.
828 
829  The result argument can be used to avoid the expensive allocation of
830  a temporary. The same object is returned by reference for efficient
831  operation in a compound expression.
832  */
833 template<class T,class ROW>
835  const SparseMatrix<T,ROW> &lhs,const DenseVector<T> &rhs)
836 {
837  result.clear();
838  lhs.postmultiplyDiagonal(rhs,result);
839  return result;
840 }
841 
842 /** SparseMatrix-SparseMatrix multiply where second matrix is presumed diagonal
843  @relates SparseMatrix
844 
845  Diagonal elements of the first matrix are inverted during the multiply.
846  Non-diagonal elements of the first matrix are ignored and treated as zero.
847 
848  The result argument can be used to avoid the expensive allocation of
849  a temporary. The same object is returned by reference for efficient
850  operation in a compound expression.
851  */
852 template<class T,class ROW>
854  SparseMatrix<T,ROW> &result,
855  const SparseMatrix<T,ROW> &lhs,const SparseMatrix<T,ROW> &rhs)
856 {
857  result.clear();
858  lhs.postmultiplyInverseDiagonal(rhs,result);
859  return result;
860 }
861 
862 /** SparseMatrix-SparseMatrix multiply where second matrix is a diagonal
863  represented by a vector
864 
865  @relates SparseMatrix
866 
867  Diagonal elements of the first matrix are inverted during the multiply.
868  Non-diagonal elements of the first matrix are ignored and treated as zero.
869 
870  The result argument can be used to avoid the expensive allocation of
871  a temporary. The same object is returned by reference for efficient
872  operation in a compound expression.
873  */
874 template<class T,class ROW>
876  SparseMatrix<T,ROW> &result,
877  const SparseMatrix<T,ROW> &lhs,const DenseVector<T> &rhs)
878 {
879  result.clear();
880  lhs.postmultiplyInverseDiagonal(rhs,result);
881  return result;
882 }
883 
884 /** SparseMatrix-Vector multiply
885  @relates SparseMatrix
886  */
887 template<class T,class ROW>
889  const DenseVector<T> &rhs)
890 {
891  DenseVector<T> b;
892  b.reset(rhs.size());
893  lhs.transform(rhs,b);
894  return b;
895 }
896 
897 /** SparseMatrix-Vector multiply with matrix
898  @relates SparseMatrix
899  */
900 template<class T,class ROW>
901 inline void transformVector(const SparseMatrix<T,ROW> &lhs,
902  const DenseVector<T>& in, DenseVector<T>& out)
903 {
904  lhs.transform(in,out);
905 }
906 
907 /** SparseMatrix-Vector multiply with matrix transposed
908  @relates SparseMatrix
909  */
910 template<class T,class ROW>
912  const DenseVector<T>& in, DenseVector<T>& out)
913 {
914  lhs.transposeTransform(in,out);
915 }
916 
917 /** SparseMatrix-Scalar post-multiply
918  @relates SparseMatrix
919  */
920 template<class T,class ROW,class U>
922  const U scalar)
923 {
924  SparseMatrix<T,ROW> result(matrix.rows(),matrix.columns());
925  matrix.scale(scalar,result);
926  return result;
927 }
928 
929 /** SparseMatrix-Scalar pre-multiply
930  @relates SparseMatrix
931  */
932 template<class T,class ROW,class U>
933 inline SparseMatrix<T,ROW> operator*(const U scalar,
934  const SparseMatrix<T,ROW> &matrix)
935 {
936  SparseMatrix<T,ROW> result(matrix.rows(),matrix.columns());
937  matrix.scale(scalar,result);
938  return result;
939 }
940 
941 /** SparseMatrix-Scalar multiply in place
942  @relates SparseMatrix
943  */
944 template<class T,class ROW>
946  const F32 scalar)
947 {
948  lhs.scale(scalar);
949  return lhs;
950 }
951 
952 // BCRS 1D, patterned after the 3D version
953 
954 template <typename T>
955 class FE_DL_EXPORT SparseMatrix1 : public Component
956 {
957  public:
958 typedef T t_real;
959 
960 virtual ~SparseMatrix1(void) {}
961 virtual void multiply(std::vector<t_real> &a_b,
962  const std::vector<t_real> &a_x) const = 0;
963 virtual void scale(t_real a_scale) = 0;
964 };
965 
966 template <typename T>
967 class FE_DL_EXPORT FullBCRS1 : public SparseMatrix1<T>
968 {
969  public:
970 typedef T t_real;
971  FullBCRS1(void);
972 virtual ~FullBCRS1(void);
973 
974 
975 virtual void multiply(std::vector<t_real> &a_b,
976  const std::vector<t_real> &a_x) const;
977 virtual void scale(t_real a_scale);
978 
979  void clear(void);
980  void startrow(void);
981 virtual void done(void);
982  t_real &insert(unsigned int a_columnIndex,
983  const t_real &a_block);
984 
985  void dump(void) const;
986 
987  void write(const String &a_filename);
988  void read(const String &a_filename);
989 
990  void writeDense(const String &a_filename);
991  void readDense(const String &a_filename, unsigned int a_M, unsigned int a_N);
992 
993  void writeStructure(const String &a_filename) const;
994 
995  void sparse(const sp<FullBCRS1> &a_other);
996  void project(const sp<FullBCRS1> &a_other);
997 
998  //void write(CRS<T> &aCRS) const;
999  //void read(const CRS<T> &aCRS);
1000 
1001 
1002  public:
1003  std::vector<t_real> &blocks(void) { return m_blocks; }
1004  std::vector<unsigned int> &colind(void) { return m_colind; }
1005  std::vector<unsigned int> &rowptr(void) { return m_rowptr; }
1006 
1007  protected:
1008  std::vector<t_real> m_blocks;
1009  std::vector<unsigned int> m_colind;
1010  std::vector<unsigned int> m_rowptr;
1011  unsigned int m_r;
1012  t_real m_zeroVector;
1013 };
1014 
1015 template <typename T>
1016 class FE_DL_EXPORT UpperTriangularBCRS1 : public FullBCRS1<T>
1017 {
1018  public:
1019 typedef T t_real;
1020  UpperTriangularBCRS1(void){}
1021 virtual ~UpperTriangularBCRS1(void){}
1022 
1023 virtual void multiply(std::vector<t_real> &a_b,
1024  const std::vector<t_real> &a_x) const;
1025 
1026  void incompleteSqrt(void);
1027  void backSub(std::vector<t_real> &a_x, const std::vector<t_real> &a_b);
1028  void transposeForeSub(std::vector<t_real> &a_x, const std::vector<t_real> &a_b);
1029  void backSolve(std::vector<t_real> &a_x, const std::vector<t_real> &a_b);
1030 virtual void done(void);
1031 
1032  private:
1033  std::vector<unsigned int> m_ptr; // buffer for transposeForeSub
1034  std::vector<t_real> m_y; // buffer for backSolve
1035 
1036 };
1037 
1038 template <typename T>
1039 inline FullBCRS1<T>::FullBCRS1(void)
1040 {
1041  m_r = 0;
1042  m_zeroVector = 0.0;
1043 }
1044 
1045 template <typename T>
1046 inline FullBCRS1<T>::~FullBCRS1(void)
1047 {
1048 }
1049 
1050 template <typename T>
1051 inline void FullBCRS1<T>::clear(void)
1052 {
1053  m_blocks.clear();
1054  m_colind.clear();
1055  m_rowptr.clear();
1056  m_r = 0;
1057 }
1058 
1059 template <typename T>
1060 inline void FullBCRS1<T>::startrow(void)
1061 {
1062  m_rowptr.push_back(m_r);
1063 }
1064 
1065 template <typename T>
1066 inline void FullBCRS1<T>::done(void)
1067 {
1068  m_rowptr.push_back(m_r);
1069 }
1070 
1071 template <typename T>
1072 inline void UpperTriangularBCRS1<T>::done(void)
1073 {
1074  m_y.resize(FullBCRS1<T>::m_rowptr.size());
1075  FullBCRS1<T>::m_rowptr.push_back(FullBCRS1<T>::m_r);
1076  m_ptr.resize(FullBCRS1<T>::m_rowptr.size());
1077 }
1078 
1079 template <typename T>
1080 inline T &FullBCRS1<T>::insert(unsigned int a_columnIndex, const t_real &a_block)
1081 {
1082  m_blocks.push_back(a_block);
1083  m_colind.push_back(a_columnIndex);
1084  m_r++;
1085  return m_blocks.back();
1086 }
1087 
1088 template <typename T>
1089 inline void FullBCRS1<T>::multiply(std::vector<t_real> &a_b, const std::vector<t_real> &a_x) const
1090 {
1091  unsigned int n = (unsigned int)(m_rowptr.size() - 1);
1092  for(unsigned int i = 0; i < n; i++)
1093  {
1094  a_b[i] = m_zeroVector;
1095  for(unsigned int k = m_rowptr[i]; k < m_rowptr[i+1]; k++)
1096  {
1097  a_b[i] += m_blocks[k] * a_x[m_colind[k]];
1098  }
1099  }
1100 }
1101 
1102 template <typename T>
1103 inline void FullBCRS1<T>::dump(void) const
1104 {
1105  t_real offdiagonal_sum;
1106  offdiagonal_sum = 0.0;
1107  unsigned int n = (unsigned int)(m_rowptr.size() - 1);
1108  for(unsigned int i = 0; i < n; i++)
1109  {
1110  fe_fprintf(stderr, " %d: ", i);
1111  for(unsigned int k = m_rowptr[i]; k < m_rowptr[i+1]; k++)
1112  {
1113 fe_fprintf(stderr, "%g ", m_blocks[k]);
1114  if(m_colind[k] != i) // diagonal
1115  {
1116  offdiagonal_sum = offdiagonal_sum + m_blocks[k];
1117  }
1118  }
1119  fe_fprintf(stderr, "\n");
1120  }
1121 
1122  feLogGroup("BCRS", "off diagonal\n%g\n", offdiagonal_sum);
1123 
1124 fe_fprintf(stderr, "--------------------------\n");
1125  for(unsigned int i = 0; i < n; i++)
1126  {
1127  unsigned int j = 0;
1128  for(unsigned int k = m_rowptr[i]; k < m_rowptr[i+1]; k++)
1129  {
1130  while(j < m_colind[k] && j < n)
1131  {
1132  fe_fprintf(stderr, "%6.3g ", 0.0);
1133  j++;
1134  }
1135  fe_fprintf(stderr, "%6.3g ", m_blocks[k]);
1136  j++;
1137  }
1138  fe_fprintf(stderr, "\n");
1139  }
1140 fe_fprintf(stderr, "--------------------------\n");
1141 }
1142 
1143 template <typename T>
1144 inline void FullBCRS1<T>::scale(t_real a_scale)
1145 {
1146  unsigned int n = (unsigned int)m_blocks.size();
1147  for(unsigned int i = 0; i < n; i++)
1148  {
1149  m_blocks[i] *= a_scale;
1150  }
1151 }
1152 
1153 template <typename T>
1154 inline void UpperTriangularBCRS1<T>::multiply(std::vector<t_real> &a_b, const std::vector<t_real> &a_x) const
1155 {
1156  unsigned int n = (unsigned int)(FullBCRS1<T>::m_rowptr.size() - 1);
1157  for(unsigned int i = 0; i < n; i++)
1158  {
1159  a_b[i] = FullBCRS1<T>::m_zeroVector;
1160  }
1161  for(unsigned int i = 0; i < n; i++)
1162  {
1163  unsigned int k = FullBCRS1<T>::m_rowptr[i];
1164  a_b[i] += FullBCRS1<T>::m_blocks[k] * a_x[i];
1165  for(k=k+1; k < FullBCRS1<T>::m_rowptr[i+1]; k++)
1166  {
1167  a_b[i] += FullBCRS1<T>::m_blocks[k] * a_x[FullBCRS1<T>::m_colind[k]];
1168  a_b[FullBCRS1<T>::m_colind[k]] += FullBCRS1<T>::m_blocks[k] * a_x[i];
1169  }
1170  }
1171 }
1172 
1173 template <typename T>
1174 inline void FullBCRS1<T>::sparse(const sp<FullBCRS1> &a_other)
1175 {
1176  m_blocks.clear();
1177  m_colind.clear();
1178  m_rowptr.clear();
1179  m_r = 0;
1180  unsigned int n = a_other->m_rowptr.size()-1;
1181  for(unsigned int i = 0; i < n; i++)
1182  {
1183  startrow();
1184  int d = a_other->m_rowptr[i];
1185  for(int k=d; k < a_other->m_rowptr[i+1]; k++)
1186  {
1187  int c = a_other->m_colind[k];
1188  if(!(0.0 == a_other->m_blocks[k]))
1189  {
1190  insert(c, a_other->m_blocks[k]);
1191  }
1192  }
1193  }
1194  done();
1195 }
1196 
1197 template <typename T>
1198 inline void FullBCRS1<T>::project(const sp<FullBCRS1> &a_other)
1199 {
1200  unsigned int n = a_other->m_rowptr.size()-1;
1201  for(unsigned int i = 0; i < n; i++)
1202  {
1203  int d = a_other->m_rowptr[i];
1204  int d_self = m_rowptr[i];
1205  for(int k=d; k < a_other->m_rowptr[i+1]; k++)
1206  {
1207  int c = a_other->m_colind[k];
1208  for(int k_self=d_self; k_self < m_rowptr[i+1]; k_self++)
1209  {
1210  int c_self = m_colind[k_self];
1211  if(c_self == c)
1212  {
1213  m_blocks[k_self] = a_other->m_blocks[k];
1214  }
1215  }
1216  }
1217  }
1218 }
1219 
1220 template <typename T>
1221 inline void UpperTriangularBCRS1<T>::backSub(std::vector<t_real> &a_x, const std::vector<t_real> &a_b)
1222 {
1223  unsigned int n = (unsigned int)(FullBCRS1<T>::m_rowptr.size()-1);
1224  //fe::backSub(FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[n-1]], a_x[n-1], a_b[n-1]);
1225  a_x[n-1] = a_b[n-1]/FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[n-1]];
1226  t_real tmp;
1227 
1228  for(int i = n-2; i >= 0; i--)
1229  {
1230  a_x[i] = a_b[i];
1231  int d = FullBCRS1<T>::m_rowptr[i];
1232  for(unsigned int k=d+1; k < FullBCRS1<T>::m_rowptr[i+1]; k++)
1233  {
1234  int c = FullBCRS1<T>::m_colind[k];
1235  tmp = FullBCRS1<T>::m_blocks[k] * a_x[c];
1236  a_x[i] -= tmp;
1237  }
1238  //fe::backSub(FullBCRS1<T>::m_blocks[d], a_x[i], a_x[i]);
1239  a_x[i] = a_x[i]/FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[i]];
1240  }
1241 }
1242 
1243 template <typename T>
1244 inline void UpperTriangularBCRS1<T>::transposeForeSub(std::vector<t_real> &a_x, const std::vector<t_real> &a_b)
1245 {
1246  unsigned int n = (unsigned int)(FullBCRS1<T>::m_rowptr.size()-1);
1247  for(unsigned int i = 0 ; i < FullBCRS1<T>::m_rowptr.size(); i++)
1248  {
1249  m_ptr[i] = FullBCRS1<T>::m_rowptr[i];
1250  }
1251  //fe::transposeForeSub(FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[0]], a_x[0], a_b[0]);
1252  a_x[0] = a_b[0] / FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[0]];
1253 
1254  for(unsigned int i = 1; i < n; i++)
1255  {
1256  a_x[i] = a_b[i];
1257  for(unsigned int m = 0; m < i; m++)
1258  {
1259  unsigned int c = FullBCRS1<T>::m_colind[m_ptr[m]];
1260  while(c < i && m_ptr[m] < FullBCRS1<T>::m_rowptr[m+1]-1)
1261  {
1262  m_ptr[m]++;
1263  c = FullBCRS1<T>::m_colind[m_ptr[m]];
1264  }
1265  if(c == i)
1266  {
1267  //a_x[i] -= fe::transposeMultiply(FullBCRS1<T>::m_blocks[m_ptr[m]], a_x[m]);
1268  a_x[i] -= FullBCRS1<T>::m_blocks[m_ptr[m]] * a_x[m];
1269  }
1270  }
1271  //fe::transposeForeSub(FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[i]], a_x[i], a_x[i]);
1272  a_x[i] = a_x[i] / FullBCRS1<T>::m_blocks[FullBCRS1<T>::m_rowptr[i]];
1273  }
1274 }
1275 
1276 template <typename T>
1277 inline void UpperTriangularBCRS1<T>::backSolve(std::vector<t_real> &a_x, const std::vector<t_real> &a_b)
1278 {
1279  transposeForeSub(m_y, a_b);
1280  backSub(a_x, m_y);
1281 }
1282 
1283 template <typename T>
1284 inline void UpperTriangularBCRS1<T>::incompleteSqrt(void)
1285 {
1286  unsigned int d;
1287  unsigned int n = (unsigned int)(FullBCRS1<T>::m_rowptr.size()-1);
1288  t_real inv_z;
1289  t_real z;
1290  for(unsigned int k = 0; k < n-1; k++)
1291  {
1292  d = FullBCRS1<T>::m_rowptr[k];
1293  FullBCRS1<T>::m_blocks[d] = sqrt(FullBCRS1<T>::m_blocks[d]);
1294  z = FullBCRS1<T>::m_blocks[d];
1295 
1296  inv_z = 1.0 / z;
1297 
1298  for(unsigned int i=d+1; i < FullBCRS1<T>::m_rowptr[k+1]; i++)
1299  {
1300  z = FullBCRS1<T>::m_blocks[i] * inv_z;
1301 
1302  FullBCRS1<T>::m_blocks[i] = z;
1303  }
1304 
1305  for(unsigned int i=d+1; i < FullBCRS1<T>::m_rowptr[k+1]; i++)
1306  {
1307  z = FullBCRS1<T>::m_blocks[i];
1308  unsigned int h = FullBCRS1<T>::m_colind[i];
1309  unsigned int g = i;
1310 
1311  for(unsigned int j = FullBCRS1<T>::m_rowptr[h]; j < FullBCRS1<T>::m_rowptr[h+1]; j++)
1312  {
1313  for(; g < FullBCRS1<T>::m_rowptr[k+1] && FullBCRS1<T>::m_colind[g] <= FullBCRS1<T>::m_colind[j]; g++)
1314  {
1315  if (FullBCRS1<T>::m_colind[g] == FullBCRS1<T>::m_colind[j])
1316  {
1317  t_real t;
1318  t = z * FullBCRS1<T>::m_blocks[g];
1319  FullBCRS1<T>::m_blocks[j] = FullBCRS1<T>::m_blocks[j] - t;
1320  }
1321  }
1322  }
1323  }
1324  }
1325  d = FullBCRS1<T>::m_rowptr[n-1];
1326  t_real tmp;
1327  tmp = sqrt(FullBCRS1<T>::m_blocks[d]);
1328  FullBCRS1<T>::m_blocks[d] = tmp;
1329 }
1330 
1331 
1332 } /* namespace */
1333 
1334 /** SparseMatrix print
1335  @relates SparseMatrix
1336 
1337  The output isn't sparse.
1338  */
1339 template<class T,class ROW>
1340 String print(const ext::SparseMatrix<T,ROW> &matrix)
1341 {
1342  String s;
1343  for(U32 i = 0; i<matrix.rows(); i++)
1344  {
1345  for(U32 j = 0; j<matrix.columns(); j++)
1346  {
1347  s.catf("%6.3f ", matrix(i,j));
1348  }
1349  s.cat("\n");
1350  }
1351  return s;
1352 }
1353 
1354 } /* namespace */
1355 
1356 #endif // __solve_SparseMatrix_h__
SparseMatrix< T, ROW > & postmultiplyInverseDiagonal(SparseMatrix< T, ROW > &result, const SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix-SparseMatrix multiply where second matrix is presumed diagonal.
Definition: SparseMatrix.h:853
Dense vector - size fixed at construction or reset.
Definition: DenseVector.h:21
SparseMatrix< T, ROW > & operator*=(SparseMatrix< T, ROW > &lhs, const F32 scalar)
SparseMatrix-Scalar multiply in place.
Definition: SparseMatrix.h:945
SparseMatrix< T, ROW > & setIdentity(SparseMatrix< T, ROW > &matrix)
Set matrix to identity matrix.
Definition: SparseMatrix.h:679
void clear(void)
Zero existing values, but do not remove.
Definition: SparseArray.h:128
void transposeTransformVector(const SparseMatrix< T, ROW > &lhs, const DenseVector< T > &in, DenseVector< T > &out)
SparseMatrix-Vector multiply with matrix transposed.
Definition: SparseMatrix.h:911
kernel
Definition: namespace.dox:3
U32 width(const SparseMatrix< T, ROW > &matrix)
Return the horizonatal dimension.
Definition: SparseMatrix.h:591
SparseMatrix< T, ROW > & postmultiplyInverseDiagonal(SparseMatrix< T, ROW > &result, const SparseMatrix< T, ROW > &lhs, const DenseVector< T > &rhs)
SparseMatrix-SparseMatrix multiply where second matrix is a diagonal represented by a vector...
Definition: SparseMatrix.h:875
SparseMatrix< T, ROW > operator-(const SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix subtract.
Definition: SparseMatrix.h:716
SparseMatrix< T, ROW > & premultiplyDiagonal(SparseMatrix< T, ROW > &result, const DenseVector< T > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix-SparseMatrix multiply where first matrix is presumed diagonal.
Definition: SparseMatrix.h:756
void premultiplyInverseDiagonal(DenseVector< T > &result, const SparseMatrix< T, ROW > &diagonal, const DenseVector< T > &vector)
Compute the per-element product of the vector and the inverse diagonal entries.
Definition: SparseMatrix.h:641
DenseVector< T > operator*(const SparseMatrix< T, ROW > &lhs, const DenseVector< T > &rhs)
SparseMatrix-Vector multiply.
Definition: SparseMatrix.h:888
SparseMatrix< T, ROW > & premultiplyDiagonal(SparseMatrix< T, ROW > &result, const SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix-SparseMatrix multiply where first matrix is presumed diagonal.
Definition: SparseMatrix.h:774
SparseMatrix< T, ROW > transpose(const SparseMatrix< T, ROW > &matrix)
Return transpose of matrix.
Definition: SparseMatrix.h:692
String & cat(const char *operand)
Append the current String with the given text.
Definition: String.cc:545
SparseMatrix< T, ROW > operator*(const SparseMatrix< T, ROW > &matrix, const U scalar)
SparseMatrix-Scalar post-multiply.
Definition: SparseMatrix.h:921
U32 entries(void) const
Return the number of actual stored entries.
Definition: SparseArray.h:55
Automatically reference-counted string container.
Definition: String.h:128
void project(Vector< 4, T > &a_r, const Matrix< 4, 4, T > &a_m, const Vector< 4, T > &a_v)
project vector through matrix. divides by transformed w
Definition: Matrix.h:1182
SparseMatrix< T, ROW > & premultiplyInverseDiagonal(SparseMatrix< T, ROW > &result, const SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix-SparseMatrix multiply where first matrix is presumed diagonal.
Definition: SparseMatrix.h:793
SparseMatrix< T, ROW > operator*(const U scalar, const SparseMatrix< T, ROW > &matrix)
SparseMatrix-Scalar pre-multiply.
Definition: SparseMatrix.h:933
SparseMatrix< T, ROW > & premultiplyInverseDiagonal(SparseMatrix< T, ROW > &result, const DenseVector< T > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix-SparseMatrix multiply where first matrix is a diagonal represented with a vector...
Definition: SparseMatrix.h:815
String & catf(const char *fmt,...)
Populate the string as with sPrintf(), but by concatenating the results to the existing string...
Definition: String.cc:554
void transformVector(const SparseMatrix< T, ROW > &lhs, const DenseVector< T > &in, DenseVector< T > &out)
SparseMatrix-Vector multiply with matrix.
Definition: SparseMatrix.h:901
Base for all interfacable components.
Definition: Component.h:20
String print(const SparseArray< T > &rhs, BWORD sparse=FALSE)
Print to a string.
Definition: SparseArray.h:227
SparseMatrix< T, ROW > & postmultiplyDiagonal(SparseMatrix< T, ROW > &result, const SparseMatrix< T, ROW > &lhs, const DenseVector< T > &rhs)
SparseMatrix-SparseMatrix multiply where second matrix is a diagonal.
Definition: SparseMatrix.h:834
U32 height(const SparseMatrix< T, ROW > &matrix)
Return the vertical dimension.
Definition: SparseMatrix.h:600
SparseMatrix< T, ROW > & operator+=(SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix add in place.
Definition: SparseMatrix.h:728
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
SparseMatrix< T, ROW > operator+(const SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix add.
Definition: SparseMatrix.h:704
Dense array of sparse rows.
Definition: ListSparseMatrix.h:25
BWORD isSquare(const SparseMatrix< T, ROW > &matrix)
Return true is matrix is square, otherwise return false.
Definition: SparseMatrix.h:670
SparseMatrix< T, ROW > & operator-=(SparseMatrix< T, ROW > &lhs, const SparseMatrix< T, ROW > &rhs)
SparseMatrix subtract in place.
Definition: SparseMatrix.h:739
void premultiplyDiagonal(DenseVector< T > &result, const SparseMatrix< T, ROW > &diagonal, const DenseVector< T > &vector)
Compute the per-element product of the vector and the diagonal entries.
Definition: SparseMatrix.h:614
void reset(U32 prealloc=FE_SA_PREALLOC)
Remove all existing values.
Definition: SparseArray.h:120
U32 size(void) const
Return the largest index.
Definition: SparseArray.h:40