33,311
社区成员
发帖
与我相关
我的任务
分享
#include <vector>
#include <memory>
#include <algorithm>
#include <assert.h>
typedef int layer_size_t;
template<typename T>
class range_t
{
public:
range_t()
{
full_ = true;
}
range_t(T begin, T end, T step = T(1))
{
assert(begin < end);
begin_ = begin;
end_ = end;
step_ = step;
full_ = false;
}
size_t size()
{
size_t ret = (end_ - begin_) / step_ + 1;
if ((end_ - begin_) % step_ == 0) ret--;
return ret;
}
size_t size() const
{
size_t ret = (end_ - begin_) / step_ + 1;
if ((end_ - begin_) % step_ == 0) ret--;
return ret;
}
T begin_;
T end_;
T step_;
bool full_;
};
typedef range_t<size_t> range_type;
template<typename T>
class extents_t
{
public:
extents_t<T>& operator[](const range_t<T>& range)
{
ranges.push_back(range);
return *this;
}
extents_t<T>& operator[](T index)
{
ranges.push_back(range_t<T>(index, index + 1));
return *this;
}
std::vector<range_t<T>> ranges;
};
typedef extents_t<size_t> extents_type;
template<typename derived,typename value_type,typename data_type>
class tensor_base_t
{
public:
typedef typename int index_value;//signed
typedef typename std::vector<index_value> shape_type;
typedef typename shape_type index_type;
typedef typename derived tensor_type;
typedef typename value_type value_type;
typedef typename std::vector<value_type> vector_type;
typedef typename data_type data_type;
protected:
data_type data_;
bool continuous_;
int offset_;
shape_type shape_;
index_type steps_;
size_t size_;
public:
tensor_base_t() = default;
void assign(const std::initializer_list<value_type>& vec)
{
assert(size_ == vec.size());
(*data_).assign(vec.begin(), vec.end());
}
derived& operator =(derived& tensor)
{
data_ = tensor.data();
offset_ = tensor.offset();
size_ = tensor.size();
shape_ = tensor.shape();
steps_ = tensor.steps();
return *this;
}
void reshape(const std::initializer_list<size_t>& sizes_list)
{
reshape(shape_type(sizes_list));
}
void reshape(const shape_type& shape)//if this failed please clone this tensor to itself
{
size_t size = calculate_size(shape);
assert(offset_ == 0 && size_ == (*data).size());
assert(size == size_);
shape_ = shape;
init_steps();
}
const data_type& data()
{
return data_;
}
bool continuous()
{
return continuous_;
}
derived clone()//iterate through view and copy data
{
derived ret(shape_);
index_type index(shape_.size(), 0);
bool finish = false;
while (true)
{
for (size_t i = 0; i < shape_.size(); ++i)
{
if (index[i] == shape_[i])
{
if (i == shape_.size() - 1)
{
finish = true;
break;
}
index[i] = 0;
index[i + 1]++;
}
else{
break;
}
}
if (finish) break;
ret(index) = (*this)(index);
index[0]++;
}
return ret;
}
derived operator()(const extents_type& extents)
{
derived ret(*static_cast<derived*>(this));
const auto& ranges = extents.ranges;
assert(dims() == ranges.size());
for (size_t i = 0; i < ranges.size(); ++i)
{
if (ranges[i].full_) continue;
ret.offset_ += ranges[i].begin_ * ret.steps_[i];
ret.shape_[i] = ranges[i].size();
ret.steps_[i] *= ranges[i].step_;
ret.update_size();
}
ret.squeeze();
return ret;
}
void squeeze()//去除大小为1的维度
{
for (size_t i = 0; i < shape_.size(); ++i)
{
if (shape_[i] == 1)
{
shape_.erase(shape_.begin() + i);
steps_.erase(steps_.begin() + i);
}
}
}
void transpose(const std::initializer_list<size_t>& permutation)
{
assert(permutation.size() == dims());
index_type index(dims());
for (size_t i = 0; i < dims(); ++i)
{
index[i] = i;
}
assert(std::is_permutation(permutation.begin(), permutation.end(), index.begin()));
index_type steps(dims());
for (size_t i = 0; i < dims(); ++i)
{
steps[permutation.begin()[i]] = steps_[i];
}
steps_ = steps;
}
void flip(const std::initializer_list<bool>& flip_flags)
{
assert(flip_flags.size() == dims());
for (size_t i = 0; i < shape_.size(); ++i)
{
if (flip_flags.begin()[i] == false) continue;
offset_ += (shape_[i] - 1) * steps_[i];
steps_[i] *= -1;
}
}
value_type& operator()(const std::initializer_list<index_value>& index)
{
return (*data_)[_index(index)];
}
const value_type& operator()(const std::initializer_list<index_value>& index) const
{
return (*data_)[_index(index)];
}
value_type& operator()(const index_type& index)
{
return (*data_)[_index(index)];
}
const value_type& operator()(const index_type&& index) const
{
return (*data_)[_index(index)];
}
value_type& operator[](size_t index)
{
#if _ITERATOR_DEBUG_LEVEL == 2
assert(offset_ == 0 && size_ == (*data_).size());
#endif
return (*data_)[index];
}
const value_type& operator[](size_t index) const
{
#if _ITERATOR_DEBUG_LEVEL == 2
assert(offset_ == 0 && size_ == (*data_).size());
#endif
return (*data_)[index];
}
private:
/*
template<int ndims>
size_t index(const std::vector<T>& coordinate)
{
return coordinate[ndims - 1] * steps_[ndims - 1] + index<ndims - 1>(coordinate);
}
template<>
size_t index<0>(const std::vector<T>& coordinate)
{
return 0;
}
*/
size_t _index(const std::initializer_list<index_value>& coordinate)
{
return _index(index_type(coordinate));
}
size_t _index(const index_type& coordinate)
{
int ret = offset_;
const size_t ndims = coordinate.size();
#if _ITERATOR_DEBUG_LEVEL == 2
assert(ndims == dims());
#endif
for (size_t i = 0; i < ndims; ++i)
{
#if _ITERATOR_DEBUG_LEVEL == 2
if (coordinate[i] >= shape_[i])
{ // report error
_DEBUG_ERROR("tensor subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
#endif
ret += coordinate[i] * steps_[i];
}
return ret;
}
public:
const index_type& shape()
{
return shape_;
}
const index_type& shape() const
{
return shape_;
}
index_value shape(size_t i)
{
return shape_[i];
}
index_value shape(size_t i) const
{
return shape_[i];
}
const index_type& steps()
{
return steps_;
}
const index_type& steps() const
{
return steps_;
}
size_t size()
{
return size_;
}
size_t size() const
{
return size_;
}
size_t dims()
{
return shape_.size();
}
size_t dims() const
{
return shape_.size();
}
int offset()
{
return offset_;
}
int offset() const
{
return offset_;
}
protected:
size_t calculate_size(const shape_type& shape)
{
double product = 1;
size_t size = 1;
for (auto& v : shape)
{
product *= v;
size *= v;
}
assert(product < std::numeric_limits<size_t>::max());//check whether size overflow
return size;
}
void update_size()
{
size_ = calculate_size(shape_);
}
void init_steps()
{
steps_.resize(shape_.size());
std::fill(steps_.begin(), steps_.end(), 1);
for (size_t i = 1; i < steps_.size(); ++i)
for (size_t k = 0; k < i; ++k)
steps_[i] *= shape_[k];
}
public:
friend class tensor_base_t<derived,value_type,data_type>;
};
//在堆中开辟一个2×3×4×5的4维int数组
#include <stdio.h>
#include <malloc.h>
int ****p;
int h,i,j,k;
void main() {
p=(int ****)malloc(2*sizeof(int ***));
if (NULL==p) return;
for (h=0;h<2;h++) {
p[h]=(int ***)malloc(3*sizeof(int **));
if (NULL==p[h]) return;
for (i=0;i<3;i++) {
p[h][i]=(int **)malloc(4*sizeof(int *));
if (NULL==p[h][i]) return;
for (j=0;j<4;j++) {
p[h][i][j]=(int *)malloc(5*sizeof(int));
if (NULL==p[h][i][j]) return;
}
}
}
for (h=0;h<2;h++) {
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
for (k=0;k<5;k++) {
p[h][i][j][k]=h*60+i*20+j*5+k;
}
}
}
}
for (h=0;h<2;h++) {
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
for (k=0;k<5;k++) {
printf(" %3d",p[h][i][j][k]);
}
printf("\n");
}
printf("--------------------\n");
}
printf("=======================\n");
}
for (h=0;h<2;h++) {
for (i=0;i<3;i++) {
for (j=0;j<4;j++) {
free(p[h][i][j]);
}
free(p[h][i]);
}
free(p[h]);
}
free(p);
}
// 0 1 2 3 4
// 5 6 7 8 9
// 10 11 12 13 14
// 15 16 17 18 19
//--------------------
// 20 21 22 23 24
// 25 26 27 28 29
// 30 31 32 33 34
// 35 36 37 38 39
//--------------------
// 40 41 42 43 44
// 45 46 47 48 49
// 50 51 52 53 54
// 55 56 57 58 59
//--------------------
//=======================
// 60 61 62 63 64
// 65 66 67 68 69
// 70 71 72 73 74
// 75 76 77 78 79
//--------------------
// 80 81 82 83 84
// 85 86 87 88 89
// 90 91 92 93 94
// 95 96 97 98 99
//--------------------
// 100 101 102 103 104
// 105 106 107 108 109
// 110 111 112 113 114
// 115 116 117 118 119
//--------------------
//=======================
//
#pragma once
#include "tensor_base_t.h"
//当数组维度大于等于2时才使用tensor_base_t,否则使用std::vector
template<typename value_type>
class tensor_t : public tensor_base_t < tensor_t<value_type>, value_type, std::shared_ptr<std::vector<value_type>> >
{
public:
typedef typename int index_value;//signed
typedef typename std::vector<index_value> shape_type;
typedef typename shape_type index_type;
typedef typename tensor_base_t < tensor_t<value_type>, value_type, std::shared_ptr<std::vector<value_type>>> base;
typedef typename base::value_type value_type;
typedef typename base::tensor_type tensor_type;
typedef typename base::vector_type vector_type;
typedef typename base::data_type data_type;
public:
tensor_t()
{
reset(1, 0);
}
tensor_t(const std::initializer_list<index_value>& sizes_list, const value_type& value = value_type())
{
reset(sizes_list, value);
}
tensor_t(const shape_type& shape, const value_type& value = value_type())
{
reset(shape, value);
}
tensor_t(tensor_type& tensor)
{
*this = tensor;
}
void reset(const shape_type& shape, const value_type& value = value_type())
{
data_.reset(new vector_type());
resize(shape, value);
}
void reset(size_t size, const value_type& value = value_type())
{
data_.reset(new vector_type());
resize(size, value);
}
void resize(const size_t& size1, const value_type& value = value_type())
{
resize(shape_type(1, size1), value);
}
void resize(const std::initializer_list<index_value>& list, const value_type& value = value_type())
{
resize(shape_type(list), value);
}
void resize(const shape_type& shape, const value_type& value = value_type()) //after resize the data is dirty,must manual initialize data
{
size_t size = calculate_size(shape);
assert(size > 0);
(*data_).resize(size, value);
offset_ = 0;
size_ = size;
shape_ = shape;
init_steps();
squeeze();
}
};
main.cpp
#include <iostream>
#include <time.h>
#include "tensor_t.h"
using namespace std;
int main()
{
tensor_t<double> tensor;
tensor.reset({ 2, 3, 5 });//重新分配内存,并设置形状
tensor({ 1, 0, 2 }) = 123456;//对给定位置的元素赋值
cout << tensor({ 1, 0, 2 }) << std::endl; //123456
cout << tensor[1 + 0 * 2 + 2 * 2 * 3] << std::endl; //123456
tensor.assign({ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2 });//复制给定数据
tensor = tensor.clone();//深度拷贝
cout << tensor({ 1, 0, 2 }) << std::endl; //2
tensor[1 + 2 * 2 + 2 * 2 * 3] = 2345;//按一维下标访问多维数组
tensor_t<double> tensor2 = tensor(extents_type()[1][range_type()][range_type(0, 5, 2)]);//切割数组
cout << tensor2({ 2,1 }) << std::endl;//2345
tensor2.transpose({ 1, 0 });//按排列转置数组
cout << tensor2({ 1, 2 }) << std::endl;//2345
tensor2.flip({ false, true });//翻转数组的指定维度
cout << tensor2({ 1, 3 - 1 - 2 }) << std::endl;//2345
system("PAUSE");
return 0;
}