Domi
Multi-dimensional, distributed data structures
 All Classes Files Functions Variables Typedefs Friends
Domi_MDIterator.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Domi: Multi-dimensional Distributed Linear Algebra Services
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia
8 // Corporation, the U.S. Government retains certain rights in this
9 // software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact William F. Spotz (wfspotz@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef DOMI_MDITERATOR_HPP
44 #define DOMI_MDITERATOR_HPP
45 
46 // Standard include
47 #include <iterator>
48 
49 // Domi includes
50 #include "Domi_Exceptions.hpp"
51 #include "Domi_Utils.hpp"
52 
53 namespace Domi
54 {
55 
99 template< class MDARRAY >
100 class MDIterator : public std::iterator< std::bidirectional_iterator_tag,
101  typename MDARRAY::value_type >
102 {
103 public:
104 
107 
109  typedef typename MDARRAY::value_type value_type;
110 
112  typedef typename MDARRAY::pointer pointer;
113 
115 
118 
132  MDIterator(const MDARRAY & mdarray,
133  bool end_index = false);
134 
146  MDIterator(const MDARRAY & mdarray,
147  const Teuchos::ArrayView< dim_type > & index);
148 
153  MDIterator(const MDIterator< MDARRAY > & source);
154 
157  ~MDIterator();
158 
160 
163 
169 
174  bool operator==(const MDIterator< MDARRAY > & other) const;
175 
180  bool operator!=(const MDIterator< MDARRAY > & other) const;
181 
183  inline value_type & operator*();
184 
186  inline pointer operator->() const;
187 
190 
193 
196 
199 
201 
206  inline dim_type index(int axis) const;
207 
210  template< typename T2 >
211  friend std::ostream & operator<<(std::ostream & os, const MDIterator< T2 > & a);
212 
213 private:
214 
215  // A copy of the dimensions of the multi-dimensional array being
216  // iterated
217  const Teuchos::Array< dim_type > _dimensions;
218 
219  // A copy of the strides of the multi-dimensional array being
220  // iterated
221  const Teuchos::Array< size_type > _strides;
222 
223  // A pointer to the data buffer of the multi-dimensional array
224  // being iterated
225  value_type * _ptr;
226 
227  // A copy of the storage order of the multi-dimensional array being
228  // iterated
229  Layout _layout;
230 
231  // The multi-dimensional index of the current iterate
232  Teuchos::Array< dim_type > _index;
233 
234  // A temporary value used to indicate the axis of the index
235  // currently being incremented or decremented
236  mutable int _axis;
237 
238  // A temporary value used to indicate whether an increment or
239  // decrement operation is complete
240  mutable bool _done;
241 
242  // We need an index that is recognized as the end index. It must
243  // not be a valid index for the MDARRAY. Since there are a nearly
244  // infinite number of indexes that could serve as the end index,
245  // this method should always be used to assign the index of an end
246  // iterator.
247  void assign_end_index();
248 
249  // Assert that the given index is valid for the given axis
250  void assert_index(dim_type i, int axis) const;
251 
252 };
253 
255 // Implementations //
257 
258 template< class MDARRAY >
259 MDIterator< MDARRAY >::MDIterator(const MDARRAY & mdarray,
260  bool end_index) :
261  _dimensions(mdarray._dimensions),
262  _strides(mdarray._strides),
263  _ptr(mdarray._ptr),
264  _layout(mdarray._layout),
265  _index(mdarray.numDims())
266 {
267  if (end_index)
268  assign_end_index();
269  else
270  {
271  if (computeSize(_dimensions) == 0)
272  assign_end_index();
273  else
274  _index.assign(_dimensions.size(), 0);
275  }
276 }
277 
279 
280 template< class MDARRAY >
282 MDIterator(const MDARRAY & mdarray,
283  const Teuchos::ArrayView< dim_type > & index) :
284  _dimensions(mdarray._dimensions),
285  _strides(mdarray._strides),
286  _ptr(mdarray._ptr),
287  _layout(mdarray._layout),
288  _index(index)
289 {
290  TEUCHOS_TEST_FOR_EXCEPTION(
291  (_dimensions.size() != _index.size()), RangeError,
292  "Input array has " << _dimensions.size() << " dimensions, while index "
293  "has " << _index.size());
294 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
295  for (_axis = 0; _axis < _index.size(); ++_axis)
296  assert_index(_index[_axis], _axis);
297 #endif
298 }
299 
301 
302 template< class MDARRAY >
304  _dimensions(source._dimensions),
305  _strides(source._strides),
306  _ptr(source._ptr),
307  _layout(source._layout),
308  _index(source._index)
309 {
310 }
311 
313 
314 template< class MDARRAY >
316 {
317 }
318 
320 
321 template< class MDARRAY >
324 {
325  _dimensions = source._dimensions;
326  _strides = source._strides;
327  _ptr = source._ptr;
328  _layout = source._layout;
329  _index = source._index;
330  return *this;
331 }
332 
334 
335 template< class MDARRAY >
336 bool
338 {
339  // If underlying MDARRAYs are different, then return not equal
340  if (_ptr != other._ptr) return false;
341  // If any of the current index values differ, then return not equal
342  for (_axis = 0; _axis < _index.size(); _axis++)
343  if (_index[_axis] != other._index[_axis]) return false;
344  // Return equal
345  return true;
346 }
347 
349 
350 template< class MDARRAY >
351 bool
353 {
354  return !(*this == other);
355 }
356 
358 
359 template< class MDARRAY >
362 {
363  size_type offset = 0;
364  for (_axis=0; _axis < _index.size(); ++_axis)
365  offset += _index[_axis] * _strides[_axis];
366  return _ptr[offset];
367 }
368 
370 
371 template< class MDARRAY >
374 {
375  return &operator*();
376 }
377 
379 
380 template< class MDARRAY >
383 {
384  if (_layout == FIRST_INDEX_FASTEST)
385  {
386  _axis = 0;
387  _done = false;
388  while (not _done)
389  {
390  _index[_axis]++;
391  _done = (_index[_axis] < _dimensions[_axis]);
392  if (not _done)
393  {
394  _index[_axis] = 0;
395  _axis++;
396  if (_axis >= _index.size())
397  {
398  _done = true;
399  assign_end_index();
400  }
401  }
402  }
403  }
404  else
405  {
406  _axis = _dimensions.size() - 1;
407  _done = false;
408  while (not _done)
409  {
410  _index[_axis]++;
411  _done = (_index[_axis] < _dimensions[_axis]);
412  if (not _done)
413  {
414  _index[_axis] = 0;
415  _axis--;
416  if (_axis < 0)
417  {
418  _done = true;
419  assign_end_index();
420  }
421  }
422  }
423  }
424  return *this;
425 }
426 
428 
429 template< class MDARRAY >
432 {
433  MDIterator< MDARRAY > result(*this);
434  ++(*this);
435  return result;
436 }
437 
439 
440 template< class MDARRAY >
443 {
444  if (_layout == FIRST_INDEX_FASTEST)
445  {
446  _axis = 0;
447  _done = false;
448  while (not _done)
449  {
450  _index[_axis]--;
451  _done = (_index[_axis] >= 0);
452  if (not _done)
453  {
454  _index[_axis] = _dimensions[_axis] - 1;
455  _axis++;
456  if (_axis >= _index.size())
457  {
458  _done = true;
459  assign_end_index();
460  }
461  }
462  }
463  }
464  else
465  {
466  _axis = _dimensions.size() - 1;
467  _done = false;
468  while (not _done)
469  {
470  _index[_axis]--;
471  _done = (_index[_axis] >= 0);
472  if (not _done)
473  {
474  _index[_axis] = _dimensions[_axis] - 1;
475  _axis--;
476  if (_axis < 0)
477  {
478  _done = true;
479  assign_end_index();
480  }
481  }
482  }
483  }
484  return *this;
485 }
486 
488 
489 template< class MDARRAY >
492 {
493  MDIterator< MDARRAY > result(*this);
494  --(*this);
495  return result;
496 }
497 
499 
500 template< class MDARRAY >
501 dim_type
503 index(int axis) const
504 {
505  return _index[axis];
506 }
507 
509 
510 template< typename T >
511 std::ostream & operator<<(std::ostream & os, const MDIterator< T > & a)
512 {
513  os << &(*a);
514  return os;
515 }
516 
518 // Private implementations //
520 
521 template< class MDARRAY >
522 void
523 MDIterator< MDARRAY >::assign_end_index()
524 {
525  // We choose the end index to be equal to the MDARRAY dimensions,
526  // where each index value is one greater than the largest valid
527  // index for that axis.
528  for (int axis = 0; axis < _index.size(); ++axis)
529  _index[axis] = _dimensions[axis];
530 }
531 
533 
534 template< class MDARRAY >
535 void
536 MDIterator< MDARRAY >::
537 assert_index(dim_type i,
538  int axis) const
539 {
540  TEUCHOS_TEST_FOR_EXCEPTION(
541  !(0 <= i && i < _dimensions[axis]), RangeError,
542  "MDIterator<MDARRAY>::assert_index(i=" << i << ",axis=" << axis << "): out"
543  << " of range i in [0, " << _dimensions[axis] << ")"
544  );
545 }
546 
547 } // namespace Domi
548 
549 #endif
MDARRAY::pointer pointer
Pointer type.
Definition: Domi_MDIterator.hpp:112
Iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDIterator.hpp:100
Range Error exception type.
Definition: Domi_Exceptions.hpp:65
~MDIterator()
Destructor.
Definition: Domi_MDIterator.hpp:315
pointer operator->() const
Dereferencing arrow operator.
Definition: Domi_MDIterator.hpp:373
MDIterator< MDARRAY > & operator++()
Prefix increment operator.
Definition: Domi_MDIterator.hpp:382
MDIterator< MDARRAY > & operator=(const MDIterator< MDARRAY > &source)
Assignment operator.
Definition: Domi_MDIterator.hpp:323
bool operator!=(const MDIterator< MDARRAY > &other) const
Inequality operator.
Definition: Domi_MDIterator.hpp:352
MDARRAY::value_type value_type
Value type.
Definition: Domi_MDIterator.hpp:109
MDIterator< MDARRAY > & operator--()
Prefix decrement operator.
Definition: Domi_MDIterator.hpp:442
value_type & operator*()
Dereferencing operator.
Definition: Domi_MDIterator.hpp:361
dim_type index(int axis) const
Return the current index value along the given axis.
Definition: Domi_MDIterator.hpp:503
MDIterator(const MDARRAY &mdarray, bool end_index=false)
MDIterator constructor.
Definition: Domi_MDIterator.hpp:259
bool operator==(const MDIterator< MDARRAY > &other) const
Equality operator.
Definition: Domi_MDIterator.hpp:337

Generated on Fri Jun 5 2020 10:07:58 for Domi by doxygen 1.8.5