-
Notifications
You must be signed in to change notification settings - Fork 1
Documentation
Following the documentation style of Boost.uBLAS, the HTML documentation is in the doc and doc/tensor directories. Additionally, most functions and data structures are doxygen documented. This page shall provide an overview and demonstrate how uBLAS was extended with tensors. Note that complete examples are found in examples/tensor directory.
In order to use all features of this work, only tensor.hpp needs to be included.
#include <boost/numeric/ublas/tensor.hpp>
For the following examples we also assume that the using-directive is set.
using namespace boost::numeric::ublas;
The templated class tensor is the base container for dense tensors and also a proxy of a one-dimensional sequence container with random-access. Every element A(i1 i1,i2,…,ip)
of a p
-order (n1xn2x...xnp)
-dimensional tensor A
is mapped to j
-th element of a one-dimensional sequence container. The tensor supports the first-order and last-order orientation where the elements along first- or last-dimension, respectively. In case of the two dimensions, first-order and last-order correspond with the column-major and row-major formats. A detailed description of the template parameters, member types and member functions are given in tensor.html.
template<class T, class F=first_order, class A=std::vector<T,std::allocator<T>>>
class tensor;
There are several constructors available in order to generate an instance of the tensor template class. The most simple ones are exemplified below.
// Constructs a 3-order tensor with shape extents (3,4,2).
// Elements are stored in the first-order layout
auto A = tensor<float>{3,4,2};
// Constructs a 4-order tensor with shape extents (5,4,3,2).
// Elements are stored in the last-order layout
auto B = tensor<std::complex<double>,last_order>(shape{5,4,3,2});
The shape object is an auxiliary class with which dimension extents are stored. Further documentation is given in extents.html. The user can copy or move construct a tensor object from tensor, matrix and vector expressions. The resulting tensor extents are automatically extracted from the expression.
// Constructs a 2-order tensor from a matrix expression.
tensor<float> A = matrix<float>(3,4) + 4;
// Constructs a 2-order tensor from a tensor expression.
tensor<float> A = matrix<float>(3,4) + tensor<float>{3,4};
Users of the tensor object can access elements can be done either with a single-index accessing the underlying one-dimensional container or with a multi-index that is translated into a single-index.
The user can read from and write to the tensor with a single-index using the operator[]
or at()
member functions.
for(auto i = 0u; i < A.size(); ++i)
A[i] = i; // or A.at(i) = i;
The user can read from and write to the tensor with a mutli-index using the at()
member function only.
for(auto i = 0u; i < A.size(2); ++i)
for(auto j = 0u; j < A.size(1); ++j)
for(auto k = 0u; k < A.size(0); ++k)
C.at(k,j,i) = A.at(i,j,k); // transposing A
The user can also call the low-level data()
member functions that returns a pointer to the first element of the one-dimensional storage array.
The interoperablility with the C++ standard library is
Entrywise arithmetic tensor operations perform a binary or unary operations on tensor, matrix and vector elements with the same multi-index. The operators are overloaded and implemented in operators_arithmetic.hpp. Consequently all objects must have the same shape. Note that none of the operators evaluate the expression but rather construct an expression template with respect to the operation. Expression templates are evaluated when the assignment operator of the tensor is encountered.
Operations | Operators | Example |
---|---|---|
Binary Operations with Tensors |
+ ,- ,/ ,*
|
Z = X*Y; |
Binary Operations with Matrices |
+ ,- ,/ ,*
|
Z = X*A; |
Binary Operations with Vectors |
+ ,- ,/ ,*
|
Z = X*v; |
Binary Operations with Scalars |
+ ,- ,/ ,*
|
Z = 4*X; |
Unary Operations |
+ ,-
|
Z = -X; |
Tensor assignments perform a binary or unary operations on tensor, matrix and vector elements with the same multi-index. The operators are overloaded and implemented in operators_arithmetic.hpp. Note that the implementation evaluates the expression.
Operations | Operators | Example |
---|---|---|
Operations with Tensors |
+= ,-= ,/= ,*=
|
Z += X; , Z *= Y;
|
Operations with Scalars |
+= ,-= ,/= ,*=
|
Z += 4; |
Comparison operations compare tensor elements with the same multi-index. The operators are overloaded and implemented in operators_comparison.hpp. Consequently all objects must have the same shape. Note that all comparisons are evaluated when the compare operator is encountered and expression objects are not generated.
Operations | Operators | Example |
---|---|---|
Tensors |
== ,!= ,< ,> ,<= ,>=
|
X==Y && Y!=Z; |
Tensors with Scalars |
== ,!= ,< ,> ,<= ,>=
|
X==Y && 3*Z<=4; |
The following free tensor functions are implemented in functions.hpp. Internally they call generic functions, defined in multiplication.hpp and algorithms.hpp, that are implemented in terms of pointers, strides and offsets. Note that the functions are evaluated immediately and no expression object is generated. Note that you can combine entrywise and compare operations as well as computed assignments with these free functions.
Operations | Operators | Example |
---|---|---|
Tensor Transposition | trans() |
auto Z = trans(X,{4,3,2}) |
k-mode Tensor-Times-Vector | prod() |
auto Z = prod(X,v,2); |
k-mode Tensor-Times-Matrix | prod() |
auto Z = prod(X,A,2); |
Tensor-Times-Tensor | prod() |
auto Z = prod(X,Y,{1,3}); , auto Z = prod(X,Y,{1,3},{4,2});
|
Inner Product | inner_prod() |
auto a = inner_prod(X,Y); |
Outer Product | outer_prod() |
auto Z = outer_prod(X,Y); |
There are three types of expression templates that are defined in expression.hpp. A more detailed documentation of tensor expressions is given in tensor_expression.html.
- The templated class
tensor_expression
is required to be a public base of thetensor
,binary_tensor_expression
andunary_tensor_expression
classes. It inherits fromublas_expression
. - The templated class
binary_tensor_expression
contains a constant reference to a left and right expression that can be evaluated by using the access operator. It inherits fromtensor_expression
. - The templated class
unary_tensor_expression
contains a constant reference to an expression that can be evaluated by using the access operator. It inherits fromtensor_expression
.
Instances of tensor expressions are generated when binary or unary entrywise operations are encountered.
Operator Type | Operand | Tensor Expression Type | Example |
---|---|---|---|
Binary Arithmetic Operators | Tensor Expression | Binary Tensor Expression |
X*Y , X*Y+X
|
Binary Arithmetic Operators | Tensor & Matrix Expression | Binary Tensor Expression | B*Y-A |
Binary Arithmetic Operators | Tensor & Vector Expression | Binary Tensor Expression | Z*u-A/X |
Binary Arithmetic Operators | Tensor Expression & Scalar | Unary Tensor Expression | Y-3 |
Unary Arithmetic Operators | Tensor Expression | Unary Tensor Expression |
-Z , -(X*v)
|
Expressions are evaluated at latest when the assignment operator is encountered. The evaluation time depends on their types. Entrywise arithmetic tensor operations generate expression objects and are evaluated when the assignment operator is encountered. The evaluation functions are located in expression_evaluation.hpp
Other tensor operations such as computed assignments, comparison operations and special functions expression objects are immediately evaluated without generating expression objects.
As an addition tensor shapes are retrieved and investigated before evaluation. This is done by using the if constexpr
expression of the C++17 standard where an instance of an expression template is analyzed. The analysis traverses the expression tree and tests if all tensor shape extents of unary or binary tensor operations are the same. The implementation is found in expression_evaluation.hpp.