154 lines
6.5 KiB
Plaintext
154 lines
6.5 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| CArrayRing.mqh |
|
|
//| Copyright 2012, Konstantin Gruzdev |
|
|
//| https://login.mql5.com/ru/users/Lizar |
|
|
//| Revision 03 Dec 2012 |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2012, Konstantin Gruzdev"
|
|
#property link "https://login.mql5.com/ru/users/Lizar"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Class CArrayRing |
|
|
//| Appointment: class is designed to work with tne finite ring |
|
|
//| buffers of data. When the buffer is crowded the oldest |
|
|
//| buffer element is replaced by the newest element. Herewith, |
|
|
//| the specified number of end elements are always |
|
|
//| available. |
|
|
//| Link: http://www.mql5.com/ru/code/1340 |
|
|
//| Remark: it should also be kept in mind that the element indexing |
|
|
//| in the ring buffer is executed as in timeseries. |
|
|
//+------------------------------------------------------------------+
|
|
class CArrayRing
|
|
{
|
|
private:
|
|
double m_data[]; // ring buffer of data
|
|
int m_size; // buffer size
|
|
int m_last_pos; // last buffer element position
|
|
double m_filling; // value, which used for the array filling
|
|
|
|
public:
|
|
CArrayRing();
|
|
~CArrayRing() { ArrayFree(m_data); }
|
|
//--- buffer initialization method:
|
|
bool Init(int size, double volue=EMPTY_VALUE);
|
|
//--- method returns the buffer size:
|
|
int Size() { return m_size-1; }
|
|
//--- method changes the ring buffer size:
|
|
bool Resize(const int size);
|
|
//--- method of adding a new element to the buffer:
|
|
void Add(const double element);
|
|
//--- method returns the value of element with the specified index:
|
|
double At(const int index) const;
|
|
double operator [](const int index) const { return(At(index)); }
|
|
//--- method returns the value of the last element stored in the buffer:
|
|
double Last() const { return(m_data[m_last_pos]); }
|
|
//--- method overwrites the value of the last element in the buffer:
|
|
void Last(const double element) { m_data[m_last_pos]=element; }
|
|
//--- method overwrites the value of element with the specified index:
|
|
bool Update(const double element,const int index=0);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor. |
|
|
//+------------------------------------------------------------------+
|
|
CArrayRing::CArrayRing()
|
|
{
|
|
m_last_pos=0; // last element position
|
|
m_filling=EMPTY_VALUE; // value for buffer filling
|
|
m_size=ArraySize(m_data); // get size of the ring buffer
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Buffer initialization method. |
|
|
//+------------------------------------------------------------------+
|
|
bool CArrayRing::Init(int size, double volue=EMPTY_VALUE)
|
|
{
|
|
m_last_pos=0; // last element position
|
|
m_filling=volue; // value for buffer filling
|
|
m_size=ArraySize(m_data); // get size of the buffer
|
|
bool result=Resize(size); // create a buffer with the desired size
|
|
ArrayFill(m_data,0,m_size,m_filling); // fill the buffer with default values
|
|
return(result);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Set the new size of the array. |
|
|
//+------------------------------------------------------------------+
|
|
bool CArrayRing::Resize(const int new_size)
|
|
{
|
|
//--- check
|
|
if(new_size<0) return(false);
|
|
//--- increase array size:
|
|
if(new_size>m_size)
|
|
{
|
|
int set_size=ArrayResize(m_data,new_size);
|
|
if(set_size<0) return(false);
|
|
//--- copy elements to restore their order:
|
|
if(set_size>m_size)
|
|
{
|
|
for(int i=m_size-1,j=set_size-1;i>m_last_pos;i--,j--)
|
|
{
|
|
m_data[j]=m_data[i];
|
|
m_data[i]=m_filling;
|
|
}
|
|
}
|
|
m_size=set_size;
|
|
//--- result:
|
|
return(true);
|
|
}
|
|
//--- reduce array size:
|
|
//--- prepare array to reduce the size:
|
|
if(new_size>m_last_pos+1)
|
|
for(int i=m_size-1,j=new_size-1;j>m_last_pos;i--,j--) m_data[j]=m_data[i];
|
|
else
|
|
{
|
|
for(int i=m_last_pos+1-new_size,j=0;i<=m_last_pos;i++,j++) m_data[j]=m_data[i];
|
|
m_last_pos=new_size-1;
|
|
}
|
|
//--- reduce the size:
|
|
m_size=new_size;
|
|
ArrayResize(m_data,new_size);
|
|
//--- result:
|
|
return(true);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Adding a new element to the buffer. |
|
|
//+------------------------------------------------------------------+
|
|
void CArrayRing::Add(const double element)
|
|
{
|
|
m_last_pos=++m_last_pos%m_size;
|
|
m_data[m_last_pos]=element;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Gets the element at the specified index. |
|
|
//+------------------------------------------------------------------+
|
|
double CArrayRing::At(const int index) const
|
|
{
|
|
//--- check the index correctness:
|
|
if((index/m_size)==0)
|
|
//--- return the value of element with the specified index:
|
|
return(m_data[(m_size+m_last_pos-index)%m_size]);
|
|
//--- if the index is wrong:
|
|
return(DBL_MAX);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update the element at the specified position in the array. |
|
|
//+------------------------------------------------------------------+
|
|
bool CArrayRing::Update(const double element,const int index=0)
|
|
{
|
|
//--- check the index correctness:
|
|
if((index/m_size)==0)
|
|
{
|
|
//--- update
|
|
m_data[(m_size+m_last_pos-index)%m_size]=element;
|
|
//--- successful
|
|
return(true);
|
|
}
|
|
//--- if the index is wrong:
|
|
return(false);
|
|
}
|
|
|
|
|