Domi
Multi-dimensional, distributed data structures
Loading...
Searching...
No Matches
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
53namespace Domi
54{
55
99template< class MDARRAY >
100class MDIterator : public std::iterator< std::bidirectional_iterator_tag,
101 typename MDARRAY::value_type >
102{
103public:
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
213private:
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
258template< class MDARRAY >
259MDIterator< 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
280template< class MDARRAY >
282MDIterator(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
302template< 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
314template< class MDARRAY >
316{
317}
318
320
321template< 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
335template< class MDARRAY >
336bool
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
350template< class MDARRAY >
351bool
353{
354 return !(*this == other);
355}
356
358
359template< 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
371template< class MDARRAY >
374{
375 return &operator*();
376}
377
379
380template< 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
429template< class MDARRAY >
432{
433 MDIterator< MDARRAY > result(*this);
434 ++(*this);
435 return result;
436}
437
439
440template< 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
489template< class MDARRAY >
492{
493 MDIterator< MDARRAY > result(*this);
494 --(*this);
495 return result;
496}
497
499
500template< class MDARRAY >
501dim_type
503index(int axis) const
504{
505 return _index[axis];
506}
507
509
510template< typename T >
511std::ostream & operator<<(std::ostream & os, const MDIterator< T > & a)
512{
513 os << &(*a);
514 return os;
515}
516
518// Private implementations //
520
521template< class MDARRAY >
522void
523MDIterator< 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
534template< class MDARRAY >
535void
536MDIterator< MDARRAY >::
537assert_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
Iterator class suitable for multi-dimensional arrays.
Definition: Domi_MDIterator.hpp:102
pointer operator->() const
Dereferencing arrow operator.
Definition: Domi_MDIterator.hpp:373
dim_type index(int axis) const
Return the current index value along the given axis.
Definition: Domi_MDIterator.hpp:503
MDARRAY::pointer pointer
Pointer type.
Definition: Domi_MDIterator.hpp:112
MDIterator< MDARRAY > & operator++()
Prefix increment operator.
Definition: Domi_MDIterator.hpp:382
bool operator==(const MDIterator< MDARRAY > &other) const
Equality operator.
Definition: Domi_MDIterator.hpp:337
value_type & operator*()
Dereferencing operator.
Definition: Domi_MDIterator.hpp:361
MDARRAY::value_type value_type
Value type.
Definition: Domi_MDIterator.hpp:109
bool operator!=(const MDIterator< MDARRAY > &other) const
Inequality operator.
Definition: Domi_MDIterator.hpp:352
MDIterator(const MDARRAY &mdarray, bool end_index=false)
MDIterator constructor.
Definition: Domi_MDIterator.hpp:259
MDIterator< MDARRAY > & operator--()
Prefix decrement operator.
Definition: Domi_MDIterator.hpp:442
friend std::ostream & operator<<(std::ostream &os, const MDIterator< T2 > &a)
Stream output operator.
MDIterator< MDARRAY > & operator=(const MDIterator< MDARRAY > &source)
Assignment operator.
Definition: Domi_MDIterator.hpp:323
~MDIterator()
Destructor.
Definition: Domi_MDIterator.hpp:315
Range Error exception type.
Definition: Domi_Exceptions.hpp:66

Generated for Domi by doxygen 1.9.6