Domi
Multi-dimensional, distributed data structures
 All Classes Files Functions Variables Typedefs Friends
Domi_MDRevIterator.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_MDREVITERATOR_HPP
44 #define DOMI_MDREVITERATOR_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 
97 template< class MDARRAY >
98 class MDRevIterator : public std::iterator< std::bidirectional_iterator_tag,
99  typename MDARRAY::value_type >
100 {
101 public:
102 
105 
107  typedef typename MDARRAY::value_type value_type;
108 
110  typedef typename MDARRAY::pointer pointer;
111 
113 
116 
130  MDRevIterator(const MDARRAY & mdarray,
131  bool end_index = false);
132 
144  MDRevIterator(const MDARRAY & mdarray,
145  const Teuchos::ArrayView< dim_type > & index);
146 
151  MDRevIterator(const MDRevIterator< MDARRAY > & source);
152 
155  ~MDRevIterator();
156 
158 
161 
167  operator=(const MDRevIterator< MDARRAY > & source);
168 
173  bool operator==(const MDRevIterator< MDARRAY > & other) const;
174 
179  bool operator!=(const MDRevIterator< MDARRAY > & other) const;
180 
182  inline value_type & operator*();
183 
185  inline pointer operator->() const;
186 
189 
192 
195 
198 
200 
205  inline dim_type index(int axis) const;
206 
209  template< typename T2 >
210  friend std::ostream & operator<<(std::ostream & os, const MDRevIterator< T2 > & a);
211 
212 private:
213 
214  // A copy of the dimensions of the multi-dimensional array being
215  // reverse iterated
216  const Teuchos::Array< dim_type > _dimensions;
217 
218  // A copy of the strides of the multi-dimensional array being
219  // reverse iterated
220  const Teuchos::Array< size_type > _strides;
221 
222  // A pointer to the data buffer of the multi-dimensional array
223  // being reverse iterated
224  value_type * _ptr;
225 
226  // A copy of the storage order of the multi-dimensional array being
227  // reverse iterated
228  Layout _layout;
229 
230  // The multi-dimensional index of the current reverse iterate
231  Teuchos::Array< dim_type > _index;
232 
233  // A temporary value used to indicate the axis of the index
234  // currently being incremented or decremented
235  mutable int _axis;
236 
237  // A temporary value used to indicate whether an increment or
238  // decrement operation is complete
239  mutable bool _done;
240 
241  // Convenience function for assigning the begin index
242  void assign_begin_index();
243 
244  // We need an index that is recognized as the end index. It must
245  // not be a valid index for the MDARRAY. Since there are a nearly
246  // infinite number of indexes that could serve as the end index,
247  // this method should always be used to assign the index of an end
248  // reverse iterator.
249  void assign_end_index();
250 
251  // Assert that the given index is valid for the given axis
252  void assert_index(dim_type i, int axis) const;
253 
254 };
255 
257 // Implementations //
259 
260 template< class MDARRAY >
262  bool end_index) :
263  _dimensions(mdarray._dimensions),
264  _strides(mdarray._strides),
265  _ptr(mdarray._ptr),
266  _layout(mdarray._layout),
267  _index(mdarray.numDims())
268 {
269  if (end_index)
270  assign_end_index();
271  else
272  {
273  if (computeSize(_dimensions) == 0)
274  assign_end_index();
275  else
276  assign_begin_index();
277  }
278 }
279 
281 
282 template< class MDARRAY >
284 MDRevIterator(const MDARRAY & mdarray,
285  const Teuchos::ArrayView< dim_type > & index) :
286  _dimensions(mdarray._dimensions),
287  _strides(mdarray._strides),
288  _ptr(mdarray._ptr),
289  _layout(mdarray._layout),
290  _index(index)
291 {
292  TEUCHOS_TEST_FOR_EXCEPTION(
293  (_dimensions.size() != _index.size()), RangeError,
294  "Input array has " << _dimensions.size() << " dimensions, while index "
295  "has " << _index.size());
296 #ifdef HAVE_DOMI_ARRAY_BOUNDSCHECK
297  for (_axis = 0; _axis < _index.size(); ++_axis)
298  assert_index(_index[_axis], _axis);
299 #endif
300 }
301 
303 
304 template< class MDARRAY >
307  _dimensions(source._dimensions),
308  _strides(source._strides),
309  _ptr(source._ptr),
310  _layout(source._layout),
311  _index(source._index)
312 {
313 }
314 
316 
317 template< class MDARRAY >
319 {
320 }
321 
323 
324 template< class MDARRAY >
327 {
328  _dimensions = source._dimensions;
329  _strides = source._strides;
330  _ptr = source._ptr;
331  _layout = source._layout;
332  _index = source._index;
333  return *this;
334 }
335 
337 
338 template< class MDARRAY >
339 bool
342 {
343  // If underlying MDARRAYs are different, then return not equal
344  if (_ptr != other._ptr) return false;
345  // If any of the current index values differ, then return not equal
346  for (_axis = 0; _axis < _index.size(); _axis++)
347  if (_index[_axis] != other._index[_axis]) return false;
348  // Return equal
349  return true;
350 }
351 
353 
354 template< class MDARRAY >
355 bool
358 {
359  return !(*this == other);
360 }
361 
363 
364 template< class MDARRAY >
367 {
368  size_type offset = 0;
369  for (_axis=0; _axis < _index.size(); ++_axis)
370  offset += _index[_axis] * _strides[_axis];
371  return _ptr[offset];
372 }
373 
375 
376 template< class MDARRAY >
379 {
380  return &operator*();
381 }
382 
384 
385 template< class MDARRAY >
388 {
389  if (_layout == FIRST_INDEX_FASTEST)
390  {
391  _axis = 0;
392  _done = false;
393  while (not _done)
394  {
395  _index[_axis]--;
396  _done = (_index[_axis] >= 0);
397  if (not _done)
398  {
399  _index[_axis] = _dimensions[_axis] - 1;
400  _axis++;
401  if (_axis >= _index.size())
402  {
403  _done = true;
404  assign_end_index();
405  }
406  }
407  }
408  }
409  else
410  {
411  _axis = _dimensions.size() - 1;
412  _done = false;
413  while (not _done)
414  {
415  _index[_axis]--;
416  _done = (_index[_axis] >= 0);
417  if (not _done)
418  {
419  _index[_axis] = _dimensions[_axis] - 1;
420  _axis--;
421  if (_axis < 0)
422  {
423  _done = true;
424  assign_end_index();
425  }
426  }
427  }
428  }
429  return *this;
430 }
431 
433 
434 template< class MDARRAY >
437 {
438  MDRevIterator< MDARRAY > result(*this);
439  ++(*this);
440  return result;
441 }
442 
444 
445 template< class MDARRAY >
448 {
449  if (_layout == FIRST_INDEX_FASTEST)
450  {
451  _axis = 0;
452  _done = false;
453  while (not _done)
454  {
455  _index[_axis]++;
456  _done = (_index[_axis] < _dimensions[_axis]);
457  if (not _done)
458  {
459  _index[_axis] = 0;
460  _axis++;
461  if (_axis >= _index.size())
462  {
463  _done = true;
464  assign_end_index();
465  }
466  }
467  }
468  }
469  else
470  {
471  _axis = _dimensions.size() - 1;
472  _done = false;
473  while (not _done)
474  {
475  _index[_axis]++;
476  _done = (_index[_axis] < _dimensions[_axis]);
477  if (not _done)
478  {
479  _index[_axis] = 0;
480  _axis--;
481  if (_axis < 0)
482  {
483  _done = true;
484  assign_end_index();
485  }
486  }
487  }
488  }
489  return *this;
490 }
491 
493 
494 template< class MDARRAY >
497 {
498  MDRevIterator< MDARRAY > result(*this);
499  --(*this);
500  return result;
501 }
502 
504 
505 template< class MDARRAY >
506 dim_type
508 index(int axis) const
509 {
510  return _index[axis];
511 }
512 
514 
515 template< typename T >
516 std::ostream & operator<<(std::ostream & os, const MDRevIterator< T > & a)
517 {
518  os << &(*a);
519  return os;
520 }
521 
523 // Private implementations //
525 
526 template< class MDARRAY >
527 void
528 MDRevIterator< MDARRAY >::assign_begin_index()
529 {
530  for (int axis = 0;
531  axis < _index.size(); ++axis)
532  _index[axis] = _dimensions[axis] - 1;
533 }
534 
536 
537 template< class MDARRAY >
538 void
539 MDRevIterator< MDARRAY >::assign_end_index()
540 {
541  // We choose the end index to be equal to an array of -1 values
542  for (int axis = 0;
543  axis < _index.size(); ++axis)
544  _index[axis] = -1;
545 }
546 
548 
549 template< class MDARRAY >
550 void
551 MDRevIterator< MDARRAY >::
552 assert_index(dim_type i,
553  int axis) const
554 {
555  TEUCHOS_TEST_FOR_EXCEPTION(
556  !(0 <= i && i < _dimensions[axis]), RangeError,
557  "MDRevIterator<MDARRAY>::assert_index(i=" << i << ",axis=" << axis << "): out"
558  << " of range i in [0, " << _dimensions[axis] << ")"
559  );
560 }
561 
562 } // namespace Domi
563 
564 #endif
MDRevIterator< MDARRAY > & operator--()
Prefix decrement operator.
Definition: Domi_MDRevIterator.hpp:447
MDARRAY::pointer pointer
Pointer type.
Definition: Domi_MDRevIterator.hpp:110
MDRevIterator< MDARRAY > & operator=(const MDRevIterator< MDARRAY > &source)
Assignment operator.
Definition: Domi_MDRevIterator.hpp:326
Range Error exception type.
Definition: Domi_Exceptions.hpp:65
MDRevIterator< MDARRAY > & operator++()
Prefix increment operator.
Definition: Domi_MDRevIterator.hpp:387
MDARRAY::value_type value_type
Value type.
Definition: Domi_MDRevIterator.hpp:107
bool operator!=(const MDRevIterator< MDARRAY > &other) const
Inequality operator.
Definition: Domi_MDRevIterator.hpp:357
MDRevIterator(const MDARRAY &mdarray, bool end_index=false)
MDRevIterator constructor.
Definition: Domi_MDRevIterator.hpp:261
value_type & operator*()
Dereferencing operator.
Definition: Domi_MDRevIterator.hpp:366
dim_type index(int axis) const
Return the current index value along the given axis.
Definition: Domi_MDRevIterator.hpp:508
~MDRevIterator()
Destructor.
Definition: Domi_MDRevIterator.hpp:318
Reverse iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDRevIterator.hpp:98
pointer operator->() const
Dereferencing arrow operator.
Definition: Domi_MDRevIterator.hpp:378
bool operator==(const MDRevIterator< MDARRAY > &other) const
Equality operator.
Definition: Domi_MDRevIterator.hpp:341

Generated on Fri Nov 22 2024 09:26:41 for Domi by doxygen 1.8.5