lucid  0.0.1
Lifting-based Uncertain Control Invariant Dynamics
Loading...
Searching...
No Matches
lucid::Tensor< T > Class Template Reference

Lightweight tensor class. More...

#include <Tensor.h>

Public Member Functions

 Tensor (std::vector< std::size_t > dims)
 Construct a new Tensor object.
 
 Tensor (const T &value, std::vector< std::size_t > dims)
 Construct a new Tensor object.
 
 Tensor (std::vector< T > data, std::vector< std::size_t > dims={})
 Construct a new Tensor object.
 
Tensorreshape (std::vector< std::size_t > dims)
 Reshape the tensor to the new dimensions.
 
template<IsAnyOf< int, float, double, std::complex< double > > TT = T>
Tensor< TT > permute (const std::vector< std::size_t > &permutation) const
 Permute the axes of the tensor.
 
template<IsAnyOf< int, float, double, std::complex< double > > TT = T, std::convertible_to< const std::size_t > I, class... Is>
Tensor< TT > permute (I i, Is... is) const
 Permute the axes of the tensor.
 
template<std::convertible_to< const std::size_t > I, class... Is>
const T & operator() (I i, Is... is) const
 Get the element in the tensor using the indices in each dimension.
 
template<std::convertible_to< const std::size_t > I, class... Is>
T & operator() (I i, Is... is)
 Get the element in the tensor using the indices in each dimension.
 
template<template< class... > class Container, class I>
const T & operator() (const Container< I > &indices) const
 Get the element in the tensor using the indices in each dimension.
 
template<template< class... > class Container, std::convertible_to< const std::size_t > I>
T & operator() (const Container< I > &indices)
 Get the element in the tensor using the indices in each dimension.
 
template<std::convertible_to< const std::size_t > I>
const T & operator[] (I i) const
 Get the element in the underlying data vector using its index.
 
std::size_t size () const
 Get read-only access to the size of the tensor.
 
std::size_t rank () const
 Get read-only access to the rank of the tensor.
 
const std::vector< std::size_t > & axes () const
 Get read-only access to the axes of the tensor.
 
const std::vector< std::size_t > & dimensions () const
 Get read-only access to the dimensions of the tensor.
 
const std::vector< T > & data () const
 Get read-only access to the data of the tensor.
 
const TensorView< T > & view () const
 Get read-only access to the view of the tensor.
 
TensorView< T > & m_view ()
 Get read-write access to the view of the tensor.
 
std::vector< T > & m_data ()
 Get read-write access to the data of the tensor.
 
TensorIterator< T > begin () const
 Get read-only access to the iterator pointing at the beginning of the tensor.
 
TensorIterator< T > end () const
 Get read-only access to the iterator pointing at the end of the tensor.
 
Tensor< T > pad (const std::vector< std::pair< Index, Index > > &padding, const T &value={}) const
 Pad the tensor with a value.
 
Tensor< T > pad (const std::vector< Index > &padding, const std::vector< Index > &start_padding={}, const T &value={}) const
 Pad the tensor with a value.
 
Tensor< std::complex< double > > fft (double coeff=std::numeric_limits< double >::quiet_NaN()) const
 Apply the Fast Fourier Transform to the tensor.
 
Tensor< double > ifft (double coeff=std::numeric_limits< double >::quiet_NaN()) const
 Apply the Inverse Fast Fourier Transform to the tensor.
 
Tensor< double > fft_upsample (const std::vector< std::size_t > &new_dims) const
 Use the Fast Fourier Transform to upsample the tensor.
 

Private Attributes

std::vector< T > data_
 Data of the tensor.
 
TensorView< T > view_
 View of the tensor.
 

Detailed Description

template<IsAnyOf< int, float, double, std::complex< double > > T>
class lucid::Tensor< T >

Lightweight tensor class.

It uses a strided vector to support any number of dimensions.

Note
Most methods in this class are implemented by the TensorView class. Its direct use is discouraged unless you can ensure proper memory management.
Template Parameters
Ttype of the elements in the tensor

Constructor & Destructor Documentation

◆ Tensor() [1/3]

template<IsAnyOf< int, float, double, std::complex< double > > T>
lucid::Tensor< T >::Tensor ( std::vector< std::size_t > dims)
explicit

Construct a new Tensor object.

The rank of the tensor is determined by the size of the dimensions vector.

Parameters
dimsshape of the tensor. Each element is the size of the corresponding dimension

◆ Tensor() [2/3]

template<IsAnyOf< int, float, double, std::complex< double > > T>
lucid::Tensor< T >::Tensor ( const T & value,
std::vector< std::size_t > dims )

Construct a new Tensor object.

The rank of the tensor is determined by the size of the dimensions vector.

Parameters
valuevalue of all the elements in the tensor
dimsshape of the tensor. Each element is the size of the corresponding dimension

◆ Tensor() [3/3]

template<IsAnyOf< int, float, double, std::complex< double > > T>
lucid::Tensor< T >::Tensor ( std::vector< T > data,
std::vector< std::size_t > dims = {} )
explicit

Construct a new Tensor object.

The rank of the tensor is determined by the size of the dimensions vector.

Parameters
datadata of the tensor. It will be copied
dimsshape of the tensor. Each element is the size of the corresponding dimension

Member Function Documentation

◆ axes()

template<IsAnyOf< int, float, double, std::complex< double > > T>
const std::vector< std::size_t > & lucid::Tensor< T >::axes ( ) const
inlinenodiscard

Get read-only access to the axes of the tensor.

Returns
axes of the tensor

◆ begin()

template<IsAnyOf< int, float, double, std::complex< double > > T>
TensorIterator< T > lucid::Tensor< T >::begin ( ) const
nodiscard

Get read-only access to the iterator pointing at the beginning of the tensor.

Returns
iterator pointing at the beginning of the tensor

◆ data()

template<IsAnyOf< int, float, double, std::complex< double > > T>
const std::vector< T > & lucid::Tensor< T >::data ( ) const
inlinenodiscard

Get read-only access to the data of the tensor.

Returns
data of the tensor

◆ dimensions()

template<IsAnyOf< int, float, double, std::complex< double > > T>
const std::vector< std::size_t > & lucid::Tensor< T >::dimensions ( ) const
inlinenodiscard

Get read-only access to the dimensions of the tensor.

Returns
dimensions of the tensor

◆ end()

template<IsAnyOf< int, float, double, std::complex< double > > T>
TensorIterator< T > lucid::Tensor< T >::end ( ) const
nodiscard

Get read-only access to the iterator pointing at the end of the tensor.

Returns
iterator pointing at the end of the tensor

◆ fft()

template<IsAnyOf< int, float, double, std::complex< double > > T>
Tensor< std::complex< double > > lucid::Tensor< T >::fft ( double coeff = std::numeric_limits<double>::quiet_NaN()) const
nodiscard

Apply the Fast Fourier Transform to the tensor.

It is just the application of the FFT to each dimension of the tensor.

Tensor<double> t{std::vector<double>{1, 2, 3, 4}, std::vector<std::size_t>{2, 2}};
// 1 2
// 3 4
t.fft();
// (10 + 0i) (-2 + 0i)
// (-4 + 0i) (0 + 0i)
Parameters
coeffcoefficient applied to the FFT. If NaN, the default coefficient, 1.0, is used
Returns
tensor with the FFT applied to each dimension
See also
ifft

◆ fft_upsample()

template<IsAnyOf< int, float, double, std::complex< double > > T>
Tensor< double > lucid::Tensor< T >::fft_upsample ( const std::vector< std::size_t > & new_dims) const
nodiscard

Use the Fast Fourier Transform to upsample the tensor.

This procedure will interpolate the signal in the frequency domain and then apply the inverse FFT.

Precondition
The new_dims must have the same shape as the original tensor plus a non-negative padding
Warning
If the functions making up the signal are not periodic or their frequency is too high (> Nyquist frequency), the result will not be inaccurate.
Parameters
new_dimsnew dimensions of the tensor
Returns
tensor with the upsampled signal
See also
fft
ifft

◆ ifft()

template<IsAnyOf< int, float, double, std::complex< double > > T>
Tensor< double > lucid::Tensor< T >::ifft ( double coeff = std::numeric_limits<double>::quiet_NaN()) const
nodiscard

Apply the Inverse Fast Fourier Transform to the tensor.

It is just the application of the IFFT to each dimension of the tensor.

Tensor<double> t{std::vector<double>{1, 2, 3, 4}, std::vector<std::size_t>{2, 2}};
// 1 2
// 3 4
Tensor<std::complex<double>> fft{t.fft()};
// (10 + 0i) (-2 + 0i)
// (-4 + 0i) (0 + 0i)
fft.ifft();
// 1 2
// 3 4
Tensor< std::complex< double > > fft(double coeff=std::numeric_limits< double >::quiet_NaN()) const
Apply the Fast Fourier Transform to the tensor.
Definition Tensor.cpp:37
Parameters
coeffcoefficient applied to the FFT. If NaN, the default coefficient, 1.0 / size(), is used
Returns
tensor with the IFFT applied to each dimension
See also
fft

◆ m_data()

template<IsAnyOf< int, float, double, std::complex< double > > T>
std::vector< T > & lucid::Tensor< T >::m_data ( )
inlinenodiscard

Get read-write access to the data of the tensor.

Returns
data of the tensor

◆ m_view()

template<IsAnyOf< int, float, double, std::complex< double > > T>
TensorView< T > & lucid::Tensor< T >::m_view ( )
inline

Get read-write access to the view of the tensor.

Returns
view of the tensor

◆ operator()() [1/4]

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<template< class... > class Container, std::convertible_to< const std::size_t > I>
T & lucid::Tensor< T >::operator() ( const Container< I > & indices)
inline

Get the element in the tensor using the indices in each dimension.

Template Parameters
Containercontainer of the indices
Iindex type
Parameters
indicesindices in each dimension
Returns
element in the tensor

◆ operator()() [2/4]

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<template< class... > class Container, class I>
const T & lucid::Tensor< T >::operator() ( const Container< I > & indices) const
inline

Get the element in the tensor using the indices in each dimension.

Template Parameters
Containercontainer of the indices
Iindex type
Parameters
indicesindices in each dimension
Returns
element in the tensor

◆ operator()() [3/4]

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<std::convertible_to< const std::size_t > I, class... Is>
T & lucid::Tensor< T >::operator() ( I i,
Is... is )
inline

Get the element in the tensor using the indices in each dimension.

Template Parameters
Iindex type
Isvariadic index types
Parameters
iindex in the first dimension
isindices in the remaining dimensions
Returns
element in the tensor

◆ operator()() [4/4]

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<std::convertible_to< const std::size_t > I, class... Is>
const T & lucid::Tensor< T >::operator() ( I i,
Is... is ) const
inline

Get the element in the tensor using the indices in each dimension.

Template Parameters
Iindex type
Isvariadic index types
Parameters
iindex in the first dimension
isindices in the remaining dimensions
Returns
element in the tensor

◆ operator[]()

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<std::convertible_to< const std::size_t > I>
const T & lucid::Tensor< T >::operator[] ( I i) const
inline

Get the element in the underlying data vector using its index.

Note
This is not the same as the tensor index, rather the linearized index
Template Parameters
Iindex type
Parameters
iindex in the data vector
Returns
element in the tensor

◆ pad() [1/2]

template<IsAnyOf< int, float, double, std::complex< double > > T>
Tensor< T > lucid::Tensor< T >::pad ( const std::vector< Index > & padding,
const std::vector< Index > & start_padding = {},
const T & value = {} ) const
nodiscard

Pad the tensor with a value.

The padding is applied to each dimension starting at the respective start_padding index. This allows the padding to be placed in the middle of the tensor.

Tensor<int> t{std::vector<int>{1, 2, 3, 4, 5, 6}, std::vector<std::size_t>{3, 2}};
// 1 2
// 3 4
// 5 6
t.pad({2, 3}, {2, 1}, 0);
// 1 0 0 0 2
// 3 0 0 0 4
// 0 0 0 0 0
// 0 0 0 0 0
// 5 0 0 0 6
t.pad({2, 3}, {0, 2}, 0);
// 0 0 0 0 0
// 0 0 0 0 0
// 1 2 0 0 0
// 3 4 0 0 0
// 5 6 0 0 0
t.pad({1, 1}, {1, 1}, 0);
// 1 0 2
// 0 0 0
// 3 0 4
// 5 0 6
Note
Setting start_padding to 0 (the size of that dimension) will place all the padding at the start (the end) of the dimension.
Parameters
paddingpadding for each dimension
start_paddingthe index where the padding starts for each dimension
valuevalue to fill the padding
Returns
padded tensor

◆ pad() [2/2]

template<IsAnyOf< int, float, double, std::complex< double > > T>
Tensor< T > lucid::Tensor< T >::pad ( const std::vector< std::pair< Index, Index > > & padding,
const T & value = {} ) const
nodiscard

Pad the tensor with a value.

The padding is applied to each dimension, and it is specified by a pair of indices, one for the beginning and one for the end of the dimension.

Tensor<int> t{std::vector<int>{1, 2, 3, 4}, std::vector<std::size_t>{2, 2}};
// 1 2
// 3 4
t.pad({{1, 2}, {0, 3}}, 0);
// 0 0 0 0 0
// 1 2 0 0 0
// 3 4 0 0 0
// 0 0 0 0 0
// 0 0 0 0 0
Parameters
paddingpadding for each dimension
valuevalue to fill the padding
Returns
padded tensor

◆ permute() [1/2]

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<IsAnyOf< int, float, double, std::complex< double > > TT = T>
Tensor< TT > lucid::Tensor< T >::permute ( const std::vector< std::size_t > & permutation) const
inlinenodiscard

Permute the axes of the tensor.

Namely, the axes are rearranged according to the permutation vector. If an axis is not specified, it will be left unchanged.

Tensor<int> t{std::vector<int>{1, 2, 3, 4, 5, 6}, std::vector<std::size_t>{2, 3}};
// 1 2 3
// 4 5 6
t.permute(std::vector<std::size_t>{0, 1});
// 1 2
// 3 4
// 5 6
Precondition
All values in permutation must be in the range [0, rank() - 1]
Parameters
permutationpermutation of the axes
Returns
reference to this object

◆ permute() [2/2]

template<IsAnyOf< int, float, double, std::complex< double > > T>
template<IsAnyOf< int, float, double, std::complex< double > > TT = T, std::convertible_to< const std::size_t > I, class... Is>
Tensor< TT > lucid::Tensor< T >::permute ( I i,
Is... is ) const
inlinenodiscard

Permute the axes of the tensor.

Namely, the axes are rearranged according to the permutation vector. If an axis is not specified, it will be left unchanged.

Tensor<int> t{std::vector<int>{1, 2, 3, 4, 5, 6}, std::vector<std::size_t>{2, 3}};
// 1 2 3
// 4 5 6
t.permute(0, 1);
// 1 2
// 3 4
// 5 6
Precondition
All values in permutation must be in the range [0, rank() - 1]
Template Parameters
Iaxis to put in the first dimension type
Isvaradic remaining permuted axis types
Parameters
iaxis to put in the first dimension
isremaining permuted axes
Returns
reference to this object

◆ rank()

template<IsAnyOf< int, float, double, std::complex< double > > T>
std::size_t lucid::Tensor< T >::rank ( ) const
inlinenodiscard

Get read-only access to the rank of the tensor.

Returns
rank of the tensor

◆ reshape()

template<IsAnyOf< int, float, double, std::complex< double > > T>
Tensor< T > & lucid::Tensor< T >::reshape ( std::vector< std::size_t > dims)

Reshape the tensor to the new dimensions.

The data is not modified, only the view is changed.

Tensor<int> t{std::vector<int>{1, 2, 3, 4}, std::vector<std::size_t>{2, 2}};
// 1 2
// 3 4
t.reshape({4});
// 1
// 2
// 3
// 4
Precondition
The number of elements must remain the same
Parameters
dimsnew dimensions of the tensor
Returns
reference to this object

◆ size()

template<IsAnyOf< int, float, double, std::complex< double > > T>
std::size_t lucid::Tensor< T >::size ( ) const
inlinenodiscard

Get read-only access to the size of the tensor.

Returns
size of the tensor

◆ view()

template<IsAnyOf< int, float, double, std::complex< double > > T>
const TensorView< T > & lucid::Tensor< T >::view ( ) const
inlinenodiscard

Get read-only access to the view of the tensor.

Returns
view of the tensor

The documentation for this class was generated from the following files: