Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#2.0 C++ list
I made LinkedListNode 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 6-Apr-11 22:02pm
Edited 6-Apr-11 22:07pm
v2
Comments
Niklas Lindquist at 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?
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

DeTrend.cs library in 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#
...
#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!
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);
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Change your Update() function to take a reference to the out vector:
public void Update(float[] inY, ref float[] outY, int nPointSize)
and call it like
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.
  Permalink  

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

  Print Answers RSS
0 BillWoodruff 360
1 Mathew Soji 309
2 DamithSL 225
3 Afzaal Ahmad Zeeshan 202
4 Maciej Los 190
0 OriginalGriff 6,249
1 Sergey Alexandrovich Kryukov 5,853
2 DamithSL 5,183
3 Manas Bhardwaj 4,673
4 Maciej Los 3,865


Advertise | Privacy | Mobile
Web01 | 2.8.1411019.1 | Last Updated 7 Apr 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100