mxnet
tuple.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
24 #ifndef NNVM_TUPLE_H_
25 #define NNVM_TUPLE_H_
26 
27 #include <algorithm>
28 #include <iostream>
29 #include <string>
30 #include <type_traits>
31 #include <utility>
32 #include <vector>
33 
34 #include "base.h"
35 
36 namespace nnvm {
37 
39 typedef int64_t dim_t;
40 
51 template <typename ValueType>
52 class Tuple {
53  public:
55  Tuple() = default;
57  inline ~Tuple() { delete[] data_heap_; }
62  inline Tuple(const Tuple<ValueType>& s) { this->assign(s.begin(), s.end()); }
67  inline Tuple(std::initializer_list<ValueType> init) { this->assign(init.begin(), init.end()); }
72  inline Tuple(std::vector<ValueType> init) { // NOLINT(runtime/explicit)
73  this->assign(init.begin(), init.end());
74  }
80  inline Tuple(Tuple<ValueType>&& src) { // NOLINT(runtime/explicit)
81  this->swap(src);
82  }
89  template <typename RandomAccessIterator>
90  inline Tuple(RandomAccessIterator begin, RandomAccessIterator end) {
91  this->assign(begin, end);
92  }
99  template <typename RandomAccessIterator>
100  inline void assign(RandomAccessIterator begin, RandomAccessIterator end) {
101  this->SetDim(end - begin);
102  std::copy(begin, end, this->begin());
103  }
108  inline void swap(Tuple<ValueType>& other) { // NOLINT(*)
109  std::swap(ndim_, other.ndim_);
110  std::swap(num_heap_allocated_, other.num_heap_allocated_);
111  std::swap(data_stack_, other.data_stack_);
112  std::swap(data_heap_, other.data_heap_);
113  }
120  this->assign(src.begin(), src.end());
121  return *this;
122  }
129  Tuple<ValueType>(std::move(src)).swap(*this);
130  return *this;
131  }
137  inline Tuple<ValueType>& operator=(std::initializer_list<ValueType> init) {
138  this->assign(init.begin(), init.end());
139  return *this;
140  }
145  inline bool operator==(const Tuple<ValueType>& s) const {
146  if (ndim_ != s.ndim_) return false;
147  return std::equal(begin(), end(), s.begin());
148  }
153  inline bool operator!=(const Tuple<ValueType>& s) const { return !(*this == s); }
155  inline const ValueType* begin() const { return ndim_ <= kStackCache ? data_stack_ : data_heap_; }
157  inline ValueType* begin() { return ndim_ <= kStackCache ? data_stack_ : data_heap_; }
159  inline const ValueType* end() const {
160  return ndim_ <= kStackCache ? (data_stack_ + ndim_) : (data_heap_ + ndim_);
161  }
163  inline ValueType* end() {
164  return ndim_ <= kStackCache ? (data_stack_ + ndim_) : (data_heap_ + ndim_);
165  }
167  inline uint32_t ndim() const { return ndim_; }
173  inline ValueType& operator[](size_t i) { return begin()[i]; }
179  inline const ValueType& operator[](size_t i) const { return begin()[i]; }
184  inline void Save(dmlc::JSONWriter* writer) const {
185  std::vector<ValueType> tmp(begin(), end());
186  writer->Write(tmp);
187  }
192  inline void Load(dmlc::JSONReader* reader) {
193  std::vector<ValueType> tmp;
194  reader->Read(&tmp);
195  this->assign(tmp.begin(), tmp.end());
196  }
203  friend std::ostream& operator<<(std::ostream& os, const Tuple<ValueType>& t) {
204  os << '[';
205  const ValueType* begin = t.begin();
206  const ValueType* end = t.end();
207  for (const ValueType* it = begin; it != end; ++it) {
208  if (it != begin) os << ',';
209  os << *it;
210  }
211  os << ']';
212  return os;
213  }
220  friend std::istream& operator>>(std::istream& is, Tuple<ValueType>& t) {
221  // get (
222  while (true) {
223  char ch = is.peek();
224  if (isdigit(ch) || ch == '-') {
225  ValueType idx;
226  if (is >> idx) {
227  t.assign(&idx, &idx + 1);
228  }
229  return is;
230  }
231  is.get();
232  if (ch == '(' || ch == '[') break;
233  if (!isspace(ch)) {
234  is.setstate(std::ios::failbit);
235  return is;
236  }
237  }
238  // Handle empty tuple
239  while (isspace(is.peek())) {
240  is.get();
241  }
242  if (is.peek() == ')' || is.peek() == ']') {
243  is.get();
244  return is;
245  }
246  // Handle non-empty tuple
247  ValueType idx;
248  std::vector<ValueType> tmp;
249  while (is >> idx) {
250  tmp.push_back(idx);
251  char ch;
252  do {
253  ch = is.get();
254  } while (isspace(ch));
255  if (std::is_integral<ValueType>::value && ch == 'L') {
256  ch = is.get();
257  }
258  if (ch == ',') {
259  while (true) {
260  ch = is.peek();
261  if (isspace(ch)) {
262  is.get();
263  continue;
264  }
265  if (ch == ')' || ch == ']') {
266  is.get();
267  break;
268  }
269  break;
270  }
271  if (ch == ')' || ch == ']') break;
272  } else if (ch == ')' || ch == ']') {
273  break;
274  } else {
275  is.setstate(std::ios::failbit);
276  return is;
277  }
278  }
279  t.assign(tmp.begin(), tmp.end());
280  return is;
281  }
288  template <typename DType = ValueType, typename TStream>
289  inline void Save(TStream* strm) const;
297  template <typename DType = ValueType, typename TStream>
298  inline bool Load(TStream* strm);
299 
300  protected:
301  // stack cache size
302  static const uint32_t kStackCache = 4;
304  uint32_t ndim_{0};
306  uint32_t num_heap_allocated_{0};
310  ValueType* data_heap_{nullptr};
311  // internal function to change the dimension
312  inline void SetDim(uint32_t ndim) {
314  delete[] data_heap_;
315  data_heap_ = new ValueType[ndim];
317  }
318  ndim_ = ndim;
319  }
320 };
321 
325 class TShape : public Tuple<dim_t> {
326  public:
328  TShape() = default;
333  inline TShape(uint32_t ndim) { // NOLINT(*)
334  this->SetDim(ndim);
335  std::fill_n(begin(), ndim, 1);
336  }
341  inline TShape(const Tuple<dim_t>& s) { // NOLINT(*)
342  this->assign(s.begin(), s.end());
343  }
348  inline TShape(std::initializer_list<dim_t> init) { this->assign(init.begin(), init.end()); }
353  inline TShape(Tuple<dim_t>&& s) { // NOLINT(*)
354  this->swap(s);
355  }
362  template <typename RandomAccessIterator>
363  inline TShape(RandomAccessIterator begin, RandomAccessIterator end) {
364  this->assign(begin, end);
365  }
371  inline TShape& operator=(const Tuple<dim_t>& src) {
372  this->assign(src.begin(), src.end());
373  return *this;
374  }
380  inline TShape& operator=(Tuple<dim_t>&& src) { // NOLINT(*)
381  TShape(std::move(src)).swap(*this); // NOLINT(*)
382  return *this;
383  }
385  inline size_t Size() const {
386  dim_t size = 1;
387  const dim_t *start = begin(), *fin = end();
388  for (const dim_t* it = start; it != fin; ++it) {
389  size *= *it;
390  }
391  return size;
392  }
398  inline size_t ProdShape(int dimstart, int dimend) const {
399  dim_t num = 1;
400  const dim_t* d = this->data();
401  for (int i = dimstart; i < dimend; ++i) {
402  num *= d[i];
403  }
404  return num;
405  }
407  inline const dim_t* data() const { return begin(); }
409  inline dim_t* data() { return begin(); }
410 #ifdef MSHADOW_XINLINE
411  template <int dim>
412  inline TShape(const mshadow::Shape<dim>& s) { // NOLINT(*)
413  this->assign(s.shape_, s.shape_ + dim);
414  }
415 
416  template <int dim>
417  inline TShape(mshadow::Shape<dim>&& s) { // NOLINT(*)
418  this->assign(s.shape_, s.shape_ + dim);
419  }
426  template <int dim>
427  inline TShape& operator=(const mshadow::Shape<dim>& shape) {
428  this->assign(shape.shape_, shape.shape_ + dim);
429  return *this;
430  }
436  template <int dim>
437  inline mshadow::Shape<dim> get() const {
438  CHECK_EQ(dim, static_cast<int>(ndim()))
439  << "dimension do not match target dimension " << dim << " vs " << ndim();
440  const dim_t* d = this->data();
442  for (int i = 0; i < dim; ++i) {
443  s[i] = d[i];
444  }
445  return s;
446  }
451  inline mshadow::Shape<2> FlatTo2D(void) const {
453  if (ndim() == 0) return mshadow::Shape2(0, 0);
454  const dim_t* d = this->data();
455  s.shape_[1] = d[ndim() - 1];
456  dim_t ymax = 1;
457  for (size_t i = 1; i < ndim(); ++i) {
458  ymax *= d[i - 1];
459  }
460  s.shape_[0] = ymax;
461  return s;
462  }
469  inline mshadow::Shape<3> FlatTo3D(size_t axis_begin, size_t axis_end) const {
470  CHECK(axis_end >= axis_begin);
472  if (ndim() == 0) return mshadow::Shape3(0, 0, 0);
473  const dim_t* d = this->data();
474  s.shape_[0] = 1;
475  s.shape_[1] = 1;
476  s.shape_[2] = 1;
477 
478  for (size_t i = 0; i < axis_begin; ++i) {
479  s.shape_[0] *= d[i];
480  }
481  for (size_t i = axis_begin; i <= axis_end; ++i) {
482  s.shape_[1] *= d[i];
483  }
484  for (size_t i = axis_end + 1; i < ndim(); ++i) {
485  s.shape_[2] *= d[i];
486  }
487  return s;
488  }
494  inline mshadow::Shape<3> FlatTo3D(size_t axis) const { return FlatTo3D(axis, axis); }
495  inline bool operator==(const TShape& s) const {
496  if (ndim() != s.ndim()) return false;
497  return std::equal(begin(), end(), s.begin());
498  }
499  inline bool operator!=(const TShape& s) const { return !(*this == s); }
505  template <int dim>
506  inline bool operator==(const mshadow::Shape<dim>& s) const {
507  if (ndim_ != dim) return false;
508  const dim_t* d = dim <= kStackCache ? data_stack_ : data_heap_;
509  for (size_t i = 0; i < dim; ++i) {
510  if (d[i] != s.shape_[i]) return false;
511  }
512  return true;
513  }
519  template <int dim>
520  inline bool operator!=(const mshadow::Shape<dim>& s) const {
521  return !(*this == s);
522  }
523 #endif
524 };
525 
527 template <typename SrcIter, typename DstIter>
528 inline DstIter ShapeTypeCast(const SrcIter begin, const SrcIter end, DstIter dst_begin) {
529  typedef typename std::iterator_traits<SrcIter>::value_type SrcDType;
530  typedef typename std::iterator_traits<DstIter>::value_type DstDType;
531  auto cast = [](const SrcDType& dim) { return static_cast<DstDType>(dim); };
532  return std::transform(begin, end, dst_begin, cast);
533 }
534 
536 template <typename SrcIter>
537 inline TShape ShapeTypeCast(const SrcIter begin, const SrcIter end) {
538  size_t ndim = std::distance(begin, end);
539  TShape res(ndim);
540  ShapeTypeCast(begin, end, res.begin());
541  return res;
542 }
543 
545 template <typename ValueType>
546 template <typename DType, typename TStream>
547 inline void Tuple<ValueType>::Save(TStream* strm) const {
548  strm->Write(&ndim_, sizeof(ndim_));
549  if (typeid(DType) == typeid(ValueType)) {
550  strm->Write(begin(), sizeof(ValueType) * ndim_);
551  } else {
552  std::vector<DType> buffer(ndim_);
553  ShapeTypeCast(begin(), end(), buffer.data());
554  strm->Write(buffer.data(), sizeof(DType) * ndim_);
555  }
556 }
557 
559 template <typename ValueType>
560 template <typename DType, typename TStream>
561 inline bool Tuple<ValueType>::Load(TStream* strm) {
562  if (strm->Read(&ndim_, sizeof(ndim_)) != sizeof(ndim_)) return false;
563  this->SetDim(ndim_);
564  size_t nread = sizeof(DType) * ndim_;
565  if (typeid(DType) == typeid(ValueType)) {
566  if (strm->Read(begin(), nread) != nread) return false;
567  } else {
568  std::vector<DType> buffer(ndim_);
569  if (strm->Read(buffer.data(), nread) != nread) return false;
570  ShapeTypeCast(buffer.begin(), buffer.end(), begin());
571  }
572  return true;
573 }
574 
575 } // namespace nnvm
576 
577 namespace std {
579 template <typename T>
580 struct hash<nnvm::Tuple<T> > {
582  size_t operator()(const nnvm::Tuple<T>& val) const {
583  std::hash<uint32_t> hash_uint;
584  size_t res = hash_uint(val.ndim());
585  for (uint32_t i = 0; i < val.ndim(); ++i) {
586  res = dmlc::HashCombine(res, val[i]);
587  }
588  return res;
589  }
590 };
591 
593 template <>
594 struct hash<nnvm::TShape> {
596  size_t operator()(const nnvm::TShape& val) const {
597  std::hash<uint32_t> hash_uint;
598  size_t res = hash_uint(val.ndim());
599  for (uint32_t i = 0; i < val.ndim(); ++i) {
600  res = dmlc::HashCombine(res, val[i]);
601  }
602  return res;
603  }
604 };
605 } // namespace std
606 
607 namespace dmlc {
609 DMLC_DECLARE_TYPE_NAME(optional<nnvm::TShape>, "Shape or None");
610 // avoid low version of MSVC
611 #if !defined(_MSC_VER)
612 template <typename T>
613 struct type_name_helper<nnvm::Tuple<T> > {
614  static inline std::string value() { return "tuple of <" + type_name<T>() + ">"; }
615 };
616 #endif
617 } // namespace dmlc
618 #endif // NNVM_TUPLE_H_
mxnet::Tuple::begin
const ValueType * begin() const
Definition: tuple.h:201
dmlc::JSONReader::Read
void Read(ValueType *out_value)
Read next ValueType.
std::hash< nnvm::TShape >::operator()
size_t operator()(const nnvm::TShape &val) const
hash a TShape into unsigned int
Definition: tuple.h:596
dmlc::type_name_helper
helper class to construct a string that represents type name
Definition: type_traits.h:86
mxnet::Tuple::ndim_
int ndim_
number of dimension of the tuple
Definition: tuple.h:392
mxnet::Tuple::end
const ValueType * end() const
Definition: tuple.h:209
mxnet::Tuple
A dynamic sized array data structure that is optimized for storing small number of elements with same...
Definition: tuple.h:57
nnvm::Tuple::assign
void assign(RandomAccessIterator begin, RandomAccessIterator end)
Assign content to tuple from iterator.
Definition: tuple.h:100
nnvm::Tuple::Load
void Load(dmlc::JSONReader *reader)
Load Tuple from JSON.
Definition: tuple.h:192
dmlc::JSONWriter::Write
void Write(const ValueType &value)
Write value to json.
nnvm::Tuple
A dynamic sized array data structure that is optimized for storing small number of elements with same...
Definition: tuple.h:52
nnvm::TShape::TShape
TShape(RandomAccessIterator begin, RandomAccessIterator end)
construct the Tuple from content of iterator
Definition: tuple.h:363
dmlc::isspace
bool isspace(char c)
Inline implementation of isspace(). Tests whether the given character is a whitespace letter.
Definition: strtonum.h:26
nnvm::TShape::operator=
TShape & operator=(const Tuple< dim_t > &src)
assignment function from tshape
Definition: tuple.h:371
nnvm::TShape::TShape
TShape(Tuple< dim_t > &&s)
move constructor.
Definition: tuple.h:353
dmlc
namespace for dmlc
Definition: array_view.h:12
nnvm::Tuple::Tuple
Tuple()=default
default constructor
nnvm::TShape::TShape
TShape(uint32_t ndim)
Definition: tuple.h:333
nnvm::TShape::operator=
TShape & operator=(Tuple< dim_t > &&src)
move assignment function from tshape
Definition: tuple.h:380
nnvm::Tuple::operator<<
friend std::ostream & operator<<(std::ostream &os, const Tuple< ValueType > &t)
allow output string of tuple to ostream
Definition: tuple.h:203
nnvm::Tuple::Tuple
Tuple(std::initializer_list< ValueType > init)
constructor from initializer list
Definition: tuple.h:67
nnvm::TShape::data
dim_t * data()
Definition: tuple.h:409
dmlc::isdigit
bool isdigit(char c)
Inline implementation of isdigit(). Tests whether the given character is a decimal digit.
Definition: strtonum.h:46
nnvm::Tuple::begin
const ValueType * begin() const
Definition: tuple.h:155
nnvm::Tuple::num_heap_allocated_
uint32_t num_heap_allocated_
number of cells allocated in data_heap_
Definition: tuple.h:306
nnvm::Tuple::~Tuple
~Tuple()
destructor
Definition: tuple.h:57
base.h
Configuration of nnvm as well as basic data structure.
dmlc::DMLC_DECLARE_TYPE_NAME
DMLC_DECLARE_TYPE_NAME(optional< int >, "int or None")
description for optional int
mxnet::Tuple::data_stack_
ValueType data_stack_[kStackCache]
in stack space used to store shape when it is small
Definition: tuple.h:396
nnvm::Tuple::operator[]
ValueType & operator[](size_t i)
get corresponding index
Definition: tuple.h:173
nnvm::Tuple::kStackCache
static const uint32_t kStackCache
Definition: tuple.h:302
nnvm::Tuple::ndim
uint32_t ndim() const
Definition: tuple.h:167
dmlc::HashCombine
size_t HashCombine(size_t key, const T &value)
hash an object and combines the key with previous keys
Definition: common.h:37
nnvm::Tuple::Tuple
Tuple(Tuple< ValueType > &&src)
move constructor from Tuple
Definition: tuple.h:80
nnvm::Tuple::operator!=
bool operator!=(const Tuple< ValueType > &s) const
Definition: tuple.h:153
nnvm::TShape::Size
size_t Size() const
Definition: tuple.h:385
dim_t
int64_t dim_t
data type to store dim size
Definition: c_api.h:69
mshadow::Shape::shape_
index_t shape_[kDimension]
storing the dimension information
Definition: tensor.h:86
nnvm::Tuple::Tuple
Tuple(RandomAccessIterator begin, RandomAccessIterator end)
construct the Tuple from content of iterator
Definition: tuple.h:90
nnvm::TShape
A Shape class that is used to represent shape of each tensor.
Definition: tuple.h:325
nnvm::TShape::TShape
TShape()=default
default constructor
nnvm::Tuple::operator>>
friend std::istream & operator>>(std::istream &is, Tuple< ValueType > &t)
read tuple from the istream
Definition: tuple.h:220
mxnet::Tuple::num_heap_allocated_
int num_heap_allocated_
number of cells allocated in data_heap_
Definition: tuple.h:394
nnvm::TShape::data
const dim_t * data() const
Definition: tuple.h:407
nnvm::TShape::TShape
TShape(const Tuple< dim_t > &s)
copy constructor of TShape
Definition: tuple.h:341
nnvm::Tuple::swap
void swap(Tuple< ValueType > &other)
Swap current object with other.
Definition: tuple.h:108
nnvm::Tuple::end
ValueType * end()
Definition: tuple.h:163
nnvm::Tuple::data_heap_
ValueType * data_heap_
space to store shape when dimension is big
Definition: tuple.h:310
nnvm::Tuple::operator==
bool operator==(const Tuple< ValueType > &s) const
Definition: tuple.h:145
nnvm::dim_t
int64_t dim_t
data type to store dim size
Definition: tuple.h:39
nnvm::Tuple::data_stack_
ValueType data_stack_[kStackCache]
in stack space used to store shape when it is small
Definition: tuple.h:308
dmlc::JSONWriter
Lightweight json to write any STL compositions.
Definition: json.h:190
nnvm::Tuple::operator[]
const ValueType & operator[](size_t i) const
get corresponding index
Definition: tuple.h:179
mshadow::Shape2
MSHADOW_XINLINE Shape< 2 > Shape2(index_t s0, index_t s1)
construct a two dimension shape, stride will equal s0
Definition: tensor.h:230
std
Definition: optional.h:251
mshadow::Shape< dim >
nnvm::Tuple::end
const ValueType * end() const
Definition: tuple.h:159
nnvm::ShapeTypeCast
DstIter ShapeTypeCast(const SrcIter begin, const SrcIter end, DstIter dst_begin)
helper function to cast type of container elements
Definition: tuple.h:528
nnvm::Tuple::operator=
Tuple< ValueType > & operator=(Tuple< ValueType > &&src)
assignment from rvalue of another tuple.
Definition: tuple.h:128
nnvm::Tuple::Tuple
Tuple(const Tuple< ValueType > &s)
copy constructor from another tuple
Definition: tuple.h:62
nnvm::TShape::ProdShape
size_t ProdShape(int dimstart, int dimend) const
Definition: tuple.h:398
nnvm::Tuple::operator=
Tuple< ValueType > & operator=(const Tuple< ValueType > &src)
assignment from another tuple.
Definition: tuple.h:119
nnvm::Tuple::ndim_
uint32_t ndim_
number of dimension of the tuple
Definition: tuple.h:304
mxnet::Tuple::assign
void assign(RandomAccessIterator begin, RandomAccessIterator end)
Assign content to tuple from iterator.
Definition: tuple.h:136
nnvm::Tuple::Save
void Save(dmlc::JSONWriter *writer) const
Save Tuple to JSON.
Definition: tuple.h:184
nnvm::Tuple::Tuple
Tuple(std::vector< ValueType > init)
constructor from vector
Definition: tuple.h:72
nnvm::Tuple::begin
ValueType * begin()
Definition: tuple.h:157
dmlc::JSONReader
Lightweight JSON Reader to read any STL compositions and structs. The user need to know the schema of...
Definition: json.h:44
nnvm::Tuple::SetDim
void SetDim(uint32_t ndim)
Definition: tuple.h:312
nnvm::TShape::TShape
TShape(std::initializer_list< dim_t > init)
constructor from initializer list
Definition: tuple.h:348
nnvm::Tuple::operator=
Tuple< ValueType > & operator=(std::initializer_list< ValueType > init)
assignment from initializer list
Definition: tuple.h:137
mxnet::Tuple::data_heap_
ValueType * data_heap_
space to store shape when dimension is big
Definition: tuple.h:398
mxnet::Tuple::swap
void swap(Tuple< ValueType > &other)
Swap current object with other.
Definition: tuple.h:145
mshadow::Shape3
MSHADOW_XINLINE Shape< 3 > Shape3(index_t s0, index_t s1, index_t s2)
construct a three dimension shape, stride will equal s0
Definition: tensor.h:241
std::hash< nnvm::Tuple< T > >::operator()
size_t operator()(const nnvm::Tuple< T > &val) const
hash a Tuple into unsigned int
Definition: tuple.h:582
dmlc::type_name_helper< nnvm::Tuple< T > >::value
static std::string value()
Definition: tuple.h:614
nnvm
Definition: base.h:35