CHROMA
circular_buffer.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /*! \file
3  * \brief Circular buffers
4  *
5  * Circular buffers for predictors
6  */
7 
8 #ifndef CIRCULAR_BUFFER_H
9 #define CIRCULAR_BUFFER_H
10 
11 #include "chromabase.h"
12 
13 using namespace QDP;
14 
15 namespace Chroma
16 {
17 
18  //! Circular Buffer
19  /*!
20  * @ingroup predictor
21  * Definitions for a templated circular buffer class to be used in Chronological Predictor.
22  *
23  * Usage: construct with CircularBuffer(int n_max)
24  * with n_max the maximum number of elements -- this allocates storage
25 
26  * add elements with push(elem);
27 
28  * reset with reset()
29 
30  * Access elements using operator[unsigned int i]
31  *
32  * i=0 most recent
33  * i=1 next most rcent
34  * ...
35  * i=size()-1 // least recent
36  */
37  template<typename T>
39  {
40  public:
41 
42  // Exception struct
44  OutOfBoundsException(const std::string& s, unsigned int i_, unsigned int size_) : error_string(s), i(i_), size(size_) {}
46  const unsigned int i;
47  const unsigned int size;
48  };
49 
50 
51 
52  //! Constructor
53  CircularBuffer(int n_max) : size_max(n_max), size_internal(0), start(n_max), end(n_max-1) {
54  q.resize(n_max);
55  }
56 
57  //! Destructor is automatic
59 
60  //! Copy constructor
61  CircularBuffer(const CircularBuffer<T>& c) : size_max(c.size_max),
62  size_internal(c.size), q(c.q), start(c.start), end(c.end) {}
63 
64 
65  // Operations:
66 
67  //! Nuke it:
68  void reset(void) { // Discard all circular buffer elements
69  size_internal = 0;
70  start= size_max - 1;
71  end = size_max - 1;
72  }
73 
74 
75  // Accessors This should maybe be replaced with iterators
76  // at some stage
77 
78  //! Get the maximum number of data items one can store
79  int sizeMax(void) const { // Maximum number of elements
80  return size_max;
81  }
82 
83  //! Get the current number of items stored
84  int size(void) const { // THe current number of elements
85  return size_internal;
86  }
87 
88  //! get the ith most recent item
89  void get(const unsigned int i, T& x) const
90  {
91  START_CODE();
92 
93  if( i >= size_internal ) {
94  throw OutOfBoundsException(std::string("Index Out of bounds"), i, size_internal);
95  }
96  else {
97  // Get index of ith element from start with wraparound
98  unsigned int index = (start + i) % size_max;
99  x= q[index];
100  }
101 
102  END_CODE();
103  }
104 
105  const T& operator[](int i) const
106  {
107  if( i >= size_internal ) {
108  throw OutOfBoundsException(std::string("Index Out of bounds"), i, size_internal);
109  }
110  unsigned int index = (start + i) % size_max;
111  return q[index];
112  }
113 
114  T& operator[](int i)
115  {
116  if( i >= size_internal ) {
117  throw OutOfBoundsException(std::string("Index Out of bounds"), i, size_internal);
118  }
119  unsigned int index = (start + i) % size_max;
120  return q[index];
121  }
122 
123  //! Is empty check
124  bool isEmpty(void) const {
125  return (size_internal == 0);
126  }
127 
128 
129  //! push in an item as most recent.
130  void push(const T& e)
131  {
132  START_CODE();
133 
134  if( size_internal == 0 ) {
135  // First element -- to the end of the list
136 
137  start = size_max -1; // end of list for first element
138  end = size_max -1; // first element is also last element
139 
140  q[start]=e; // store element
141 
142  size_internal = 1; // size is now 1
143  }
144  else {
145 
146  // Not empty:
147 
148  // if adding this element overruns buffer size
149  // then we drop the least recent element,
150  // and we don't increment the size of the array
151 
152  // Otherwise if adding the element doesn't exhaust buffer
153  // we decrease start(with wraparound) and increase the size.
154 
155 
156  if( size_internal+1 > size_max ) {
157  // We would exceed max size
158 
159  // decrease end pointer
160  // with wraparound -- this drops last element
161  if (end > 0) {
162  end--;
163  }
164  else {
165  end = size_max - 1;
166  }
167 
168  // decrease start pointer
169  // with wraparound
170  // the result of this that the start pointer can point
171  // to the slot just vacated by decreasing the end pointer
172  if( start > 0 ) {
173  start--;
174  }
175  else {
176  start = size_max -1;
177  }
178 
179  // copy element to start
180  q[start] = e;
181 
182  // don't increase size
183  }
184  else {
185  // We still have room before we hit max size
186  // decrease start (with wraparound of course).
187  // If there is still space we should not need to
188  // worry about overtaking the end pointer.
189  if ( start > 0 ) {
190  start--;
191  }
192  else {
193  start = size_max -1;
194  }
195 
196  // Store element
197  q[start] = e;
198 
199  // Increase size count
200  size_internal++;
201  }
202  }
203 
204  END_CODE();
205  }
206 
207  void replaceHead(const T& x)
208  {
209  q[start]=x;
210  }
211 
212 
213  private:
214  unsigned int size_max;
215  unsigned int size_internal;
216  multi1d<T> q;
217  unsigned int start; // Start index -- these move as things are added
218  unsigned int end; // End index -- these move as things are added
219  };
220 
221 
222  //! Circular buffer of arrays
223  /*! @ingroup predictor */
224  template<typename T>
226  {
227  public:
228 
229  // Exception struct
231  OutOfBoundsException(const std::string& s, unsigned int i_, unsigned int size_, unsigned int n5_) : error_string(s), i(i_), size(size_), n5(n5_) {}
233  const unsigned int i;
234  const unsigned int size;
235  const unsigned int n5;
236  };
237 
238 
240  SizeMismatchException(const std::string& s, unsigned int N5_buf_, unsigned int N5_vec_) : error_string(s), N5_buf(N5_buf_), N5_vec(N5_vec_) {}
242  const unsigned int N5_buf;
243  const unsigned int N5_vec;
244  };
245 
246  //! Constructor
247  CircularBufferArray(unsigned int n_max, unsigned int n5) : size_max(n_max), size_internal(0), start(n_max), end(n_max-1), N5(n5) {
248  q.resize(n_max, n5);
249  }
250 
251  //! Destructor is automatic
253 
254  //! Copy constructor
255  CircularBufferArray(const CircularBufferArray<T>& c) : size_max(c.size_max),
256  size_internal(c.size), q(c.q), start(c.start), end(c.end), N5(c.N5) {}
257 
258 
259  // Operations:
260 
261  //! Nuke it:
262  void reset(void) { // Discard all circular buffer elements
263  size_internal = 0;
264  start= size_max - 1;
265  end = size_max - 1;
266  }
267 
268 
269  // Accessors This should maybe be replaced with iterators
270  // at some stage
271 
272  //! Get the maximum number of data items one can store
273  int sizeMax(void) const { // Maximum number of elements
274  return size_max;
275  }
276 
277  //! Get the current number of items stored
278  int size(void) const { // THe current number of elements
279  return size_internal;
280  }
281 
282  //! get the ith most recent item
283  void get(const unsigned int i, multi1d<T>& x) const
284  {
285  START_CODE();
286 
287  if( i >= size_internal ) {
288  throw OutOfBoundsException(std::string("Index Out of bounds"), i, size_internal, N5);
289  }
290  else {
291  // Get index of ith element from start with wraparound
292  unsigned int index = (start + i) % size_max;
293 
294  x.resize(N5);
295  for(unsigned int s=0; s < N5; s++) {
296  x[s] = q[index][s];
297  }
298  }
299 
300  END_CODE();
301  }
302 
303  //! Is empty check
304  bool isEmpty(void) const {
305  return (size_internal == 0);
306  }
307 
308 
309  //! push in an item as most recent.
310  void push(const multi1d<T>& e)
311  {
312  START_CODE();
313 
314  if( static_cast<int>(e.size()) != N5) {
315  throw SizeMismatchException("Attempting to push std::vector of wrong size into circular buffer", N5, e.size());
316  }
317 
318  if( size_internal == 0 ) {
319  // First element -- to the end of the list
320 
321  start = size_max -1; // end of list for first element
322  end = size_max -1; // first element is also last element
323 
324  for(unsigned int s = 0; s < N5; s++) {
325  q[start][s]=e[s]; // store element
326  }
327 
328  size_internal = 1; // size is now 1
329  }
330  else {
331 
332  // Not empty:
333 
334  // if adding this element overruns buffer size
335  // then we drop the least recent element,
336  // and we don't increment the size of the array
337 
338  // Otherwise if adding the element doesn't exhaust buffer
339  // we decrease start(with wraparound) and increase the size.
340 
341 
342  if( size_internal+1 > size_max ) {
343  // We would exceed max size
344 
345  // decrease end pointer
346  // with wraparound -- this drops last element
347  if (end > 0) {
348  end--;
349  }
350  else {
351  end = size_max - 1;
352  }
353 
354  // decrease start pointer
355  // with wraparound
356  // the result of this that the start pointer can point
357  // to the slot just vacated by decreasing the end pointer
358  if( start > 0 ) {
359  start--;
360  }
361  else {
362  start = size_max -1;
363  }
364 
365  // copy element to start
366  for(unsigned int s = 0; s < N5; s++) {
367  q[start][s] = e[s];
368  }
369  // don't increase size
370  }
371  else {
372  // We still have room before we hit max size
373  // decrease start (with wraparound of course).
374  // If there is still space we should not need to
375  // worry about overtaking the end pointer.
376  if ( start > 0 ) {
377  start--;
378  }
379  else {
380  start = size_max -1;
381  }
382 
383  // Store element
384  for(unsigned int s = 0; s < N5; s++) {
385  q[start][s] = e[s];
386  }
387  // Increase size count
388  size_internal++;
389  }
390  }
391 
392  END_CODE();
393  }
394 
395 
396 
397  private:
398  unsigned int size_max;
399  unsigned int size_internal;
400  multi2d<T> q;
401  unsigned int start; // Start index -- these move as things are added
402  unsigned int end; // End index -- these move as things are added
403  unsigned int N5;
404  };
405 
406 } // End namespace Chroma
407 #endif
Primary include file for CHROMA library code.
#define END_CODE()
Definition: chromabase.h:65
#define START_CODE()
Definition: chromabase.h:64
Circular buffer of arrays.
int sizeMax(void) const
Get the maximum number of data items one can store.
void push(const multi1d< T > &e)
push in an item as most recent.
CircularBufferArray(const CircularBufferArray< T > &c)
Copy constructor.
bool isEmpty(void) const
Is empty check.
int size(void) const
Get the current number of items stored.
~CircularBufferArray()
Destructor is automatic.
CircularBufferArray(unsigned int n_max, unsigned int n5)
Constructor.
void get(const unsigned int i, multi1d< T > &x) const
get the ith most recent item
Circular Buffer.
CircularBuffer(int n_max)
Constructor.
void replaceHead(const T &x)
void reset(void)
Nuke it:
int sizeMax(void) const
Get the maximum number of data items one can store.
CircularBuffer(const CircularBuffer< T > &c)
Copy constructor.
int size(void) const
Get the current number of items stored.
void get(const unsigned int i, T &x) const
get the ith most recent item
bool isEmpty(void) const
Is empty check.
void push(const T &e)
push in an item as most recent.
const T & operator[](int i) const
~CircularBuffer()
Destructor is automatic.
unsigned s
Definition: ldumul_w.cc:37
unsigned i
Definition: ldumul_w.cc:34
int c
Definition: meslate.cc:61
int x
Definition: meslate.cc:34
Double q
Definition: mesq.cc:17
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
LinOpSysSolverMGProtoClover::T T
::std::string string
Definition: gtest.h:1979
OutOfBoundsException(const std::string &s, unsigned int i_, unsigned int size_, unsigned int n5_)
SizeMismatchException(const std::string &s, unsigned int N5_buf_, unsigned int N5_vec_)
OutOfBoundsException(const std::string &s, unsigned int i_, unsigned int size_)
#define index(c)