Wiki
Clone wikiblaze / 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:
using blaze::DynamicVector;
using blaze::AlignedAllocator;
using blaze::Group0;
using blaze::Group1;
using blaze::columnVector;
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
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
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'
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
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: Vector and Matrix Customization ---- Next: Error Reporting Customization
Updated