MeteoIODoc  MeteoIODoc-2.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Array1D.h
Go to the documentation of this file.
1 /***********************************************************************************/
2 /* Copyright 2009 WSL Institute for Snow and Avalanche Research SLF-DAVOS */
3 /***********************************************************************************/
4 /* This file is part of MeteoIO.
5  MeteoIO is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  MeteoIO is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with MeteoIO. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #ifndef ARRAY1D_H
19 #define ARRAY1D_H
20 
21 #include <vector>
22 #include <limits>
23 #include <iostream>
24 #include <iterator>
25 
26 #include <meteoio/IOUtils.h>
27 #include <meteoio/IOExceptions.h>
28 
29 namespace mio {
30 
41 template<class T> class Array1D {
42  public:
43  Array1D(const size_t& asize=0);
44 
50  Array1D(const size_t& asize, const T& init);
51 
57  void setKeepNodata(const bool i_keep_nodata);
58 
63  bool getKeepNodata();
64 
65  void size(size_t& nx) const;
66  size_t size() const;
67  size_t getNx() const;
68 
69  void resize(const size_t& asize);
70  void resize(const size_t& asize, const T& init);
71  void clear();
72  bool empty() const;
73 
74  void insertAt(const int& index, T e);
75  void removeAt(const size_t& index);
76 
81  T getMin() const;
86  T getMax() const;
91  T getMean() const;
98  size_t getCount() const;
103  const Array1D<T> getAbs() const;
104  void abs();
105 
106 
107  const std::string toString() const;
108  template<class P> friend std::iostream& operator<<(std::iostream& os, const Array1D<P>& array);
109  template<class P> friend std::iostream& operator>>(std::iostream& is, Array1D<P>& array);
110 
111  bool checkEpsilonEquality(const Array1D<double>& rhs, const double& epsilon) const;
112  static bool checkEpsilonEquality(const Array1D<double>& rhs1, const Array1D<double>& rhs2, const double& epsilon);
113 
114  T& operator [](const size_t& index);
115  const T operator [](const size_t& index) const;
116  T& operator ()(const size_t& index);
117  const T operator ()(const size_t& index) const;
118 
120  Array1D<T>& operator =(const T& value);
121 
122  Array1D<T>& operator+=(const T& rhs);
123  const Array1D<T> operator+(const T& rhs) const;
124  Array1D<T>& operator+=(const Array1D<T>& rhs);
125  const Array1D<T> operator+(const Array1D<T>& rhs) const;
126 
127  Array1D<T>& operator-=(const T& rhs);
128  const Array1D<T> operator-(const T& rhs) const;
129  Array1D<T>& operator-=(const Array1D<T>& rhs);
130  const Array1D<T> operator-(const Array1D<T>& rhs) const;
131 
132  Array1D<T>& operator*=(const T& rhs);
133  const Array1D<T> operator*(const T& rhs) const;
134  Array1D<T>& operator*=(const Array1D<T>& rhs);
135  const Array1D<T> operator*(const Array1D<T>& rhs) const;
136 
137  Array1D<T>& operator/=(const T& rhs);
138  const Array1D<T> operator/(const T& rhs) const;
139  Array1D<T>& operator/=(const Array1D<T>& rhs);
140  const Array1D<T> operator/(const Array1D<T>& rhs) const;
141 
142  bool operator==(const Array1D<T>&) const;
143  bool operator!=(const Array1D<T>&) const;
144 
145  protected:
146  std::vector<T> vecData;
147  size_t nx;
149 };
150 
151 template<class T> Array1D<T>::Array1D(const size_t& asize)
152  : vecData(asize), nx(asize), keep_nodata(true)
153 {
154  //resize(asize);
155 }
156 
157 template<class T> Array1D<T>::Array1D(const size_t& asize, const T& init)
158  : vecData(asize, init), nx(asize), keep_nodata(true)
159 {
160  //resize(asize, init);
161 }
162 
163 template<class T> void Array1D<T>::setKeepNodata(const bool i_keep_nodata) {
164  keep_nodata = i_keep_nodata;
165 }
166 
167 template<class T> bool Array1D<T>::getKeepNodata() {
168  return keep_nodata;
169 }
170 
171 template<class T> void Array1D<T>::size(size_t& o_nx) const {
172  o_nx = nx;
173 }
174 
175 template<class T> size_t Array1D<T>::size() const {
176  return nx;
177 }
178 
179 template<class T> size_t Array1D<T>::getNx() const {
180  return nx;
181 }
182 
183 template<class T> void Array1D<T>::resize(const size_t& asize) {
184  vecData.clear();
185  vecData.resize(asize);
186  nx = asize;
187 }
188 
189 template<class T> void Array1D<T>::resize(const size_t& asize, const T& init) {
190  vecData.clear();
191  vecData.resize(asize, init);
192  nx = asize;
193 }
194 
195 template<class T> inline T& Array1D<T>::operator()(const size_t& index) {
196 #ifndef NOSAFECHECKS
197  if (index >= nx) {
198  std::stringstream ss;
199  ss << "Trying to access array(" << index << ")";
200  ss << " while array is (" << nx << ")";
201  throw IndexOutOfBoundsException(ss.str(), AT);
202  }
203 #endif
204  return vecData[index];
205 }
206 
207 template<class T> inline const T Array1D<T>::operator()(const size_t& index) const {
208 #ifndef NOSAFECHECKS
209  if (index >= nx) {
210  std::stringstream ss;
211  ss << "Trying to access array(" << index << ")";
212  ss << " while array is (" << nx << ")";
213  throw IndexOutOfBoundsException(ss.str(), AT);
214  }
215 #endif
216  return vecData[index];
217 }
218 
219 template<class T> inline T& Array1D<T>::operator [](const size_t& index) {
220 #ifndef NOSAFECHECKS
221  return vecData.at(index);
222 #else
223  return vecData[index];
224 #endif
225 }
226 
227 template<class T> inline const T Array1D<T>::operator [](const size_t& index) const {
228 #ifndef NOSAFECHECKS
229  return vecData.at(index);
230 #else
231  return vecData[index];
232 #endif
233 }
234 
235 template<class T> void Array1D<T>::clear() {
236  vecData.clear();
237  nx = 0;
238 }
239 
240 template<class T> bool Array1D<T>::empty() const {
241  return (nx==0);
242 }
243 
244 template<class T> const std::string Array1D<T>::toString() const {
245  std::stringstream os;
246  os << "<array1d>\n";
247  for (size_t ii=0; ii<nx; ii++) {
248  os << vecData[ii] << " ";
249  }
250  os << "\n</array1d>\n";
251  return os.str();
252 }
253 
254 template<class P> std::iostream& operator<<(std::iostream& os, const Array1D<P>& array) {
255  os.write(reinterpret_cast<const char*>(&array.keep_nodata), sizeof(array.keep_nodata));
256  os.write(reinterpret_cast<const char*>(&array.nx), sizeof(array.nx));
257  os.write(reinterpret_cast<const char*>(&array.vecData[0]), static_cast<std::streamsize>(array.nx*sizeof(P)));
258  return os;
259 }
260 
261 template<class P> std::iostream& operator>>(std::iostream& is, Array1D<P>& array) {
262  is.read(reinterpret_cast<char*>(&array.keep_nodata), sizeof(array.keep_nodata));
263  is.read(reinterpret_cast<char*>(&array.nx), sizeof(array.nx));
264  array.vecData.resize(array.nx);
265  is.read(reinterpret_cast<char*>(&array.vecData[0]), static_cast<std::streamsize>(array.nx*sizeof(P))); //30 times faster than assign() or copy()
266  return is;
267 }
268 
269 template<class T> void Array1D<T>::insertAt(const int& index, T e) {
270  if (index < 0) {
271  vecData.push_back(e);
272  nx++;
273  } else if ((index >= 0) && (index < (int)vecData.size())) {
274  vecData.insert(vecData.begin() + index, e);
275  nx++;
276  } else {
277  std::stringstream ss;
278  ss << "Inserting an element at (" << index << ") in an array of size [" << nx << "]";
279  throw IndexOutOfBoundsException(ss.str(), AT);
280  }
281 }
282 
283 template<class T> void Array1D<T>::removeAt(const size_t& index) {
284  if (index < vecData.size()) {
285  vecData.erase(vecData.begin()+index);
286  nx--;
287  }
288 }
289 
290 template<class T> T Array1D<T>::getMin() const {
291 
292  T min = std::numeric_limits<T>::max();
293 
294  if (keep_nodata==false) {
295  for (size_t ii=0; ii<nx; ii++) {
296  const T val = vecData[ii];
297  if (val<min) min=val;
298  }
299  return min;
300  } else {
301  for (size_t ii=0; ii<nx; ii++) {
302  const T val = vecData[ii];
303  if (val!=IOUtils::nodata && val<min) min=val;
304  }
305  if (min!=std::numeric_limits<T>::max()) return min;
306  else return (T)IOUtils::nodata;
307  }
308 }
309 
310 template<class T> T Array1D<T>::getMax() const {
311 
312  T max = -std::numeric_limits<T>::max();
313 
314  if (keep_nodata==false) {
315  for (size_t ii=0; ii<nx; ii++) {
316  const T val = vecData[ii];
317  if (val>max) max=val;
318  }
319  return max;
320  } else {
321  for (size_t ii=0; ii<nx; ii++) {
322  const T val = vecData[ii];
323  if (val!=IOUtils::nodata && val>max) max=val;
324  }
325  if (max!=-std::numeric_limits<T>::max()) return max;
326  else return (T)IOUtils::nodata;
327  }
328 }
329 
330 template<class T> T Array1D<T>::getMean() const {
331 
332  T mean = 0;
333 
334  if (keep_nodata==false) {
335  for (size_t ii=0; ii<nx; ii++) {
336  const T val = vecData[ii];
337  mean += val;
338  }
339  const size_t count = nx;
340  if (count>0) return mean/(T)(count);
341  else return (T)0;
342  } else {
343  size_t count = 0;
344  for (size_t ii=0; ii<nx; ii++) {
345  const T val = vecData[ii];
346  if (val!=IOUtils::nodata) {
347  mean += val;
348  count++;
349  }
350  }
351  if (count>0) return mean/(T)(count);
352  else return (T)IOUtils::nodata;
353  }
354 }
355 
356 template<class T> size_t Array1D<T>::getCount() const
357 {
358  if (keep_nodata==false) {
359  return (size_t)nx;
360  } else {
361  size_t count = 0;
362  for (size_t ii=0; ii<nx; ii++) {
363  if (vecData[ii]!=IOUtils::nodata) count++;
364  }
365  return count;
366  }
367 }
368 
369 template<class T> void Array1D<T>::abs() {
370  if (std::numeric_limits<T>::is_signed) {
371  if (keep_nodata==false) {
372  for (size_t ii=0; ii<nx; ii++) {
373  T& val = vecData[ii];
374  if (val<0) val=-val;
375  }
376  } else {
377  for (size_t ii=0; ii<nx; ii++) {
378  T& val = vecData[ii];
379  if (val<0 && val!=IOUtils::nodata) val=-val;
380  }
381  }
382  }
383 }
384 
385 template<class T> const Array1D<T> Array1D<T>::getAbs() const {
386  Array1D<T> result(*this); //make a copy
387  result.abs(); //already implemented
388 
389  return result;
390 }
391 
392 //arithmetic operators
393 template<class T> bool Array1D<T>::checkEpsilonEquality(const Array1D<double>& rhs, const double& epsilon) const {
394  if (nx!=rhs.nx) return false;
395 
396  for (size_t jj=0; jj<nx; jj++)
397  if (IOUtils::checkEpsilonEquality(vecData[jj], rhs.vecData[jj], epsilon)==false) return false;
398 
399  return true;
400 }
401 
402 template<class T> bool Array1D<T>::checkEpsilonEquality(const Array1D<double>& rhs1, const Array1D<double>& rhs2, const double& epsilon) {
403  return rhs1.checkEpsilonEquality(rhs2, epsilon);
404 }
405 
406 template<class T> Array1D<T>& Array1D<T>::operator=(const Array1D<T>& source) {
407  if (this != &source) {
408  vecData = source.vecData;
409  nx = source.nx;
410  keep_nodata = source.keep_nodata;
411  }
412  return *this;
413 }
414 
415 template<class T> Array1D<T>& Array1D<T>::operator=(const T& value) {
416  //reset every single member of the Array1D<T>
417  std::fill(vecData.begin(), vecData.end(), value);
418  return *this;
419 }
420 
421 template<class T> Array1D<T>& Array1D<T>::operator+=(const Array1D<T>& rhs)
422 {
423  //They have to have equal size
424  if (rhs.nx != nx) {
425  std::stringstream ss;
426  ss << "Trying to add two Array1D objects with different dimensions: ";
427  ss << "(" << nx << ") + (" << rhs.nx << ")";
428  throw IOException(ss.str(), AT);
429  }
430 
431  //Add to every single member of the Array1D<T>
432  if (keep_nodata==false) {
433  for (size_t ii=0; ii<nx; ii++) {
434  vecData[ii] += rhs(ii);
435  }
436  } else {
437  for (size_t ii=0; ii<nx; ii++) {
438  if (vecData[ii]==IOUtils::nodata || rhs(ii)==IOUtils::nodata)
439  vecData[ii] = IOUtils::nodata;
440  else
441  vecData[ii] += rhs(ii);
442  }
443  }
444 
445  return *this;
446 }
447 
448 template<class T> const Array1D<T> Array1D<T>::operator+(const Array1D<T>& rhs) const
449 {
450  Array1D<T> result(*this); //make a copy
451  result += rhs; //already implemented
452 
453  return result;
454 }
455 
456 template<class T> Array1D<T>& Array1D<T>::operator+=(const T& rhs)
457 {
458  if (rhs==0.) return *this;
459 
460  //Add to every single member of the Array1D<T>
461  if (keep_nodata==false) {
462  for (size_t ii=0; ii<nx; ii++) {
463  vecData[ii] += rhs;
464  }
465  } else {
466  for (size_t ii=0; ii<nx; ii++) {
467  if (vecData[ii]!=IOUtils::nodata)
468  vecData[ii] += rhs;
469  }
470  }
471 
472  return *this;
473 }
474 
475 template<class T> const Array1D<T> Array1D<T>::operator+(const T& rhs) const
476 {
477  Array1D<T> result(*this);
478  result += rhs; //already implemented
479 
480  return result;
481 }
482 
483 template<class T> Array1D<T>& Array1D<T>::operator-=(const Array1D<T>& rhs)
484 {
485  //They have to have equal size
486  if (rhs.nx != nx) {
487  std::stringstream ss;
488  ss << "Trying to substract two Array1D objects with different dimensions: ";
489  ss << "(" << nx << ") - (" << rhs.nx << ")";
490  throw IOException(ss.str(), AT);
491  }
492 
493  //Substract to every single member of the Array1D<T>
494  if (keep_nodata==false) {
495  for (size_t ii=0; ii<nx; ii++) {
496  vecData[ii] -= rhs(ii);
497  }
498  } else {
499  for (size_t ii=0; ii<nx; ii++) {
500  if (vecData[ii]==IOUtils::nodata || rhs(ii)==IOUtils::nodata)
501  vecData[ii] = IOUtils::nodata;
502  else
503  vecData[ii] -= rhs(ii);
504  }
505  }
506 
507  return *this;
508 }
509 
510 template<class T> const Array1D<T> Array1D<T>::operator-(const Array1D<T>& rhs) const
511 {
512  Array1D<T> result(*this); //make a copy
513  result -= rhs; //already implemented
514 
515  return result;
516 }
517 
518 template<class T> Array1D<T>& Array1D<T>::operator-=(const T& rhs)
519 {
520  *this += -rhs;
521  return *this;
522 }
523 
524 template<class T> const Array1D<T> Array1D<T>::operator-(const T& rhs) const
525 {
526  Array1D<T> result(*this);
527  result += -rhs; //already implemented
528 
529  return result;
530 }
531 
532 template<class T> Array1D<T>& Array1D<T>::operator*=(const Array1D<T>& rhs)
533 {
534  //They have to have equal size
535  if (rhs.nx != nx){
536  std::stringstream ss;
537  ss << "Trying to multiply two Array1D objects with different dimensions: ";
538  ss << "(" << nx << ") * (" << rhs.nx << ")";
539  throw IOException(ss.str(), AT);
540  }
541  //Multiply every single member of the Array1D<T>
542  if (keep_nodata==false) {
543  for (size_t ii=0; ii<nx; ii++) {
544  vecData[ii] *= rhs(ii);
545  }
546  } else {
547  for (size_t ii=0; ii<nx; ii++) {
548  if (vecData[ii]==IOUtils::nodata || rhs(ii)==IOUtils::nodata)
549  vecData[ii] = IOUtils::nodata;
550  else
551  vecData[ii] *= rhs(ii);
552  }
553  }
554 
555  return *this;
556 }
557 
558 template<class T> const Array1D<T> Array1D<T>::operator*(const Array1D<T>& rhs) const
559 {
560  Array1D<T> result(*this); //make a copy
561  result *= rhs; //already implemented
562 
563  return result;
564 }
565 
566 template<class T> Array1D<T>& Array1D<T>::operator*=(const T& rhs)
567 {
568  if (rhs==1.) return *this;
569 
570  //Multiply every single member of the Array1D<T>
571  if (keep_nodata==false) {
572  for (size_t ii=0; ii<nx; ii++) {
573  vecData[ii] *= rhs;
574  }
575  } else {
576  for (size_t ii=0; ii<nx; ii++) {
577  if (vecData[ii]!=IOUtils::nodata)
578  vecData[ii] *= rhs;
579  }
580  }
581 
582  return *this;
583 }
584 
585 template<class T> const Array1D<T> Array1D<T>::operator*(const T& rhs) const
586 {
587  Array1D<T> result(*this);
588  result *= rhs; //already implemented
589 
590  return result;
591 }
592 
593 template<class T> Array1D<T>& Array1D<T>::operator/=(const Array1D<T>& rhs)
594 {
595  //They have to have equal size
596  if (rhs.nx != nx){
597  std::stringstream ss;
598  ss << "Trying to divide two Array1D objects with different dimensions: ";
599  ss << "(" << nx << ") / (" << rhs.nx << ")";
600  throw IOException(ss.str(), AT);
601  }
602  //Divide every single member of the Array1D<T>
603  if (keep_nodata==false) {
604  for (size_t ii=0; ii<nx; ii++) {
605  vecData[ii] /= rhs(ii);
606  }
607  } else {
608  for (size_t ii=0; ii<nx; ii++) {
609  if (vecData[ii]==IOUtils::nodata || rhs(ii)==IOUtils::nodata)
610  vecData[ii] = IOUtils::nodata;
611  else
612  vecData[ii] /= rhs(ii);
613  }
614  }
615 
616  return *this;
617 }
618 
619 template<class T> const Array1D<T> Array1D<T>::operator/(const Array1D<T>& rhs) const
620 {
621  Array1D<T> result(*this); //make a copy
622  result /= rhs; //already implemented
623 
624  return result;
625 }
626 
627 template<class T> Array1D<T>& Array1D<T>::operator/=(const T& rhs)
628 {
629  *this *= (1./rhs);
630  return *this;
631 }
632 
633 template<class T> const Array1D<T> Array1D<T>::operator/(const T& rhs) const
634 {
635  Array1D<T> result(*this);
636  result *= 1./rhs; //already implemented
637 
638  return result;
639 }
640 
641 template<class T> bool Array1D<T>::operator==(const Array1D<T>& in) const {
642  const size_t in_nx = in.getNx();
643 
644  if (nx!=in_nx)
645  return false;
646 
647  for (size_t jj=0; jj<nx; jj++)
648  if ( !IOUtils::checkEpsilonEquality( vecData[jj] , in.vecData[jj], 1e-6) ) return false;
649 
650  return true;
651 }
652 
653 template<class T> bool Array1D<T>::operator!=(const Array1D<T>& in) const {
654  return !(*this==in);
655 }
656 
657 } //end namespace mio
658 
659 #endif
void resize(const size_t &asize)
Definition: Array1D.h:183
std::vector< T > vecData
the actual data structure, that holds the objects of type T
Definition: Array1D.h:146
T getMin() const
returns the minimum value contained in the grid
Definition: Array1D.h:290
const std::string toString() const
Definition: Array1D.h:244
void abs()
Definition: Array1D.h:369
const Array1D< T > operator*(const T &rhs) const
Definition: Array1D.h:585
Array1D< T > & operator=(const Array1D< T > &)
Definition: Array1D.h:406
T getMax() const
returns the maximum value contained in the grid
Definition: Array1D.h:310
size_t getNx() const
Definition: Array1D.h:179
bool keep_nodata
Definition: Array1D.h:148
size_t size() const
Definition: Array1D.h:175
T & operator()(const size_t &index)
Definition: Array1D.h:195
bool checkEpsilonEquality(const double &val1, const double &val2, const double &epsilon)
Check whether two values are equal regarding a certain epsilon environment (within certain radius of ...
Definition: IOUtils.h:81
bool operator!=(const Array1D< T > &) const
Operator that tests for inequality.
Definition: Array1D.h:653
T getMean() const
returns the mean value contained in the grid
Definition: Array1D.h:330
const Array1D< T > getAbs() const
returns the grid of the absolute value of values contained in the grid
Definition: Array1D.h:385
size_t nx
this is introduced to omit the costly vecData.size()
Definition: Array1D.h:147
bool getKeepNodata()
get how to process nodata values (ie: as nodata or as normal numbers)
Definition: Array1D.h:167
bool checkEpsilonEquality(const Array1D< double > &rhs, const double &epsilon) const
Definition: Array1D.h:393
Array1D< T > & operator-=(const T &rhs)
Definition: Array1D.h:518
bool empty() const
Definition: Array1D.h:240
void clear()
Definition: Array1D.h:235
size_t getCount() const
returns the number of points contained in the grid. If setNodataHandling(IOUtils::RAW_NODATA), then the number of points is the size of the grid. If setNodataHandling(IOUtils::PARSE_NODATA), then it is the number of non-nodata values in the grid
Definition: Array1D.h:356
Array1D(const size_t &asize=0)
Definition: Array1D.h:151
const Array1D< T > operator-(const T &rhs) const
Definition: Array1D.h:524
void setKeepNodata(const bool i_keep_nodata)
set how to process nodata values (ie: as nodata or as normal numbers)
Definition: Array1D.h:163
#define AT
Definition: IOExceptions.h:29
friend std::iostream & operator>>(std::iostream &is, Array1D< P > &array)
Definition: Array1D.h:261
const double nodata
This is the internal nodata value.
Definition: IOUtils.h:60
Array1D< T > & operator*=(const T &rhs)
Definition: Array1D.h:566
Array1D< T > & operator+=(const T &rhs)
Definition: Array1D.h:456
bool operator==(const Array1D< T > &) const
Operator that tests for equality.
Definition: Array1D.h:641
The template class Array1D is a 1D array (vector) able to hold any type of object as datatype...
Definition: Array1D.h:41
const Array1D< T > operator+(const T &rhs) const
Definition: Array1D.h:475
thrown when an index is out of bounds
Definition: IOExceptions.h:108
const double e
Definition: Meteoconst.h:66
The basic exception class adjusted for the needs of SLF software.
Definition: IOExceptions.h:41
const Array1D< T > operator/(const T &rhs) const
Definition: Array1D.h:633
void insertAt(const int &index, T e)
Definition: Array1D.h:269
T & operator[](const size_t &index)
Definition: Array1D.h:219
std::iostream & operator>>(std::iostream &is, Config &cfg)
Definition: Config.cc:141
void removeAt(const size_t &index)
Definition: Array1D.h:283
Array1D< T > & operator/=(const T &rhs)
Definition: Array1D.h:627
value::array array
Definition: picojson.h:194