MeteoIODoc  2.10.0
Array2D.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-or-later
2 /***********************************************************************************/
3 /* Copyright 2009 WSL Institute for Snow and Avalanche Research SLF-DAVOS */
4 /***********************************************************************************/
5 /* This file is part of MeteoIO.
6  MeteoIO is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  MeteoIO is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with MeteoIO. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef ARRAY2D_H
20 #define ARRAY2D_H
21 
22 #include <meteoio/IOExceptions.h>
23 #include <meteoio/IOUtils.h>
24 
25 #include <vector>
26 #include <limits>
27 #include <iostream>
28 #include <numeric>
29 #include <algorithm>
30 
31 //forward declaration
32 namespace mio { template <class T> class Array2D; }
34 
35 namespace mio {
43 template <class T> class Array2DProxy {
44  public:
45  friend class Array2D<T>;
46  T& operator[](const size_t& j) {
47  return array2D(anx, j);
48  }
49 
50  private:
51  Array2DProxy(Array2D<T>& i_array2D, const size_t& i_anx) : array2D(i_array2D), anx(i_anx){}
52  Array2D<T>& array2D;
53  const size_t anx;
54 };
55 
65 template<class T> class Array2D {
66  public:
68 
74  Array2D(const size_t& anx, const size_t& any);
75 
82  Array2D(const size_t& anx, const size_t& any, const T& init);
83 
94  Array2D(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
95  const size_t& i_ncols, const size_t& i_nrows);
96 
102  Array2D(const Array3D<T>& array3D, const size_t& depth);
103 
114  void subset(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
115  const size_t& i_ncols, const size_t& i_nrows);
116 
127  void fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
128  const size_t& i_ncols, const size_t& i_nrows);
129 
130  void fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny);
131 
137  void setKeepNodata(const bool i_keep_nodata);
138 
143  bool getKeepNodata() const;
144 
145  void resize(const size_t& anx, const size_t& any);
146  void resize(const size_t& anx, const size_t& any, const T& init);
147  void size(size_t& anx, size_t& any) const;
148  size_t size() const;
149  size_t getNx() const;
150  size_t getNy() const;
151 
152  void clear();
153  bool empty() const;
154 
159  T getMin() const;
164  T getMax() const;
169  T getMean() const;
176  size_t getCount() const;
181  const Array2D<T> getAbs() const;
182  void abs();
183 
184  const std::string toString() const;
185  template<class P> friend std::ostream& operator<<(std::ostream& os, const Array2D<P>& array);
186  template<class P> friend std::istream& operator>>(std::istream& is, Array2D<P>& array);
187 
188  bool checkEpsilonEquality(const Array2D<double>& rhs, const double& epsilon) const;
189  static bool checkEpsilonEquality(const Array2D<double>& rhs1, const Array2D<double>& rhs2, const double& epsilon);
190 
191  T& operator ()(const size_t& x, const size_t& y);
192  const T operator ()(const size_t& x, const size_t& y) const;
193  T& operator ()(const size_t& i);
194  const T operator ()(const size_t& i) const;
195  Array2DProxy<T> operator[](const size_t& i);
196 
197  Array2D<T>& operator =(const T& value);
198 
199  Array2D<T>& operator+=(const T& rhs);
200  const Array2D<T> operator+(const T& rhs) const;
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;
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;
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;
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  //ROW-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(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
278  const size_t& i_ncols, const size_t& i_nrows) :
279  vecData(i_ncols*i_nrows), nx(i_ncols), ny(i_nrows), keep_nodata(true)
280 {
281  subset(i_array2D, i_nx, i_ny, i_ncols, i_nrows);
282 }
283 
284 template<class T> Array2D<T>::Array2D(const Array3D<T>& array3D, const size_t& depth)
285  : vecData(array3D.getNx()*array3D.getNy()), nx(array3D.getNx()), ny(array3D.getNy()), keep_nodata(array3D.getKeepNodata())
286 {
287  //copy plane in the correct position
288  for (size_t jj=0; jj<ny; jj++) {
289  for (size_t ii=0; ii<nx; ii++) {
290  operator()(ii,jj) = array3D(ii, jj, depth);
291  }
292  }
293 }
294 
295 template<class T> void Array2D<T>::subset(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
296  const size_t& i_ncols, const size_t& i_nrows)
297 {
298  if (((i_nx+i_ncols) > i_array2D.nx) || ((i_ny+i_nrows) > i_array2D.ny)) {
299  std::stringstream ss;
300  ss << "Trying to cut an array of size (" << i_array2D.nx << "," << i_array2D.ny << ") ";
301  ss << "to size (" << i_ncols << "," << i_nrows << ") starting at (" << i_nx << "," << i_ny << ")";
302  throw IndexOutOfBoundsException(ss.str(), AT);
303  }
304 
305  if ((i_ncols == 0) || (i_nrows == 0)) //the plane to copy has to make sense
306  throw IndexOutOfBoundsException("Trying to cut an array into a null sized array!", AT);
307 
308  resize(i_ncols, i_nrows); //create new Array2D object
309  //Copy by value subspace
310  for (size_t jj=0; jj<ny; jj++) {
311  for (size_t ii=0; ii<nx; ii++) {
312  operator()(ii,jj) = i_array2D(i_nx+ii, i_ny+jj);
313  }
314  }
315 }
316 
317 template<class T> void Array2D<T>::fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny)
318 {
319  size_t i_ncols, i_nrows;
320  i_array2D.size(i_ncols, i_nrows);
321  fill(i_array2D, i_nx, i_ny, i_ncols, i_nrows);
322 }
323 
324 template<class T> void Array2D<T>::fill(const Array2D<T>& i_array2D, const size_t& i_nx, const size_t& i_ny,
325  const size_t& i_ncols, const size_t& i_nrows)
326 {
327  if (((i_nx+i_ncols) > nx) || ((i_ny+i_nrows) > ny)) {
328  std::stringstream ss;
329  ss << "Filling an array of size (" << nx << "," << ny << ") ";
330  ss << "with an array of size (" << i_ncols << "," << i_nrows << ") ";
331  ss << "starting at (" << i_nx << "," << i_ny << ")";
332  throw IndexOutOfBoundsException(ss.str(), AT);
333  }
334 
335  if ((i_ncols == 0) || (i_nrows == 0)) //the plane to copy has to make sense
336  throw IndexOutOfBoundsException("Filling an array with a null sized array!", AT);
337 
338  for (size_t jj=i_ny; jj<(i_ny+i_nrows); jj++) {
339  const size_t iy = jj-i_ny;
340  for (size_t ii=i_nx; ii<(i_nx+i_ncols); ii++) {
341  const size_t ix = ii-i_nx;
342  operator()(ii,jj) = i_array2D(ix, iy);
343  }
344  }
345 }
346 
347 template<class T> Array2D<T>::Array2D(const size_t& anx, const size_t& any, const T& init) :
348  vecData(anx*any, init), nx(anx), ny(any), keep_nodata(true) {}
349 
350 template<class T> Array2D<T>::Array2D(const size_t& anx, const size_t& any) :
351  vecData(anx*any), nx(anx), ny(any), keep_nodata(true) {}
352 
353 template<class T> void Array2D<T>::setKeepNodata(const bool i_keep_nodata) {
354  keep_nodata = i_keep_nodata;
355 }
356 
357 template<class T> bool Array2D<T>::getKeepNodata() const {
358  return keep_nodata;
359 }
360 
361 template<class T> void Array2D<T>::resize(const size_t& anx, const size_t& any) {
362  clear(); //we won't be able to "rescue" old values, so we reset the whole vector
363  vecData.resize(anx*any);
364  nx = anx;
365  ny = any;
366 }
367 
368 template<class T> void Array2D<T>::resize(const size_t& anx, const size_t& any, const T& init) {
369  clear(); //we won't be able to "rescue" old values, so we reset the whole vector
370  vecData.resize(anx*any, init);
371  nx = anx;
372  ny = any;
373 }
374 
375 template<class T> void Array2D<T>::size(size_t& anx, size_t& any) const {
376  anx=nx;
377  any=ny;
378 }
379 
380 template<class T> size_t Array2D<T>::size() const {
381  return nx*ny;
382 }
383 
384 template<class T> size_t Array2D<T>::getNx() const {
385  return nx;
386 }
387 
388 template<class T> size_t Array2D<T>::getNy() const {
389  return ny;
390 }
391 
392 template<class T> void Array2D<T>::clear() {
393  vecData.clear();
394  nx=ny=0;
395 }
396 
397 template<class T> bool Array2D<T>::empty() const {
398  return (nx==0 && ny==0);
399 }
400 
401 template<class T> const std::string Array2D<T>::toString() const {
402  std::ostringstream os;
403  os << "<array2d>\n";
404  for (size_t jj=0; jj<ny; jj++) {
405  const size_t jnx = jj*nx;
406  for (size_t ii=0; ii<nx; ii++) {
407  os << vecData[ii+jnx] << " "; //COLUMN-MAJOR alignment
408  }
409  os << "\n";
410  }
411  os << "</array2d>\n";
412  return os.str();
413 }
414 
415 template<class P> std::ostream& operator<<(std::ostream& os, const Array2D<P>& array) {
416  os.write(reinterpret_cast<const char*>(&array.keep_nodata), sizeof(array.keep_nodata));
417  os.write(reinterpret_cast<const char*>(&array.nx), sizeof(array.nx));
418  os.write(reinterpret_cast<const char*>(&array.ny), sizeof(array.ny));
419  os.write(reinterpret_cast<const char*>(&array.vecData[0]), static_cast<std::streamsize>(array.nx*array.ny*sizeof(P)));
420  return os;
421 }
422 
423 template<class P> std::istream& operator>>(std::istream& is, Array2D<P>& array) {
424  is.read(reinterpret_cast<char*>(&array.keep_nodata), sizeof(array.keep_nodata));
425  is.read(reinterpret_cast<char*>(&array.nx), sizeof(array.nx));
426  is.read(reinterpret_cast<char*>(&array.ny), sizeof(array.ny));
427  array.vecData.resize(array.nx*array.ny);
428  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()
429  return is;
430 }
431 
432 template<class T> T Array2D<T>::getMin() const {
433 
434  T min = std::numeric_limits<T>::max();
435 
436  const size_t nxy = ny*nx;
437  if (keep_nodata==false) {
438  min = *min_element(vecData.begin(), vecData.end());
439  if (min!=std::numeric_limits<T>::max()) return min;
440  else return (T)IOUtils::nodata;
441  } else {
442  for (size_t jj=0; jj<nxy; jj++) {
443  const T val = vecData[jj];
444  if (val!=IOUtils::nodata && val<min) min=val;
445  }
446  if (min!=std::numeric_limits<T>::max()) return min;
447  else return (T)IOUtils::nodata;
448  }
449 }
450 
451 template<class T> T Array2D<T>::getMax() const {
452 
453  T max = -std::numeric_limits<T>::max();
454 
455  const size_t nxy = ny*nx;
456  if (keep_nodata==false) {
457  max = *max_element(vecData.begin(), vecData.end());
458  if (max!=-std::numeric_limits<T>::max()) return max;
459  else return (T)IOUtils::nodata;
460  } else {
461  for (size_t jj=0; jj<nxy; jj++) {
462  const T val = vecData[jj];
463  if (val!=IOUtils::nodata && val>max) max=val;
464  }
465  if (max!=-std::numeric_limits<T>::max()) return max;
466  else return (T)IOUtils::nodata;
467  }
468 }
469 
470 template<class T> T Array2D<T>::getMean() const {
471 
472  T mean = 0;
473  const size_t nxy = nx*ny;
474 
475  if (keep_nodata==false) {
476  if (nxy>0) return std::accumulate(vecData.begin(), vecData.end(), 0.) / (T)(nxy);
477  else return (T)IOUtils::nodata;
478  } else {
479  size_t count = 0;
480  for (size_t jj=0; jj<nxy; jj++) {
481  const T val = vecData[jj];
482  if (val!=IOUtils::nodata) {
483  mean += val;
484  count++;
485  }
486  }
487  if (count>0) return mean/(T)(count);
488  else return (T)IOUtils::nodata;
489  }
490 }
491 
492 template<class T> size_t Array2D<T>::getCount() const
493 {
494  const size_t nxy = nx*ny;
495 
496  if (keep_nodata==false) {
497  return (size_t)nxy;
498  } else {
499  size_t count = 0;
500  for (size_t ii=0; ii<nxy; ii++) {
501  if (vecData[ii]!=IOUtils::nodata) count++;
502  }
503  return count;
504  }
505 }
506 
507 template<class T> void Array2D<T>::abs() {
508  if (std::numeric_limits<T>::is_signed) {
509  const size_t nxy = nx*ny;
510  if (keep_nodata==false) {
511  for (size_t ii=0; ii<nxy; ii++) {
512  T& val = vecData[ii];
513  if (val<0) val=-val;
514  }
515  } else {
516  for (size_t ii=0; ii<nxy; ii++) {
517  T& val = vecData[ii];
518  if (val<0 && val!=IOUtils::nodata) val=-val;
519  }
520  }
521  }
522 }
523 
524 template<class T> const Array2D<T> Array2D<T>::getAbs() const {
525  Array2D<T> result(*this); //make a copy
526  result.abs(); //already implemented
527 
528  return result;
529 }
530 
531 
532 //arithmetic operators
533 template<class T> bool Array2D<T>::checkEpsilonEquality(const Array2D<double>& rhs, const double& epsilon) const {
534  if (nx!=rhs.nx || ny!=rhs.ny) return false;
535 
536  const size_t nxy = nx*ny;
537  for (size_t jj=0; jj<nxy; jj++)
538  if (IOUtils::checkEpsilonEquality(vecData[jj], rhs.vecData[jj], epsilon)==false) return false;
539 
540  return true;
541 }
542 
543 template<class T> bool Array2D<T>::checkEpsilonEquality(const Array2D<double>& rhs1, const Array2D<double>& rhs2, const double& epsilon) { //static
544  return rhs1.checkEpsilonEquality(rhs2, epsilon);
545 }
546 
547 template<class T> Array2D<T>& Array2D<T>::operator=(const T& value) {
548  std::fill(vecData.begin(), vecData.end(), value);
549  return *this;
550 }
551 
552 template<class T> Array2D<T>& Array2D<T>::operator+=(const Array2D<T>& rhs)
553 {
554  //They have to have equal size
555  if ((rhs.nx != nx) || (rhs.ny != ny)) {
556  std::stringstream ss;
557  ss << "Trying to add two Array2D objects with different dimensions: ";
558  ss << "(" << nx << "," << ny << ") + (" << rhs.nx << "," << rhs.ny << ")";
559  throw IOException(ss.str(), AT);
560  }
561 
562  const size_t nxy = nx*ny;
563  //Add to every single member of the Array2D<T>
564  if (keep_nodata==false) {
565  for (size_t jj=0; jj<nxy; jj++)
566  vecData[jj] += rhs(jj);
567  } else {
568  for (size_t jj=0; jj<nxy; jj++) {
569  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
570  vecData[jj] = IOUtils::nodata;
571  else
572  vecData[jj] += rhs(jj);
573  }
574  }
575 
576  return *this;
577 }
578 
579 template<class T> const Array2D<T> Array2D<T>::operator+(const Array2D<T>& rhs) const
580 {
581  Array2D<T> result(*this); //make a copy
582  result += rhs; //already implemented
583 
584  return result;
585 }
586 
587 template<class T> Array2D<T>& Array2D<T>::operator+=(const T& rhs)
588 {
589  if (rhs==0.) return *this;
590 
591  //Add to every single member of the Array2D<T>
592  const size_t nxy = nx*ny;
593 
594  if (keep_nodata==false) {
595  for (size_t jj=0; jj<nxy; jj++)
596  vecData[jj] += rhs;
597  } else {
598  for (size_t jj=0; jj<nxy; jj++) {
599  if (vecData[jj]!=IOUtils::nodata)
600  vecData[jj] += rhs;
601  }
602  }
603 
604  return *this;
605 }
606 
607 template<class T> const Array2D<T> Array2D<T>::operator+(const T& rhs) const
608 {
609  Array2D<T> result(*this);
610  result += rhs; //already implemented
611 
612  return result;
613 }
614 
615 template<class T> Array2D<T>& Array2D<T>::operator-=(const Array2D<T>& rhs)
616 {
617  //They have to have equal size
618  if ((rhs.nx != nx) || (rhs.ny != ny)){
619  std::stringstream ss;
620  ss << "Trying to substract two Array2D objects with different dimensions: ";
621  ss << "(" << nx << "," << ny << ") - (" << rhs.nx << "," << rhs.ny << ")";
622  throw IOException(ss.str(), AT);
623  }
624  //Substract to every single member of the Array2D<T>
625  const size_t nxy = nx*ny;
626 
627  if (keep_nodata==false) {
628  for (size_t jj=0; jj<nxy; jj++)
629  vecData[jj] -= rhs(jj);
630  } else {
631  for (size_t jj=0; jj<nxy; jj++) {
632  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
633  vecData[jj] = IOUtils::nodata;
634  else
635  vecData[jj] -= rhs(jj);
636  }
637  }
638 
639  return *this;
640 }
641 
642 template<class T> const Array2D<T> Array2D<T>::operator-(const Array2D<T>& rhs) const
643 {
644  Array2D<T> result(*this); //make a copy
645  result -= rhs; //already implemented
646 
647  return result;
648 }
649 
650 template<class T> Array2D<T>& Array2D<T>::operator-=(const T& rhs)
651 {
652  *this += -rhs;
653  return *this;
654 }
655 
656 template<class T> const Array2D<T> Array2D<T>::operator-(const T& rhs) const
657 {
658  Array2D<T> result(*this);
659  result += -rhs; //already implemented
660 
661  return result;
662 }
663 
664 template<class T> Array2D<T>& Array2D<T>::operator*=(const Array2D<T>& rhs)
665 {
666  //They have to have equal size
667  if ((rhs.nx != nx) || (rhs.ny != ny)){
668  std::stringstream ss;
669  ss << "Trying to multiply two Array2D objects with different dimensions: ";
670  ss << "(" << nx << "," << ny << ") * (" << rhs.nx << "," << rhs.ny << ")";
671  throw IOException(ss.str(), AT);
672  }
673  //Add to every single member of the Array2D<T>
674  const size_t nxy = nx*ny;
675 
676  if (keep_nodata==false) {
677  for (size_t jj=0; jj<nxy; jj++)
678  vecData[jj] *= rhs(jj);
679  } else {
680  for (size_t jj=0; jj<nxy; jj++) {
681  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
682  vecData[jj] = IOUtils::nodata;
683  else
684  vecData[jj] *= rhs(jj);
685  }
686  }
687 
688  return *this;
689 }
690 
691 template<class T> const Array2D<T> Array2D<T>::operator*(const Array2D<T>& rhs) const
692 {
693  Array2D<T> result(*this); //make a copy
694  result *= rhs; //already implemented
695 
696  return result;
697 }
698 
699 template<class T> Array2D<T>& Array2D<T>::operator*=(const T& rhs)
700 {
701  if (rhs==1.) return *this;
702 
703  //Multiply to every single member of the Array2D<T>
704  const size_t nxy = nx*ny;
705 
706  if (keep_nodata==false) {
707  for (size_t jj=0; jj<nxy; jj++)
708  vecData[jj] *= rhs;
709  } else {
710  for (size_t jj=0; jj<nxy; jj++) {
711  if (vecData[jj]!=IOUtils::nodata)
712  vecData[jj] *= rhs;
713  }
714  }
715 
716  return *this;
717 }
718 
719 template<class T> const Array2D<T> Array2D<T>::operator*(const T& rhs) const
720 {
721  Array2D<T> result(*this);
722  result *= rhs; //already implemented
723 
724  return result;
725 }
726 
727 template<class T> Array2D<T>& Array2D<T>::operator/=(const Array2D<T>& rhs)
728 {
729  //They have to have equal size
730  if ((rhs.nx != nx) || (rhs.ny != ny)){
731  std::stringstream ss;
732  ss << "Trying to divide two Array2D objects with different dimensions: ";
733  ss << "(" << nx << "," << ny << ") / (" << rhs.nx << "," << rhs.ny << ")";
734  throw IOException(ss.str(), AT);
735  }
736  //Divide every single member of the Array2D<T>
737  const size_t nxy = nx*ny;
738 
739  if (keep_nodata==false) {
740  for (size_t jj=0; jj<nxy; jj++)
741  vecData[jj] /= rhs(jj);
742  } else {
743  for (size_t jj=0; jj<nxy; jj++) {
744  if (vecData[jj]==IOUtils::nodata || rhs(jj)==IOUtils::nodata)
745  vecData[jj] = IOUtils::nodata;
746  else
747  vecData[jj] /= rhs(jj);
748  }
749  }
750 
751  return *this;
752 }
753 
754 template<class T> const Array2D<T> Array2D<T>::operator/(const Array2D<T>& rhs) const
755 {
756  Array2D<T> result(*this); //make a copy
757  result /= rhs; //already implemented
758 
759  return result;
760 }
761 
762 template<class T> Array2D<T>& Array2D<T>::operator/=(const T& rhs)
763 {
764  *this *= (1./rhs);
765  return *this;
766 }
767 
768 template<class T> const Array2D<T> Array2D<T>::operator/(const T& rhs) const
769 {
770  Array2D<T> result(*this);
771  result *= (1./rhs); //already implemented
772 
773  return result;
774 }
775 
776 template<class T> bool Array2D<T>::operator==(const Array2D<T>& in) const {
777  const size_t in_nx=in.getNx(), in_ny=in.getNy();
778 
779  if (nx!=in_nx || ny!=in_ny)
780  return false;
781 
782  const size_t nxy = nx*ny;
783  for (size_t jj=0; jj<nxy; jj++)
784  if ( !IOUtils::checkEpsilonEquality( vecData[jj] , in.vecData[jj], 1e-6) ) return false;
785 
786  return true;
787 }
788 
789 template<class T> bool Array2D<T>::operator!=(const Array2D<T>& in) const {
790  return !(*this==in);
791 }
792 
793 } //end namespace mio
794 
795 #endif
#define AT
Definition: IOExceptions.h:28
The template class Array2D is a 2D Array (Matrix) able to hold any type of object as datatype....
Definition: Array2D.h:65
const Array2D< T > operator/(const T &rhs) const
Definition: Array2D.h:768
const Array2D< T > getAbs() const
returns the grid of the absolute value of values contained in the grid
Definition: Array2D.h:524
static bool checkEpsilonEquality(const Array2D< double > &rhs1, const Array2D< double > &rhs2, const double &epsilon)
Definition: Array2D.h:543
Array2D< T > & operator*=(const T &rhs)
Definition: Array2D.h:699
size_t getCount() const
returns the number of points contained in the grid. If setNodataHandling(IOUtils::RAW_NODATA),...
Definition: Array2D.h:492
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:324
void resize(const size_t &anx, const size_t &any)
Definition: Array2D.h:361
Array2D(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)
Definition: Array2D.h:277
T getMin() const
returns the minimum value contained in the grid
Definition: Array2D.h:432
Array2D< T > & operator*=(const Array2D< T > &rhs)
Definition: Array2D.h:664
const Array2D< T > operator*(const Array2D< T > &rhs) const
Definition: Array2D.h:691
const Array2D< T > operator-(const T &rhs) const
Definition: Array2D.h:656
Array2D< T > & operator/=(const Array2D< T > &rhs)
Definition: Array2D.h:727
std::vector< T > vecData
Definition: Array2D.h:223
const Array2D< T > operator-(const Array2D< T > &rhs) const
Definition: Array2D.h:642
const Array2D< T > operator+(const T &rhs) const
Definition: Array2D.h:607
size_t getNx() const
Definition: Array2D.h:384
void abs()
Definition: Array2D.h:507
Array2DProxy< T > operator[](const size_t &i)
Definition: Array2D.h:269
void setKeepNodata(const bool i_keep_nodata)
set how to process nodata values (ie: as nodata or as normal numbers)
Definition: Array2D.h:353
size_t ny
Definition: Array2D.h:225
bool checkEpsilonEquality(const Array2D< double > &rhs, const double &epsilon) const
Definition: Array2D.h:533
size_t getNy() const
Definition: Array2D.h:388
T getMax() const
returns the maximum value contained in the grid
Definition: Array2D.h:451
bool getKeepNodata() const
get how to process nodata values (ie: as nodata or as normal numbers)
Definition: Array2D.h:357
Array2D< T > & operator-=(const Array2D< T > &rhs)
Definition: Array2D.h:615
bool operator==(const Array2D< T > &) const
Operator that tests for equality.
Definition: Array2D.h:776
Array2D< T > & operator+=(const T &rhs)
Definition: Array2D.h:587
bool operator!=(const Array2D< T > &) const
Operator that tests for inequality.
Definition: Array2D.h:789
size_t nx
Definition: Array2D.h:224
friend std::istream & operator>>(std::istream &is, Array2D< P > &array)
Definition: Array2D.h:423
const std::string toString() const
Definition: Array2D.h:401
Array2D< T > & operator/=(const T &rhs)
Definition: Array2D.h:762
T getMean() const
returns the mean value contained in the grid
Definition: Array2D.h:470
Array2D()
Definition: Array2D.h:273
Array2D< T > & operator=(const T &value)
Definition: Array2D.h:547
T & operator()(const size_t &x, const size_t &y)
Definition: Array2D.h:244
Array2D(const size_t &anx, const size_t &any)
Definition: Array2D.h:350
Array2D(const Array3D< T > &array3D, const size_t &depth)
Definition: Array2D.h:284
bool keep_nodata
Definition: Array2D.h:226
const Array2D< T > operator/(const Array2D< T > &rhs) const
Definition: Array2D.h:754
friend std::ostream & operator<<(std::ostream &os, const Array2D< P > &array)
Definition: Array2D.h:415
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:295
size_t size() const
Definition: Array2D.h:380
Array2D< T > & operator-=(const T &rhs)
Definition: Array2D.h:650
void resize(const size_t &anx, const size_t &any, const T &init)
Definition: Array2D.h:368
Array2D(const size_t &anx, const size_t &any, const T &init)
Definition: Array2D.h:347
void clear()
Definition: Array2D.h:392
void size(size_t &anx, size_t &any) const
Definition: Array2D.h:375
bool empty() const
Definition: Array2D.h:397
const Array2D< T > operator+(const Array2D< T > &rhs) const
Definition: Array2D.h:579
void fill(const Array2D< T > &i_array2D, const size_t &i_nx, const size_t &i_ny)
Definition: Array2D.h:317
const Array2D< T > operator*(const T &rhs) const
Definition: Array2D.h:719
Array2D< T > & operator+=(const Array2D< T > &rhs)
Definition: Array2D.h:552
The template class Array3D is a 3D Array (Tensor) able to hold any type of object as datatype....
Definition: Array3D.h:87
The basic exception class adjusted for the needs of SLF software.
Definition: IOExceptions.h:40
thrown when an index is out of bounds
Definition: IOExceptions.h:106
static const double e
Definition: Meteoconst.h:68
const double nodata
This is the internal nodata value.
Definition: IOUtils.h:75
size_t count(const std::string &input, const std::string &search)
count how many times a substring appears in a string
Definition: IOUtils.cc:226
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:121
Definition: Config.cc:30
std::ostream & operator<<(std::ostream &os, const Config &cfg)
Definition: Config.cc:419
std::istream & operator>>(std::istream &is, Config &cfg)
Definition: Config.cc:454