MeteoIODoc 20240505.aefd3c94
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
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
32namespace mio { template <class T> class Array2D; }
34
35namespace mio {
43template <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
65template<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
229template<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
237template<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}
244template<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
257template<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
269template<class T> Array2DProxy<T> Array2D<T>::operator[](const size_t& i) {
270 return Array2DProxy<T>(*this, i);
271}
272
273template<class T> Array2D<T>::Array2D() : vecData(), nx(0), ny(0), keep_nodata(true)
274{
275}
276
277template<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
284template<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
295template<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
317template<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
324template<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
347template<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
350template<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
353template<class T> void Array2D<T>::setKeepNodata(const bool i_keep_nodata) {
354 keep_nodata = i_keep_nodata;
355}
356
357template<class T> bool Array2D<T>::getKeepNodata() const {
358 return keep_nodata;
359}
360
361template<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
368template<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
375template<class T> void Array2D<T>::size(size_t& anx, size_t& any) const {
376 anx=nx;
377 any=ny;
378}
379
380template<class T> size_t Array2D<T>::size() const {
381 return nx*ny;
382}
383
384template<class T> size_t Array2D<T>::getNx() const {
385 return nx;
386}
387
388template<class T> size_t Array2D<T>::getNy() const {
389 return ny;
390}
391
392template<class T> void Array2D<T>::clear() {
393 vecData.clear();
394 nx=ny=0;
395}
396
397template<class T> bool Array2D<T>::empty() const {
398 return (nx==0 && ny==0);
399}
400
401template<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
415template<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
423template<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
432template<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
451template<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
470template<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
492template<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
507template<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
524template<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
533template<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
543template<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
547template<class T> Array2D<T>& Array2D<T>::operator=(const T& value) {
548 std::fill(vecData.begin(), vecData.end(), value);
549 return *this;
550}
551
552template<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
579template<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
587template<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
607template<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
615template<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
642template<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
650template<class T> Array2D<T>& Array2D<T>::operator-=(const T& rhs)
651{
652 *this += -rhs;
653 return *this;
654}
655
656template<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
664template<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
691template<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
699template<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
719template<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
727template<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
754template<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
762template<class T> Array2D<T>& Array2D<T>::operator/=(const T& rhs)
763{
764 *this *= (1./rhs);
765 return *this;
766}
767
768template<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
776template<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
789template<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
friend std::ostream & operator<<(std::ostream &os, const Array2D< P > &array)
Definition: Array2D.h:415
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
friend std::istream & operator>>(std::istream &is, Array2D< P > &array)
Definition: Array2D.h:423
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
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
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:258
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:31
std::istream & operator>>(std::istream &is, Config &cfg)
Definition: Config.cc:468
std::ostream & operator<<(std::ostream &os, const Config &cfg)
Definition: Config.cc:433