Domi
Multi-dimensional, distributed data structures
Loading...
Searching...
No Matches
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
53namespace Domi
54{
55
97template< class MDARRAY >
98class MDRevIterator : public std::iterator< std::bidirectional_iterator_tag,
99 typename MDARRAY::value_type >
100{
101public:
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
152
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
212private:
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
260template< 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
282template< class MDARRAY >
284MDRevIterator(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
304template< 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
317template< class MDARRAY >
319{
320}
321
323
324template< 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
338template< class MDARRAY >
339bool
341operator==(const MDRevIterator< MDARRAY > & other) const
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
354template< class MDARRAY >
355bool
357operator!=(const MDRevIterator< MDARRAY > & other) const
358{
359 return !(*this == other);
360}
361
363
364template< 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
376template< class MDARRAY >
379{
380 return &operator*();
381}
382
384
385template< 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
434template< class MDARRAY >
437{
438 MDRevIterator< MDARRAY > result(*this);
439 ++(*this);
440 return result;
441}
442
444
445template< 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
494template< class MDARRAY >
497{
498 MDRevIterator< MDARRAY > result(*this);
499 --(*this);
500 return result;
501}
502
504
505template< class MDARRAY >
506dim_type
508index(int axis) const
509{
510 return _index[axis];
511}
512
514
515template< typename T >
516std::ostream & operator<<(std::ostream & os, const MDRevIterator< T > & a)
517{
518 os << &(*a);
519 return os;
520}
521
523// Private implementations //
525
526template< class MDARRAY >
527void
528MDRevIterator< MDARRAY >::assign_begin_index()
529{
530 for (int axis = 0;
531 axis < _index.size(); ++axis)
532 _index[axis] = _dimensions[axis] - 1;
533}
534
536
537template< class MDARRAY >
538void
539MDRevIterator< 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
549template< class MDARRAY >
550void
551MDRevIterator< MDARRAY >::
552assert_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
Reverse iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDRevIterator.hpp:100
MDRevIterator< MDARRAY > & operator=(const MDRevIterator< MDARRAY > &source)
Assignment operator.
Definition: Domi_MDRevIterator.hpp:326
MDRevIterator< MDARRAY > & operator++()
Prefix increment operator.
Definition: Domi_MDRevIterator.hpp:387
~MDRevIterator()
Destructor.
Definition: Domi_MDRevIterator.hpp:318
pointer operator->() const
Dereferencing arrow operator.
Definition: Domi_MDRevIterator.hpp:378
dim_type index(int axis) const
Return the current index value along the given axis.
Definition: Domi_MDRevIterator.hpp:508
friend std::ostream & operator<<(std::ostream &os, const MDRevIterator< T2 > &a)
Stream output operator.
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< MDARRAY > & operator--()
Prefix decrement operator.
Definition: Domi_MDRevIterator.hpp:447
MDRevIterator(const MDARRAY &mdarray, bool end_index=false)
MDRevIterator constructor.
Definition: Domi_MDRevIterator.hpp:261
bool operator==(const MDRevIterator< MDARRAY > &other) const
Equality operator.
Definition: Domi_MDRevIterator.hpp:341
value_type & operator*()
Dereferencing operator.
Definition: Domi_MDRevIterator.hpp:366
MDARRAY::pointer pointer
Pointer type.
Definition: Domi_MDRevIterator.hpp:110
Range Error exception type.
Definition: Domi_Exceptions.hpp:66

Generated for Domi by doxygen 1.9.6