Skip to content

Dynamic Subtensor Docs

Kannav Mehta edited this page Aug 20, 2021 · 2 revisions

Subtensor for Dynamic Tensor

Subtensors are used to adapt the shape of an dynamic_tensor without changing it, nor copying it. Subtensors are convinient tools for assigning parts of an expression: since they do not copy the underlying tensor, assigning to the subtensor actually assigns to the underlying expression.

For dynamic_tensor the following example shows the ways in which spans can be specified.

The subtensor is an alias for the type :

template<typename T>
tensor_core<subtensor_engine<T>>

where T is the parent tensor.

Thus a subtensor for a dynamic tensor has the following type:

template<class V/*Value type*/, class L/*Layout*/>
tensor_core<subtensor_engine<tensor_dynamic<V,L>>>
#include <boost/numeric/ublas/tensor.hpp>

namespace ublas = boost::numeric::ublas;
using value   = float;
using layout  = ublas::layout::first_order; // storage format
using tensor  = boost::numeric::ublas::tensor_dynamic<value,layout>;
constexpr auto ones = ublas::ones<value,layout>{};
using span = ublas::span<>;

tensor a = ones(3,2,4);

auto s1 = a(span(1,2), span(), span(1,2));
// => s1.extents() = {2, 2, 2}
// => s1(0, 0, 0) = a(1, 0, 1)
// => s1(1, 1, 1) = a(2 ,1, 2)

auto s2 = a(span(1,1), span(), span(0,2,3));
// => s2.extents() = {1, 2, 2}
// => s2(0, 0, 0) = a(1, 0, 0)
// => s2(0, 1, 1) = a(1, 1, 2)

We can also create subtensors of subtensors:

tensor a = ones(3,2,4);

auto s1 = a(span(1,2), span(), span(1,2));
// => s1.extents() = {2, 2, 2}
// => s1(0, 0, 0) = a(1, 0, 1)
// => s1(1, 1, 1) = a(2 ,1, 2)

auto s2 = s1(span(1,1), span(), span());
// => s2.extents() = {1, 2, 2}
// => s2(0, 0, 0) = a(1, 0, 0)
// => s2(0, 1, 1) = a(1, 1, 2)

In this case subtensor s2 still points towards the data from the parent tensor i,e a.

One can also create subtensors using the subtensor helper function:

tensor a = ones(3,2,4);

auto s1 = subtensor(a, span(1,2), span(), span(1,2));
// => s1.extents() = {2, 2, 2}
// => s1(0, 0, 0) = a(1, 0, 1)
// => s1(1, 1, 1) = a(2 ,1, 2)

auto v2 = subtensor(s1, span(1,1), span(), span());
// => s2.extents() = {1, 2, 2}
// => s2(0, 0, 0) = a(1, 0, 0)
// => s2(0, 1, 1) = a(1, 1, 2)

The subtensors can be used interchangeably with tensors in expressions

tensor t1 = ones(4,5,5);

auto A = t1(span(2), span(4), span()); // shape (3,4,5)
auto B = A(span(), span(), span()); // shape (3,4,5)
tensor t2 = ones(1,2,2);

// Binary operators
tensor t3 = t2 * B + A;

// Assingment operators
t3 += A;

// Unary Operatos
t3 = -A;

// Tensor times Tensor multiplication
tensor c1 = ones(5, 5);
tensor c2 = c1 + A(_i,_j,_m)*A(_i,_j,_l) + 5;

// Ostream operators
std::cout << A << std::endl;