ALP User Documentation  0.8.preview
Algebraic Programming User Documentation
regular.hpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2021 Huawei Technologies Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
29 #ifndef _H_GRB_ITERATOR_REGULAR
30 #define _H_GRB_ITERATOR_REGULAR
31 
32 #include <utility>
33 #include <iterator>
34 #include <functional>
35 
36 #include <assert.h>
37 
38 
39 namespace grb {
40 
41  namespace utils {
42 
46  namespace iterators {
47 
48  template< typename T >
49  class Repeater;
50 
51  template< typename T >
52  class Sequence;
53 
54  }
55 
56  namespace internal {
57 
75  template<
76  typename R,
77  typename T,
78  typename SelfType
79  >
80  class PosBasedIterator {
81 
82  friend class grb::utils::iterators::Repeater< R >;
83 
84  friend class grb::utils::iterators::Sequence< R >;
85 
86  protected:
87 
94  static constexpr const size_t block_size = 256;
95 
99  size_t _count;
100 
107  size_t _pos;
108 
114  R _val;
115 
119  T _state;
120 
124  PosBasedIterator(
125  const size_t count, const size_t pos,
126  const R val, const T state
127  ) :
128  _count( count ), _pos( pos ), _val( val ), _state( state )
129  {}
130 
131 
132  public:
133 
134  // standard STL typedefs
135 
136  typedef std::random_access_iterator_tag iterator_category;
137 
138  typedef size_t difference_type;
139 
140  typedef R value_type;
141 
142  typedef const R * pointer;
143 
144  typedef const R & reference;
145 
146  // STL-like typedefs
147 
148  typedef PosBasedIterator< R, T, SelfType > self_type;
149 
150  typedef self_type & self_reference_type;
151 
152  typedef const PosBasedIterator< R, T, SelfType > self_const_reference_type;
153 
154  // constructor
155 
185  PosBasedIterator(
186  const size_t count,
187  const bool start,
188  const T state,
189  const R dummy = R(),
190  const size_t s = 0,
191  const size_t P = 1
192  ) :
193  _count( count ), _val( dummy ), _state( state )
194  {
195  // static run-time checks
196  static_assert( block_size > 0,
197  "Regular iterator: internal block size must be larger than zero" );
198  // run-time checks
199  if( P == 0 || s >= P ) {
200  throw std::runtime_error( "Illegal values for s and/or P" );
201  }
202  // adjust count according to P
203  size_t entries_per_process = count;
204  if( P > 1 && count > block_size ) {
205  const size_t bcount = (count % block_size) > 0
206  ? count / block_size + 1
207  : count / block_size;
208  const size_t bcount_per_process = (bcount % P) > 0
209  ? bcount / P + 1
210  : bcount / P;
211  entries_per_process = bcount_per_process * block_size;
212  }
213  // adjust count according to s
214  _count = (s+1) * entries_per_process;
215  if( _count > count ) { _count = count; }
216  // select start position according to s
217  _pos = start
218  ? s * entries_per_process
219  : _count;
220  // correct potential overflow of starting position
221  if( _pos > _count ) { _pos = _count; }
222  // initialise selected starting position
223  if( _pos != count ) {
224  SelfType::func( _val, state, _pos );
225  }
226  }
227 
233  PosBasedIterator( const self_const_reference_type &other ) :
234  _count( other._count ), _pos( other._pos ),
235  _val( other._val ), _state( other._state )
236  {}
237 
243  PosBasedIterator( PosBasedIterator< R, T, SelfType > &&other ) :
244  _count( other._count ), _pos( other._pos )
245  {
246  _val = std::move( other._val );
247  _state = std::move( other._state );
248  other._count = other._pos = 0;
249  }
250 
256  ~PosBasedIterator() {}
257 
258  // standard iterator interface
259 
265  reference operator*() const noexcept {
266  return _val;
267  }
268 
276  self_reference_type operator=( self_const_reference_type other ) noexcept {
277  _count = other._count;
278  _pos = other._pos;
279  _val = other._val;
280  _state = other._state;
281  return *this;
282  }
283 
291  self_reference_type operator=(
292  PosBasedIterator< R, T, SelfType > &&other
293  ) noexcept {
294  _count = other._count;
295  _pos = other._pos;
296  _val = std::move( other._val );
297  _state = std::move( other._state );
298  other._count = other._pos = 0;
299  return *this;
300  }
301 
313  self_reference_type operator++() noexcept {
314  assert( _pos < _count );
315  (void) ++_pos;
316  if( _pos != _count ) {
317  SelfType::func( _val, _state, _pos );
318  }
319  return *this;
320  }
321 
332  friend void swap( self_reference_type left, self_reference_type right ) {
333  std::swap( left._count, right._count );
334  std::swap( left._pos, right._pos );
335  std::swap( left._val, right._val );
336  std::swap( left._state, right._state );
337  }
338 
339  // input iterator interface
340 
352  pointer operator->() const noexcept {
353  return &_val;
354  }
355 
365  self_type operator++(int) noexcept {
366  assert( _pos < _count );
367  self_type ret =
368  SelfType::create_iterator( _count, _pos, _val, _state );
369  (void) _pos++;
370  if( _pos != _count ) {
371  SelfType::func( _val, _state, _pos );
372  }
373  return ret;
374  }
375 
388  friend bool operator==(
389  self_const_reference_type left, self_const_reference_type right
390  ) noexcept {
391  assert( left._count == right._count );
392  return left._pos == right._pos;
393  }
394 
407  friend bool operator!=(
408  self_const_reference_type left, self_const_reference_type right
409  ) noexcept {
410  return !(left == right);
411  }
412 
413  // bi-directional iterator interface
414 
425  self_reference_type operator--() noexcept {
426  assert( _pos > 0 );
427  (void) --_pos;
428  if( _pos < _count ) {
429  SelfType::func( _val, _state, _pos );
430  }
431  return *this;
432  }
433 
444  self_type operator--(int) noexcept {
445  assert( _pos > 0 );
446  self_type ret =
447  SelfType::make_iterator( _pos, _count, _val, _pos );
448  (void) _pos--;
449  if( _pos < _count ) {
450  SelfType::func( _val, _state, _pos );
451  }
452  return ret;
453  }
454 
455  // random access iterator interface
456 
476  value_type operator[]( const size_t i ) const noexcept {
477  assert( i < PosBasedIterator::_count );
478  R ret = _val;
479  SelfType::func( ret, _state, i );
480  return ret;
481  }
482 
500  friend bool operator<(
501  self_const_reference_type left,
502  self_const_reference_type right
503  ) {
504  assert( left._count == right._count );
505  return left._pos < right._pos;
506  }
507 
525  friend bool operator>(
526  self_const_reference_type left,
527  self_const_reference_type right
528  ) {
529  return left._count == right._count &&
530  left._state == right._state &&
531  left._pos > right._pos;
532  }
533 
552  friend bool operator<=(
553  self_const_reference_type left,
554  self_const_reference_type right
555  ) {
556  return left._count == right._count &&
557  left._state == right._state &&
558  left._pos <= right._pos;
559  }
560 
579  friend bool operator>=(
580  self_const_reference_type left,
581  self_const_reference_type right
582  ) {
583  return left._count == right._count &&
584  left._state == right._state &&
585  left._pos >= right._pos;
586  }
587 
605  self_reference_type operator+=( const size_t count ) noexcept {
606  assert( _pos + count <= _count );
607  _pos += count;
608  if( _pos != _count ) {
609  SelfType::func( _val, _state, _pos );
610  }
611  return *this;
612  }
613 
632  friend self_type operator+(
633  self_const_reference_type iterator,
634  const size_t count
635  ) noexcept {
636  assert( iterator._pos + count <= iterator._count );
637  const size_t pos = iterator._pos + count;
638  R val = iterator._val;
639  if( pos != iterator._count ) {
640  SelfType::func( val, iterator._state, pos );
641  }
642  return self_type(
643  iterator._count, pos,
644  val, iterator._state
645  );
646  }
647 
656  friend self_type operator+(
657  const size_t count,
658  self_const_reference_type iterator
659  ) noexcept {
660  assert( iterator._pos + count <= iterator._count );
661  const size_t pos = iterator._pos + count;
662  R val = iterator._val;
663  if( pos != iterator._count ) {
664  SelfType::func( val, iterator._state, pos );
665  }
666  return self_type(
667  iterator._count, pos,
668  val, iterator._state
669  );
670  }
671 
689  self_reference_type operator-=( const size_t count ) noexcept {
690  assert( _pos >= count );
691  _pos -= count;
692  return *this;
693  }
694 
713  friend self_type operator-(
714  self_const_reference_type iterator,
715  const size_t count
716  ) noexcept {
717  assert( iterator._pos >= count );
718  const size_t pos = iterator._pos - count;
719  R val = iterator._val;
720  if( pos != iterator._count ) {
721  SelfType::func( val, iterator._state, pos );
722  }
723  return self_type(
724  iterator._count, pos,
725  val, iterator._state
726  );
727  }
728 
737  friend self_type operator-(
738  const size_t count,
739  self_const_reference_type iterator
740  ) noexcept {
741  assert( iterator._pos >= count );
742  const size_t pos = iterator._pos - count;
743  R val = iterator._val;
744  if( pos != iterator._count ) {
745  SelfType::func( val, iterator._state, pos );
746  }
747  return self_type(
748  iterator._count, pos,
749  val, iterator._state
750  );
751  }
752 
767  difference_type operator-(
768  self_const_reference_type iterator
769  ) const noexcept {
770  assert( iterator._count == _count );
771  assert( iterator._state == _state );
772  return static_cast< difference_type >( _pos - iterator._pos );
773  }
774 
775  };
776 
777  } // end namespace grb::utils::internal
778 
779  namespace iterators {
780 
791  template< typename T >
792  class Repeater {
793 
794  friend class internal::PosBasedIterator< T, T, Repeater< T > >;
795 
796  public:
797 
806  typedef grb::utils::internal::PosBasedIterator< T, T, Repeater< T > >
808 
809 
810  protected:
811 
812 
828  static RealType create_iterator(
829  const size_t count,
830  const size_t pos,
831  const T val,
832  const T state
833  ) {
834  return RealType( count, pos, val, state );
835  }
836 
845  inline static void func( T&, const T&, const size_t ) {}
846 
847 
848  public:
849 
870  const size_t count,
871  const bool start,
872  const T val,
873  const size_t s = 0,
874  const size_t P = 1
875  ) {
876  return RealType( count, start, val, val, s, P );
877  }
878 
879  };
880 
899  template< typename T >
900  class Sequence {
901 
902  friend class internal::PosBasedIterator<
903  T, std::tuple< size_t, size_t, size_t >,
904  Sequence< T >
905  >;
906 
907  public:
908 
916  typedef grb::utils::internal::PosBasedIterator<
917  T, std::tuple< size_t, size_t, size_t >, Sequence< T >
919 
920 
921  protected:
922 
923 
939  static RealType create_iterator(
940  const size_t count,
941  const size_t pos,
942  const T val,
943  const std::tuple< size_t, size_t, size_t > state
944  ) {
945  return RealType( count, pos, val, state );
946  }
947 
954  inline static void func(
955  T &val,
956  const std::tuple< size_t, size_t, size_t > &state,
957  const size_t pos
958  ) {
959  const size_t offset = std::get<0>(state);
960  const size_t stride = std::get<1>(state);
961  const size_t repetitions = std::get<2>(state);
962  val = offset + ( pos / repetitions ) * stride;
963  }
964 
965 
966  public:
967 
990  const size_t count,
991  const bool start,
992  const size_t offset = static_cast< size_t >( 0 ),
993  const size_t stride = static_cast< size_t >( 1 ),
994  const size_t repetitions = static_cast< size_t >( 1 ),
995  T dummy = T(),
996  const size_t s = 0,
997  const size_t P = 1
998  ) {
999  return RealType(
1000  count,
1001  start,
1002  std::tuple< size_t, size_t, size_t >( offset, stride, repetitions ),
1003  dummy,
1004  s, P
1005  );
1006  }
1007 
1008  };
1009 
1010  } // end namespace grb::utils::iterators
1011 
1013  namespace containers {
1014 
1025  template< typename T >
1027 
1028  private:
1029 
1032 
1034  const T _val;
1035 
1037  const size_t _n;
1038 
1039 
1040  public:
1041 
1044 
1052 
1061  ConstantVector( const T val, const size_t n ) : _val( val ), _n( n ) {}
1062 
1092  iterator begin( const size_t s = 0, const size_t P = 1 ) const {
1093  return FactoryType::make_iterator( _n, true, _val, s, P );
1094  }
1095 
1125  iterator end( const size_t s = 0, const size_t P = 1 ) const {
1126  return FactoryType::make_iterator( _n, false, _val, s, P );
1127  }
1128 
1136  const_iterator cbegin( const size_t s = 0, const size_t P = 1 ) const {
1137  return FactoryType::make_iterator( _n, true, _val, s, P );
1138  }
1139 
1146  const_iterator cend( const size_t s = 0, const size_t P = 1 ) const {
1147  return FactoryType::make_iterator( _n, false, _val, s, P );
1148  }
1149 
1150  };
1151 
1162  template< typename T = size_t >
1163  class Range {
1164 
1165  private:
1166 
1169 
1171  const size_t _start, _end;
1172 
1174  const size_t _stride;
1175 
1177  const size_t _repetitions;
1178 
1180  const size_t _count;
1181 
1182 
1183  public:
1184 
1187 
1195 
1224  const size_t start, const size_t end,
1225  const size_t stride = static_cast< size_t >( 1 ),
1226  const size_t repetitions = static_cast< size_t >( 1 )
1227  ) noexcept :
1228  _start( start ),
1229  _end( end ),
1230  _stride( stride ),
1231  _repetitions( repetitions ),
1232  _count(
1233  start == end
1234  ? 0
1235  : ( (end-start) % stride > 0
1236  ? ((end-start) / stride + 1)
1237  : (end-start) / stride
1238  ) * repetitions
1239  )
1240  {
1241  assert( start <= end );
1242  }
1243 
1273  iterator begin( const size_t s = 0, const size_t P = 1 ) const {
1274  return FactoryType::make_iterator( _count, true, _start, _stride,
1275  _repetitions, T(), s, P );
1276  }
1277 
1307  iterator end( const size_t s = 0, const size_t P = 1 ) const {
1308  return FactoryType::make_iterator( _count, false, _start, _stride,
1309  _repetitions, T(), s, P );
1310  }
1311 
1319  const_iterator cbegin( const size_t s = 0, const size_t P = 1 ) const {
1320  return FactoryType::make_iterator( _count, true, _start, _stride,
1321  _repetitions, T(), s, P );
1322  }
1323 
1330  const_iterator cend( const size_t s = 0, const size_t P = 1 ) const {
1331  return FactoryType::make_iterator( _count, false, _start, _stride,
1332  _repetitions, T(), s, P );
1333  }
1334 
1335  };
1336 
1337  } // end namespace grb::utils::containers
1338 
1339  } // end namespace grb::utils
1340 
1341 } // end namespace grb
1342 
1343 #endif // end _H_GRB_ITERATOR_REGULAR
1344 
const_iterator cbegin(const size_t s=0, const size_t P=1) const
Returns a const-iterator at start position to this container.
Definition: regular.hpp:1319
static RealType make_iterator(const size_t count, const bool start, const T val, const size_t s=0, const size_t P=1)
Constructs an iterator over a collection that contains the same constant value val count times.
Definition: regular.hpp:869
const_iterator cbegin(const size_t s=0, const size_t P=1) const
Returns a const-iterator at start position to this container.
Definition: regular.hpp:1136
iterator begin(const size_t s=0, const size_t P=1) const
Returns a const-iterator at start position to this container.
Definition: regular.hpp:1273
An iterator that repeats the same value for a set number of times.
Definition: regular.hpp:49
iterator end(const size_t s=0, const size_t P=1) const
Returns a const-iterator at end position to this container.
Definition: regular.hpp:1307
iterator begin(const size_t s=0, const size_t P=1) const
Returns a const-iterator at start position to this container.
Definition: regular.hpp:1092
grb::utils::iterators::Repeater< T >::RealType iterator
The iterator type.
Definition: regular.hpp:1043
iterator end(const size_t s=0, const size_t P=1) const
Returns a const-iterator at end position to this container.
Definition: regular.hpp:1125
An iterator over a collection of items that for each item returns , where is of the form .
Definition: regular.hpp:52
iterator const_iterator
The const-iterator type.
Definition: regular.hpp:1051
The sequential reference implementation.
Definition: backends.hpp:55
ConstantVector(const T val, const size_t n)
Constructs a container with memory usage that represents some vector of length n with contents .
Definition: regular.hpp:1061
A (dense) vector of a given size that holds the same constant value at each entry.
Definition: regular.hpp:1026
The ALP/GraphBLAS namespace.
Definition: graphblas.hpp:477
const_iterator cend(const size_t s=0, const size_t P=1) const
Returns a const-iterator at end position to this container.
Definition: regular.hpp:1330
A container that contains a sequence of numbers with a given stride, and optionally a given number of...
Definition: regular.hpp:1163
iterator const_iterator
The const-iterator type.
Definition: regular.hpp:1194
grb::utils::internal::PosBasedIterator< T, std::tuple< size_t, size_t, size_t >, Sequence< T > > RealType
The return type of the factory methods.
Definition: regular.hpp:918
static RealType make_iterator(const size_t count, const bool start, const size_t offset=static_cast< size_t >(0), const size_t stride=static_cast< size_t >(1), const size_t repetitions=static_cast< size_t >(1), T dummy=T(), const size_t s=0, const size_t P=1)
Constructs an iterator over a given sequence.
Definition: regular.hpp:989
const_iterator cend(const size_t s=0, const size_t P=1) const
Returns a const-iterator at end position to this container.
Definition: regular.hpp:1146
grb::utils::internal::PosBasedIterator< T, T, Repeater< T > > RealType
The return type of the factory methods.
Definition: regular.hpp:807
Range(const size_t start, const size_t end, const size_t stride=static_cast< size_t >(1), const size_t repetitions=static_cast< size_t >(1)) noexcept
Constructs a range.
Definition: regular.hpp:1223
grb::utils::iterators::Sequence< T >::RealType iterator
The iterator type.
Definition: regular.hpp:1186