MeteoIODoc  MeteoIODoc-2.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Array2D.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 ARRAY2D_H
19 #define ARRAY2D_H
20 
21 #include <meteoio/IOExceptions.h>
22 #include <meteoio/IOUtils.h>
23 
24 #include <vector>
25 #include <limits>
26 #include <iostream>
27 
28 //forward declaration
29 namespace mio { template <class T> class Array2D; }
31 
32 namespace mio {
40 template <class T> class Array2DProxy {
41  public:
42  friend class Array2D<T>;
43  T& operator[](const size_t& j) {
44  return array2D(anx, j);
45  }
46 
47  private:
48  Array2DProxy(Array2D<T>& i_array2D, const size_t& i_anx) : array2D(i_array2D), anx(i_anx){}
49  Array2D<T>& array2D;
50  const size_t anx;
51 };
52 
62 template<class T> class Array2D {
63  public:
64  Array2D();
65 
71  Array2D(const size_t& anx, const size_t& any);
72 
79  Array2D(const size_t& anx, const size_t& any, const T& init);
80 
81  virtual ~Array2D();
82 
93  Array2D(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
94  const size_t& i_ncols, const size_t& i_nrows);
95 
101  Array2D(const Array3D<T>& array3D, const size_t& depth);
102 
113  void subset(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
114  const size_t& i_ncols, const size_t& i_nrows);
115 
126  void fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
127  const size_t& i_ncols, const size_t& i_nrows);
128 
129  void fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny);
130 
136  void setKeepNodata(const bool i_keep_nodata);
137 
142  bool getKeepNodata() const;
143 
144  void resize(const size_t& nx, const size_t& ny);
145  void resize(const size_t& nx, const size_t& ny, const T& init);
146  void size(size_t& nx, size_t& ny) const;
147  size_t size() const;
148  size_t getNx() const;
149  size_t getNy() const;
150 
151  void clear();
152  bool empty() const;
153 
158  T getMin() const;
163  T getMax() const;
168  T getMean() const;
175  size_t getCount() const;
180  const Array2D<T> getAbs() const;
181  void abs();
182 
183  const std::string toString() const;
184  template<class P> friend std::iostream& operator<<(std::iostream& os, const Array2D<P>& array);
185  template<class P> friend std::iostream& operator>>(std::iostream& is, Array2D<P>& array);
186 
187  bool checkEpsilonEquality(const Array2D<double>& rhs, const double& epsilon) const;
188  static bool checkEpsilonEquality(const Array2D<double>& rhs1, const Array2D<double>& rhs2, const double& epsilon);
189 
190  T& operator ()(const size_t& x, const size_t& y);
191  const T operator ()(const size_t& x, const size_t& y) const;
192  T& operator ()(const size_t& i);
193  const T operator ()(const size_t& i) const;
194  Array2DProxy<T> operator[](const size_t& i);
195 
196  Array2D<T>& operator =(const Array2D<T>&);
197  Array2D<T>& operator =(const T& value);
198 
199  Array2D<T>& operator+=(const T& rhs);
200  const Array2D<T> operator+(const T& rhs) const;
201  Array2D<T>& operator+=(const Array2D<T>& rhs);
202  const Array2D<T> operator+(const Array2D<T>& rhs) const;
203 
204  Array2D<T>& operator-=(const T& rhs);
205  const Array2D<T> operator-(const T& rhs) const;
206  Array2D<T>& operator-=(const Array2D<T>& rhs);
207  const Array2D<T> operator-(const Array2D<T>& rhs) const;
208 
209  Array2D<T>& operator*=(const T& rhs);
210  const Array2D<T> operator*(const T& rhs) const;
211  Array2D<T>& operator*=(const Array2D<T>& rhs);
212  const Array2D<T> operator*(const Array2D<T>& rhs) const;
213 
214  Array2D<T>& operator/=(const T& rhs);
215  const Array2D<T> operator/(const T& rhs) const;
216  Array2D<T>& operator/=(const Array2D<T>& rhs);
217  const Array2D<T> operator/(const Array2D<T>& rhs) const;
218 
219  bool operator==(const Array2D<T>&) const;
220  bool operator!=(const Array2D<T>&) const;
221 
222  protected:
223  std::vector<T> vecData;
224  size_t nx;
225  size_t ny;
227 };
228 
229 template<class T> inline T& Array2D<T>::operator()(const size_t& i) {
230 #ifndef NOSAFECHECKS
231  return vecData.at(i);
232 #else
233  return vecData[i];
234 #endif
235 }
236 
237 template<class T> inline const T Array2D<T>::operator()(const size_t& i) const {
238 #ifndef NOSAFECHECKS
239  return vecData.at(i);
240 #else
241  return vecData[i];
242 #endif
243 }
244 template<class T> inline T& Array2D<T>::operator()(const size_t& x, const size_t& y) {
245 #ifndef NOSAFECHECKS
246  if ((x >= nx) || (y >= ny)) {
247  std::stringstream ss;
248  ss << "Trying to access array(" << x << "," << y << ")";
249  ss << " while array is (" << nx << "," << ny << ")";
250  throw IndexOutOfBoundsException(ss.str(), AT);
251  }
252 #endif
253  //COLUMN-MAJOR alignment of the vector: fully C-compatible memory layout
254  return vecData[x + y*nx];
255 }
256 
257 template<class T> inline const T Array2D<T>::operator()(const size_t& x, const size_t& y) const {
258 #ifndef NOSAFECHECKS
259  if ((x >= nx) || (y >= ny)) {
260  std::stringstream ss;
261  ss << "Trying to access array(" << x << "," << y << ")";
262  ss << " while array is (" << nx << "," << ny << ")";
263  throw IndexOutOfBoundsException(ss.str(), AT);
264  }
265 #endif
266  return vecData[x + y*nx];
267 }
268 
269 template<class T> Array2DProxy<T> Array2D<T>::operator[](const size_t& i) {
270  return Array2DProxy<T>(*this, i);
271 }
272 
273 template<class T> Array2D<T>::Array2D() : vecData(), nx(0), ny(0), keep_nodata(true)
274 {
275 }
276 
277 template<class T> Array2D<T>::~Array2D() { }
278 
279 template<class T> Array2D<T>::Array2D(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
280  const size_t& i_ncols, const size_t& i_nrows) :
281  vecData(i_ncols*i_nrows), nx(i_ncols), ny(i_nrows), keep_nodata(true)
282 {
283  subset(i_array2D, i_nx, i_ny, i_ncols, i_nrows);
284 }
285 
286 template<class T> Array2D<T>::Array2D(const Array3D<T>& array3D, const size_t& depth)
287  : vecData(array3D.getNx()*array3D.getNy()), nx(array3D.getNx()), ny(array3D.getNy()), keep_nodata(array3D.getKeepNodata())
288 {
289  //copy plane in the correct position
290  for (size_t jj=0; jj<ny; jj++) {
291  for (size_t ii=0; ii<nx; ii++) {
292  operator()(ii,jj) = array3D(ii, jj, depth);
293  }
294  }
295 }
296 
297 template<class T> void Array2D<T>::subset(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
298  const size_t& i_ncols, const size_t& i_nrows)
299 {
300  if (((i_nx+i_ncols) > i_array2D.nx) || ((i_ny+i_nrows) > i_array2D.ny)) {
301  std::stringstream ss;
302  ss << "Trying to cut an array of size (" << i_array2D.nx << "," << i_array2D.ny << ") ";
303  ss << "to size (" << i_ncols << "," << i_nrows << ") starting at (" << i_nx << "," << i_ny << ")";
304  throw IndexOutOfBoundsException(ss.str(), AT);
305  }
306 
307  if ((i_ncols == 0) || (i_nrows == 0)) //the plane to copy has to make sense
308  throw IndexOutOfBoundsException("Trying to cut an array into a null sized array!", AT);
309 
310  resize(i_ncols, i_nrows); //create new Array2D object
311  //Copy by value subspace
312  for (size_t jj=0; jj<ny; jj++) {
313  for (size_t ii=0; ii<nx; ii++) {
314  operator()(ii,jj) = i_array2D(i_nx+ii, i_ny+jj);
315  }
316  }
317 }
318 
319 template<class T> void Array2D<T>::fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny)
320 {
321  size_t i_ncols, i_nrows;
322  i_array2D.size(i_ncols, i_nrows);
323  fill(i_array2D, i_nx, i_ny, i_ncols, i_nrows);
324 }
325 
326 template<class T> void Array2D<T>::fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
327  const size_t& i_ncols, const size_t& i_nrows)
328 {
329  if (((i_nx+i_ncols) > nx) || ((i_ny+i_nrows) > ny)) {
330  std::stringstream ss;
331  ss << "Filling an array of size (" << nx << "," << ny << ") ";
332  ss << "with an array of size (" << i_ncols << "," << i_nrows << ") ";
333  ss << "starting at (" << i_nx << "," << i_ny << ")";
334  throw IndexOutOfBoundsException(ss.str(), AT);
335  }
336 
337  if ((i_ncols == 0) || (i_nrows == 0)) //the plane to copy has to make sense
338  throw IndexOutOfBoundsException("Filling an array with a null sized array!", AT);
339 
340  for (size_t jj=i_ny; jj<(i_ny+i_nrows); jj++) {
341  for (size_t ii=i_nx; ii<(i_nx+i_ncols); ii++) {
342  const size_t ix = ii-i_nx;
343  const size_t iy = jj-i_ny;
344  operator()(ii,jj) = i_array2D(ix, iy);
345  }
346  }
347 }
348 
349 template<class T> Array2D<T>::Array2D(const size_t& anx, const size_t& any, const T& init) :
350  vecData(anx*any, init), nx(anx), ny(any), keep_nodata(true) {}
351 
352 template<class T> Array2D<T>::Array2D(const size_t& anx, const size_t& any) :
353  vecData(anx*any), nx(anx), ny(any), keep_nodata(true) {}
354 
355 template<class T> void Array2D<T>::setKeepNodata(const bool i_keep_nodata) {
356  keep_nodata = i_keep_nodata;
357 }
358 
359 template<class T> bool Array2D<T>::getKeepNodata() const {
360  return keep_nodata;
361 }
362 
363 template<class T> void Array2D<T>::resize(const size_t& anx, const size_t& any) {
364  clear(); //we won't be able to "rescue" old values, so we reset the whole vector
365  vecData.resize(anx*any);
366  nx = anx;
367  ny = any;
368 }
369 
370 template<class T> void Array2D<T>::resize(const size_t& anx, const size_t& any, const T& init) {
371  clear(); //we won't be able to "rescue" old values, so we reset the whole vector
372  vecData.resize(anx*any, init);
373  nx = anx;
374  ny = any;
375 }
376 
377 template<class T> void Array2D<T>::size(size_t& anx, size_t& any) const {
378  anx=nx;
379  any=ny;
380 }
381 
382 template<class T> size_t Array2D<T>::size() const {
383  return nx*ny;
384 }
385 
386 template<class T> size_t Array2D<T>::getNx() const {
387  return nx;
388 }
389 
390 template<class T> size_t Array2D<T>::getNy() const {
391  return ny;
392 }
393 
394 template<class T> void Array2D<T>::clear() {
395  vecData.clear();
396  nx=ny=0;
397 }
398 
399 template<class T> bool Array2D<T>::empty() const {
400  return (nx==0 && ny==0);
401 }
402 
403 template<class T> const std::string Array2D<T>::toString() const {
404  std::ostringstream os;
405  os << "<array2d>\n";
406  for (size_t jj=0; jj<ny; jj++) {
407  const size_t jnx = jj*nx;
408  for (size_t ii=0; ii<nx; ii++) {
409  os << vecData[ii+jnx] << " "; //COLUMN-MAJOR alignment
410  }
411  os << "\n";
412  }
413  os << "</array2d>\n";
414  return os.str();
415 }
416 
417 template<class P> std::iostream& operator<<(std::iostream& os, const Array2D<P>& array) {
418  os.write(reinterpret_cast<const char*>(&array.keep_nodata), sizeof(array.keep_nodata));
419  os.write(reinterpret_cast<const char*>(&array.nx), sizeof(array.nx));
420  os.write(reinterpret_cast<const char*>(&array.ny), sizeof(array.ny));
421  os.write(reinterpret_cast<const char*>(&array.vecData[0]), static_cast<std::streamsize>(array.nx*array.ny*sizeof(P)));
422  return os;
423 }
424 
425 template<class P> std::iostream& operator>>(std::iostream& is, Array2D<P>& array) {
426  is.read(reinterpret_cast<char*>(&array.keep_nodata), sizeof(array.keep_nodata));
427  is.read(reinterpret_cast<char*>(&array.nx), sizeof(array.nx));
428  is.read(reinterpret_cast<char*>(&array.ny), sizeof(array.ny));
429  array.vecData.resize(array.nx*array.ny);
430  is.read(reinterpret_cast<char*>(&array.vecData[0]), static_cast<std::streamsize>(array.nx*array.ny*sizeof(P))); //30 times faster than assign() or copy()
431  return is;
432 }
433 
434 template<class T> T Array2D<T>::getMin() const {
435 
436  T min = std::numeric_limits<T>::max();
437 
438  const size_t nxy = ny*nx;
439  if (keep_nodata==false) {
440  for (size_t jj=0; jj<nxy; jj++) {
441  const T val = vecData[jj];
442  if (val<min) min=val;
443  }
444  return min;
445  } else {
446  for (size_t jj=0; jj<nxy; jj++) {
447  const T val = vecData[jj];
448  if (val!=IOUtils::nodata && val<min) min=val;
449  }
450  if (min!=std::numeric_limits<T>::max()) return min;
451  else return (T)IOUtils::nodata;
452  }
453 }
454 
455 template<class T> T Array2D<T>::getMax() const {
456 
457  T max = -std::numeric_limits<T>::max();
458 
459  const size_t nxy = ny*nx;
460  if (keep_nodata==false) {
461  for (size_t jj=0; jj<nxy; jj++) {
462  const T val = vecData[jj];
463  if (val>max) max=val;
464  }
465  return max;
466  } else {
467  for (size_t jj=0; jj<nxy; jj++) {
468  const T val = vecData[jj];
469  if (val!=IOUtils::nodata && val>max) max=val;
470  }
471  if (max!=-std::numeric_limits<T>::max()) return max;
472  else return (T)IOUtils::nodata;
473  }
474 }
475 
476 template<class T> T Array2D<T>::getMean() const {
477 
478  T mean = 0;
479  const size_t nxy = nx*ny;
480 
481  if (keep_nodata==false) {
482  for (size_t jj=0; jj<nxy; jj++) {
483  const T val = vecData[jj];
484  mean += val;
485  }
486  if (nxy>0) return mean/(T)(nxy);
487  else return (T)0;
488  } else {
489  size_t count = 0;
490  for (size_t jj=0; jj<nxy; jj++) {
491  const T val = vecData[jj];
492  if (val!=IOUtils::nodata) {
493  mean += val;
494  count++;
495  }
496  }
497  if (count>0) return mean/(T)(count);
498  else return (T)IOUtils::nodata;
499  }
500 }
501 
502 template<class T> size_t Array2D<T>::getCount() const
503 {
504  const size_t nxy = nx*ny;
505 
506  if (keep_nodata==false) {
507  return (size_t)nxy;
508  } else {
509  size_t count = 0;
510  for (size_t ii=0; ii<nxy; ii++) {
511  if (vecData[ii]!=IOUtils::nodata) count++;
512  }
513  return count;
514  }
515 }
516 
517 template<class T> void Array2D<T>::abs() {
518  if (std::numeric_limits<T>::is_signed) {
519  const size_t nxy = nx*ny;
520  if (keep_nodata==false) {
521  for (size_t ii=0; ii<nxy; ii++) {
522  T& val = vecData[ii];
523  if (val<0) val=-val;
524  }
525  } else {
526  for (size_t ii=0; ii<nxy; ii++) {
527  T& val = vecData[ii];
528  if (val<0 && val!=IOUtils::nodata) val=-val;
529  }
530  }
531  }
532 }
533 
534 template<class T> const Array2D<T> Array2D<T>::getAbs() const {
535  Array2D<T> result(*this); //make a copy
536  result.abs(); //already implemented
537 
538  return result;
539 }
540 
541 
542 //arithmetic operators
543 template<class T> bool Array2D<T>::checkEpsilonEquality(const Array2D<double>& rhs, const double& epsilon) const {
544  if (nx!=rhs.nx || ny!=rhs.ny) return false;
545 
546  const size_t nxy = nx*ny;
547  for (size_t jj=0; jj<nxy; jj++)
548  if (IOUtils::checkEpsilonEquality(vecData[jj], rhs.vecData[jj], epsilon)==false) return false;
549 
550  return true;
551 }
552 
553 template<class T> bool Array2D<T>::checkEpsilonEquality(const Array2D<double>& rhs1, const Array2D<double>& rhs2, const double& epsilon) { //static
554  return rhs1.checkEpsilonEquality(rhs2, epsilon);
555 }
556 
557 template<class T> Array2D<T>& Array2D<T>::operator=(const Array2D<T>& source) {
558  if (this != &source) {
559  keep_nodata = source.keep_nodata;
560  nx = source.nx;
561  ny = source.ny;
562  vecData = source.vecData;
563  }
564  return *this;
565 }
566 
567 template<class T> Array2D<T>& Array2D<T>::operator=(const T& value) {
568  std::fill(vecData.begin(), vecData.end(), value);
569  return *this;
570 }
571 
572 template<class T> Array2D<T>& Array2D<T>::operator+=(const Array2D<T>& rhs)
573 {
574  //They have to have equal size
575  if ((rhs.nx != nx) || (rhs.ny != ny)) {
576  std::stringstream ss;
577  ss << "Trying to add two Array2D objects with different dimensions: ";
578  ss << "(" << nx << "," << ny << ") + (" << rhs.nx << "," << rhs.ny << ")";
579  throw IOException(ss.str(), AT);
580  }
581 
582  const size_t nxy = nx*ny;
583  //Add to every single member of the Array2D<T>
584  if (keep_nodata==false) {
585  for (size_t jj=0; jj<nxy; jj++)
586  vecData[jj] += rhs(jj);
587  } else {
588  for (size_t jj=0; jj<nxy; jj++) {
589  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
590  vecData[jj] = IOUtils::nodata;
591  else
592  vecData[jj] += rhs(jj);
593  }
594  }
595 
596  return *this;
597 }
598 
599 template<class T> const Array2D<T> Array2D<T>::operator+(const Array2D<T>& rhs) const
600 {
601  Array2D<T> result(*this); //make a copy
602  result += rhs; //already implemented
603 
604  return result;
605 }
606 
607 template<class T> Array2D<T>& Array2D<T>::operator+=(const T& rhs)
608 {
609  if (rhs==0.) return *this;
610 
611  //Add to every single member of the Array2D<T>
612  const size_t nxy = nx*ny;
613 
614  if (keep_nodata==false) {
615  for (size_t jj=0; jj<nxy; jj++)
616  vecData[jj] += rhs;
617  } else {
618  for (size_t jj=0; jj<nxy; jj++) {
619  if (vecData[jj]!=IOUtils::nodata)
620  vecData[jj] += rhs;
621  }
622  }
623 
624  return *this;
625 }
626 
627 template<class T> const Array2D<T> Array2D<T>::operator+(const T& rhs) const
628 {
629  Array2D<T> result(*this);
630  result += rhs; //already implemented
631 
632  return result;
633 }
634 
635 template<class T> Array2D<T>& Array2D<T>::operator-=(const Array2D<T>& rhs)
636 {
637  //They have to have equal size
638  if ((rhs.nx != nx) || (rhs.ny != ny)){
639  std::stringstream ss;
640  ss << "Trying to substract two Array2D objects with different dimensions: ";
641  ss << "(" << nx << "," << ny << ") - (" << rhs.nx << "," << rhs.ny << ")";
642  throw IOException(ss.str(), AT);
643  }
644  //Substract to every single member of the Array2D<T>
645  const size_t nxy = nx*ny;
646 
647  if (keep_nodata==false) {
648  for (size_t jj=0; jj<nxy; jj++)
649  vecData[jj] -= rhs(jj);
650  } else {
651  for (size_t jj=0; jj<nxy; jj++) {
652  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
653  vecData[jj] = IOUtils::nodata;
654  else
655  vecData[jj] -= rhs(jj);
656  }
657  }
658 
659  return *this;
660 }
661 
662 template<class T> const Array2D<T> Array2D<T>::operator-(const Array2D<T>& rhs) const
663 {
664  Array2D<T> result(*this); //make a copy
665  result -= rhs; //already implemented
666 
667  return result;
668 }
669 
670 template<class T> Array2D<T>& Array2D<T>::operator-=(const T& rhs)
671 {
672  *this += -rhs;
673  return *this;
674 }
675 
676 template<class T> const Array2D<T> Array2D<T>::operator-(const T& rhs) const
677 {
678  Array2D<T> result(*this);
679  result += -rhs; //already implemented
680 
681  return result;
682 }
683 
684 template<class T> Array2D<T>& Array2D<T>::operator*=(const Array2D<T>& rhs)
685 {
686  //They have to have equal size
687  if ((rhs.nx != nx) || (rhs.ny != ny)){
688  std::stringstream ss;
689  ss << "Trying to multiply two Array2D objects with different dimensions: ";
690  ss << "(" << nx << "," << ny << ") * (" << rhs.nx << "," << rhs.ny << ")";
691  throw IOException(ss.str(), AT);
692  }
693  //Add to every single member of the Array2D<T>
694  const size_t nxy = nx*ny;
695 
696  if (keep_nodata==false) {
697  for (size_t jj=0; jj<nxy; jj++)
698  vecData[jj] *= rhs(jj);
699  } else {
700  for (size_t jj=0; jj<nxy; jj++) {
701  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
702  vecData[jj] = IOUtils::nodata;
703  else
704  vecData[jj] *= rhs(jj);
705  }
706  }
707 
708  return *this;
709 }
710 
711 template<class T> const Array2D<T> Array2D<T>::operator*(const Array2D<T>& rhs) const
712 {
713  Array2D<T> result(*this); //make a copy
714  result *= rhs; //already implemented
715 
716  return result;
717 }
718 
719 template<class T> Array2D<T>& Array2D<T>::operator*=(const T& rhs)
720 {
721  if (rhs==1.) return *this;
722 
723  //Multiply to every single member of the Array2D<T>
724  const size_t nxy = nx*ny;
725 
726  if (keep_nodata==false) {
727  for (size_t jj=0; jj<nxy; jj++)
728  vecData[jj] *= rhs;
729  } else {
730  for (size_t jj=0; jj<nxy; jj++) {
731  if (vecData[jj]!=IOUtils::nodata)
732  vecData[jj] *= rhs;
733  }
734  }
735 
736  return *this;
737 }
738 
739 template<class T> const Array2D<T> Array2D<T>::operator*(const T& rhs) const
740 {
741  Array2D<T> result(*this);
742  result *= rhs; //already implemented
743 
744  return result;
745 }
746 
747 template<class T> Array2D<T>& Array2D<T>::operator/=(const Array2D<T>& rhs)
748 {
749  //They have to have equal size
750  if ((rhs.nx != nx) || (rhs.ny != ny)){
751  std::stringstream ss;
752  ss << "Trying to divide two Array2D objects with different dimensions: ";
753  ss << "(" << nx << "," << ny << ") / (" << rhs.nx << "," << rhs.ny << ")";
754  throw IOException(ss.str(), AT);
755  }
756  //Divide every single member of the Array2D<T>
757  const size_t nxy = nx*ny;
758 
759  if (keep_nodata==false) {
760  for (size_t jj=0; jj<nxy; jj++)
761  vecData[jj] /= rhs(jj);
762  } else {
763  for (size_t jj=0; jj<nxy; jj++) {
764  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
765  vecData[jj] = IOUtils::nodata;
766  else
767  vecData[jj] /= rhs(jj);
768  }
769  }
770 
771  return *this;
772 }
773 
774 template<class T> const Array2D<T> Array2D<T>::operator/(const Array2D<T>& rhs) const
775 {
776  Array2D<T> result(*this); //make a copy
777  result /= rhs; //already implemented
778 
779  return result;
780 }
781 
782 template<class T> Array2D<T>& Array2D<T>::operator/=(const T& rhs)
783 {
784  *this *= (1./rhs);
785  return *this;
786 }
787 
788 template<class T> const Array2D<T> Array2D<T>::operator/(const T& rhs) const
789 {
790  Array2D<T> result(*this);
791  result *= (1./rhs); //already implemented
792 
793  return result;
794 }
795 
796 template<class T> bool Array2D<T>::operator==(const Array2D<T>& in) const {
797  const size_t in_nx=in.getNx(), in_ny=in.getNy();
798 
799  if (nx!=in_nx || ny!=in_ny)
800  return false;
801 
802  const size_t nxy = nx*ny;
803  for (size_t jj=0; jj<nxy; jj++)
804  if ( !IOUtils::checkEpsilonEquality( vecData[jj] , in.vecData[jj], 1e-6) ) return false;
805 
806  return true;
807 }
808 
809 template<class T> bool Array2D<T>::operator!=(const Array2D<T>& in) const {
810  return !(*this==in);
811 }
812 
813 } //end namespace mio
814 
815 #endif
T & operator()(const size_t &x, const size_t &y)
Definition: Array2D.h:244
bool operator==(const Array2D< T > &) const
Operator that tests for equality.
Definition: Array2D.h:796
Array2D()
Definition: Array2D.h:273
size_t getNx() const
Definition: Array2D.h:386
friend std::iostream & operator>>(std::iostream &is, Array2D< P > &array)
Definition: Array2D.h:425
void subset(const Array2D< T > &i_array2D, const size_t &i_nx, const size_t &i_ny, const size_t &i_ncols, const size_t &i_nrows)
A method that can be used to cut out a subplane of an existing Array2D object that is passed as i_arr...
Definition: Array2D.h:297
const Array2D< T > operator+(const T &rhs) const
Definition: Array2D.h:627
void resize(const size_t &nx, const size_t &ny)
Definition: Array2D.h:363
T getMax() const
returns the maximum value contained in the grid
Definition: Array2D.h:455
const Array2D< T > operator/(const T &rhs) const
Definition: Array2D.h:788
bool checkEpsilonEquality(const Array2D< double > &rhs, const double &epsilon) const
Definition: Array2D.h:543
bool getKeepNodata() const
get how to process nodata values (ie: as nodata or as normal numbers)
Definition: Array2D.h:359
size_t nx
Definition: Array2D.h:224
void setKeepNodata(const bool i_keep_nodata)
set how to process nodata values (ie: as nodata or as normal numbers)
Definition: Array2D.h:355
The template class Array2D is a 2D Array (Matrix) able to hold any type of object as datatype...
Definition: Array2D.h:29
std::vector< T > vecData
Definition: Array2D.h:223
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
const Array2D< T > operator*(const T &rhs) const
Definition: Array2D.h:739
void clear()
Definition: Array2D.h:394
Array2D< T > & operator+=(const T &rhs)
Definition: Array2D.h:607
T getMin() const
returns the minimum value contained in the grid
Definition: Array2D.h:434
const std::string toString() const
Definition: Array2D.h:403
void abs()
Definition: Array2D.h:517
bool keep_nodata
Definition: Array2D.h:226
Array2D< T > & operator-=(const T &rhs)
Definition: Array2D.h:670
bool empty() const
Definition: Array2D.h:399
#define AT
Definition: IOExceptions.h:29
bool operator!=(const Array2D< T > &) const
Operator that tests for inequality.
Definition: Array2D.h:809
const double nodata
This is the internal nodata value.
Definition: IOUtils.h:60
size_t size() const
Definition: Array2D.h:382
T getMean() const
returns the mean value contained in the grid
Definition: Array2D.h:476
virtual ~Array2D()
Definition: Array2D.h:277
Array2DProxy< T > operator[](const size_t &i)
Definition: Array2D.h:269
Array2D< T > & operator*=(const T &rhs)
Definition: Array2D.h:719
size_t ny
Definition: Array2D.h:225
void fill(const Array2D< T > &i_array2D, const size_t &i_nx, const size_t &i_ny, const size_t &i_ncols, const size_t &i_nrows)
A method that can be used to insert a subplane into an existing Array2D object that is passed as i_ar...
Definition: Array2D.h:326
thrown when an index is out of bounds
Definition: IOExceptions.h:108
const double e
Definition: Meteoconst.h:66
Array2D< T > & operator=(const Array2D< T > &)
Definition: Array2D.h:557
The template class Array3D is a 3D Array (Tensor) able to hold any type of object as datatype...
Definition: Array3D.h:29
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: Array2D.h:502
const Array2D< T > operator-(const T &rhs) const
Definition: Array2D.h:676
The basic exception class adjusted for the needs of SLF software.
Definition: IOExceptions.h:41
size_t getNy() const
Definition: Array2D.h:390
std::iostream & operator>>(std::iostream &is, Config &cfg)
Definition: Config.cc:141
value::array array
Definition: picojson.h:194
Array2D< T > & operator/=(const T &rhs)
Definition: Array2D.h:782
const Array2D< T > getAbs() const
returns the grid of the absolute value of values contained in the grid
Definition: Array2D.h:534