Manipulation
Devices and information
Move to CPU
- 
void Tensor::toCPU(int dev = DEV_CPU)
 Clone a tensor to the CPU.
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->toCPU(); // Tensor transferred to CPU
Move to GPU
- 
void Tensor::toGPU(int dev = DEV_GPU)
 Clone a tensor to the GPU.
Tensor* t1 = Tensor::zeros({2, 3}, DEV_CPU); // Tensor created in the CPU
t1->toGPU(); // Tensor transferred to GPU
Check tensor device
- 
int Tensor::isCPU()
 Check if the tensor is in CPU.
- Returns
 int
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->isCPU(); // returns 0
- 
int Tensor::isGPU()
 Check if the tensor is in GPU.
- Returns
 int
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->isGPU(); // returns 1
- 
int Tensor::isFPGA()
 Check if the tensor is in FPGA.
- Returns
 int
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->isFPGA(); // returns 0
- 
string Tensor::getDeviceName() const
 Returns the device name where the tensor is allocated (“CPU”, “GPU” or “FPGA”)
- Returns
 string
Tensor* t1 = Tensor::zeros({2, 3}, DEV_GPU); // Tensor created in the GPU
t1->getDeviceName(); // returns "GPU"
Get information from tensor
- 
void Tensor::info()
 Print shape, device and size information.
- Returns
 void
Tensor* t1 = Tensor::empty({2, 3});
t1->info();
// -------------------------------
// class:         Tensor
// ndim:          2
// shape:         (2, 3)
// strides:       (3, 1)
// itemsize:      6
// contiguous:    1
// order:         C
// data pointer:  0x7f827a6060d8
// is shared:     0
// type:          float (4 bytes)
// device:        CPU (code = 0)
// -------------------------------
Print tensor contents
- 
void Tensor::print(int precision = 6, bool raw = false)
 Print the tensor values.
Prints the content of the tensor.
- Parameters
 precision – Number of decimals places to use
raw – Print the tensor without format
- Returns
 void
Tensor* t1 = Tensor::randn({3, 3});
t1->print();
// [
// [0.135579 -0.208483 0.537894]
// [0.666481 0.242867 -1.957334]
// [-1.447633 1.231033 0.670430]
// ]
t1->print(0);  // No decimals
// [
// [0 -0 1]
// [1 0 -2]
// [-1 1 1]
// ]
t1->print(3);   // 3 decimals
// [
// [0.136 -0.208 0.538]
// [0.666 0.243 -1.957]
// [-1.448 1.231 0.670]
// ]
t1->print(3, true);   // 3 decimals, presented in row major
// [
// 0.136 -0.208 0.538 0.666 0.243 -1.957 -1.448 1.231 0.670
// ]
Dimension check
- 
static bool Tensor::isSquared(Tensor *A)
 Check if all dimensions in the tensor are the same.
- Parameters
 A – Tensor
- Returns
 bool
Tensor* t1 = Tensor::zeros({3, 3});
Tensor::isSquared(t1);
// true
Tensor* t2 = Tensor::zeros({3, 3, 3});
Tensor::isSquared(t2);
// true
Tensor* t3 = Tensor::zeros({3, 1, 3});
Tensor::isSquared(t3);
// false
Changing array shape
reshape
- 
Tensor *Tensor::reshape(const vector<int> &new_shape)
 Set a new shape to a tensor.
- Parameters
 new_shape – A vector containing the new shape.
- Returns
 A new tensor with the result
Tensor* t1 = Tensor::zeros({3, 4});
// [
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// ]
t1->reshape_({6, 2});
// [
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// [0.00 0.00]
// ]
// Other ways
Tensor* t2 = Tensor::reshape(t1, {6, 2}); // returns new tensor
t1->reshape(t2, {6,2}) // static
flatten
- 
Tensor *Tensor::flatten()
 In-place conversion tensor to a 1D tensor.
- Returns
 A new tensor with the result
 Tensor* t1 = Tensor::zeros({3, 4});
// [
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// [0.00 0.00 0.00 0.00]
// ]
t1->flatten_();  // In-place
// [0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00]
// Other ways
Tensor *t2 = Tensor::flatten(t1);  // returns new tensor
t1->flatten(t2) // static
Tiling arrays
repeat
- 
static Tensor *Tensor::repeat(Tensor *A, const vector<unsigned int> &repeats, unsigned int axis = 0, Tensor *output = nullptr, bool derivative = false)
 Repeats the elements of a tensor along the specified dimension.
- Parameters
 A – Input tensor.
repeats – The number of repetitions for the specified dimension (“int” or “vector of ints”)
axis – The axis along which to repeat values.
output – Output tensor
derivative – Apply derivative for: output = repeat(A)
- 
static Tensor *Tensor::repeat(Tensor *A, unsigned int repeats, unsigned int axis = 0, Tensor *output = nullptr, bool derivative = false)
 
Tensor* t1 = Tensor::range(1, 6); t1->reshape_({2, 3});
// [
// [1 2 3]
// [4 5 6]
// ]
// Repeat all rows 2 times. (repeat=2, axis=0)
Tensor *t2 = Tensor::repeat(t1, 2, 0);  // returns new tensor
// [
// [1 2 3]
// [1 2 3]
// [4 5 6]
// [4 5 6]
// ]
// Repeat col 1 => 3 times; col 2 => 2 times; col 3 => 1 time. (repeat=[3,2,1], axis=1)
Tensor *t2 = Tensor::repeat(t1, {3, 2, 1}, 1);  // returns new tensor
// [
// [1 1 1 2 2 3]
// [4 4 4 5 5 6]
// ]
tile
- 
static Tensor *Tensor::tile(Tensor *A, const vector<int> &repeats)
 Construct an array by repeating A the number of times given by reps.
- Parameters
 A – Input tensor.
repeats – The number of repetitions of A along each axis.
output – Output tensor
derivative – Apply derivative for: output = repeat(A)
// New tensor
Tensor* t1 = new Tensor({1, 2}, {2, 1});
// [
// [1]
// [2]
// ]
// Repeat all rows and columns 2 times each
Tensor* t1_res = Tensor::tile(t1, {2, 2});
// [
// [1 1]
// [2 2]
// [1 1]
// [2 2]
// ]
// New tensor
Tensor* t2 = new Tensor({1, 2, 3}, {3, 1});
// [
// [1]
// [2]
// [3]
// ]
// Repeat columns three times but not rows
Tensor* t2_res = Tensor::tile(t2, {1, 3});
// [
// [1 1 1]
// [2 2 2]
// [3 3 3]
// ]
broadcast
- 
static Tensor *Tensor::broadcast(Tensor *A, Tensor *B, Tensor *output = nullptr)
 Returns a new tensor A to be broadcasted into B.
- Parameters
 A – Input tensor.
B – Input tensor.
output – Output tensor (optional).
- Returns
 A new tensor C based on A, but prepared to be broadcasted in to B
// Example: Image - constant RGB
// Define mean
auto* mean = new Tensor( {0.485, 0.456, 0.406}, {3}, DEV_CPU);
// [0.485 0.456 0.406]
// Fake image
auto* image = Tensor::ones( {3, 224, 244});
// -------------------------------
// class:         Tensor
// ndim:          3
// shape:         (3, 224, 244)
// strides:       (54656, 244, 1)
// itemsize:      163968
// contiguous:    1
// order:         C
// data pointer:  0x56305561baa8
// is shared:     0
// type:          float (4 bytes)
// device:        CPU (code = 0)
// -------------------------------
// Compute broadcast for mean
Tensor* mean_broadcasted = Tensor::broadcast(mean, image);
// -------------------------------
// class:         Tensor
// ndim:          3
// shape:         (3, 224, 244)
// strides:       (54656, 244, 1)
// itemsize:      163968
// contiguous:    1
// order:         C
// data pointer:  0x56305561f2c8
// is shared:     0
// type:          float (4 bytes)
// device:        CPU (code = 0)
// -------------------------------
// Apply: X-mean
image->sub_(mean_broadcasted);
Transpose-like operations
permute
- 
Tensor *Tensor::permute(const vector<int> &dims)
 In-place permutation of tensor dimensions.
- Parameters
 dims – A vector containing the new order of the dimensions.
- Returns
 A new tensor with the result
Tensor* t1 = Tensor::range(1, 24); t1->reshape_({2, 3, 4});
// [
// [[1.00 2.00 3.00 4.00]     [5.00 6.00 7.00 8.00]     [9.00 10.00 11.00 12.00]]
// [[13.00 14.00 15.00 16.00] [17.00 18.00 19.00 20.00] [21.00 22.00 23.00 24.00]]
// ]
t1->permute_({2, 1, 0});  // In-place
// [
// [[1.00 13.00] [5.00 17.00] [9.00 21.00]]
// [[2.00 14.00] [6.00 18.00] [10.00 22.00]]
// [[3.00 15.00] [7.00 19.00] [11.00 23.00]]
// [[4.00 16.00] [8.00 20.00] [12.00 24.00]]
// ]
// Other ways
Tensor *t2 = Tensor::permute(t1, {2, 1, 0});  // returns new tensor
t1->permute(t2, {2, 1, 0});  // static
moveaxis
- 
Tensor *Tensor::moveaxis(int source, int destination)
 Move axes of an array to new positions.
- Parameters
 source – Original position of the axis to move. These must be unique.
destination – Destination position for the original axis. These must also be unique
- Returns
 A new tensor with the result
Tensor* t1 = Tensor::zeros({1, 2, 3, 4});
// ndim:          4
// shape:         (1, 2, 3, 4)
// strides:       (24, 12, 4, 1)
t1->moveaxis_(0, 2);  // In-place
// ndim:          4
// shape:         (2, 3, 1, 4)
// strides:       (12, 4, 4, 1)
// Other ways
Tensor *t2 = Tensor::moveaxis(t1, 0, 2);  // returns new tensor
t1->moveaxis(t2, 0, 2);  // static
swapaxis
- 
Tensor *Tensor::swapaxis(int axis1, int axis2)
 Interchange two axes of an array.
- Parameters
 axis1 – First axis.
axis2 – Destination position for the original axis. These must also be unique
- Returns
 A new tensor with the result
Tensor* t1 = Tensor::zeros({1, 2, 3, 4});
// ndim:          4
// shape:         (1, 2, 3, 4)
// strides:       (24, 12, 4, 1)
t1->swapaxis_(0, 2);  // In-place
// ndim:          4
// shape:         (3, 2, 1, 4)
// strides:       (8, 4, 4, 1)
// Other ways
Tensor *t2 = Tensor::swapaxis(t1, 0, 2);  // returns new tensor
t1->swapaxis(t2, 0, 2); // static
Changing number of dimensions
squeeze
- 
static Tensor *Tensor::squeeze(Tensor *A, int axis = -1)
 Remove all the dimensions of size 1 from the vector.
- Parameters
 A – Output tensor where the squeeze is stored.
axis – if given, the input will be squeezed only in this dimension. Else (-1), squeezes all dimensions of size 1
- Returns
 A new tensor with the result
Tensor* t1 = Tensor::zeros({1, 3, 4, 1});
// ndim:          4
// shape:         (1, 3, 4, 1)
// strides:       (12, 4, 1, 1)
Tensor* t2 = t1->squeeze();  // returns new tensor
// shape:         (3, 4)
Tensor* t3 = t1->squeeze(0);  // returns new tensor
// shape:         (3, 4, 1)
Tensor* t3 = t1->squeeze(3);  // returns new tensor
// shape:         (1, 3, 4)
// Other ways
t1->squeeze_(); // In-place
Tensor *t2 = Tensor::squeeze(t1);  // static
unsqueeze
- 
static Tensor *Tensor::unsqueeze(Tensor *A, int axis = 0)
 Returns a new tensor with a dimension of size one inserted at the specified position.
- Parameters
 A – Output tensor where the unsqueeze is stored.
axis – the index at which to insert the singleton dimension. Default: axis=0
- Returns
 A new tensor with the result
Tensor* t1 = Tensor::zeros({2, 3, 4});
// ndim:          3
// shape:         (2, 3, 4)
// strides:       (12, 4, 1)
Tensor* t2 = t1->unsqueeze(); // returns new tensor
 // shape:         (1, 2, 3, 4)
Tensor* t3 = t1->unsqueeze(2); // returns new tensor
 // shape:         (2, 3, 4, 1)
// Other ways
t1->unsqueeze_();  // In-place
Tensor *t2 = Tensor::unsqueeze(t1);  // Static
Joining arrays
concatenate
- 
static Tensor *Tensor::concat(vector<Tensor*> A, unsigned int axis = 0, Tensor *output = nullptr)
 Join a sequence of arrays along an existing axis.
- Parameters
 Vector – of Tensors The Tensors must have the same shape, except in the dimension corresponding to axis (the first, by default).
axis – The axis along which the arrays will be joined. If axis is None, arrays are flattened before use. Default is 0.
output – Output tensor
Example:
Tensor* t1 = Tensor::full({2, 2, 2}, 2);
Tensor* t2 = Tensor::full({2, 2, 2}, 5);
Tensor* t3 = Tensor::concat({t1, t2});
// ndim:          3
// shape:         (4, 2, 2)
// strides:       (4, 2, 1)
// [
// [[2.00 2.00] [2.00 2.00]]
// [[2.00 2.00] [2.00 2.00]]
// [[5.00 5.00] [5.00 5.00]]
// [[5.00 5.00] [5.00 5.00]]
// ]
Tensor *t4 = Tensor::concat({t1, t2}, 2);
// ndim:          3
// shape:         (2, 2, 4)
// strides:       (8, 4, 1)
//
// [
// [[2.00 2.00 5.00 5.00] [2.00 2.00 5.00 5.00]]
// [[2.00 2.00 5.00 5.00] [2.00 2.00 5.00 5.00]]
// ]
stack
- 
static Tensor *Tensor::stack(vector<Tensor*> A, unsigned int axis = 0, Tensor *output = nullptr)
 Join a sequence of arrays along a new axis.
- Parameters
 A – Input tensor.
axis – The axis in the result array along which the input arrays are stacked.
output – Output tensor
Example:
Tensor* t1 = Tensor::full({2, 2}, 2);
Tensor* t2 = Tensor::full({2, 2}, 5);
Tensor* t3 = Tensor::stack({t1, t2});  // axis = 0
// [
// [[2.00 2.00] [2.00 2.00]]
// [[5.00 5.00] [5.00 5.00]]
// ]
Tensor *t4 = Tensor::stack({t1, t2}, 1);  // axis = 1
// [
// [[2.00 2.00] [5.00 5.00]]
// [[2.00 2.00] [5.00 5.00]]
// ]
Value operations
Fill constant
- 
static void Tensor::fill(Tensor *A, float v)
 Fill tensor with a value.
- Parameters
 A – The output tensor.
v – the value to fill the tensor with
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_(3.0f);  // In-place
// [
// [3.00 3.00 3.00]
// [3.00 3.00 3.00]
// ]
// Other ways
Tensor* t2 = t1->fill(3.0f); // returns new tensor
Tensor::fill(t1, 3.0f);  // static
Fill Random Uniform
- 
void Tensor::fill_rand_uniform_(float v)
 Fills a tensor in-place, with values randomly sampled from a uniform distribution.
- Parameters
 v – Scale factor of the values generated by the uniform distribution.
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_uniform_(1.0f);  // In-place
// [
// [0.10 0.53 0.88]
// [0.57 0.57 0.89]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_uniform(1.0f); // returns new tensor
Tensor::fill_rand_uniform(t1, 1.0f);  // static
Fill Random Signed Uniform
- 
void Tensor::fill_rand_signed_uniform_(float v)
 Fills a tensor in-place, with values randomly sampled from a signed uniform distribution.
- Parameters
 v – Scale factor of the values generated by the signed uniform distribution.
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_signed_uniform_(1.0f);  // In-place
// [
// [0.22 -0.34 -0.78]
// [-0.03 0.10 0.90]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_signed_uniform(1.0f); // returns new tensor
Tensor::fill_rand_signed_uniform(t1, 1.0f);  // static
Fill Random Normal
- 
void Tensor::fill_rand_normal_(float m, float s, bool fast_math = true)
 Fills a tensor in-place, with values randomly sampled from a normal distribution.
- Parameters
 m – Mean of the normal distribution.
s – Standard deviation of the normal distribution.
fast_math – Whether to use or not the fast math mode.
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_normal_(0.0f, 1.0f);  // In-place
// [
// [-0.57 0.49 -1.09]
// [0.75 0.37 -0.32]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_normal(0.0f, 1.0f); // returns new tensor
Tensor::fill_rand_normal(t1, 0.0f, 1.0f);  // static
Fill Random Binary
- 
void Tensor::fill_rand_binary_(float v)
 Fills a tensor in-place, with values randomly sampled from a binary distribution.
- Parameters
 v – Binarization threshold. 1 if rnd() >= t, 0 otherwise
Tensor* t1 = Tensor::empty({2, 3});
t1->fill_rand_binary_(0.5f);  // In-place
// [
// [0.00 1.00 0.00]
// [1.00 1.00 0.00]
// ]
// Other ways
Tensor* t2 = t1->fill_rand_binary(0.5f); // returns new tensor
Tensor::fill_rand_binary(t1, 0.5f);  // static