#pragma once #include "traits.h" #include class BaseParameters { public: virtual ~BaseParameters(); }; class BaseData { protected: static constexpr real fillval = 1.0e10; std::vector data; BaseData(size_t n): data(n) {} public: 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; } }; 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(const Data& d) { if(!d) return; if(!*this) { *static_cast(this) = 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;