DeTrend.cs library in C#
public class DeTrend
{
public DeTrend(int nWindowSize)
{
m_nWindowSize = nWindowSize;
m_TrendList = new LinkedList<float>();
}
public void Dispose()
{
if (null != m_TrendList) m_TrendList.Clear(); m_TrendList = null;
}
public void Update(float[] inY, float[] outY, int nPointSize)
{
int i;
m_nPointSize = nPointSize;
if (m_nPointSize < m_nWindowSize)
{
throw new Exception("nPointSize < nWindowSize");
}
for (i = 0; i < m_nPointSize; i++)
{
m_TrendList.AddLast(inY[i]);
}
if (m_bFirstCall)
{
m_CurIter = m_TrendList.First;
}
for (i = 0; i < m_nPointSize; i++)
{
outY[i] = m_CurIter.Value - m_PreNMeanVal();
m_CurIter = m_CurIter.Next;
}
i = m_nPointSize - m_nWindowSize;
while (0 != i)
{
m_TrendList.RemoveFirst();
i--;
}
m_bFirstCall = false;
}
#region Private Variable
private bool m_bFirstCall = true;
private int m_nWindowSize = 101;
private int m_nPointSize = 200;
private LinkedList<float> m_TrendList = null;
private LinkedListNode<float> m_CurIter = null;
#endregion
private float m_PreNMeanVal()
{
float nRet = 0.0f;
float nTotal = 0.0f;
int i, nCount = 0;
LinkedListNode<float> iter;
for (iter = m_TrendList.First; m_CurIter != iter; ) iter = iter.Next;
for (i = 0; i < m_nWindowSize && iter != m_TrendList.First; i++)
{
nTotal += iter.Value;
nCount++;
iter = iter.Previous;
}
if (0 == nCount) return nRet;
nRet = nTotal / nCount;
return nRet;
}
}
LibDeTrend.cpp can be DllImport by C#
...
#include <list>
namespace CCTEC
{
class DeTrend
{
public:
DeTrend(int nWindowSize)
{
m_nWindowSize = nWindowSize;
m_bFirstCall = true;
}
~DeTrend() { m_TrendList.clear(); }
public:
void Update(float *inY, float *outY, int nPointSize)
{
int i;
m_nPointSize = nPointSize;
if (m_nPointSize < m_nWindowSize) throw "WindowSize > PointSize";
for (i = 0; i < m_nPointSize; i++)
{
m_TrendList.push_back(inY[i]);
}
if (m_bFirstCall)
{
m_CurIter = m_TrendList.begin();
}
for (i = 0; i < m_nPointSize; i++, m_CurIter++)
{
outY[i] = *m_CurIter - m_PreNMeanVal();
}
i = m_nPointSize - m_nWindowSize;
while (i)
{
m_TrendList.pop_front();
i--;
}
m_bFirstCall = false;
}
private:
int m_nWindowSize;
int m_nPointSize;
bool m_bFirstCall;
std::list<float> m_TrendList;
std::list<float>::iterator m_CurIter;
private:
float m_PreNMeanVal()
{
float nRet = 0.0f;
float nTotal = 0.0f;
int i, nCount = 0;
std::list<float>::iterator iter;
for (iter = m_TrendList.begin(); m_CurIter != iter;) iter++;
for (i = 0; i < m_nWindowSize && iter != m_TrendList.begin(); i++, iter--)
{
nTotal += *iter;
nCount++;
}
if (0 == nCount) return nRet;
nRet = nTotal / nCount;
return nRet;
}
};
};
static CCTEC::DeTrend *m_DeTrend = NULL;
DLLEXPORT void LibDeTrendInit(int nWindowSize)
{
m_DeTrend = new CCTEC::DeTrend(nWindowSize);
}
DLLEXPORT void LibDeTrendCleanup()
{
if (m_DeTrend) delete m_DeTrend; m_DeTrend = NULL;
}
DLLEXPORT void LibDeTrendUpdate(float *inY, float *outY, int nPointSize)
{
if (m_DeTrend) m_DeTrend->Update(inY, outY, nPointSize);
}
C# testcase, there are 2 DeTrend objects, the Update(...) outYXXX output weired!
m_objDeTrend1 = new DeTrend(101, m_nPointSize);
m_objDeTrend2 = new DeTrend(101, m_nPointSize);
float[] outYInteg1 = new float[m_nPointSize];
float[] outYDeTrend1 = new float[m_nPointSize];
float[] outYInteg2 = new float[m_nPointSize];
float[] outYDeTrend2 = new float[m_nPointSize];
if (null != m_objDeTrend1) m_objDeTrend1.Update(outYInteg1, outYDeTrend1, m_nPointSize);
if (null != m_objDeTrend1) m_objDeTrend1.Update(outYInteg2, outYDeTrend2, m_nPointSize);