Click here to Skip to main content
15,881,898 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I made LinkedListNode<float> m_CurIter = null as a private member, and set a boolean variable m_bFirstCall = true, when called Update(...) if the m_bFirstCall is true then m_CurIter = m_TrendList.First (be called at first time) the m_bFirstCall be set to false;

However when called Update(...) after the first time, the private member m_CurIter became to null! How to fix such issue that C++ worked well.

DeTrend.cs
public class DeTrend
{
    public DeTrend(int nWindowSize, int nPointSize)
    {
        if (nPointSize < nWindowSize) 
            throw new Exception("nPointSize < nWindowSize");
        m_nWindowSize = nWindowSize;
        m_nPointSize = nPointSize;
        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++)
        {
            // FIXME: m_CurIter became null after the first call ?
            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;
        // XXX: From WindowSize to CurIter
        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;
    }
}</float></float></float></float>


DeTrend.cpp worked well but DllImport by C# weired
///////////////////////////////////////////////////////////////////////////////
// DeTrend Class
namespace CCTEC
{
    class DeTrend
    {
    // Construct / Destruct
    public:
        DeTrend(int nWindowSize, int nPointSize)
        {
            if (nPointSize < nWindowSize) throw "WindowSize < PointSize";
            m_nWindowSize = nWindowSize;
            m_nPointSize = nPointSize;
            m_bFirstCall = true;
        }
        ~DeTrend() { m_TrendList.clear(); }
    // Operation
    public:
        void Update(float *inY, float *outY, int nPointSize)
        {
            m_nPointSize = nPointSize;
            int i;
            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;
        }
    // Attribute
    private:
        int m_nWindowSize;
        int m_nPointSize;
        bool m_bFirstCall;
        std::list<float> m_TrendList;
        std::list<float>::iterator m_CurIter;
    // Operation
    private:
        float m_PreNMeanVal()
        {
            float nRet = 0.0f;
            float nTotal = 0.0f;
            int i, nCount = 0;
            std::list<float>::iterator iter;
            // XXX: From WindowSize to CurIter
            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;
        }
    };
};</float></float></float>


[edit]Code blocks added, "Ignore HTML..." option disabled - OriginalGriff.[/edit]
Posted
Updated 6-Apr-11 21:07pm
v2
Comments
Niklas L 7-Apr-11 3:15am    
If you send a nWindowSize of zero to your constructor, your code will break. Why do you send nPointSize to the constructor, and then again to Update and overwite the old value? Could you not remove it from the constructor, or do you have more code not shown here?

DeTrend.cs library in C#
C#
// TODO: DeTrend class acts like mathwords detrend(...)
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++)
        {
            // FIXME: m_CurIter became to null after the first call
            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

    // XXX: What is the Preview N Mean Value?
    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#
C++
...
#include <list>

///////////////////////////////////////////////////////////////////////////////
// DeTrend Class
namespace CCTEC 
{
    class DeTrend 
    {
    // Construct / Destruct
    public:
        DeTrend(int nWindowSize) 
        {
            m_nWindowSize = nWindowSize;
            m_bFirstCall = true; 
        }
        ~DeTrend() { m_TrendList.clear(); }

    // Operation
    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;
        }

    // Attribute
    private:
        int m_nWindowSize;
        int m_nPointSize;
        bool m_bFirstCall;
        std::list<float> m_TrendList;
        std::list<float>::iterator m_CurIter;

    // Operation
    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;
        }
    };
};

///////////////////////////////////////////////////////////////////////////////
// Private Variable
static CCTEC::DeTrend *m_DeTrend = NULL;

///////////////////////////////////////////////////////////////////////////////
// Public Operation
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!
C#
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);
 
Share this answer
 
Change your Update() function to take a reference to the out vector:
C#
public void Update(float[] inY, ref float[] outY, int nPointSize)

and call it like
C#
m_objDeTrend1.Update(outYInteg1, ref outYDeTrend1, m_nPointSize);


Your Update() function is also incorrect, and will break if you enter it a second time. It looks like you should skip the m_bFirstCall altogether to avoid a dangling pointer, m_CurIter.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900