DASH  0.3.0
Dimensional.h
1 #ifndef DASH__DIMENSIONAL_H_
2 #define DASH__DIMENSIONAL_H_
3 
4 #include <dash/Types.h>
5 #include <dash/Distribution.h>
6 #include <dash/Team.h>
7 #include <dash/Exception.h>
8 
9 #include <array>
10 #include <sstream>
11 #include <utility>
50 namespace dash {
51 
55 template <typename DimensionalType>
56 constexpr dim_t ndim(const DimensionalType & d) {
57  return d.ndim();
58 }
59 
63 template <typename DimensionalType>
64 constexpr dim_t rank(const DimensionalType & d) {
65  return d.rank();
66 }
67 
71 template <dim_t Dim, typename DimensionalType>
72 constexpr typename DimensionalType::extent_type
73 extent(const DimensionalType & d) {
74  return d.extent(Dim);
75 }
76 
80 template <typename DimensionalType>
81 constexpr typename DimensionalType::extent_type
82 extent(dim_t dim, const DimensionalType & d) {
83  return d.extent(dim);
84 }
85 
100 template <typename ElementType, dim_t NumDimensions>
102 {
103  template <typename E_, dim_t ND_>
104  friend std::ostream & operator<<(
105  std::ostream & os,
106  const Dimensional<E_, ND_> & dimensional);
107 
108 private:
110 
111 protected:
112  std::array<ElementType, NumDimensions> _values;
113 
114 public:
118  template <typename ... Values>
119  constexpr Dimensional(
120  ElementType & value, Values ... values)
121  : _values {{ value, (ElementType)values... }} {
122  static_assert(
123  sizeof...(values) == NumDimensions-1,
124  "Invalid number of arguments");
125  }
126 
130  constexpr Dimensional(std::array<ElementType, NumDimensions> values)
131  : _values(std::move(values))
132  {
133  }
134 
135  constexpr Dimensional(const self_t & other) = default;
136  self_t & operator=(const self_t & other) = default;
137 
142  constexpr const std::array<ElementType, NumDimensions> & values() const {
143  return _values;
144  }
145 
152  ElementType dim(dim_t dimension) const {
153  DASH_ASSERT_LT(
154  dimension, NumDimensions,
155  "Dimension for Dimensional::extent() must be lower than " <<
156  NumDimensions);
157  return _values[dimension];
158  }
159 
167  constexpr ElementType operator[](size_t dimension) const {
168  return _values[dimension];
169  }
170 
179  ElementType & operator[](size_t dimension) {
180  return _values[dimension];
181  }
182 
186  constexpr bool operator==(const self_t & other) const {
187  return this == &other || _values == other._values;
188  }
189 
193  constexpr bool operator!=(const self_t & other) const {
194  return !(*this == other);
195  }
196 
200  constexpr dim_t rank() const {
201  return NumDimensions;
202  }
203 
207  constexpr static dim_t ndim() {
208  return NumDimensions;
209  }
210 
211 protected:
214  Dimensional() = default;
215 };
216 
221 template <dim_t NumDimensions>
222 class DistributionSpec : public Dimensional<Distribution, NumDimensions>
223 {
224  template<dim_t NumDimensions_>
225  friend
226  std::ostream & operator<<(
227  std::ostream & os,
228  const DistributionSpec<NumDimensions_> & distspec);
229 
230 private:
232 
233 public:
239  {
240  this->_values[0] = BLOCKED;
241  for (dim_t i = 1; i < NumDimensions; ++i) {
242  this->_values[i] = NONE;
243  }
244  }
245 
257  template <typename... Values>
259  : Dimensional<Distribution, NumDimensions>::Dimensional(value, values...)
260  {
261  for (dim_t i = 1; i < NumDimensions; ++i) {
262  if (this->_values[i].type == dash::internal::DIST_TILE) {
263  _is_tiled = true;
264  break;
265  }
266  }
267  }
268 
280  DistributionSpec(const std::array<Distribution, NumDimensions>& values)
281  : Dimensional<Distribution, NumDimensions>::Dimensional(values)
282  {
283  DASH_LOG_TRACE_VAR("DistributionSpec(distribution[])", values);
284  for (dim_t i = 1; i < NumDimensions; ++i) {
285  if (this->_values[i].type == dash::internal::DIST_TILE) {
286  _is_tiled = true;
287  break;
288  }
289  }
290  }
291 
296  unsigned int dimension) const {
297  return (_is_tiled &&
298  this->_values[dimension].type == dash::internal::DIST_TILE);
299  }
300 
304  bool is_tiled() const {
305  return _is_tiled;
306  }
307 
308 private:
309  bool _is_tiled{false};
310 };
311 
312 template<dim_t NumDimensions>
313 std::ostream & operator<<(
314  std::ostream & os,
315  const DistributionSpec<NumDimensions> & distspec)
316 {
317  os << "dash::DistributionSpec<" << NumDimensions << ">(";
318  for (dim_t d = 0; d < NumDimensions; d++) {
319  if (distspec._values[d].type == dash::internal::DIST_TILE) {
320  os << "TILE(" << distspec._values[d].blocksz << ")";
321  }
322  else if (distspec._values[d].type == dash::internal::DIST_BLOCKCYCLIC) {
323  os << "BLOCKCYCLIC(" << distspec._values[d].blocksz << ")";
324  }
325  else if (distspec._values[d].type == dash::internal::DIST_CYCLIC) {
326  os << "CYCLIC";
327  }
328  else if (distspec._values[d].type == dash::internal::DIST_BLOCKED) {
329  os << "BLOCKED";
330  }
331  else if (distspec._values[d].type == dash::internal::DIST_NONE) {
332  os << "NONE";
333  }
334  if (d < NumDimensions-1) {
335  os << ", ";
336  }
337  }
338  os << ")";
339  return os;
340 }
341 
345 template<typename IndexType = int>
346 struct ViewPair {
347  typedef typename std::make_unsigned<IndexType>::type SizeType;
349  IndexType offset;
351  SizeType extent;
352 };
353 
358 template<
359  dim_t NumDimensions,
360  typename IndexType = dash::default_index_t>
361 struct ViewRegion {
362  // Region origin coordinates.
363  std::array<IndexType, NumDimensions> begin;
364  // Region end coordinates.
365  std::array<IndexType, NumDimensions> end;
366 };
367 
368 template<
369  typename IndexType = dash::default_index_t>
370 struct ViewRange {
371  // Range begin offset.
372  IndexType begin;
373  // Range end offset.
374  IndexType end;
375 };
376 
377 template<typename IndexType>
378 std::ostream & operator<<(
379  std::ostream & os,
380  const ViewRange<IndexType> & viewrange) {
381  os << "dash::ViewRange<" << typeid(IndexType).name() << ">("
382  << "begin:" << viewrange.begin << " "
383  << "end:" << viewrange.end << ")";
384  return os;
385 }
386 
390 template<typename IndexType>
391 static bool operator==(
392  const ViewPair<IndexType> & lhs,
393  const ViewPair<IndexType> & rhs) {
394  if (&lhs == &rhs) {
395  return true;
396  }
397  return (
398  lhs.offset == rhs.offset &&
399  lhs.extent == rhs.extent);
400 }
401 
405 template<typename IndexType>
406 static bool operator!=(
407  const ViewPair<IndexType> & lhs,
408  const ViewPair<IndexType> & rhs) {
409  return !(lhs == rhs);
410 }
411 
412 template<typename IndexType>
413 std::ostream & operator<<(
414  std::ostream & os,
415  const ViewPair<IndexType> & viewpair) {
416  os << "dash::ViewPair<" << typeid(IndexType).name() << ">("
417  << "offset:" << viewpair.offset << " "
418  << "extent:" << viewpair.extent << ")";
419  return os;
420 }
421 
427 template<
428  dim_t NumDimensions,
429  typename IndexType = dash::default_index_t >
430 class ViewSpec
431 {
432 private:
434  self_t;
435  typedef typename std::make_unsigned<IndexType>::type
436  SizeType;
437  typedef ViewPair<IndexType>
438  ViewPair_t;
439 
440 public:
443 
444  using index_type = IndexType;
445  using size_type = SizeType;
446 
447 public:
448  template<dim_t NDim_, typename IndexType_>
449  friend std::ostream& operator<<(
450  std::ostream & os,
451  const ViewSpec<NDim_, IndexType_> & viewspec);
452 
453 private:
454  SizeType _size = 0;
455  SizeType _rank = NumDimensions;
456  std::array<SizeType, NumDimensions> _extents = {{ }};
457  std::array<IndexType, NumDimensions> _offsets = {{ }};
458 
459 public:
465  : _size(0),
466  _rank(NumDimensions)
467  {
468  for (dim_t i = 0; i < NumDimensions; i++) {
469  _extents[i] = 0;
470  _offsets[i] = 0;
471  }
472  }
473 
479  const std::array<SizeType, NumDimensions> & extents)
480  : _size(1),
481  _rank(NumDimensions),
482  _extents(extents)
483  {
484  for (auto i = 0; i < NumDimensions; ++i) {
485  _offsets[i] = 0;
486  _size *= _extents[i];
487  }
488  }
489 
494  const std::array<IndexType, NumDimensions> & offsets,
495  const std::array<SizeType, NumDimensions> & extents)
496  : _size(1),
497  _rank(NumDimensions),
498  _extents(extents),
499  _offsets(offsets)
500  {
501  for (auto i = 0; i < NumDimensions; ++i) {
502  _size *= _extents[i];
503  }
504  }
505 
509  constexpr ViewSpec(const self_t & other) = default;
510 
514  constexpr ViewSpec(self_t && other) = default;
515 
519  self_t & operator=(const self_t & other) = default;
520 
524  self_t & operator=(self_t && other) = default;
525 
526  static constexpr auto ndim() { return NumDimensions; }
527 
531  constexpr bool operator==(const self_t & other) const
532  {
533  return (_extents == other._extents &&
534  _offsets == other._offsets &&
535  _rank == other._rank);
536  }
537 
541  constexpr bool operator!=(const self_t & other) const
542  {
543  return !(*this == other);
544  }
545 
549  template<typename ... Args>
550  void resize(SizeType arg, Args... args)
551  {
552  static_assert(
553  sizeof...(Args) == (NumDimensions-1),
554  "Invalid number of arguments");
555  std::array<SizeType, NumDimensions> extents =
556  { arg, (SizeType)(args)... };
557  resize(extents);
558  }
559 
563  void resize(const std::array<ViewPair_t, NumDimensions> & view)
564  {
565  _rank = NumDimensions;
566  for (dim_t i = 0; i < NumDimensions; i++) {
567  _offsets[i] = view[i].offset;
568  _extents[i] = view[i].extent;
569  }
570  update_size();
571  }
572 
576  template<typename SizeType_>
577  void resize(const std::array<SizeType_, NumDimensions> & extents)
578  {
579  _rank = NumDimensions;
580  for (dim_t i = 0; i < NumDimensions; i++) {
581  _extents[i] = extents[i];
582  }
583  update_size();
584  }
585 
591  dim_t dimension,
592  IndexType offset,
593  SizeType extent)
594  {
595  _offsets[dimension] = offset;
596  _extents[dimension] = extent;
597  update_size();
598  }
599 
626  ViewSpec<NumDimensions-1, IndexType>
627  slice(dim_t dimension)
628  {
629  std::array<SizeType, NumDimensions-1> slice_extents;
630  std::array<IndexType, NumDimensions-1> slice_offsets;
631  for (dim_t d = dimension; d < _rank-1; d++) {
632  slice_offsets[d] = _offsets[d+1];
633  slice_extents[d] = _extents[d+1];
634  }
635  return ViewSpec<NumDimensions-1, IndexType>(slice_offsets,
636  slice_extents);
637  }
638 
643  void set_rank(dim_t dimensions)
644  {
645  DASH_ASSERT_LT(
646  dimensions, NumDimensions+1,
647  "Maximum dimension for ViewSpec::set_rank is " << NumDimensions);
648  _rank = dimensions;
649  update_size();
650  }
651 
652  constexpr SizeType size() const
653  {
654  return _size;
655  }
656 
657  constexpr SizeType size(dim_t dimension) const
658  {
659  return _extents[dimension];
660  }
661 
662  constexpr const std::array<SizeType, NumDimensions> & extents() const
663  {
664  return _extents;
665  }
666 
667  constexpr SizeType extent(dim_t dim) const {
668  return _extents[dim];
669  }
670 
671  constexpr const std::array<IndexType, NumDimensions> & offsets() const
672  {
673  return _offsets;
674  }
675 
676  constexpr range_type range(dim_t dim) const
677  {
678  return range_type {
679  static_cast<IndexType>(_offsets[dim]),
680  static_cast<IndexType>(_offsets[dim] + _extents[dim]) };
681  }
682 
683  constexpr IndexType offset(dim_t dim) const
684  {
685  return _offsets[dim];
686  }
687 
688  region_type region() const
689  {
690  region_type reg;
691  reg.begin = _offsets;
692  reg.end = _offsets;
693  for (dim_t d = 0; d < NumDimensions; ++d) {
694  reg.end[d] += static_cast<IndexType>(_extents[d]);
695  }
696  return reg;
697  }
698 
699 private:
700  void update_size()
701  {
702  _size = 1;
703  for (SizeType d = 0; d < NumDimensions; ++d) {
704  _size *= _extents[d];
705  }
706  }
707 };
708 
709 template<typename ElementType, dim_t NumDimensions>
710 std::ostream & operator<<(
711  std::ostream & os,
712  const Dimensional<ElementType, NumDimensions> & dimensional)
713 {
714  std::ostringstream ss;
715  ss << "dash::Dimensional<"
716  << typeid(ElementType).name() << ","
717  << NumDimensions << ">(";
718  for (auto d = 0; d < NumDimensions; ++d) {
719  ss << dimensional._values[d] << ((d < NumDimensions-1) ? "," : "");
720  }
721  ss << ")";
722  return operator<<(os, ss.str());
723 }
724 
725 template<dim_t NumDimensions, typename IndexType>
726 std::ostream& operator<<(
727  std::ostream & os,
728  const ViewSpec<NumDimensions, IndexType> & viewspec)
729 {
730  std::ostringstream ss;
731  ss << "dash::ViewSpec<" << NumDimensions << ">"
732  << "(offsets:";
733  for (auto d = 0; d < NumDimensions; ++d) {
734  if (d > 0) {
735  ss << ",";
736  }
737  ss << viewspec.offsets()[d];
738  }
739  ss << " extents:";
740  for (auto d = 0; d < NumDimensions; ++d) {
741  if (d > 0) {
742  ss << ",";
743  }
744  ss << viewspec.extents()[d];
745  }
746  ss << ")";
747  return operator<<(os, ss.str());
748 }
749 
750 } // namespace dash
751 
752 #endif // DASH__DIMENSIONAL_H_
void resize_dim(dim_t dimension, IndexType offset, SizeType extent)
Change the view specification&#39;s extent and offset in the given dimension.
Definition: Dimensional.h:590
void resize(const std::array< ViewPair_t, NumDimensions > &view)
Change the view specification&#39;s extent and offset in every dimension.
Definition: Dimensional.h:563
constexpr dim_t rank(const DimensionalType &d)
Definition: Dimensional.h:64
ViewSpec()
Default constructor, initialize with extent and offset 0 in all dimensions.
Definition: Dimensional.h:464
IndexType offset
Offset in dimension.
Definition: Dimensional.h:349
constexpr const std::array< ElementType, NumDimensions > & values() const
Return value with all dimensions as array of NumDimensions elements.
Definition: Dimensional.h:142
Representation of a ViewPair as region specified by origin and end coordinates.
Definition: Dimensional.h:361
DistributionSpec()
Default constructor, initializes default blocked distribution (BLOCKED, NONE*).
Definition: Dimensional.h:238
size_t size()
Return the number of units in the global team.
constexpr auto end(RangeType &&range) -> decltype(std::forward< RangeType >(range).end())
Definition: Range.h:98
This class is a simple memory pool which holds allocates elements of size ValueType.
Definition: AllOf.h:8
constexpr dim_t rank() const
The number of dimensions of the value.
Definition: Dimensional.h:200
ElementType & operator[](size_t dimension)
Subscript assignment operator, access to value in dimension given by index.
Definition: Dimensional.h:179
static constexpr dim_t ndim()
The number of dimensions of the value.
Definition: Dimensional.h:207
DistributionSpec(const std::array< Distribution, NumDimensions > &values)
Constructor, initializes distribution with given distribution types for every dimension.
Definition: Dimensional.h:280
bool is_tiled() const
Whether the distribution is tiled in any dimension.
Definition: Dimensional.h:304
Specifies view parameters for implementing submat, rows and cols.
Definition: Dimensional.h:430
constexpr auto begin(RangeType &&range) -> decltype(std::forward< RangeType >(range).begin())
Definition: Range.h:89
int dim_t
Scalar type for a dimension value, with 0 indicating the first dimension.
Definition: Types.h:39
bool is_tiled_in_dimension(unsigned int dimension) const
Whether the distribution in the given dimension is tiled.
Definition: Dimensional.h:295
constexpr Dimensional(std::array< ElementType, NumDimensions > values)
Constructor, expects array containing values for every dimension.
Definition: Dimensional.h:130
SizeType extent
Extent in dimension.
Definition: Dimensional.h:351
constexpr bool operator!=(const self_t &other) const
Equality comparison operator.
Definition: Dimensional.h:193
ViewSpec(const std::array< IndexType, NumDimensions > &offsets, const std::array< SizeType, NumDimensions > &extents)
Constructor, initialize with given extents and offsets.
Definition: Dimensional.h:493
ViewSpec(const std::array< SizeType, NumDimensions > &extents)
Constructor, initialize with given extents and offset 0 in all dimensions.
Definition: Dimensional.h:478
internal::default_signed_index default_index_t
Signed integer type used as default for index values.
Definition: Types.h:59
void resize(SizeType arg, Args... args)
Change the view specification&#39;s extent in every dimension.
Definition: Dimensional.h:550
ElementType dim(dim_t dimension) const
The value in the given dimension.
Definition: Dimensional.h:152
Base class for dimensional attributes, stores an n-dimensional value with identical type all dimensio...
Definition: Dimensional.h:101
constexpr dim_t ndim(const DimensionalType &d)
Definition: Dimensional.h:56
Specifies how a Pattern distributes elements to units in a specific dimension.
Definition: Distribution.h:24
constexpr ElementType operator[](size_t dimension) const
Subscript operator, access to value in dimension given by index.
Definition: Dimensional.h:167
ViewSpec< NumDimensions-1, IndexType > slice(dim_t dimension)
Slice the view in the specified dimension at the given offset.
Definition: Dimensional.h:627
void set_rank(dim_t dimensions)
Set rank of the view spec to a dimensionality between 1 and NumDimensions.
Definition: Dimensional.h:643
constexpr bool operator==(const self_t &other) const
Equality comparison operator.
Definition: Dimensional.h:186
DistributionSpec(Distribution value, Values... values)
Constructor, initializes distribution with given distribution types for every dimension.
Definition: Dimensional.h:258
void resize(const std::array< SizeType_, NumDimensions > &extents)
Change the view specification&#39;s extent in every dimension.
Definition: Dimensional.h:577
constexpr bool operator!=(const self_t &other) const
Equality comparison operator.
Definition: Dimensional.h:541
constexpr Dimensional(ElementType &value, Values ... values)
Constructor, expects one value for every dimension.
Definition: Dimensional.h:119
Offset and extent in a single dimension.
Definition: Dimensional.h:346
constexpr DimensionalType::extent_type extent(const DimensionalType &d)
Definition: Dimensional.h:73
see https://en.cppreference.com/w/cpp/feature_test for recommended feature tests
Definition: cstddef.h:8
constexpr bool operator==(const self_t &other) const
Equality comparison operator.
Definition: Dimensional.h:531
DistributionSpec describes distribution patterns of all dimensions,.
Definition: Dimensional.h:222