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  */
24 #ifndef MXNET_TUPLE_H_
25 #define MXNET_TUPLE_H_
26 
27 #include <vector>
28 #include <type_traits>
29 #include <algorithm>
30 #include <utility>
31 #include <iostream>
32 #include <string>
33 #include "nnvm/op_attr_types.h"
34 #include "nnvm/graph_attr_types.h"
35 #include "nnvm/graph.h"
36 #include "nnvm/pass.h"
37 
38 namespace mxnet {
39 
53 template<typename ValueType>
54 class Tuple {
55  public:
57  Tuple() = default;
59  inline ~Tuple() {
60  delete [] data_heap_;
61  }
66  inline Tuple(const Tuple<ValueType>& s) {
67  if (s.ndim() == -1) {
68  this->SetDim(-1);
69  } else {
70  this->assign(s.begin(), s.end());
71  }
72  }
77  inline Tuple(std::initializer_list<ValueType> init) {
78  this->assign(init.begin(), init.end());
79  }
84  inline Tuple(std::vector<ValueType> init) { // NOLINT(runtime/explicit)
85  this->assign(init.begin(), init.end());
86  }
92  inline Tuple(Tuple<ValueType>&& src) { // NOLINT(runtime/explicit)
93  this->swap(src);
94  }
101  template<typename RandomAccessIterator>
102  inline Tuple(RandomAccessIterator begin,
103  RandomAccessIterator end) {
104  this->assign(begin, end);
105  }
112  template<typename RandomAccessIterator>
113  inline void assign(RandomAccessIterator begin,
114  RandomAccessIterator end) {
115  this->SetDim(end - begin);
116  CHECK_GE(ndim(), 0);
117  std::copy(begin, end, this->begin());
118  }
123  inline void swap(Tuple<ValueType>& other) { // NOLINT(*)
124  std::swap(ndim_, other.ndim_);
125  std::swap(num_heap_allocated_, other.num_heap_allocated_);
126  std::swap(data_stack_, other.data_stack_);
127  std::swap(data_heap_, other.data_heap_);
128  }
135  if (src.ndim() == -1) {
136  this->SetDim(-1);
137  } else {
138  this->assign(src.begin(), src.end());
139  }
140  return *this;
141  }
148  Tuple<ValueType>(std::move(src)).swap(*this);
149  return *this;
150  }
156  inline Tuple<ValueType> &operator=(std::initializer_list<ValueType> init) {
157  this->assign(init.begin(), init.end());
158  return *this;
159  }
164  inline bool operator==(const Tuple<ValueType> &s) const {
165  if (ndim_ != s.ndim_) return false;
166  if (ndim() == -1) return true;
167  return std::equal(begin(), end(), s.begin());
168  }
173  inline bool operator!=(const Tuple<ValueType> &s) const {
174  return !(*this == s);
175  }
177  inline const ValueType *begin() const {
178  return ndim_ <= kStackCache ? data_stack_ : data_heap_;
179  }
181  inline ValueType *begin() {
182  return ndim_ <= kStackCache ? data_stack_ : data_heap_;
183  }
185  inline const ValueType* end() const {
186  return ndim_ <= kStackCache ? (data_stack_ + ndim_): (data_heap_ + ndim_);
187  }
189  inline ValueType* end() {
190  return ndim_ <= kStackCache ? (data_stack_ + ndim_): (data_heap_ + ndim_);
191  }
193  inline int ndim() const {
194  return ndim_;
195  }
201  inline ValueType& operator[](int i) {
202  // it fixes the false alarm of assuming signed overflow does not occur
203  // when assuming that (X - c) > X is always false [-Werror=strict-overflow]
204  #pragma GCC diagnostic push
205  #pragma GCC diagnostic ignored "-Wstrict-overflow"
206  CHECK(i >= 0 && i < ndim()) << "index = " << i << " must be in range [0, " << ndim() << ")";
207  #pragma GCC diagnostic pop
208  return begin()[i];
209  }
215  inline const ValueType& operator[](int i) const {
216  // it fixes the false alarm of assuming signed overflow does not occur
217  // when assuming that (X - c) > X is always false [-Werror=strict-overflow]
218  #pragma GCC diagnostic push
219  #pragma GCC diagnostic ignored "-Wstrict-overflow"
220  CHECK(i >= 0 && i < ndim()) << "index = " << i << " must be in range [0, " << ndim() << ")";
221  #pragma GCC diagnostic pop
222  return begin()[i];
223  }
228  inline void Save(dmlc::JSONWriter* writer) const {
229  std::vector<ValueType> tmp(begin(), end());
230  writer->Write(tmp);
231  }
236  inline void Load(dmlc::JSONReader* reader) {
237  std::vector<ValueType> tmp;
238  reader->Read(&tmp);
239  this->assign(tmp.begin(), tmp.end());
240  }
247  friend std::ostream &operator<<(std::ostream &os, const Tuple<ValueType> &t) {
248  if (t.ndim() == -1) {
249  // If t is an unknown shape, return string "None".
250  // This is consistent with returning unknown shape in Python and generating
251  // C++ operator APIs by OpWrapperGenerator.py (defaultString) in cpp-package.
252  os << "None";
253  return os;
254  }
255  os << '[';
256  const ValueType* begin = t.begin();
257  const ValueType* end = t.end();
258  for (const ValueType* it = begin; it != end; ++it) {
259  if (it != begin) os << ',';
260  os << *it;
261  }
262  os << ']';
263  return os;
264  }
271  friend std::istream &operator>>(std::istream &is, Tuple<ValueType> &t) {
272  // get (
273  while (true) {
274  char ch = is.peek();
275  if (isdigit(ch) || ch == '-') {
276  ValueType idx;
277  if (is >> idx) {
278  t.assign(&idx, &idx + 1);
279  }
280  return is;
281  }
282  is.get();
283  if (ch == '(' || ch == '[') break;
284  if (!isspace(ch)) {
285  if (ch == 'N') {
286  std::string tmp_val;
287  is >> tmp_val;
288  if (tmp_val == "one") { // is stores "None"
289  t.SetDim(-1);
290  return is;
291  }
292  }
293  is.setstate(std::ios::failbit);
294  return is;
295  }
296  }
297  // Handle empty tuple. A tensor whose shape is an empty tuple
298  // represents a scalar with ndim = 0.
299  while (isspace(is.peek())) {
300  is.get();
301  }
302  if (is.peek() == ')' || is.peek() == ']') {
303  is.get();
304  t.SetDim(0);
305  return is;
306  }
307  // Handle non-empty tuple
308  ValueType idx;
309  std::vector<ValueType> tmp;
310  while (is >> idx) {
311  tmp.push_back(idx);
312  char ch;
313  do {
314  ch = is.get();
315  } while (isspace(ch));
316  if (std::is_integral<ValueType>::value && ch == 'L') {
317  ch = is.get();
318  }
319  if (ch == ',') {
320  while (true) {
321  ch = is.peek();
322  if (isspace(ch)) {
323  is.get(); continue;
324  }
325  if (ch == ')' || ch == ']') {
326  is.get(); break;
327  }
328  break;
329  }
330  if (ch == ')' || ch == ']') break;
331  } else if (ch == ')' || ch == ']') {
332  break;
333  } else {
334  is.setstate(std::ios::failbit);
335  return is;
336  }
337  }
338  t.assign(tmp.begin(), tmp.end());
339  return is;
340  }
347  template<typename DType = ValueType, typename TStream>
348  inline void Save(TStream *strm) const;
356  template<typename DType = ValueType, typename TStream>
357  inline bool Load(TStream *strm);
358 
359  protected:
360  // stack cache size
361  static const int kStackCache = 4;
363  int ndim_{0};
369  ValueType* data_heap_{nullptr};
370  // internal function to change the dimension
371  inline void SetDim(int ndim) {
372  CHECK_GE(ndim, -1) << "ndim cannot be less than -1, received " << ndim;
373  if (ndim > kStackCache &&
374  ndim > num_heap_allocated_) {
375  delete [] data_heap_;
376  data_heap_ = new ValueType[ndim];
378  } else if (ndim <= 0 && data_heap_ != nullptr) {
379  delete [] data_heap_;
380  data_heap_ = nullptr;
382  }
383  ndim_ = ndim;
384  }
385 };
386 
387 
389 inline bool ndim_is_known(const int ndim) {
390  CHECK_GE(ndim, -1) << "shape ndim must be >= -1, while received " << ndim;
391  return ndim != -1;
392 }
393 
395 inline bool dim_size_is_known(const dim_t dim_size) {
396  CHECK_GE(dim_size, -1) << "shape dim size must be >= -1, while received " << dim_size;
397  return dim_size != -1;
398 }
399 
413 class TShape : public Tuple<dim_t> {
414  public:
416  TShape() {
417  this->SetDim(-1);
418  }
424  inline TShape(const int ndim, const dim_t value) { // NOLINT(*)
425  this->SetDim(ndim);
426  if (ndim > 0) {
427  std::fill_n(begin(), ndim, value);
428  }
429  }
434  inline TShape(const Tuple<dim_t>& s) { // NOLINT(*)
435  if (s.ndim() == -1) {
436  this->SetDim(-1);
437  } else {
438  this->assign(s.begin(), s.end());
439  }
440  }
445  inline TShape(std::initializer_list<dim_t> init) {
446  this->assign(init.begin(), init.end());
447  }
452  inline TShape(Tuple<dim_t>&& s) { // NOLINT(*)
453  this->swap(s);
454  }
463  template<typename RandomAccessIterator,
464  typename std::enable_if<
465  std::is_same<typename std::iterator_traits<RandomAccessIterator>::iterator_category,
466  std::random_access_iterator_tag>::value, int>::type = 0>
467  inline TShape(RandomAccessIterator begin,
468  RandomAccessIterator end) {
469  this->assign(begin, end);
470  }
476  inline TShape& operator=(const Tuple<dim_t>& src) {
477  if (src.ndim() == -1) {
478  this->SetDim(-1);
479  } else {
480  this->assign(src.begin(), src.end());
481  }
482  return *this;
483  }
489  inline TShape& operator=(Tuple<dim_t>&& src) { // NOLINT(*)
490  TShape(std::move(src)).swap(*this); // NOLINT(*)
491  return *this;
492  }
494  inline size_t Size() const {
495  CHECK(ndim_is_known(this->ndim())) << "Shape is unknown.";
496  dim_t size = 1;
497  const dim_t* start = begin(), *fin = end();
498  for (const dim_t* it = start; it != fin; ++it) {
499  CHECK(dim_size_is_known(*it)) << "Shape dim size cannot be a negative value " << *it;
500  size *= *it;
501  }
502  return size;
503  }
509  inline size_t ProdShape(int dimstart, int dimend) const {
510  CHECK(ndim_is_known(this->ndim())) << "Shape is unknown.";
511  CHECK_GE(dimstart, 0) << "dimstart must be >= 0, while received " << dimstart;
512  CHECK_LE(dimend, this->ndim()) << "dimend must be <= " << this->ndim()
513  << ", while received " << dimend;
514  dim_t num = 1;
515  const dim_t *d = this->data();
516  for (int i = dimstart; i < dimend; ++i) {
517  CHECK(dim_size_is_known(d[i])) << "Shape dim size must be known, while received " << d[i];
518  num *= d[i];
519  }
520  return num;
521  }
523  inline const dim_t *data() const {
524  return begin();
525  }
527  inline dim_t *data() {
528  return begin();
529  }
530 #ifdef MSHADOW_XINLINE
531  template<int dim>
532  inline TShape(const mshadow::Shape<dim> &s) {// NOLINT(*)
533  this->assign(s.shape_, s.shape_ + dim);
534  }
535 
536  template<int dim>
537  inline TShape(mshadow::Shape<dim> &&s) {// NOLINT(*)
538  this->assign(s.shape_, s.shape_ + dim);
539  }
546  template<int dim>
547  inline TShape &operator=(const mshadow::Shape<dim> &shape) {
548  this->assign(shape.shape_, shape.shape_ + dim);
549  return *this;
550  }
556  template<int dim>
557  inline mshadow::Shape<dim> get() const {
558  CHECK_EQ(dim, ndim())
559  << "dimension do not match target dimension " << dim << " vs " << ndim();
560  const dim_t *d = this->data();
562  for (int i = 0; i < dim; ++i) {
563  s[i] = d[i];
564  }
565  return s;
566  }
571  inline mshadow::Shape<2> FlatTo2D(void) const {
573  CHECK(ndim_is_known(ndim())) << "shape must have a valid ndim";
574  if (ndim() == 0) return mshadow::Shape2(1, 1);
575  const dim_t *d = this->data();
576  s.shape_[1] = d[ndim() - 1];
577  dim_t ymax = 1;
578  for (int i = 1; i < ndim(); ++i) {
579  ymax *= d[i - 1];
580  }
581  s.shape_[0] = ymax;
582  return s;
583  }
590  inline mshadow::Shape<3> FlatTo3D(int axis_begin, int axis_end) const {
591  CHECK(axis_end >= axis_begin);
593  CHECK(ndim_is_known(ndim())) << "shape must have a valid ndim";
594  if (ndim() == 0) return mshadow::Shape3(1, 1, 1);
595  const dim_t *d = this->data();
596  s.shape_[0] = 1;
597  s.shape_[1] = 1;
598  s.shape_[2] = 1;
599 
600  for (int i = 0; i < axis_begin; ++i) {
601  s.shape_[0] *= d[i];
602  }
603  for (int i = axis_begin; i <= axis_end; ++i) {
604  s.shape_[1] *= d[i];
605  }
606  for (int i = axis_end + 1; i < ndim(); ++i) {
607  s.shape_[2] *= d[i];
608  }
609  return s;
610  }
616  inline mshadow::Shape<3> FlatTo3D(int axis) const {
617  return FlatTo3D(axis, axis);
618  }
619  inline bool operator==(const TShape &s) const {
620  if (ndim() != s.ndim()) return false;
621  return std::equal(begin(), end(), s.begin());
622  }
623  inline bool operator!=(const TShape &s) const {
624  return !(*this == s);
625  }
631  template<int dim>
632  inline bool operator==(const mshadow::Shape<dim> &s) const {
633  if (ndim_ != dim) return false;
634  const dim_t *d = dim <= kStackCache ? data_stack_ : data_heap_;
635  for (size_t i = 0; i < dim; ++i) {
636  if (d[i] != s.shape_[i]) return false;
637  }
638  return true;
639  }
645  template<int dim>
646  inline bool operator!=(const mshadow::Shape<dim> &s) const {
647  return !(*this == s);
648  }
649 #endif
650 };
651 
653 inline bool ndim_is_known(const TShape& x) {
654  return ndim_is_known(x.ndim());
655 }
656 
658 inline bool dim_size_is_known(const TShape& x, const int idx) {
659  CHECK(idx >= 0 && idx < x.ndim())
660  << "idx = " << idx << " exceeds shape dimension range [0, " << x.ndim() << ")";
661  return dim_size_is_known(x[idx]);
662 }
663 
666 inline bool shape_is_known(const TShape& x) {
667  if (!ndim_is_known(x)) return false;
668  for (int i = 0; i < x.ndim(); ++i) {
669  if (!dim_size_is_known(x, i)) return false;
670  }
671  return true;
672 }
673 
674 inline bool shape_is_known(const std::vector<TShape>& shapes) {
675  for (const TShape& shape : shapes) {
676  if (!shape_is_known(shape)) return false;
677  }
678  return true;
679 }
680 
682 template<typename SrcIter, typename DstIter>
683 inline DstIter ShapeTypeCast(const SrcIter begin,
684  const SrcIter end,
685  DstIter dst_begin) {
686  typedef typename std::iterator_traits<SrcIter>::value_type SrcDType;
687  typedef typename std::iterator_traits<DstIter>::value_type DstDType;
688  auto cast = [](const SrcDType& dim) { return static_cast<DstDType>(dim); };
689  return std::transform(begin, end, dst_begin, cast);
690 }
691 
693 template<typename SrcIter>
694 inline TShape ShapeTypeCast(const SrcIter begin, const SrcIter end) {
695  size_t ndim = std::distance(begin, end);
696  TShape res(ndim, -1);
697  ShapeTypeCast(begin, end, res.begin());
698  return res;
699 }
700 
702 template<typename ValueType>
703 template<typename DType, typename TStream>
704 inline void Tuple<ValueType>::Save(TStream *strm) const {
705  strm->Write(&ndim_, sizeof(ndim_));
706  if (typeid(DType) == typeid(ValueType)) {
707  strm->Write(begin(), sizeof(ValueType) * ndim_);
708  } else {
709  std::vector<DType> buffer(ndim_);
710  ShapeTypeCast(begin(), end(), buffer.data());
711  strm->Write(buffer.data(), sizeof(DType) * ndim_);
712  }
713 }
714 
716 template<typename ValueType>
717 template<typename DType, typename TStream>
718 inline bool Tuple<ValueType>::Load(TStream *strm) {
719  if (strm->Read(&ndim_, sizeof(ndim_)) != sizeof(ndim_)) return false;
720  this->SetDim(ndim_);
721  size_t nread = sizeof(DType) * ndim_;
722  if (typeid(DType) == typeid(ValueType)) {
723  if (strm->Read(begin(), nread) != nread) return false;
724  } else {
725  std::vector<DType> buffer(ndim_);
726  if (strm->Read(buffer.data(), nread) != nread) return false;
727  ShapeTypeCast(buffer.begin(), buffer.end(), begin());
728  }
729  return true;
730 }
731 
732 } // namespace mxnet
733 
734 namespace std {
736 template<typename T>
737 struct hash<mxnet::Tuple<T> > {
739  size_t operator()(const mxnet::Tuple<T>& val) const {
740  std::hash<int> hash_int;
741  size_t res = hash_int(val.ndim());
742  for (int i = 0; i < val.ndim(); ++i) {
743  res = dmlc::HashCombine(res, val[i]);
744  }
745  return res;
746  }
747 };
748 
750 template<>
751 struct hash<mxnet::TShape> {
753  size_t operator()(const mxnet::TShape& val) const {
754  std::hash<int> hash_int;
755  size_t res = hash_int(val.ndim());
756  for (int i = 0; i < val.ndim(); ++i) {
757  res = dmlc::HashCombine(res, val[i]);
758  }
759  return res;
760  }
761 };
762 } // namespace std
763 
764 namespace dmlc {
766 DMLC_DECLARE_TYPE_NAME(optional<mxnet::TShape>, "Shape or None");
767 DMLC_DECLARE_TYPE_NAME(optional<mxnet::Tuple<int>>, "Shape or None");
768 // avoid low version of MSVC
769 #if !(defined(_MSC_VER) && _MSC_VER < 1900)
770 template<typename T>
772  static inline std::string value() {
773  return "tuple of <" + type_name<T>() + ">";
774  }
775 };
776 #endif
777 } // namespace dmlc
778 
779 namespace mxnet {
793 using ShapeVector = std::vector<mxnet::TShape>;
794 
806 
807 } // namespace mxnet
808 
809 #endif // MXNET_TUPLE_H_
#define DMLC_DECLARE_TYPE_NAME(Type, Name)
macro to quickly declare traits information
Definition: type_traits.h:133
helper class to construct a string that represents type name
Definition: type_traits.h:86
Tuple< ValueType > & operator=(const Tuple< ValueType > &src)
assignment from another tuple.
Definition: tuple.h:134
bool operator==(const Tuple< ValueType > &s) const
Definition: tuple.h:164
size_t operator()(const mxnet::TShape &val) const
hash a TShape into unsigned int
Definition: tuple.h:753
Tuple< ValueType > & operator=(Tuple< ValueType > &&src)
assignment from rvalue of another tuple.
Definition: tuple.h:147
dim_t * data()
Definition: tuple.h:527
TShape(const Tuple< dim_t > &s)
copy constructor of TShape
Definition: tuple.h:434
ValueType data_stack_[kStackCache]
in stack space used to store shape when it is small
Definition: tuple.h:367
namespace of mxnet
Definition: base.h:89
TShape & operator=(Tuple< dim_t > &&src)
move assignment function from tshape
Definition: tuple.h:489
Tuple(std::initializer_list< ValueType > init)
constructor from initializer list
Definition: tuple.h:77
size_t operator()(const mxnet::Tuple< T > &val) const
hash a Tuple into unsigned int
Definition: tuple.h:739
TShape()
default constructor
Definition: tuple.h:416
Definition: optional.h:241
DstIter ShapeTypeCast(const SrcIter begin, const SrcIter end, DstIter dst_begin)
helper function to cast type of container elements
Definition: tuple.h:683
Tuple(Tuple< ValueType > &&src)
move constructor from Tuple
Definition: tuple.h:92
void Load(dmlc::JSONReader *reader)
Load Tuple from JSON.
Definition: tuple.h:236
const dim_t * data() const
Definition: tuple.h:523
void assign(RandomAccessIterator begin, RandomAccessIterator end)
Assign content to tuple from iterator.
Definition: tuple.h:113
ValueType * end()
Definition: tuple.h:189
TShape(RandomAccessIterator begin, RandomAccessIterator end)
construct the Tuple from content of iterator. This function is enforced with template arguments of ra...
Definition: tuple.h:467
Data structures that can appear in graph attributes.
ValueType & operator[](int i)
get corresponding index
Definition: tuple.h:201
const ValueType & operator[](int i) const
get corresponding index
Definition: tuple.h:215
size_t HashCombine(size_t key, const T &value)
hash an object and combines the key with previous keys
Definition: common.h:37
std::vector< mxnet::TShape > ShapeVector
The result holder of shape of each NodeEntry in the graph.
Definition: tuple.h:793
size_t Size() const
Definition: tuple.h:494
Tuple(const Tuple< ValueType > &s)
copy constructor from another tuple
Definition: tuple.h:66
Lightweight JSON Reader to read any STL compositions and structs. The user need to know the schema of...
Definition: json.h:44
bool isspace(char c)
Inline implementation of isspace(). Tests whether the given character is a whitespace letter...
Definition: strtonum.h:26
~Tuple()
destructor
Definition: tuple.h:59
Tuple(std::vector< ValueType > init)
constructor from vector
Definition: tuple.h:84
namespace for dmlc
Definition: array_view.h:12
Tuple(RandomAccessIterator begin, RandomAccessIterator end)
construct the Tuple from content of iterator
Definition: tuple.h:102
void Write(const ValueType &value)
Write value to json.
bool dim_size_is_known(const dim_t dim_size)
Definition: tuple.h:395
Tuple()=default
default constructor
int num_heap_allocated_
number of cells allocated in data_heap_
Definition: tuple.h:365
static std::string value()
Definition: tuple.h:772
static const int kStackCache
Definition: tuple.h:361
const ValueType * end() const
Definition: tuple.h:185
void SetDim(int ndim)
Definition: tuple.h:371
std::function< bool(const NodeAttrs &attrs, std::vector< AttrType > *in_attrs, std::vector< AttrType > *out_attrs)> FInferNodeEntryAttr
Inference function of certain type.
Definition: op_attr_types.h:95
void swap(Tuple< ValueType > &other)
Swap current object with other.
Definition: tuple.h:123
index_t shape_[kDimension]
storing the dimension information
Definition: tensor.h:57
Pass that can be applied to a graph.
TShape(Tuple< dim_t > &&s)
move constructor.
Definition: tuple.h:452
void Read(ValueType *out_value)
Read next ValueType.
MSHADOW_XINLINE Shape< 2 > Shape2(index_t s0, index_t s1)
construct a two dimension shape, stride will equal s0
Definition: tensor.h:198
A dynamic sized array data structure that is optimized for storing small number of elements with same...
Definition: tuple.h:54
TShape(std::initializer_list< dim_t > init)
constructor from initializer list
Definition: tuple.h:445
Configuation of nnvm as well as basic data structure.
const ValueType * begin() const
Definition: tuple.h:177
int ndim_
number of dimension of the tuple
Definition: tuple.h:363
A Shape class that is used to represent shape of each tensor.
Definition: tuple.h:413
nnvm::FInferNodeEntryAttr< mxnet::TShape > FInferShape
Shape inference function. Update the shapes given the input shape information. TShape.ndim() == -1 means the shape is still unknown.
Definition: tuple.h:805
TShape & operator=(const Tuple< dim_t > &src)
assignment function from tshape
Definition: tuple.h:476
TShape(const int ndim, const dim_t value)
Definition: tuple.h:424
size_t ProdShape(int dimstart, int dimend) const
Definition: tuple.h:509
int ndim() const
Definition: tuple.h:193
Tuple< ValueType > & operator=(std::initializer_list< ValueType > init)
assignment from initializer list
Definition: tuple.h:156
bool operator!=(const Tuple< ValueType > &s) const
Definition: tuple.h:173
bool shape_is_known(const TShape &x)
Definition: tuple.h:666
bool ndim_is_known(const int ndim)
Definition: tuple.h:389
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:209
ValueType * data_heap_
space to store shape when dimension is big
Definition: tuple.h:369
ValueType * begin()
Definition: tuple.h:181
friend std::istream & operator>>(std::istream &is, Tuple< ValueType > &t)
read tuple from the istream
Definition: tuple.h:271
int64_t dim_t
data type to store dim size
Definition: c_api.h:62
bool isdigit(char c)
Inline implementation of isdigit(). Tests whether the given character is a decimal digit...
Definition: strtonum.h:46
Data structures that can appear in operator attributes.
Lightweight json to write any STL compositions.
Definition: json.h:189
void Save(dmlc::JSONWriter *writer) const
Save Tuple to JSON.
Definition: tuple.h:228