Table of Contents
VSIPL++ defines a number of mathematical types for linear algebra: vectors, matrices, and (3D) tensors. They provide a high-level interface suitable for solving linear algebra equations. All these types give an intuitive access to their elements. They are collectively referred to as views as the actual data they provide access to is sharable among views.
// create an uninitialized vector of 10 elements Vector<float> vector1(10); // create a zero-initialized vector of 10 elements Vector<float> vector2(10, 0.f); // assign vector2 to vector1 vector1 = vector2; // set the first element to 1.f vector1(0) = 1.f; // access the last element float value = vector1(9);
Every view has an associated Block, which is responsible for storing or computing the data in the view. More than one view may be associated with the same block.
Depending on how a view is constructed it may allocate the block, or refer to a block from another view. All views created via copy-construction will share the blocks with the views they were constructed with.
// copy-construct a new vector from an existing one Vector<float> vector3(vector1); // modify the original vector vector1.put(1, 1.f); // the new vector reflects the new value assert(vector3(1) == 1.f);
A domain represents a logical set of indices. Constructing a one-dimensional domain requires a start index, a stride, and a length. For convenience an additional constructor is provided that only takes a length argument, setting the starting index to 0 and the stride to 1.
// [0...9] vsip::Domain<1> all(10); // [0, 2, 4, 6, 8] vsip::Domain<1> pair(0, 2, 5); // [1, 3, 5, 7, 9] vsip::Domain<1> impair(1, 2, 5);
Two- and three-dimensional domains are composed out of one-dimensional ones.
// [(0,0), (0,2), (0,4),...,(1,0),...] vsip::Domain<2> dom(Domain<1>(10), Domain<1>(0, 2, 5));
Views provide convenient access to subviews in terms of subdomains. For example, to assign new values to every second element of a vector, simply write:
// assign 1.f to all elements in [0, 2, 4, 6, 8] vector1(pair) = 1.f;
All complex views provide real and imaginary subviews:
// a function manipulating a float vector in-place void filter(Vector<float>); // create a complex vector Vector<complex> vector(10); // filter the real part of the vector filter(vector.real());
VSIPL++ provides elementwise functions and operations that are defined in terms of their scalar counterpart.
Vector<float> vector1(10, 1.f); Vector<complex<float> > vector2(10, complex<float>(2.f, 1.f)); // apply operator+ elementwise Vector<complex<float> > sum = vector1 + vector2; // apply conj(complex<float>) elementwise Vector<complex<float> > result = conj(sum);
For binary and ternary functions VSIPL++ provides overloaded versions with mixed view / scalar parameter types:
// delegates to operator*=(complex<float>, complex<float>) result *= complex<float>(2.f, 0.f); // error: no operator*=(complex<float>, complex<double>) result *= complex<double>(5., 0.);
Matrices provide a number of additional subviews. All of them
Matrix<float> matrix(10, 10); //... // return the first column vector Matrix<float>::col_type column = matrix.col(0); // return the first row vector Matrix<float>::row_type row = matrix.row(0); // return the diagonal vector Matrix<float>::diag_type diag = matrix.diag(); // return the transpose of the matrix Matrix<float>::transpose_type trans = matrix.trans();
Tensors are three-dimensional views. In addition to the types, methods, and operations defined for all view types, they provide additional methods to access specific subviews:
// a 5x6x3 cube initialized to 0.f Tensor<float> tensor(5, 6, 3, 0.f); // a subvector Vector<float> vector1 = tensor(0, 0, whole_domain);
The symbolic constant whole_domain is used to indicate
that the whole domain the target view holds in a particular dimension should
be used. In the example above that not only provides a more compact syntax
compared to explicitly writing Domain<1>(6) but it also enables
better optimization opportunities.
// a submatrix Matrix<float> plane = tensor(whole_domain, 0, whole_domain); Tensor<float> upper_half = tensor(whole_domain, Domain<1>(3), whole_domain);