OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
Shape.cc
Go to the documentation of this file.
1 // This file is part of the "NcML Module" project, a BES module designed
3 // to allow NcML files to be used to be used as a wrapper to add
4 // AIS to existing datasets of any format.
5 //
6 // Copyright (c) 2009 OPeNDAP, Inc.
7 // Author: Michael Johnson <m.johnson@opendap.org>
8 //
9 // For more information, please also see the main website: http://opendap.org/
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // Please see the files COPYING and COPYRIGHT for more information on the GLPL.
26 //
27 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
29 
30 #include "Shape.h"
31 #include "NCMLDebug.h"
32 #include <sstream> // for std::stringstream
33 
34 namespace ncml_module
35 {
36  typedef vector<Array::dimension>::const_iterator DimItC;
37 
40  : _dims()
41  {
42  }
43 
44  Shape::Shape(const Array& copyDimsFrom)
45  {
46  Array& from = const_cast<Array&>(copyDimsFrom);
47  Array::Dim_iter endIt = from.dim_end();
48  Array::Dim_iter it;
49  for (it = from.dim_begin(); it != endIt; ++it)
50  {
51  const Array::dimension& dim = (*it);
52  _dims.push_back(dim);
53  }
54  }
55 
56  Shape::Shape(const Shape& proto)
57  {
58  _dims = proto._dims;
59  }
60 
62  {
63  _dims.resize(0);
64  }
65 
66  Shape&
67  Shape::operator=(const Shape& rhs)
68  {
69  if (&rhs == this)
70  {
71  return *this;
72  }
73 
74  _dims = rhs._dims;
75  return *this;
76  }
77 
78  bool
79  Shape::operator==(const Shape& rhs) const
80  {
81  bool ret = true;
82 
83  // Simple dimensionality check must pass first
84  if (rhs._dims.size() != _dims.size())
85  {
86  ret = false;
87  }
88  else // then compare all the dimensions
89  {
90  for (unsigned int i=0; i<_dims.size(); ++i)
91  {
92  ret = areDimensionsEqual(_dims[i], rhs._dims[i]);
93  if (!ret) // just give up...
94  {
95  break;
96  }
97  }
98  }
99  return ret;
100  }
101 
102  bool
104  {
105  bool ret = false;
106  for (unsigned int i=0; i<_dims.size(); ++i)
107  {
108  const Array::dimension& dim = _dims[i];
109  ret |= (dim.c_size != dim.size);
110  if (ret)
111  {
112  break;
113  }
114  }
115  return ret;
116  }
117 
118  void
120  {
121  for (unsigned int i=0; i<_dims.size(); ++i)
122  {
123  Array::dimension& dim = _dims[i];
124  dim.c_size = dim.size;
125  dim.start = 0;
126  dim.stop = dim.size-1;
127  dim.stride = 1;
128  }
129  }
130 
131 
132  bool
133  Shape::areDimensionsEqual(const Array::dimension& lhs, const Array::dimension& rhs)
134  {
135  // Stolen from Array::dimension....
136  /*
137  int size; ///< The unconstrained dimension size.
138  string name; ///< The name of this dimension.
139  int start; ///< The constraint start index
140  int stop; ///< The constraint end index
141  int stride; ///< The constraint stride
142  int c_size; ///< Size of dimension once constrained
143  */
144  // Must all match
145  bool equal = true;
146  equal &= (lhs.size == rhs.size);
147  equal &= (lhs.name == rhs.name);
148  equal &= (lhs.start == rhs.start);
149  equal &= (lhs.stride == rhs.stride);
150  equal &= (lhs.c_size == rhs.c_size);
151  return equal;
152  }
153 
154  unsigned int
155  Shape::getRowMajorIndex(const IndexTuple& indices, bool validate /* = true */) const
156  {
157  if (validate && !validateIndices(indices))
158  {
159  THROW_NCML_INTERNAL_ERROR("Shape::getRowMajorIndex got indices that were out of range for the given space dimensions!");
160  }
161 
162  NCML_ASSERT(indices.size() >= 1);
163  unsigned int index = indices[0];
164  for (unsigned int i=1; i<indices.size(); ++i)
165  {
166  index = indices[i] + (_dims[i].size * index);
167  }
168  return index;
169  }
170 
173  {
174  return IndexIterator(*this, false);
175  }
176 
179  {
180  return IndexIterator(*this, true);
181  }
182 
183  std::string
185  {
186  std::stringstream sos;
187  print(sos);
188  return sos.str();
189  }
190 
191  void
192  Shape::print(std::ostream& strm) const
193  {
194  strm << "Shape = { ";
195  for (unsigned int i=0; i<_dims.size(); ++i)
196  {
197  const Array::dimension& dim = _dims[i];
198  printDimension(strm, dim);
199  }
200  strm << " }\n";
201  }
202 
203  void
204  Shape::printDimension(std::ostream& strm, const Array::dimension& dim)
205  {
206  strm << "\tDim = { \n";
207  strm << "\t\tname=" << dim.name << "\n";
208  strm << "\t\tsize=" << dim.size << "\n";
209  strm << "\t\tc_size=" << dim.c_size << "\n";
210  strm << "\t\tstart=" << dim.start << "\n";
211  strm << "\t\tstop=" << dim.stop << "\n";
212  strm << "\t\tstride=" << dim.stride << "\n";
213  }
214 
215  bool
216  Shape::validateIndices(const IndexTuple& indices) const
217  {
218  if (indices.size() != _dims.size())
219  {
220  return false;
221  }
222 
223  for (unsigned int i=0; i<_dims.size(); ++i)
224  {
225  // Must be > 0 and <= size-1
226  if (indices[i] >= static_cast<unsigned int>(_dims[i].size))
227  {
228  return false;
229  }
230  }
231 
232  return true;
233  }
234 
235 
238 
240  : _shape(0)
241  , _current()
242  , _end(true)
243  {
244  }
245 
246  Shape::IndexIterator::IndexIterator(const Shape& shape, bool isEnd/*=false*/)
247  : _shape(&shape)
248  , _current(shape.getNumDimensions()) // start with default of proper size, we'll fix it later.
249  , _end(isEnd)
250  {
251  setCurrentToStart();
252  }
253 
255  : _shape(proto._shape)
256  , _current(proto._current)
257  , _end(proto._end)
258  {
259  }
260 
262  {
263  _shape = 0;
264  _current.resize(0);
265  _end = true;
266  }
267 
270  {
271  if (this == &rhs)
272  {
273  return *this;
274  }
275 
276  _shape = rhs._shape;
277  _current = rhs._current;
278  _end = rhs._end;
279  return *this;
280  }
281 
282  bool
284  {
285  // The ptr's must be the same... It has to come from the same Shape object.
286  // We could use Shape::operator== but this is too slow for every increment.
287  if (_shape != rhs._shape)
288  {
289  return false;
290  }
291 
292  // If one has end set, the other needs to as well to be equal
293  if (_end != rhs._end)
294  {
295  return false;
296  }
297 
298  // Finally, make sure the arrays have the same values.
299  return (_current == rhs._current);
300  }
301 
320  void
321  Shape::IndexIterator::advanceCurrent()
322  {
323  // We're done already, let the caller know they goofed. This works for uninitialize with null _shape as well.
324  if (_end)
325  {
326  THROW_NCML_INTERNAL_ERROR("Shape::IndexIterator::advanceCurrent(): tried to advance beyond end()!");
327  }
328 
329  bool carry = true; // if a dimension's index wraps back to start on increment, this is set. Starts true to initiate loop.
330  unsigned int dimInd = _shape->getNumDimensions();
331  while (carry && dimInd-- > 0) // first pass will decrement this so it starts at N-1m as we desire.
332  {
333  const Array::dimension& dim = _shape->_dims[dimInd];
334  // grab the reference so we mutate the elt itself
335  unsigned int& currentDimIndex = _current[dimInd];
336  currentDimIndex += dim.stride;
337  carry = false; // assume no carry to start
338  // if we wrap, then set the carry bit to propagate the increment to the dimension to our left in the tuple
339  if (currentDimIndex > static_cast<unsigned int>(dim.stop))
340  {
341  currentDimIndex = dim.start;
342  carry = true;
343  }
344  }
345 
346  // If we end the loop with carry still set, we've wrapped the slowest varying dimension
347  // and we're back to the starting group element. Set _end!
348  if (carry)
349  {
350  _end = true;
351  }
352  }
353 
354  void
355  Shape::IndexIterator::setCurrentToStart()
356  {
357  VALID_PTR(_shape);
358  for (unsigned int i=0; i<_shape->getNumDimensions(); ++i)
359  {
360  _current[i] = _shape->_dims[i].start;
361  }
362  }
363 
364 } // namespace ncml_module
IndexIterator()
isEnd is only set by Shape for creating an end() iterator...
Definition: Shape.cc:239
Shape::IndexIterator endSpaceEnumeration() const
The end of the enumeration for testing end conditions.
Definition: Shape.cc:178
bool validateIndices(const IndexTuple &indices) const
Definition: Shape.cc:216
A custom iterator that enumerates all the points in the space defined by a Shape in row major order...
Definition: Shape.h:72
#define NCML_ASSERT(cond)
Definition: NCMLDebug.h:80
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
std::vector< unsigned int > IndexTuple
Definition: Shape.h:63
IndexIterator & operator=(const IndexIterator &rhs)
Definition: Shape.cc:269
void print(std::ostream &strm) const
Print the contents of this to the stream.
Definition: Shape.cc:192
Shape & operator=(const Shape &rhs)
Definition: Shape.cc:67
void setToUnconstrained()
Go through and set all the values to be the unconstrained values.
Definition: Shape.cc:119
A wrapper class for a vector of Array::dimension structs.
Definition: Shape.h:59
Shape()
The empty shape, with no dimensions.
Definition: Shape.cc:39
bool isConstrained() const
Are there constraints on the dimension?
Definition: Shape.cc:103
bool operator==(const IndexIterator &rhs) const
Definition: Shape.cc:283
Shape::IndexIterator beginSpaceEnumeration() const
Create a forward iterator that returns IndexTuple's in a row major order (leftmost dimension slowest ...
Definition: Shape.cc:172
static bool areDimensionsEqual(const Array::dimension &lhs, const Array::dimension &rhs)
Helper:
Definition: Shape.cc:133
#define THROW_NCML_INTERNAL_ERROR(msg)
Definition: NCMLDebug.h:61
bool operator==(const Shape &rhs) const
Return if this contains the same shape as rhs.
Definition: Shape.cc:79
std::string toString() const
Make a string that prints the contents of this.
Definition: Shape.cc:184
vector< Array::dimension >::const_iterator DimItC
Definition: Shape.cc:36
#define VALID_PTR(ptr)
Definition: NCMLDebug.h:88
unsigned int getNumDimensions() const
Definition: Shape.h:153
unsigned int getRowMajorIndex(const IndexTuple &indices, bool validate=true) const
Return the row major linear index into a slowest varying dimension first flattening of the given UNCO...
Definition: Shape.cc:155
friend class IndexIterator
Definition: Shape.h:124
static void printDimension(std::ostream &strm, const Array::dimension &dim)
Helper to print the dimension to a stream.
Definition: Shape.cc:204