Content

Symmetric and Hermitian Matrices with Full Storage

Concepts of TrMatrix shown on the previous page can be transfered to symmetric and hermitian matrices. Classes SyMatrix and HeMatrix represent symmertric and hermitian matrix classes with full storage respectively. Either the lower or upper triangular part of the full storage schemes is used to represent the symmetric or hermitian matrix.

Using views the same full storage scheme can be used for a GeMatrix, TrMatrix, SyMatrix or HeMatrix type:

Chaining methods allows any combination of view creation.

Matrix Types SyMatrix and HeMatrix

Symmetric and hermitian matrices are always square. The types SyMatrix and HeMatrix use a full storage scheme for their data:

In most cases you first allocate a GeMatrix and then create a symmetric or hermitian view from some triangular part. But you also can go the way around, i.e. allocate a symmetric/hermitian matrix and create triangular or general matrix views referencing the underlying full storage scheme.

Common Interface of SyMatrix and HeMatrix

 SyMatrix(IndexType dim, StorageUpLo upLo);          

Allocates a memory for dim x dim elements. The triangular part specified by upLo (Lower or Upper) is used to represent a symmetric or hermitian matrix.

 HeMatrix(IndexType dim, StorageUpLo upLo);          
                                                     
 IndexType                                           
 dim() const;                                        

Returns the matrix dimension.

 StorageUpLo                                         
 upLo() const;                                       

Returns Lower if the matrix is represented by lower triangular part. Otherwise Upper.

In non-const context the method returns a reference of the attribute. So you can change it.

 StorageUpLo &                                       
 upLo();                                             
 const ElementType &                                 
 operator()(IndexType i, IndexType j) const;         

Return a reference to element in row \(i\) and column \(j\). Only accessing elements from the triangular part specified by upLo() is allowed. Otherwise a runtime assertion gets triggered.

Note: The operator returns a reference to value actually stored in memory. If you have a hermitian matrix and you access a diagonal element it is your responsibility to ignore the imaginary part and assume it to be zero.

 ElementType &                                       
 operator()(IndexType i, IndexType j);               
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
 const ElementType *                                 
 data() const;                                       
                                                     

Pointer to the first element of the matrix. So this is the address of A(1,1)

                                                     
 ElementType *                                       
 data();                                             
                                                     
                                                     
 StorageOrder                                        
 order() const;                                      
                                                     
                                                     
                                                     
                                                     

Returns RowMajor, ColMajor or Grid.

An storage order Grid occurs if you have e.g. a matrix view that references every second row and every third column of a matrix.

 IndexType                                           
 strideRow() const;                                  
                                                     
                                                     
                                                     

Stride in memory between elements in the same column. So A.data() + A.strideRow() is the address of A(2,1).

If your matrix is ColMajor this is 1.

 IndexType                                           
 strideCol() const;                                  
                                                     
                                                     
                                                     

Stride in memory between elements in the same row. So A.data() + A.strideCol() is the address of A(2,1).

If your matrix is RowMajor this is 1.

 IndexType                                           
 leadingDimension() const;                           
                                                     
                                                     
                                                     
                                                     
  • For ColMajor matrices returns strideCol().

  • For RowMajor matrices returns strideRow().

  • For Grid matrices this method triggers an runtime assertion.

Creating Matrix Views from GeMatrix

From a GeMatrix you only can create TrMatrix views directly. Other matrix views like symmetric or hermitian views can be created by chaining view creation.

The following list of GeMatrix methods was already listed on the previous page:

 const ConstTriangularView   
 upper() const;              

Return a triangular or trapezoidal matrix view represented by the upper triangular part.

 TriangularView              
 upper();                    
 const ConstTriangularView   
 upperUnit() const;          

Return a triangular or trapezoidal matrix view represented by the upper triangular part. Elements on the diagonal must be assumed to be one.

 TriangularView              
 upperUnit();                
 const ConstTriangularView   
 lower() const;              

Return a triangular or trapezoidal matrix view represented by the lower triangular part.

 TriangularView              
 lower();                    
 const ConstTriangularView   
 lowerUnit() const;          

Return a triangular or trapezoidal matrix view represented by the lower triangular part. Elements on the diagonal must be assumed to be one.

 TriangularView              
 lowerUnit();                

Example

#include <flens/flens.cxx>
#include <iostream>

using namespace flens;
using namespace std;

int
main()
{
    GeMatrix<FullStorage<double> >   A(3,4);

    A =  1,  2,  3,  4,
         5,  6,  7,  8,
         9101112;

    cout << "A = " << A << endl;
    cout << "A.upper() = " << A.upper() << endl;
    cout << "A.upperUnit() = " << A.upperUnit() << endl;
    cout << "A.lower() = " << A.lower() << endl;
    cout << "A.lowerUnit() = " << A.lowerUnit() << endl;
}

Compile and Run

$shell> cd flens/examples                                                       
$shell> g++ -Wall -std=c++11 -I../.. matrixviews_from_gematrix.cc               
$shell> ./a.out                                                                 
A = 
            1             2             3             4 
            5             6             7             8 
            9            10            11            12 
A.upper() = 
            1             2             3             4 
            0             6             7             8 
            0             0            11            12 
A.upperUnit() = 
            1             2             3             4 
            0             1             7             8 
            0             0             1            12 
A.lower() = 
            1             0             0             0 
            5             6             0             0 
            9            10            11             0 
A.lowerUnit() = 
            1             0             0             0 
            5             1             0             0 
            9            10             1             0 

Creating Matrix Views from TrMatrix

From a TrMatrix you can create GeMatrix, SyMatrix and HeMatrix views directly:

const ConstGeneralView general() const;

Return a general matrix view referencing the complete underlying full storage scheme. Through this view any element can be accessed.

GeneralView general();

const ConstHermitianView hermitian() const;

If the TrMatrix is triangular (and not trapezoidal returns a hermitian matrix view. The hermitian matrix is represented by the given triangular part.

If the TrMatrix is trapezoidal this causes an assertion failure at runtime.

HermitianView hermitian();

const ConstSymmetricView symmetric() const;

If the TrMatrix is triangular (and not trapezoidal returns a symmetric matrix view. The symmetric matrix is represented by the given triangular part.

If the TrMatrix is trapezoidal this causes an assertion failure at runtime.

SymmetricView symmetric();

Example

#include <flens/flens.cxx>
#include <complex>
#include <iostream>

using namespace flens;
using namespace std;

int
main()
{
    typedef std::complex<double>      zcomplex;
    GeMatrix<FullStorage<zcomplex> >  A(3,3);

    A =  zcomplex(1,1), zcomplex(1,2), zcomplex(1,3),
         zcomplex(2,1), zcomplex(2,2), zcomplex(2,3),
         zcomplex(3,1), zcomplex(3,2), zcomplex(3,3);

    auto U = A.upper();

    cout << "U = " << U << endl;
    cout << "U.general() = " << U.general() << endl;
    cout << "U.hermitian() = " << U.hermitian() << endl;
    cout << "U.symmetric() = " << U.symmetric() << endl;
}

Compile and Run

$shell> cd flens/examples                                                       
$shell> g++ -Wall -std=c++11 -I../.. matrixviews_from_trmatrix.cc               
$shell> ./a.out                                                                 
U = 
                       (1,1)                        (1,2)                        (1,3) 
                       (0,0)                        (2,2)                        (2,3) 
                       (0,0)                        (0,0)                        (3,3) 
U.general() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (2,1)                        (2,2)                        (2,3) 
                       (3,1)                        (3,2)                        (3,3) 
U.hermitian() = 
                       (1,0)                       (1,2)                       (1,3)
                      (1,-2)                       (2,0)                       (2,3)
                      (1,-3)                      (2,-3)                       (3,0)
U.symmetric() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (1,2)                        (2,2)                        (2,3) 
                       (1,3)                        (2,3)                        (3,3) 

Creating Matrix Views from SyMatrix

const ConstGeneralView general() const;

Return a general matrix view referencing the complete underlying full storage scheme. Through this view any element can be accessed.

GeneralView general();

const ConstHermitianView hermitian() const;

Returns a hermitian matrix view. The hermitian matrix is represented by the same triangular part that represents the SyMatrix.

HermitianView hermitian();

const ConstTriangularView triangular() const;

Returns a triangular matrix view. The triangular matrix is represented by the same triangular part that represents the SyMatrix.

TriangularView triangular();

Example

#include <flens/flens.cxx>
#include <complex>
#include <iostream>

using namespace flens;
using namespace std;

int
main()
{
    typedef std::complex<double>      zcomplex;
    GeMatrix<FullStorage<zcomplex> >  A(3,3);

    A =  zcomplex(1,1), zcomplex(1,2), zcomplex(1,3),
         zcomplex(2,1), zcomplex(2,2), zcomplex(2,3),
         zcomplex(3,1), zcomplex(3,2), zcomplex(3,3);

    auto S = A.upper().symmetric();

    cout << "S = " << S << endl;
    cout << "S.triangular() = " << S.triangular() << endl;
    cout << "S.general() = " << S.general() << endl;
    cout << "S.hermitian() = " << S.hermitian() << endl;
}

Compile and Run

$shell> cd flens/examples                                                       
$shell> g++ -Wall -std=c++11 -I../.. matrixviews_from_symatrix.cc               
$shell> ./a.out                                                                 
S = 
                       (1,1)                        (1,2)                        (1,3) 
                       (1,2)                        (2,2)                        (2,3) 
                       (1,3)                        (2,3)                        (3,3) 
S.triangular() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (0,0)                        (2,2)                        (2,3) 
                       (0,0)                        (0,0)                        (3,3) 
S.general() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (2,1)                        (2,2)                        (2,3) 
                       (3,1)                        (3,2)                        (3,3) 
S.hermitian() = 
                       (1,0)                       (1,2)                       (1,3)
                      (1,-2)                       (2,0)                       (2,3)
                      (1,-3)                      (2,-3)                       (3,0)

Creating Matrix Views from HeMatrix

const ConstGeneralView general() const;

Return a general matrix view referencing the complete underlying full storage scheme. Through this view any element can be accessed.

GeneralView general();

const ConstSymmetricView symmetric() const;

Returns a symmetric matrix view. The symmetric matrix is represented by the same triangular part that represents the HeMatrix.

SymmetricView symmetric();

const ConstTriangularView triangular() const;

Returns a triangular matrix view. The triangular matrix is represented by the same triangular part that represents the HeMatrix.

TriangularView triangular();

Example

#include <flens/flens.cxx>
#include <complex>
#include <iostream>

using namespace flens;
using namespace std;

int
main()
{
    typedef std::complex<double>      zcomplex;
    GeMatrix<FullStorage<zcomplex> >  A(3,3);

    A =  zcomplex(1,1), zcomplex(1,2), zcomplex(1,3),
         zcomplex(2,1), zcomplex(2,2), zcomplex(2,3),
         zcomplex(3,1), zcomplex(3,2), zcomplex(3,3);

    auto H = A.upper().hermitian();

    cout << "H = " << H << endl;
    cout << "H.triangular() = " << H.triangular() << endl;
    cout << "H.general() = " << H.general() << endl;
    cout << "H.symmetric() = " << H.symmetric() << endl;
}

Compile and Run

$shell> cd flens/examples                                                       
$shell> g++ -Wall -std=c++11 -I../.. matrixviews_from_hematrix.cc               
$shell> ./a.out                                                                 
H = 
                       (1,0)                       (1,2)                       (1,3)
                      (1,-2)                       (2,0)                       (2,3)
                      (1,-3)                      (2,-3)                       (3,0)
H.triangular() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (0,0)                        (2,2)                        (2,3) 
                       (0,0)                        (0,0)                        (3,3) 
H.general() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (2,1)                        (2,2)                        (2,3) 
                       (3,1)                        (3,2)                        (3,3) 
H.symmetric() = 
                       (1,1)                        (1,2)                        (1,3) 
                       (1,2)                        (2,2)                        (2,3) 
                       (1,3)                        (2,3)                        (3,3) 

Matrix Views from Rectangular Parts

The same concepts introduced for TrMatrix apply to SyMatrix and HeMatrix: You can create a general matrix view from a SyMatrix or HeMatrix. From there you can select any block and create a GeMatrix view:

  SyMatrix<FullStorage<double> >   S(n, Upper);

  auto A = S.general();

  A12 = A(_(1,4),_(5,8));
  // ...

As this is a frequently needed task we offer a more direct support. The return type of the following methods is always a GeMatrix view (even if you select a block on the diagonal that logically would be symmetric or hermitian):

  const ConstGeneralView                             
  operator()(const Range<IndexType> &rows,           
             const Range<IndexType> &cols) const;    

Select a rectangualr area of the form (fromRow:toRow, fromCol:toCol) or (fromRow:stepRow:toRow, fromCol:stepRow:toCol)

  GeneralView                                        
  operator()(const Range<IndexType> &rows,           
             const Range<IndexType> &cols);          
  const ConstGeneralView                             
  operator()(const Underscore<IndexType> &,          
             const Range<IndexType> &cols) const;    

All rows are selected. So the range has the form (all, from:to).

  GeneralView                                        
  operator()(const Underscore<IndexType> &,          
             const Range<IndexType> &cols);          
  const ConstGeneralView                             
  operator()(const Range<IndexType> &rows,           
             const Underscore<IndexType> &) const;   

All columns are selected. So the range has the form (from:to, all).

  GeneralView                                        
  operator()(const Range<IndexType> &rows,           
             const Underscore<IndexType> &);         

Vector Views

The return type is always a DenseVector view:

  const ConstVectorView                                            
  operator()(IndexType row, const Underscore<IndexType> &) const;  

Select (row, all), i.e. the row with index row.

  VectorView                                                       
  operator()(IndexType row, const Underscore<IndexType> &);        
  const ConstVectorView                                            
  operator()(IndexType row, const Range<IndexType> &cols) const;   

Select (row, from:to), i.e. from the row with index row the elements in the column in range from:to.

  VectorView                                                       
  operator()(IndexType row, const Range<IndexType> &cols);         
  const ConstVectorView                                            
  operator()(const Underscore<IndexType> &, IndexType col) const;  

Select (all, col), i.e. the column with index col.

  VectorView                                                       
  operator()(const Underscore<IndexType> &, IndexType col);        
  const ConstVectorView                                            
  operator()(const Range<IndexType> &rows, IndexType col) const;   

Select (from:to, col), i.e. from the column with index col the elements in the row range from:to.

  VectorView                                                       
  operator()(const Range<IndexType> &rows, IndexType col);