26 #ifndef SRC_TYPES_TENSOR_HPP_
27 #define SRC_TYPES_TENSOR_HPP_
35 #include <boost/serialization/serialization.hpp>
37 #include <boost/serialization/vector.hpp>
39 #include <boost/serialization/array.hpp>
40 #include <boost/serialization/version.hpp>
44 namespace serialization {
77 Tensor(std::initializer_list<size_t> dims_) {
80 for (
auto ith_dimension : dims_) {
82 assert(ith_dimension > 0);
104 for (
auto ith_dimension : dims_) {
106 assert(ith_dimension > 0);
129 std::copy(t.dimensions.begin(), t.dimensions.end(),
135 memcpy(data_ptr, t.data_ptr,
sizeof(T) *
elements);
144 elements = mat_.cols() * mat_.rows();
171 std::copy(t.dimensions.begin(), t.dimensions.end(),
203 for (
auto ith_dimension : dims_) {
205 assert(ith_dimension > 0);
206 new_size *= ith_dimension;
213 std::copy(dims_.begin(), dims_.end(), std::back_inserter(
dimensions));
227 for (
auto ith_dimension : dims_) {
229 assert(ith_dimension > 0);
230 new_size *= ith_dimension;
236 std::copy(dims_.begin(), dims_.end(), std::back_inserter(
dimensions));
250 memcpy(
data_ptr, old_prt,
sizeof(T) * block_size);
262 #pragma omp parallel for
263 for (
size_t i = 0; i <
elements; i++) {
274 #pragma omp parallel for
275 for (
size_t i = 0; i <
elements; i++) {
288 std::random_device rd;
289 std::mt19937 mt(rd());
290 std::normal_distribution<> dist(mean, stddev);
292 #pragma omp parallel for
293 for (
size_t i = 0; i <
elements; i++) {
338 #pragma omp parallel for
339 for (
size_t i = 0; i <
elements; i++)
347 #pragma omp parallel for
348 for (
size_t i = 0; i <
elements; i++)
357 #pragma omp parallel for
358 for (
size_t i = 0; i <
elements; i++)
368 void randn(T mean = 0, T stddev = 1) {
371 std::random_device rd;
372 std::mt19937 mt(rd());
373 std::normal_distribution<T> dist(mean, stddev);
375 #pragma omp parallel for
376 for (
size_t i = 0; i <
elements; i++) {
387 void rand(T min = 0, T max = 1) {
390 std::random_device rd;
391 std::mt19937 mt(rd());
392 std::uniform_real_distribution<T> dist(min, max);
394 #pragma omp parallel for
395 for (
size_t i = 0; i <
elements; i++) {
415 #pragma omp parallel for
416 for (
size_t i = 0; i <
elements; i++)
437 #pragma omp parallel for
438 for (
size_t i = 0; i <
elements; i++)
451 for (
size_t i = 0; i <
elements; i++)
466 for (
size_t i = 0; i < obj_.dimensions.size() - 1; i++)
467 os_ << obj_.dimensions[i] <<
" x ";
468 os_ << obj_.dimensions.back() <<
"]: [";
471 for (
size_t i = 0; i < obj_.elements - 1; i++)
472 os_ << obj_.data_ptr[i] <<
", ";
473 os_ << obj_.data_ptr[obj_.elements - 1] <<
"]";
510 inline const T&
operator()(std::vector<size_t> coordinates_)
const {
520 inline size_t getIndex(std::vector<size_t> coordinates_) {
522 assert(
dims().
size() == coordinates_.size());
531 switch (coordinates_.size()) {
533 return coordinates_[0];
535 return coordinates_[1] *
dimensions[0] + coordinates_[0];
555 std::vector<size_t> new_dims;
556 for (
size_t i=0; i < ranges_.size(); i++) {
558 assert((ranges_[i].
size() >0) && (ranges_[i].
size() < 3));
560 if (ranges_[i].
size() == 1)
561 ranges_[i].push_back(ranges_[i][0]);
563 size_t ith_dimension = ranges_[i][1] - ranges_[i][0] +1;
565 assert(ranges_[i][0] >= 0);
567 assert(ith_dimension > 0);
569 new_dims.push_back(ith_dimension);
577 switch (new_dims.size()) {
580 memcpy(new_tensor.
data_ptr, (
data_ptr + ranges_[0][0]), new_dims[0]*
sizeof(T));
585 for (
size_t i=ranges_[1][0], j=0; i<=ranges_[1][1]; i++, j++) {
593 for (
size_t i2=ranges_[2][0], j2=0; i2<=ranges_[2][1]; i2++, j2++) {
594 for (
size_t i1=ranges_[1][0], j1=0; i1<=ranges_[1][1]; i1++, j1++) {
603 std::vector<size_t> is;
604 std::vector<size_t> js;
619 assert(
dimensions.size() == obj_.dimensions.size());
631 memcpy(
data_ptr + elements, obj_.data_ptr,
sizeof(T) * obj_.elements);
638 elements += obj_.elements;
648 size_t new_block_size = 0;
649 size_t added_zero_dim = 0;
650 for (
auto tensor: tensors_) {
651 assert(
dimensions.size() == tensor.dimensions.size());
653 assert(
dimensions[d] == tensor.dimensions[d]);
655 new_block_size += tensor.elements;
656 added_zero_dim += tensor.dimensions[0];
671 for (
auto tensor: tensors_) {
672 memcpy(
data_ptr + block_end, tensor.data_ptr,
sizeof(T) * tensor.elements);
673 block_end += tensor.elements;
678 elements += new_block_size;
706 if (dim_ == coordinates_.size() - 1)
707 return coordinates_[dim_];
726 void recursiveBlockCopy (
size_t dim_, std::vector< std::vector<size_t> > ranges_, std::vector<size_t> is_, std::vector<size_t> js_, std::vector<size_t> new_dims_, T* tgt_data_ptr_) {
728 assert(new_dims_.size()>1);
730 if (dim_ == new_dims_.size()){
738 memcpy(tgt_data_ptr_ + tgt_index, (
data_ptr + src_index), new_dims_[0]*
sizeof(T));
742 for (
size_t i=ranges_[dim_][0], j=0; i<=ranges_[dim_][1]; i++, j++) {
762 if (dim_ == js_.size()) {
765 }
else if (dim_ == 0) {
768 size_t tmp2 = tmp * dims_[dim_];
775 size_t tmp2 = tmp * dims_[dim_] + js_[dim_-1];
789 if (dim_ == is_.size()) {
792 }
else if (dim_ == 0) {
795 size_t tmp2 = tmp *
dimensions[dim_] + offset_;
801 size_t tmp2 = tmp *
dimensions[dim_] + is_[dim_-1];
815 template<
class Archive>
816 void save(Archive & ar,
const unsigned int version)
const {
827 template<
class Archive>
828 void load(Archive & ar,
const unsigned int version) {
839 BOOST_SERIALIZATION_SPLIT_MEMBER()
847 BOOST_CLASS_VERSION(mic::types::Tensor<
short>, 1)
848 BOOST_CLASS_VERSION(mic::types::Tensor<
int>, 1)
849 BOOST_CLASS_VERSION(mic::types::Tensor<
long>, 1)
850 BOOST_CLASS_VERSION(mic::types::Tensor<
float>, 1)
851 BOOST_CLASS_VERSION(mic::types::Tensor<
double>, 1)
friend std::ostream & operator<<(std::ostream &os_, const Tensor &obj_)
void conservativeResize(std::vector< size_t > dims_)
const T & operator()(std::vector< size_t > coordinates_) const
T & operator()(std::vector< size_t > coordinates_)
mic::types::Tensor< T > operator-(mic::types::Tensor< T > obj_)
Tensor(const Tensor< T > &t)
size_t recursiveIndex(size_t dim_, std::vector< size_t > coordinates_)
void recursiveBlockCopy(size_t dim_, std::vector< std::vector< size_t > > ranges_, std::vector< size_t > is_, std::vector< size_t > js_, std::vector< size_t > new_dims_, T *tgt_data_ptr_)
void concatenate(const Tensor &obj_)
void elementwiseFunction(T(*func)(T))
std::vector< size_t > dimensions
void randn(T mean=0, T stddev=1)
void concatenate(std::vector< mic::types::Tensor< T > > tensors_)
void elementwiseFunctionScalar(T(*func)(T, T), T scalar)
void rand(T min=0, T max=1)
const Tensor< T > & operator=(const Tensor< T > &t)
void resize(std::vector< size_t > dims_)
void normRandReal(float mean=0, float stddev=1)
Tensor< T > block(std::vector< std::vector< size_t > > ranges_)
const T & operator()(size_t index_) const
friend class boost::serialization::access
size_t getIndex(std::vector< size_t > coordinates_)
void save(Archive &ar, const unsigned int version) const
size_t recursiveCalculateSourceIndex(size_t dim_, std::vector< size_t > is_, size_t offset_)
mic::types::Tensor< T > operator+(mic::types::Tensor< T > obj_)
Tensor(std::vector< size_t > dims_)
size_t recursiveCalculateTargetIndex(size_t dim_, std::vector< size_t > js_, std::vector< size_t > dims_)
void load(Archive &ar, const unsigned int version)
Template class representing an nD (n-Dimensional) tensor. Tensor is row-major, i.e. first dimension is height (rows), second is width (cols), third is depth (channels) etc.
Template-typed Matrix of dynamic size. Uses OpenBLAS if found by CMAKE - overloaded, specializations of * operator for types: float, double.
Tensor(std::initializer_list< size_t > dims_)
Tensor(const mic::types::Matrix< T > &mat_)
T & operator()(size_t index_)
std::vector< size_t > dims()