Generic Class Library - bugs, description, questions, usage and suggestions - page 28

 
Alexey Volchanskiy:

What the fuck is going on here again? They're deleting perfectly good LinkedList posts. I can just imagine an anonymous moderator sitting somewhere in Europe and deleting posts from hated Russians, giggling maliciously. It's such a dump, it makes you not want to write.

Stop fighting the windmills - there are no deleted posts from this thread.

 
Artyom Trishkin:

Stop fighting windmills - there are no deleted posts from this thread.

Artem, I'm not drunk or under the influence. I wrote a short reply half an hour ago that in MQL LinkedList is implemented as a ring buffer and the described behaviour is just normal. And I've implemented a ring buffer in my filters using an array. Then I went to the .NET sources to look at the implementation, and after half an hour my message has been deleted. It was the first time I did it.

On the Russian moderators I just do not think.

Here is filter class with FIR, watch double FilterTick(double tick) function. There are two ring buffers - input ticks and output filtered values. The difference with linked list is that it's less possible, but it's an order of magnitude faster, which is important to me.

#ifndef  Filter
#define  Filter

//+------------------------------------------------------------------+
//|                                                       Filter.mqh |
//|                                               Alexey Volchanskiy |
//|                                      https://mql4.wordpress.com/ |
//+------------------------------------------------------------------+
#property copyright "Alexey Volchanskiy"
#property link      "https://mql4.wordpress.com/"
#property version   "1.04"
#property strict
#include <Object.mqh>
#include <AvLib-4-5\coeff.mqh>
#include <AvLib-4-5\Errors.mqh>

/*
Формат массива или файла коэффициентов фильтра
double coeff[] = {FiltersCount, FilterAddr, FilterLen, FilterAddr, FilterLen..., coeff1, coeff2, coeff3...};
*/
enum EErrors {EOk, ENumFilterOutOfRange};

class CFilter : CObject
{
#define  TICK_BUF_SIZE       0x1000              // 4096
#define  TICK_BUF_MAX_IDX    (TICK_BUF_SIZE - 1) // 0xFFF
#define  OUT_BUF_SIZE        0x10000             // 65536
#define  OUT_BUF_MAX_IDX     (OUT_BUF_SIZE - 1)  // 0xFFFF   

private:
    double  TickBuf[TICK_BUF_SIZE]; // промежуточный кольцевой буфер для хранения тиков
    double  OutBuf[OUT_BUF_SIZE];   // выходной кольцевой буфер
    double  Coeff[];                // массив коэффициентов
    int     TickBufIdx;             // индекс для нового входящего тика в TickBuf
    int     OutBufIdx;              // индекс для выходного буфера 
public:
    enum Errors {OK, NUM_FILTER_OUT_OF_RANGE };  
public:
    CFilter() {}
    ~CFilter() 
    {
        ArrayFree(Coeff);
    }
    
    double  GetOutBuf(const int idx)
    {
        int tmp = OutBufIdx-idx-1;
        double out = tmp >= 0 ? OutBuf[tmp] : OutBuf[OUT_BUF_SIZE+(tmp)]; 
        return out;
    }

    void    Init()
    {
        TickBufIdx = TICK_BUF_MAX_IDX;
        OutBufIdx = 0;
        for(int n = 0; n < TICK_BUF_SIZE; n++)
            TickBuf[n] = 0;
        for(int n = 0; n < OUT_BUF_SIZE; n++)
            OutBuf[n] = 0;
    }        

    EErrors  LoadCoeffFromArray(int numFilter, double &coeffArray[])
    {
        if(numFilter >= coeffArray[0])  // количество фильтров в массиве
            return ENumFilterOutOfRange;
        uint addr = (uint)coeffArray[1 + numFilter * 2];
        uint len = (uint)coeffArray[2 + numFilter * 2];   
        ArrayResize(Coeff, len);
        for(uint n = 0; n < len; n++)
            Coeff[n] = coeffArray[addr++];
        Init();    
        return EOk;
    }

    void    LoadCoeffFromArray(double &coeffArray[])
    {
        int len = ArraySize(coeffArray); 
        ArrayResize(Coeff, len);
        for(int n = 0; n < len; n++)
            Coeff[n] = coeffArray[n];
        Init();    
    }
    
    bool    LoadCoeffFromFile(int numFilter, string fileName)
    {
        // не реализовано
        return true;
    }
    
    // фильтрация одного тика
    double  FilterTick(double tick)
    {
        TickBuf[TickBufIdx] = tick;
        if (TickBufIdx == 0)
            TickBufIdx = TICK_BUF_MAX_IDX;
        else
            TickBufIdx--;
        int asize = ArraySize(Coeff); // вынести из функции!!!
        double acc = 0;
        int tbIdx = TickBufIdx;
        // делаем фильтрацию в цикле for
        for (int n = 0; n < asize; n++)
        {
            tbIdx++;
            /* вместо
            if(tbIdx > TICK_BUF_MAX_IDX)
            tbIdx = 0;
            */
            tbIdx &= TICK_BUF_MAX_IDX; // небольшая оптимизация вместо if
            acc += TickBuf[tbIdx] * Coeff[n];
        }
        OutBuf[OutBufIdx] = acc;
        OutBufIdx++;
        OutBufIdx &= OUT_BUF_MAX_IDX;
        return acc;
    }
    
    // фильтрация массива
    void    FilterTickSeries(double &ticks[], int count)
    {
        for(int n = 0; n < count; n++)
            ticks[n] = FilterTick(ticks[n]);
    }
};
#endif
 
Alexey Volchanskiy:

Artem, I'm not drunk and I'm not on drugs. I wrote a short reply half an hour ago that MQL LinkedList is implemented as a ring buffer and the described behaviour is just normal. And I've implemented a ring buffer in my filters using an array. Then I went to the .NET sources to look at the implementation, and after half an hour my message has been deleted. It was the first time I did it.

On the Russian moderators I just do not think.

Here is the filter class with FIR, watch double FilterTick(double tick) function. There are two ring buffers - input ticks and output filtered values. The difference with linked list is less possibilities, but it's much faster, which is important to me.

I don't know - looked through deleted posts - nothing from this thread. Shaitan ...

It seems logical to me, too, that a "linked list" is a linked list. A simple list has no looping and works as Alexey Navoikov said: "The Next of the last node is zero, just like thePrevious of the first node", while a linked list does, and works like a ring buffer. Which to me is convenient.

 
Artyom Trishkin:

I don't know - looked through the deleted posts - nothing from this thread. Shaitan...

It also seems logical to me that a "linked list" is a linked list. A simple list has no looping and works like Alexey Navoikov said: "Next of last node equals zero and so does Previous of first n ode" while a linked list has and works like a ring buffer. Which to me is convenient.

Ah, that's a possibility, didn't know. Well, I can assume that I got distracted and, without sending a message, went straight from that page somewhere. But such complaints occur regularly, and I'm not the only one. Ok, let's not talk about it anymore.

 
Alexey Volchanskiy:

Ah, that's a possibility, I didn't know. Well, I can assume that I got distracted and went straight from that page without sending a message. But such complaints occur regularly, and I'm not the only one. All right, let's not talk about it anymore.

Here, here, need to be more attentive, all buttons neatly pressed.

 
Artyom Trishkin:

It also seems logical to me that a "linked list" is a linked list. A simple list has no looping and works like Alexey Navoikov said: "Next last node is zero, so is Previous first one", while a linked list has and works like a ring buffer. Which to me is convenient.

A linked list is a list that stores pointers to the next and previous items. "Ringing has nothing to do with it. Anyway, this is something new. Where has it been seen?

Alexey Volchanskiy:
Here is the filter class with FIR, watch double FilterTick(double tick) function. There just two ring buffers - input ticks and output filtered values. The difference with linked list is less possibilities, but it's much faster, which is important to me.

It has nothing to do with a filter class... We are talking specifically about a linked list. It is a standard container which has certain properties. Iteration through the list is unidirectional. There cannot be any ringing. There is none in C# (the identical LinkedList class) or C++ (the std::list class).

Besides, this library is ported from .Net, implying compatibility with C#, otherwise why the hell do we need another homemade bicycle? Have we not had enough of crummy MQ bicycles? All we needed was to port a ready-made library (even if with language-specific restrictions, but at least to preserve the logic of work). But no... Naughty hands interfered here too )

Most likely, whoever ported those classes decided to simplify his life, having simplified the code. Instead of two m_first and m_last pointers he made one m_head pointer...

Of course, I've fixed everything as it should be, but nevertheless...

 
Alexey Navoykov:

A linked list is a list that stores pointers to the next and previous items. "Ringing has nothing to do with it. Anyway, this is something new. Where has it been seen?

It has nothing to do with a filter class... We are talking specifically about a linked list. It is a standard container which has certain properties. Iteration through the list is unidirectional. There cannot be any ringing. There is none in C# (the identical LinkedList class) or C++ (the std::list class).

Besides, this library is ported from .Net, implying compatibility with C#, otherwise why the hell do we need another homemade bicycle? Have we not had enough of crummy MQ bicycles? All we needed was to port a ready-made library (even if with language-specific restrictions, but at least to preserve the logic of work). But no... Naughty hands interfered here too )

Most likely, whoever ported those classes decided to simplify his life, having simplified the code. Instead of two m_first and m_last pointers he made one m_head pointer...

Of course, I fixed everything as I should, but nevertheless...

MSDN calls it a ring buffer, I haven't invented the name.

The main thing is not to fix it in Include folder, otherwise it will be erased when you upgrade to the new build of MT5.

 
Vladimir Karputov:

There, there, you have to be more careful and press all the right buttons carefully.

The probability of that happening is close to zero. But it's a fact that my branch in the English language thread was anonymously killed. ***

 
Alexey Volchanskiy:

The likelihood of that happening is very low. But it's a fact that my branch in the English language thread was anonymously killed. ***

Enough about that branch. You bring it up again and I'll give you a birch broom. I'm sick of it.

 
Alexey Volchanskiy:

Most importantly, don't edit in the Include folder, or it will get overwritten when you upgrade to a new build of MT5.

I have it in a separate folder Generic_. In fact, I had to make a lot of changes there, starting with const for methods (the developers did not consider it necessary), and ending with redesigning for arguments by reference, not only by value.

Reason: