Content

Array Storage and Dense Vectors

For dense vectors we follow the same concepts known from general matrices. We have three array storage schemes for realizing allocated, referenced and const referenced storage. Each of these storage classes can be used as template parameter for a dense vector class for the sake of providing a unified interface without runtime overhead.

Array Storage Schemes

FLENS defines three template classes for storing/referring an array:

For the moment we will not discuss further template parameters of the storage classes that allow to change the default index type (which is `long), the default index base (which is 1) and the memory allocator.

DenseVector: Dense Vector with Array Storage

The DenseVector class has only one templated paramter that defines the underlying storage scheme. So this again means that means a storage scheme gets a mathematical meaning by encapsulating it.

Examples:

DenseVector<Array<double> >

A dense vector where memory gets allocated when instantiated and released at the end of its scope.

DenseVector<Array<double> >::View

A dense vector that references elements divided by a constant stride. In practise these can be elements from another vector but also from a row, column, diagonal, etc. of a general matrix.

Creation/destruction is cheap.

View is a publib typedef in DenseVector and in this case defined as DenseVector<ArrayView<double> >

DenseVector<Array<double> >::ConstView

Like DenseVector<..>::View just const. Attempts of calling a non-const method will trigger an static assertion failure. So an instance must be defined as const.

ConstView is a public typedef in DenseVector and in this case defined as DenseVector<ConstArrayView<double> >

Some Public Typedefs

IndexType

Like its name suggests the type used for indexing.

ElementType

The element type.

View, ConstView

Types for referencing elements separated by a constant stride.

NoView

Vector type with memory allocation. If you want to copy vector parts instead of referencing use this type.

EngineView, EngineConstView

Storage schemes for referencing vectors. For DenseVector these are typedefs for ArrayView<..> and ConstArrayView<..>.

Some Methods and operations for Matrix Manipulation

DenseVector(IndexType n)

Constructor for a dense vector of length \(n\).

IndexType length() const

Returns the vector length.

const ElementType & operator()(IndexType i) const

Returns a reference to \(i\)-th element.

ElementType & operator()(IndexType i)

Initializer operator=(const ElementType &value)

List initializer.

Allows to initialize the vector with a comma separated list of values.

If the list contains only a single value it is used to fill the vector.

Like for matrices, by default indices start at 1, i.e. the index base is 1. Again, we are dealing with math entities not STL container. So usually that is what you want in numerical linear algebra. If you chance for some good reason the index base the following methods become useful:

IndexType firstIndex() const

Return the first valid index.

IndexType lastIndex() const

Return the last valid index.

Simple Example for using DenseVector

In a first example we show:

Example Code

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

using namespace flens;
using namespace std;

int
main()
{
    typedef DenseVector<Array<double> >  DDenseVector;

    DDenseVector x(5);
    x = 12345;

    cout << "x = " << x << endl;

    cout << "Length of x: " << x.length() << endl;
    cout << endl;
    cout << "Indices: " << x.firstIndex() << ".." << x.lastIndex() << endl;
    cout << endl;

    x(2) = 42;

    cout << "changed element: x(2) = " << x(2) << endl;

    cout << endl;

    cout << "x = " << x << endl;

    x = 42;

    cout << "x = " << x << endl;

    return 0;
}

Comments on Example Code

We simply include everything of FLENS

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

Typedef for a dense vector with elements of type double.

    typedef DenseVector<Array<double> >  DDenseVector;

Vector x gets dynamically allocated and then initialized.

    DDenseVector x(5);
    x = 12345;

Print the vector content using output streams:

    cout << "x = " << x << endl;

We print some information about vector length and index ranges. You will see that by default in FLENS indices start at 1 (like in Fortran):

    cout << "Length of x: " << x.length() << endl;
    cout << endl;
    cout << "Indices: " << x.firstIndex() << ".." << x.lastIndex() << endl;
    cout << endl;

Also for element access (write) we provide a Fortran-Style interface:

    x(2) = 42;

The same for read access:

    cout << "changed element: x(2) = " << x(2) << endl;

You also can fill the whole vector with a new value:

    x = 42;

Compile and Run

$shell> cd flens/examples                                                       
$shell> g++ -Wall -std=c++11 -I../.. tut01-page02-example1.cc                   
$shell> ./a.out                                                                 
x = 
            1              2              3              4              5 
Length of x: 5
Indices: 1..5
changed element: x(2) = 42
x = 
            1             42              3              4              5 
x = 
           42             42             42             42             42 

Simple Example for using DenseVector Views

In this example we show:

Example Code

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

using namespace flens;
using namespace std;

int
main()
{
    typedef GeMatrix<FullStorage<double> >  DGeMatrix;
    typedef DenseVector<Array<double> >     DDenseVector;

    Underscore<DDenseVector::IndexType>     _;

    DDenseVector x(5);
    x = 12345;

    DGeMatrix A(45);
    A = 1112131415,
        2122232425,
        3132333435,
        4142434445;

    cout << "x = " << x << endl;
    cout << "A = " << A << endl;
    cout << endl;

    DDenseVector::View  y = x(_(1,2,5));

    cout << "y = x(1:2:5) = " << y << endl;
    cout << endl;


    DDenseVector::View row = A(2,_);

    cout << "row = A(2,:) = " << row << endl;
    cout << endl;

    DDenseVector::View rowPart = A(2,_(2,4));

    cout << "rowPart = A(2,2:4) = " << rowPart << endl;
    cout << endl;


    DDenseVector::View col = A(_,3);

    cout << "col = A(:,3) = " << col << endl;
    cout << endl;

    DDenseVector::View d0 = A.diag(0);

    cout << "d0 = A.diag(0) = " << d0 << endl;
    cout << endl;

    DDenseVector::View d_1 = A.diag(-1);

    cout << "d_1 = A.diag(-1) = " << d_1 << endl;
    cout << endl;

    DDenseVector::View d1 = A.diag(1);

    cout << "d1 = A.diag(1) = " << d1 << endl;
    cout << endl;


    return 0;
}

Comments on Example Code

Allocate and initialize some vector ...

    DDenseVector x(5);
    x = 12345;

... and matrix.

    DGeMatrix A(45);
    A = 1112131415,
        2122232425,
        3132333435,
        4142434445;

Print the vector and matrix

    cout << "x = " << x << endl;
    cout << "A = " << A << endl;
    cout << endl;

Create a vector view that references every second element of x.

    DDenseVector::View  y = x(_(1,2,5));

Create a vector view that references the second row of A

    DDenseVector::View row = A(2,_);

Create a vector view that references part of second row of A

    DDenseVector::View rowPart = A(2,_(2,4));

Create a vector view that references the third column of A

    DDenseVector::View col = A(_,3);

Create a vector view that references the diagonal of A

    DDenseVector::View d0 = A.diag(0);

Create a vector view that references the first sub-diagonal of A

    DDenseVector::View d_1 = A.diag(-1);

Create a vector view that references the first super-diagonal of A

    DDenseVector::View d1 = A.diag(1);

Compile and Run

$shell> cd flens/examples                                                       
$shell> g++ -Wall -std=c++11 -I../.. tut01-page02-example2.cc                   
$shell> ./a.out                                                                 
x = 
            1              2              3              4              5 
A = 
           11            12            13            14            15 
           21            22            23            24            25 
           31            32            33            34            35 
           41            42            43            44            45 
y = x(1:2:5) = 
            1              3              5 
row = A(2,:) = 
           21             22             23             24             25 
rowPart = A(2,2:4) = 
           22             23             24 
col = A(:,3) = 
           13             23             33             43 
d0 = A.diag(0) = 
           11             22             33             44 
d_1 = A.diag(-1) = 
           21             32             43 
d1 = A.diag(1) = 
           12             23             34             45