bes  Updated for version 3.20.13
Odometer.h
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2015 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #ifndef ODOMETER_H_
26 #define ODOMETER_H_
27 
28 #include <vector>
29 
30 namespace functions {
31 
56 class Odometer
57 {
58 public:
59  typedef std::vector<unsigned int> shape;
60 
61 private:
62  // The state set by the ctor
63  shape d_shape;
64  size_t d_highest_offset;
65  size_t d_rank;
66 
67  // The varying state of the Odometer
68  shape d_indices;
69  size_t d_offset{0};
70 
71 public:
80  explicit Odometer(shape shape) : d_shape(std::move(shape))
81  {
82  d_rank = d_shape.size();
83 
84  // compute the highest offset value based on the array shape
85  d_highest_offset = 1;
86  for (unsigned int i = 0; i < d_rank; ++i) {
87  d_highest_offset *= d_shape.at(i);
88  }
89 
90  d_indices.resize(d_rank, 0);
91  }
92 
97  void reset()
98  {
99  for (unsigned int i = 0; i < d_rank; ++i)
100  d_indices.at(i) = 0;
101  d_offset = 0;
102  }
103 
115  inline unsigned int next()
116  {
117  // About 2.4 seconds for 10^9 elements
118  auto si = d_shape.rbegin();
119  for (auto i = d_indices.rbegin(), e = d_indices.rend(); i != e; ++i, ++si) {
120  if (++(*i) == *si) {
121  *i = 0;
122  }
123  else {
124  break;
125  }
126  }
127 
128  return ++d_offset;
129  }
130 
131  // This version throws Error if offset() == end()
132  unsigned int next_safe();
133 
141  inline unsigned int set_indices(const shape &indices)
142  {
143  d_indices = indices;
144 
145  // I copied this algorithm from Nathan's code in NDimenensionalArray in the
146  // ugrid function module. jhrg 5/22/15
147 
148  auto shape_index = d_shape.rbegin();
149  auto index = d_indices.rbegin(), index_end = d_indices.rend();
150  d_offset = *index++;
151  unsigned int chunk_size = *shape_index++;
152  while (index != index_end) {
153  d_offset += chunk_size * *index++;
154  chunk_size *= *shape_index++;
155  }
156 
157  return d_offset;
158  }
159 
160  unsigned int set_indices(const std::vector<int> &indices)
161  {
162  shape temp;
163  std::copy(indices.begin(), indices.end(), std::back_inserter(temp));
164 
165  return set_indices(temp);
166  }
167 
174  inline void indices(shape &indices)
175  {
176  indices = d_indices;
177  }
178 
182  inline unsigned int offset()
183  {
184  return d_offset;
185  }
186 
194  inline unsigned int end()
195  {
196  return d_highest_offset;
197  }
198 
199 };
200 
201 } // namespace libdap
202 
203 #endif /* ODOMETER_H_ */
unsigned int offset()
Definition: Odometer.h:182
unsigned int set_indices(const shape &indices)
Definition: Odometer.h:141
Odometer(shape shape)
Definition: Odometer.h:80
void indices(shape &indices)
Definition: Odometer.h:174
unsigned int end()
Definition: Odometer.h:194
unsigned int next()
Definition: Odometer.h:115