#pragma once #include "traits.h" #include using TIndex = std::vector; class BaseParameters { public: virtual ~BaseParameters(); }; struct Region { real lonb, lone, latb, late; }; class BaseData { protected: static constexpr real fillval = 1.0e10; std::vector data; MString unit, stname, lname, comment; BaseData(size_t n, MString&& unit_ = ""): data(n), unit(std::move(unit_)) {} public: BaseData() = default; BaseData(const BaseData&) = delete; BaseData(BaseData&&) = default; BaseData& operator=(BaseData&&) = default; const real& V(size_t i) const { return data[i]; } real& V(size_t i) { return data[i]; } const real& operator()(size_t i) const { return data[i]; } real& operator()(size_t i) { return data[i]; } size_t N() const { return data.size(); } bool IsFill(size_t i) const { return V(i) == Fillval(); } static real Fillval() { return fillval; } explicit operator bool() const { return N() != 0; } void SetUnit(const MString& str) { unit = str; } void SetStandartName(const MString& str) { stname = str; } void SetLongName(const MString& str) { lname = str; } void SetComment(const MString& str) { comment = str; } const MString& Unit() const { return unit; } const MString& StandartName() const { return stname; } const MString& LongName() const { return lname; } const MString& Comment() const { return comment; } }; class UngriddedData: public BaseData { std::vector lons, lats; public: template UngriddedData(size_t n, Lon genlon, Lat genlat, MString&& unit = ""): BaseData(n, std::move(unit)), lons(n), lats(n) { for(size_t i = 0; i < n; i++) { lons[i] = genlon(i); lats[i] = genlat(i); } }; UngriddedData() = default; real Lon(size_t i) const { return lons[i]; } real Lat(size_t i) const { return lats[i]; } }; template class DefaultAverager: public Data { static constexpr bool isuv = IsUVData; std::vector count; static bool DataOk(const Data* d, size_t i) { if constexpr(isuv) return d->U(i) != Data::Fillval() && d->V(i) != Data::Fillval(); else return d->V(i) != Data::Fillval(); } public: void Add(Data&& d) { if(!d) return; if(!*this) { *static_cast(this) = std::move(d); count.resize(Data::N()); for(size_t i = 0; i < Data::N(); i++) count[i] = DataOk(this, i) ? 1 : 0; return; } if(Data::N() != d.N()) return; for(size_t i = 0; i < Data::N(); i++) if(DataOk(&d, i)) { if(DataOk(this, i)) { if constexpr(isuv) { Data::U(i) += d.U(i); Data::U2(i) += d.U2(i); } Data::V(i) += d.V(i); count[i]++; } else { if constexpr(isuv) { Data::U(i) = d.U(i); Data::U2(i) = d.U2(i); } Data::V(i) = d.V(i); count[i] = 1; } } } DefaultAverager& Div() { if(!*this) return *this; for(size_t i = 0; i < Data::N(); i++) if(count[i] != 0) { if constexpr(isuv) { Data::U(i) /= count[i]; Data::U2(i) /= count[i]; } Data::V(i) /= count[i]; } return *this; } }; namespace internal { template struct GetAverager_ { using type = DefaultAverager; }; template struct GetAverager_> { using type = typename Data::Averager; }; } // namespace internal template using Averager = internal::GetAverager_::type;