cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
nmrMultiIndexCounter.h
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3 
4 /*
5 
6  Author(s): Ofri Sadowsky
7  Created on: 2003
8 
9  (C) Copyright 2003-2007 Johns Hopkins University (JHU), All Rights
10  Reserved.
11 
12 --- begin cisst license - do not edit ---
13 
14 This software is provided "as is" under an open source license, with
15 no warranty. The complete license can be found in license.txt and
16 http://www.cisst.org/cisst/license.txt.
17 
18 --- end cisst license ---
19 */
20 
21 
22 #ifndef _nmrMultiIndexCounter_h
23 #define _nmrMultiIndexCounter_h
24 
29 #ifndef DEFINE_FORMATTED_OUTPUT
30 #define DEFINE_FORMATTED_OUTPUT 0
31 #endif
32 
33 #include <vector>
36 
37 // class nmrMultiIndexCounter
38 // Implements a multi-counter iterator type.
39 //
40 // Usage example:
41 //
42 // nmrMultiIndexCounter counter(3);
43 // nmrMultiIndexCounter::IndexType lowBounds[] = {0, 0, 0};
44 // nmrMultiIndexCounter::IndexType highBounds[] = {2, 3, 4};
45 // counter.SetBounds(lowBounds, highBounds);
46 //
47 // // go over all values between lowBounds and highBounds.
48 // for(counter.GoToLowBounds(); counter.IsBelowHighBounds(); counter.Increment()) {
49 // // use the counter cells, addressing them with operator[]
50 // }
51 //
52 // Note 1: the bounds are "weak", in the sense that the test is for <= or >=
53 // rather than the strict < or >. That is, the above program is equivalent to:
54 //
55 // for (i0 = 0; i0 <= 2; ++i0)
56 // for (i1 = 0; i1 <= 3; ++i1)
57 // for (i2 = 0; i2 <= 4; ++i2) {
58 // // do something
59 // }
60 // }
61 // }
62 //
63 //
64 // Note 2: Increment() and Decrement() are complementary operations, except for overflow
65 // and underflow cases. If a counter reaches overflow or underflow after Increment() or
66 // Decrement(), the result of the opposite operation is COUNTER_UNDEFINED.
68 {
69 public:
70  typedef int IndexType;
71 
73 
74  enum CounterStatus {COUNTER_UNDERFLOW = -1, COUNTER_IN_BOUNDS = 0, COUNTER_OVERFLOW = 1, COUNTER_UNDEFINED = 2};
75 
76  // Initialize the counter by specifying the size (number of cells).
77  // The counter is initialized as all zeros, except for the increments which
78  // are all DefaultIncrement.
79  nmrMultiIndexCounter(unsigned int size);
80 
81  // Set all the increments to the default value (1)
82  void SetAllIncrements(IndexType increment)
83  {
84  Increments.assign( GetSize(), increment );
85  }
86 
87  // return the size (number of cells) of the counter.
88  unsigned int GetSize() const
89  {
90  return Index.size();
91  }
92 
93  // Set low and high bounds (inclusive!) for the counter. The low bounds
94  // must be <= the high bounds. In the current implementation, there is
95  // no check for it, and the user must take care of it.
96  // Set the status to COUNTER_UNDEFINED, since we don't check for the relationship
97  // between the actual index and the bounds at this stage.
98  // Note that the bounds are "weak", in the sense that the test is for <= or >=
99  // rather than the strict < or >.
100  void SetBounds(const IndexType lowBounds[], const IndexType highBounds[])
101  {
102  register int i;
103  register const int s = GetSize();
104  for (i = 0; i < s; i++) {
105  LowBounds[i] = lowBounds[i];
106  HighBounds[i] = highBounds[i];
107  }
108  Status = COUNTER_UNDEFINED;
109  }
110 
111  // Set the lower bound of a single counter. 'counter' is the zero-based indicator
112  // of the counter to be set, 'bound' is the bound value for the counter.
113  void SetLowBound(unsigned int counter, IndexType bound)
114  {
115  LowBounds[counter] = bound;
116  }
117 
118  // Set the higher bound of a single counter. 'counter' is the zero-based indicator
119  // of the counter to be set, 'bound' is the bound value for the counter.
120  void SetHighBound(unsigned int counter, IndexType bound)
121  {
122  HighBounds[counter] = bound;
123  }
124 
125 
126  // Set the increments for each of the cells. This does not affect the status.
127  // The increments have to be positive, although there is no assertion for it in
128  // the current implementation.
129  void SetIncrements(const IndexType increments[])
130  {
131  register int i;
132  register const int s = GetSize();
133  for (i = 0; i < s; i++) {
134  Increments[i] = increments[i];
135  }
136  }
137 
138  // Set the increment of a single counter. 'counter' is the zero-based indicator
139  // of the counter to be set, 'increment' is the incrementation value for the counter.
140  void SetIncrement(unsigned int counter, IndexType increment)
141  {
142  Increments[counter] = increment;
143  }
144 
145  // Return the value in a single cell.
146  IndexType operator[](unsigned int i) const
147  { return Index[i]; }
148 
149  // Return a pointer to the cells as an array, if one wants to initialize other
150  // objects with the current values of the cells.
151  const IndexType * GetIndexCells() const
152  {
153  return &(Index[0]);
154  }
155 
156  // Return the same pointer as GetIndexCells() but pointing unsigned int.
157  const unsigned int * GetIndexCellsAsUnsigned() const
158  {
159  return reinterpret_cast<const unsigned int *>(GetIndexCells());
160  }
161 
162  const IndexType * GetLowBounds() const
163  {
164  return &(LowBounds[0]);
165  }
166 
167  IndexType GetLowBound(unsigned int counter) const
168  {
169  return LowBounds[counter];
170  }
171 
172  const IndexType * GetHighBounds() const
173  {
174  return &(HighBounds[0]);
175  }
176 
177  IndexType GetHighBound(unsigned int counter) const
178  {
179  return HighBounds[counter];
180  }
181 
182  const IndexType * GetIncrements() const
183  {
184  return &(Increments[0]);
185  }
186 
187  IndexType GetIncrement(unsigned int counter) const
188  {
189  return Increments[counter];
190  }
191 
192  // Set the index of a single cell to a given value without checking the status first.
193  // If the new value exceeds the bounds, then the function sets the status to COUNTER_UNDEFINED.
194  void SetIndex(unsigned int cell, IndexType value)
195  {
196  Index[cell] = value;
197  if ( (value < LowBounds[cell]) || (HighBounds[cell] < value) )
198  Status = COUNTER_UNDEFINED;
199  }
200 
201  // Update the status of this object: first set it to COUNTER_UNDEFINED. If all the cells are
202  // in bounds, set it to COUNTER_IN_BOUNDS.
204  {
205  register int i;
206  register const int s = GetSize();
207  Status = COUNTER_UNDEFINED;
208  for (i = 0; i < s; i++) {
209  if ( (Index[i] < LowBounds[i]) || (HighBounds[i] < Index[i]) )
210  return;
211  }
212 
213  Status = COUNTER_IN_BOUNDS;
214  }
215 
218  bool IndexIsEqualTo(const nmrMultiIndexCounter & other) const;
219 
223  {
224  register int i;
225  register const int s = GetSize();
226  for (i = 0; i < s; i++) {
227  Index[i] = LowBounds[i];
228  }
229  Status = COUNTER_IN_BOUNDS;
230  }
231 
232 
233  // Set the counter to the high bounds specified in SetBounds().
234  // Set the status to COUNTER_IN_BOUNDS.
236  {
237  register int i;
238  register const int s = GetSize();
239  for (i = 0; i < s; i++) {
240  Index[i] = HighBounds[i];
241  }
242  Status = COUNTER_IN_BOUNDS;
243  }
244 
245  void GoTo(const IndexType where[])
246  {
247  register int i;
248  register const int s = GetSize();
249  for (i = 0; i < s; i++) {
250  Index[i] = where[i];
251  }
252  Status = COUNTER_UNDEFINED;
253  }
254 
268  void Increment();
269 
283  void Decrement();
284 
287  {
288  return Status;
289  }
290 
292  bool IsAboveLowBounds() const
293  {
294  return ( (GetStatus() != COUNTER_UNDEFINED) && (GetStatus() != COUNTER_UNDERFLOW) );
295  }
296 
298  bool IsBelowHighBounds() const
299  {
300  return ( (GetStatus() != COUNTER_UNDEFINED) && (GetStatus() != COUNTER_OVERFLOW) );
301  }
302 
304  bool IsBetweenBounds() const
305  {
306  return ( GetStatus() == COUNTER_IN_BOUNDS );
307  }
308 
310  unsigned long GetNumberOfCombinations() const;
311 
312 protected:
313  typedef std::vector<IndexType> CounterType;
318 
320 
321 };
322 
323 
324 #endif
#define CISST_EXPORT
Definition: cmnExportMacros.h:50
int IndexType
Definition: nmrMultiIndexCounter.h:70
void SetIndex(unsigned int cell, IndexType value)
Definition: nmrMultiIndexCounter.h:194
CounterType Increments
Definition: nmrMultiIndexCounter.h:317
Portability across compilers and operating systems tools.
std::vector< IndexType > CounterType
Definition: nmrMultiIndexCounter.h:313
void SetHighBound(unsigned int counter, IndexType bound)
Definition: nmrMultiIndexCounter.h:120
void UpdateStatus()
Definition: nmrMultiIndexCounter.h:203
CounterStatus
Definition: nmrMultiIndexCounter.h:74
const IndexType * GetLowBounds() const
Definition: nmrMultiIndexCounter.h:162
IndexType GetHighBound(unsigned int counter) const
Definition: nmrMultiIndexCounter.h:177
void SetIncrement(unsigned int counter, IndexType increment)
Definition: nmrMultiIndexCounter.h:140
static const IndexType DefaultIncrement
Definition: nmrMultiIndexCounter.h:72
CounterStatus Status
Definition: nmrMultiIndexCounter.h:319
IndexType operator[](unsigned int i) const
Definition: nmrMultiIndexCounter.h:146
bool IsBelowHighBounds() const
Definition: nmrMultiIndexCounter.h:298
void GoTo(const IndexType where[])
Definition: nmrMultiIndexCounter.h:245
CounterType Index
Definition: nmrMultiIndexCounter.h:314
CounterType HighBounds
Definition: nmrMultiIndexCounter.h:316
IndexType GetIncrement(unsigned int counter) const
Definition: nmrMultiIndexCounter.h:187
CounterType LowBounds
Definition: nmrMultiIndexCounter.h:315
const IndexType * GetIncrements() const
Definition: nmrMultiIndexCounter.h:182
void SetAllIncrements(IndexType increment)
Definition: nmrMultiIndexCounter.h:82
bool IsAboveLowBounds() const
Definition: nmrMultiIndexCounter.h:292
bool IsBetweenBounds() const
Definition: nmrMultiIndexCounter.h:304
const unsigned int * GetIndexCellsAsUnsigned() const
Definition: nmrMultiIndexCounter.h:157
void SetIncrements(const IndexType increments[])
Definition: nmrMultiIndexCounter.h:129
IndexType GetLowBound(unsigned int counter) const
Definition: nmrMultiIndexCounter.h:167
void SetBounds(const IndexType lowBounds[], const IndexType highBounds[])
Definition: nmrMultiIndexCounter.h:100
const IndexType * GetIndexCells() const
Definition: nmrMultiIndexCounter.h:151
Definition: nmrMultiIndexCounter.h:67
unsigned int GetSize() const
Definition: nmrMultiIndexCounter.h:88
CounterStatus GetStatus() const
Definition: nmrMultiIndexCounter.h:286
void GoToLowBounds()
Definition: nmrMultiIndexCounter.h:222
void SetLowBound(unsigned int counter, IndexType bound)
Definition: nmrMultiIndexCounter.h:113
void GoToHighBounds()
Definition: nmrMultiIndexCounter.h:235
Rules of exporting.
const IndexType * GetHighBounds() const
Definition: nmrMultiIndexCounter.h:172