source: XIOS/trunk/src/filter/temporal_filter.cpp @ 1124

Last change on this file since 1124 was 1124, checked in by rlacroix, 4 years ago

Temporal filters: Avoid intermediate copies whenever possible for once and instant operations.

File size: 3.7 KB
Line 
1#include "temporal_filter.hpp"
2#include "functor_type.hpp"
3#include "calendar_util.hpp"
4
5namespace xios
6{
7  static func::CFunctor* createFunctor(const std::string& opId, bool ignoreMissingValue, double missingValue, CArray<double, 1>& tmpData);
8
9  CTemporalFilter::CTemporalFilter(CGarbageCollector& gc, const std::string& opId,
10                                   const CDate& initDate, const CDuration samplingFreq, const CDuration samplingOffset, const CDuration opFreq,
11                                   bool ignoreMissingValue /*= false*/, double missingValue /*= 0.0*/)
12    : CFilter(gc, 1, this)
13    , functor(createFunctor(opId, ignoreMissingValue, missingValue, tmpData))
14    , isOnceOperation(functor->timeType() == func::CFunctor::once)
15    , isInstantOperation(functor->timeType() == func::CFunctor::instant)
16    // If we can optimize the sampling when dealing with an instant functor we do it
17    , samplingFreq((isInstantOperation && samplingFreq == TimeStep && samplingOffset == NoneDu) ? opFreq : samplingFreq)
18    , samplingOffset((isInstantOperation && samplingFreq == TimeStep && samplingOffset == NoneDu) ? opFreq - initDate.getRelCalendar().getTimeStep() : samplingOffset)
19    , opFreq(opFreq)
20    , nextSamplingDate(initDate + this->samplingOffset + initDate.getRelCalendar().getTimeStep())
21    , nextOperationDate(initDate + this->samplingOffset + opFreq)
22    , isFirstOperation(true)
23  {
24  }
25
26  CDataPacketPtr CTemporalFilter::apply(std::vector<CDataPacketPtr> data)
27  {
28    CDataPacketPtr packet;
29
30    if (data[0]->status != CDataPacket::END_OF_STREAM)
31    {
32      bool usePacket, outputResult, copyLess;
33      if (isOnceOperation)
34        usePacket = outputResult = copyLess = isFirstOperation;
35      else
36      {
37        usePacket = (data[0]->date >= nextSamplingDate);
38        outputResult = (data[0]->date + samplingFreq > nextOperationDate);
39        copyLess = (isInstantOperation && usePacket && outputResult);
40      }
41
42      if (usePacket)
43      {
44        if (!copyLess)
45        {
46          if (!tmpData.numElements())
47            tmpData.resize(data[0]->data.numElements());
48
49          (*functor)(data[0]->data);
50        }
51
52        nextSamplingDate = nextSamplingDate + samplingFreq;
53      }
54
55      if (outputResult)
56      {
57        if (!copyLess)
58        {
59          functor->final();
60
61          packet = CDataPacketPtr(new CDataPacket);
62          packet->date = data[0]->date;
63          packet->timestamp = data[0]->timestamp;
64          packet->status = data[0]->status;
65          packet->data.resize(tmpData.numElements());
66          packet->data = tmpData;
67        }
68        else
69          packet = data[0];
70
71        isFirstOperation = false;
72        nextOperationDate = nextOperationDate + samplingFreq + opFreq - samplingFreq;
73      }
74    }
75
76    return packet;
77  }
78
79  bool CTemporalFilter::isDataExpected(const CDate& date) const
80  {
81    return isOnceOperation ? isFirstOperation : (date >= nextSamplingDate || date + samplingFreq > nextOperationDate);
82  }
83
84  static func::CFunctor* createFunctor(const std::string& opId, bool ignoreMissingValue, double missingValue, CArray<double, 1>& tmpData)
85  {
86    func::CFunctor* functor = NULL;
87
88    double defaultValue = ignoreMissingValue ? std::numeric_limits<double>::quiet_NaN() : missingValue;
89
90#define DECLARE_FUNCTOR(MType, mtype) \
91    if (opId.compare(#mtype) == 0) \
92    { \
93      if (ignoreMissingValue) \
94      { \
95        functor = new func::C##MType(tmpData, defaultValue); \
96      } \
97      else \
98      { \
99        functor = new func::C##MType(tmpData); \
100      } \
101    }
102
103#include "functor_type.conf"
104
105    if (!functor)
106      ERROR("createFunctor(const std::string& opId, ...)",
107            << "\"" << opId << "\" is not a valid operation.");
108
109    return functor;
110  }
111} // namespace xios
Note: See TracBrowser for help on using the repository browser.