You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
2.5 KiB

#pragma once
2 years ago
#include "comdefs.h"
#include <vector>
2 years ago
using michlib::real;
class BaseParameters
{
public:
virtual ~BaseParameters();
};
2 years ago
class BaseData
{
protected:
static constexpr real fillval = 1.0e10;
std::vector<real> data;
std::vector<real> lons, lats;
2 years ago
BaseData(size_t n): data(n), lons(n), lats(n) {}
2 years ago
template<class Lon, class Lat> BaseData(size_t n, Lon genlon, Lat genlat): data(n), lons(n), lats(n)
{
for(size_t i = 0; i < n; i++)
{
lons[i] = genlon(i);
lats[i] = genlat(i);
}
};
2 years ago
public:
BaseData() = default;
2 years ago
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]; }
real Lon(size_t i) const { return lons[i]; }
real Lat(size_t i) const { return lats[i]; }
2 years ago
size_t N() const { return data.size(); }
bool IsFill(size_t i) const { return V(i) == Fillval(); }
2 years ago
static real Fillval() { return fillval; }
explicit operator bool() const { return N() != 0; }
2 years ago
};
template<class T>
concept HaveU = requires(T t) {
{
t.template U(0)
} -> std::convertible_to<real>;
};
template<class T>
concept HaveV = requires(T t) {
{
t.template V(0)
} -> std::convertible_to<real>;
};
template<class Data> class Averager: public Data
{
std::vector<size_t> count;
static constexpr bool haveu = HaveU<Data>;
static constexpr bool havev = HaveV<Data>;
static bool DataOk(const Data* d, size_t i)
{
bool uok = true;
bool vok = true;
if constexpr(haveu) uok = d->U(i) != Data::Fillval();
if constexpr(havev) uok = d->V(i) != Data::Fillval();
return uok && vok;
}
public:
void Add(const Data& d)
{
if(!d) return;
if(!*this)
{
*static_cast<Data*>(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(haveu) Data::U(i) += d.U(i);
if constexpr(havev) Data::V(i) += d.V(i);
count[i]++;
}
else
{
if constexpr(haveu) Data::U(i) = d.U(i);
if constexpr(havev) Data::V(i) = d.V(i);
count[i] = 1;
}
}
}
Averager& Div()
{
if(!*this) return *this;
for(size_t i = 0; i < Data::N(); i++)
{
if constexpr(haveu)
{
if(count[i] != 0) Data::U(i) /= count[i];
}
if constexpr(havev)
{
if(count[i] != 0) Data::V(i) /= count[i];
}
}
return *this;
}
};