WSL/SLF GitLab Repository

Commit b79a85a4 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

A few "consts" have been added. The dates are now considered to be positive...

A few "consts" have been added. The dates are now considered to be positive which allows comparison operators to be optimized: converting 1 year of hourly data with data_converter got almost 30% faster. Moreover, when looking for resampling window, two extra checks have been added to quickly see if the start and end point are even in the input vector. This reduces data read miss (because we start by reading vecM[0]) and skips browsing through the whole vector if we are in a large data gap. On the same 1 year data set with one large gap for one parameter, the gain is of almost 20%. Overall, these two optimizations lead to almost a doubling of the speed with data_converter... Soon we'll be so fast that we will get the data before it is even measured!
parent 3c140e10
......@@ -47,6 +47,9 @@ const float Date::Unix_offset = 2440587.5; ///<offset between julian date and Un
const float Date::Excel_offset = 2415018.5; ///<offset between julian date and Excel dates (note that excel invented some days...)
const float Date::Matlab_offset = 1721058.5; ///<offset between julian date and Matlab dates
const double Date::epsilon=1./(24.*3600.); ///< minimum difference between two dates. 1 second in units of days
//NOTE: For the comparison operators, we assume that dates are positive so we can bypass a call to abs()
// CONSTUCTORS
/**
* @brief Default constructor: timezone is set to GMT without DST, julian date is set to 0 (meaning -4713-01-01T12:00)
......@@ -628,7 +631,7 @@ bool Date::operator==(const Date& indate) const {
if(undef==true || indate.isUndef()) {
return( undef==true && indate.isUndef() );
}
const double epsilon=1./(24.*3600.); //that is, 1 second in units of days
return( fabs(indate.gmt_julian - gmt_julian) < epsilon );
}
......@@ -636,15 +639,16 @@ bool Date::operator!=(const Date& indate) const {
return !(*this==indate);
}
//If dates could be negative, all comparison operators would have to
//test equality between *this and indate and then run the standard operator
//on gmt_julian and indate (deleting the epsilon from the expressions).
bool Date::operator<(const Date& indate) const {
if(undef==true || indate.isUndef()) {
throw UnknownValueException("Date object is undefined!", AT);
}
if (*this == indate) {
return false;
}
return (gmt_julian < indate.gmt_julian);
//if(*this==indate) return false;
return (gmt_julian < (indate.gmt_julian-epsilon));
}
bool Date::operator<=(const Date& indate) const {
......@@ -652,10 +656,8 @@ bool Date::operator<=(const Date& indate) const {
throw UnknownValueException("Date object is undefined!", AT);
}
if (*this == indate) {
return true;
}
return (gmt_julian <= indate.gmt_julian);
//if(*this==indate) return true;
return (gmt_julian <= (indate.gmt_julian+epsilon));
}
bool Date::operator>(const Date& indate) const {
......@@ -663,11 +665,8 @@ bool Date::operator>(const Date& indate) const {
throw UnknownValueException("Date object is undefined!", AT);
}
if (*this == indate) {
return false;
}
return (gmt_julian > indate.gmt_julian);
//if(*this==indate) return false;
return (gmt_julian > (indate.gmt_julian+epsilon));
}
bool Date::operator>=(const Date& indate) const {
......@@ -675,10 +674,8 @@ bool Date::operator>=(const Date& indate) const {
throw UnknownValueException("Date object is undefined!", AT);
}
if (*this == indate) {
return true;
}
return (gmt_julian >= indate.gmt_julian);
//if(*this==indate) return true;
return (gmt_julian >= (indate.gmt_julian-epsilon));
}
const Date Date::operator+(const Date& indate) const {
......
......@@ -38,7 +38,8 @@ namespace mio {
* it can not be automatically calculated. Therefore, it has to be provided by the caller: when the dst flag
* is set, the dst time shift is automatically applied. When the dst flag ceases to be set, the dst time shift
* is no longer applied. This is very crude, but please keep in mind that using DST for monitoring data is
* usually a bad idea...
* usually a bad idea... Finally, we assume that dates are positive. If this would not be the case, the
* comparison operators would have to be modified (as shown in the source code).
*
* Internally, the date is stored as true julian date in GMT.
* The maximal precision is 1 minute (that can be easily brought to 1 seconds if
......@@ -162,7 +163,7 @@ class Date {
const Date operator/(const double&) const;
protected:
double localToGMT(const double& in_julian)const;
double localToGMT(const double& in_julian) const;
double GMTToLocal(const double& in_gmt_julian) const;
double calculateJulianDate(const int& in_year, const int& in_month, const int& in_day, const int& in_hour, const int& in_minute) const;
void calculateValues(const double& i_julian, int& out_year, int& out_month, int& out_day, int& out_hour, int& out_minute) const;
......@@ -175,6 +176,7 @@ class Date {
int gmt_year, gmt_month, gmt_day, gmt_hour, gmt_minute;
bool dst;
bool undef;
static const double epsilon;
};
typedef Date Duration; //so that later, we can implement a true Interval/Duration class
......
......@@ -248,7 +248,7 @@ const double& MeteoData::operator()(const size_t& parindex) const
double& MeteoData::operator()(const std::string& parname)
{
size_t index = getParameterIndex(parname);
const size_t index = getParameterIndex(parname);
if (index == IOUtils::npos)
throw IndexOutOfBoundsException("Trying to access meteo parameter that does not exist: " + parname, AT);
......@@ -257,7 +257,7 @@ double& MeteoData::operator()(const std::string& parname)
const double& MeteoData::operator()(const std::string& parname) const
{
size_t index = getParameterIndex(parname);
const size_t index = getParameterIndex(parname);
if (index == IOUtils::npos)
throw IndexOutOfBoundsException("Trying to access meteo parameter that does not exist: " + parname, AT);
......
......@@ -372,7 +372,7 @@ double ResamplingAlgorithms::funcval(size_t pos, const size_t& paramindex, const
const double valstart = vecM[pos](paramindex);
if (vecM[pos].date == date) return valstart;
size_t end = pos+1;
const size_t end = pos+1;
if(end>=vecM.size()) return IOUtils::nodata; //reaching the end of the input vector
const double valend = vecM[end](paramindex);
......@@ -403,23 +403,26 @@ void ResamplingAlgorithms::getNearestValidPts(const size_t& pos, const size_t& p
indexP2=IOUtils::npos;
const Date dateStart = resampling_date - window_size;
for (size_t ii=pos; (ii--) > 0; ) {
if (vecM[ii].date < dateStart) break;
if (vecM[ii](paramindex) != IOUtils::nodata){
indexP1 = ii;
break;
if(vecM[0].date<=dateStart) { //we try to find a valid point only if it's even worth it...
for (size_t ii=pos; (ii--) > 0; ) {
if (vecM[ii].date < dateStart) break;
if (vecM[ii](paramindex) != IOUtils::nodata){
indexP1 = ii;
break;
}
}
}
Date dateEnd;
if (indexP1 != IOUtils::npos) dateEnd = vecM[indexP1].date + window_size; //so the search window remains window_size
else dateEnd = resampling_date + window_size;
//make sure the search window remains window_size
const Date dateEnd = (indexP1 != IOUtils::npos)? vecM[indexP1].date+window_size : resampling_date+window_size;
for (size_t ii=pos; ii<vecM.size(); ii++) {
if (vecM[ii].date > dateEnd) break;
if (vecM[ii](paramindex) != IOUtils::nodata) {
indexP2 = ii;
break;
if(vecM[vecM.size()].date>=dateEnd) { //we try to find a valid point only if it's even worth it...
for (size_t ii=pos; ii<vecM.size(); ii++) {
if (vecM[ii].date > dateEnd) break;
if (vecM[ii](paramindex) != IOUtils::nodata) {
indexP2 = ii;
break;
}
}
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment