Blaze 3.9
Grouping/Tagging


Tagging and Groups


Sometimes it may be desirable to separate two or more distinct groups of vectors and matrices, for instance in order to allow operations only within a group and to prevent operations across groups. This goal can be achieved by means of tags. All vector and matrix classes provide a template parameter to specify a tag (for instance, the fourth template parameter for blaze::DynamicVector and the sixth template parameter for blaze::StaticVector):

template< typename Type, bool TF, typename Alloc, typename Tag >
class DynamicVector;
template< typename Type, size_t N, bool TF, AlignmentFlag AF, PaddingFlag PF, typename Tag >
class StaticVector;

By default, all vectors and matrices are associated with blaze::Group0 (i.e. the tag is set to blaze::Group0). However, it is possible to explicitly associate vectors and matrices with different groups:

DynamicVector<int,columnVector,AlignedAllocator<int>,Group0> a0, b0;
DynamicVector<int,columnVector,AlignedAllocator<int>,Group1> a1, b1;
a0 + b0; // Compiles, a0 and b0 are in the same group (Group0)
a1 + b1; // Compiles, a1 and b1 are in the same group (Group1)
a0 + b1; // Compilation error: a0 and b1 are not in the same group
Allocator for type-specific aligned memory.
Definition: AlignedAllocator.h:72
Efficient implementation of an arbitrary sized vector.
Definition: DynamicVector.h:223
GroupTag< 1UL > Group1
Tag for group 1.
Definition: GroupTag.h:99
GroupTag< 0UL > Group0
Tag for group 0. This is the default tag for vectors and matrices.
Definition: GroupTag.h:91
constexpr bool columnVector
Transpose flag for column vectors.
Definition: TransposeFlag.h:58

All vectors or matrices that are associated with the same group can be freely combined with any other vector or matrix from the same group. The attempt to combine vectors and matrices from different groups results in a compilation error.


Creating New Groups


Blaze provides the tags for the ten predefined groups blaze::Group0 through blaze::Group9. In order to create further groups, all that needs to be done is to create new instances of the blaze::GroupTag class template:

using Group10 = blaze::GroupTag<10>;
using Group11 = blaze::GroupTag<11>;
// ... further groups
Group tag for vectors and matrices.
Definition: GroupTag.h:83

All groups based on the blaze::GroupTag class template will be treated as separate groups just as the ten predefined groups.


Custom Tags


Sometimes it is not enough to separate vectors and matrices into different groups, but it is required to define the interaction between different groups. This situation for instance occurs if a vector or matrix is associated with a physical quantity. This problem can be solved by using custom tags. The following example gives an impression on how to define the physics on meters (represented by the Meter tag) and seconds (represented by the Second tag):

struct Meter {}; // Definition of the 'Meter' tag
struct Second {}; // Definition of the 'Second' tag
struct SquareMeter {}; // Definition of the 'SquareMeter' tag
struct MeterPerSecond {}; // Definition of the 'MeterPerSecond' tag

The Meter and Second tags are not associated with the blaze::GroupTag class template. For that reason, by default, it is not possible to perform any operation on an accordingly tagged vector or matrix. All required operations need to be declared explicitly in order to specify the resulting tag of an operation. In the following code example, this happens by declaring both the addition for the Meter tag and the Second tag, the multiplication between two Meter tags and the division between Meter and Second. Note that it is enough to declare the operations, it is not necessary to define them!

Meter operator+( Meter , Meter ); // Enabling addition between 'Meter'
Second operator+( Second, Second ); // Enabling addition between 'Second'
SquareMeter operator*( Meter , Meter ); // Enabling multiplication between 'Meter'
MeterPerSecond operator/( Meter , Second ); // Enabling division between 'Meter' and 'Second'
constexpr const DenseIterator< Type, AF > operator+(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Addition between a DenseIterator and an integral value.
Definition: DenseIterator.h:719
decltype(auto) operator/(ST scalar, const DenseMatrix< MT, SO > &mat)
Division operator for the division of a scalar value and a dense matrix ( ).
Definition: DMatMapExpr.h:2840
decltype(auto) operator*(const DenseMatrix< MT1, false > &lhs, const DenseMatrix< MT2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:9640

With these declarations it is now possible to add meters and seconds, but not to subtract them (no subtraction operator was declared). Also, it is possible to multiply meters and to divide meters and seconds:

const DynamicVector<int,rowVector,AlignedAllocator<int>,Meter> m1{ 1, 2, 3 };
const DynamicVector<int,rowVector,AlignedAllocator<int>,Meter> m2{ 4, 5, 6 };
const DynamicVector<int,rowVector,AlignedAllocator<int>,Second> s1{ 1, 2, 3 };
const DynamicVector<int,rowVector,AlignedAllocator<int>,Second> s2{ 4, 5, 6 };
m1 + m2; // Compiles and results in vector tagged with 'Meter'
s1 + s2; // Compiles and results in vector tagged with 'Second'
m1 - m2; // Compilation error: No subtraction defined for 'Meter'!
m1 + s2; // Compilation error: No addition between 'Meter' and 'Second' defined!
m1 * m2; // Compiles and results in vector tagged with 'SquareMeter'
m1 / s1; // Compiles and results in vector tagged with 'MeterPerSecond'

At this point it is possible to use the pow2() function for vectors and matrices tagged with Meter since pow2() is based on multiplication, which has already been declared. However, it is not possible to use the abs() function:

pow2( m1 ); // Compiles and results in vector tagged with 'SquareMeter'
abs ( m1 ); // Compilation error: No 'abs()' declared for the 'Meter' tag
decltype(auto) abs(const DenseMatrix< MT, SO > &dm)
Applies the abs() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1296
decltype(auto) pow2(const Matrix< MT, SO > &m)
Computes the square for each single element of the matrix m.
Definition: Matrix.h:686

In order to enable the abs() function it also needs to be explicitly declared for the Meter tag:

Meter abs( Meter ); // Enabling the 'abs()' function on 'Meter'
abs ( m1 ); // Compiles and results in vector tagged with 'Meter'


Previous: Customization of Vectors and Matrices     Next: Customization of the Error Reporting Mechanism