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