Skip to content

Dynamic Subtensor Docs

Kannav Mehta edited this page Aug 24, 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 arithmetic and comparison 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;

Assignment operators

t3 += A;

Unary operators

t3 = -A;

Inner Product and Outer product

tensor t4 = ublas::inner_product(A, t2);
tensor t5 = ublas::outer_product(A, t2);

Tensor times matrix multiplication

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

Tensor times vector multiplication

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

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;