Original_NNB/MQL5/Include/NeuroNetworksBook/realization/bufferdouble.mqh
super.admin e81e22b7b8 convert
2025-05-30 16:15:14 +02:00

305 lines
24 KiB
MQL5

//+------------------------------------------------------------------+
//| BufferDouble.mqh |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Подключаем библиотеки |
//+------------------------------------------------------------------+
#include <Arrays\ArrayDouble.mqh>
#include "opencl.mqh"
#include "defines.mqh"
//+------------------------------------------------------------------+
//| Class CBufferDouble |
//| Назначение: Класс динамического буфера данных |
//+------------------------------------------------------------------+
class CBufferDouble : public CArrayDouble
{
protected:
CMyOpenCL *m_cOpenCL; // Объект контекста OpenCL
int m_myIndex; // Индекс буфера данных в контексте
public:
CBufferDouble(void);
~CBufferDouble(void);
//--- Метод инициализации буфера начальными значениями
virtual bool BufferInit(uint count, double value);
//--- Сложение векторов
virtual bool SumArray(const CArrayDouble *src);
//--- Созданиие нового буфера в контексте OpenCL
virtual bool BufferCreate(CMyOpenCL *opencl);
//--- Удаление буфера в контексте OpenCL
virtual bool BufferFree(void);
//--- Чтение данных буфера из контекста OpenCL
virtual bool BufferRead(void);
//--- Запись данных буфера в контекст OpenCL
virtual bool BufferWrite(void);
//--- Получение индекса буфера
virtual int GetIndex(void);
//--- Изменение индекса буфера
virtual bool SetIndex(int index)
{
if(!m_cOpenCL.BufferFree(m_myIndex)) return false;
m_myIndex = index; return true;
}
//--- Копирование данных буфера в массив
virtual int GetData(double &values[], bool load = true);
virtual int GetData(CArrayDouble *values, bool load = true);
//--- Рассчёт среднего значения буфера данных
virtual double MathMean(void);
//--- Масштабирование значений буфера
virtual int Scaling(double value);
//--- Обновдение данных в буфере из массива
virtual bool UpdateArray(const int start_pos,
const CArrayDouble *src,
const int start_src, int count);
virtual bool UpdateArray(const int start_pos,
const double &src[],
const int start_src, int count);
//--- Идентификатор класса
virtual int Type(void) const { return defBufferDouble; }
};
//+------------------------------------------------------------------+
//| Конструктор класса |
//+------------------------------------------------------------------+
CBufferDouble::CBufferDouble(void) : m_myIndex(-1)
{
m_cOpenCL = NULL;
}
//+------------------------------------------------------------------+
//| Деструктор класса |
//+------------------------------------------------------------------+
CBufferDouble::~CBufferDouble(void)
{
if(CheckPointer(m_cOpenCL) != POINTER_INVALID && m_myIndex >= 0)
{
if(m_cOpenCL.BufferFree(m_myIndex))
{
m_myIndex = -1;
m_cOpenCL = NULL;
}
}
Shutdown();
}
//+------------------------------------------------------------------+
//| Созданиие нового буфера в контексте OpenCL |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferCreate(CMyOpenCL *opencl)
{
//--- Блок проверки исходных данных
if(CheckPointer(opencl) == POINTER_INVALID)
{
BufferFree();
return false;
}
//--- Если полученный указатель совпадает с ранее сохранённым просто копируем содержимое буфера в память контекста
if(opencl == m_cOpenCL && m_myIndex >= 0)
{
if(BufferWrite())
return true;
}
//--- Проверяем наличие ранее сохранённого указателя на контекст OpenCL
//--- При наличии, удаляем буфер из неиспользуемого контекста
if(CheckPointer(m_cOpenCL) != POINTER_INVALID && m_myIndex >= 0)
{
if(m_cOpenCL.BufferFree(m_myIndex))
{
m_myIndex = -1;
m_cOpenCL = NULL;
}
else
return false;
}
//--- Создаём новый буфер в указнном контексте OpenCL
if((m_myIndex = opencl.AddBufferFromArray(m_data, 0, m_data_total, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR)) < 0)
return false;
m_cOpenCL = opencl;
//---
return true;
}
//+------------------------------------------------------------------+
//| Метод удаления буфера из памяти контекста OpenCL |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferFree(void)
{
//--- Проверяем наличие ранее сохранённого указателя на контекст OpenCL
//--- При наличии, удаляем буфер из неиспользуемого контекста
if(CheckPointer(m_cOpenCL) != POINTER_INVALID && m_myIndex >= 0)
if(m_cOpenCL.BufferFree(m_myIndex))
{
m_myIndex = -1;
m_cOpenCL = NULL;
return true;
}
if(m_myIndex >= 0)
m_myIndex = -1;
//---
return false;
}
//+------------------------------------------------------------------+
//| Метод чтения данных из буфера контекста OpenCL |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferRead(void)
{
if(CheckPointer(m_cOpenCL) == POINTER_INVALID || m_myIndex < 0)
return false;
//---
return m_cOpenCL.BufferRead(m_myIndex, m_data, 0, 0, m_data_total);
}
//+------------------------------------------------------------------+
//| Метод записи данных в буфера контекста OpenCL |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferWrite(void)
{
if(CheckPointer(m_cOpenCL) == POINTER_INVALID || m_myIndex < 0)
return false;
//---
return m_cOpenCL.BufferWrite(m_myIndex, m_data, 0, 0, m_data_total);
}
//+------------------------------------------------------------------+
//| Метод инициализации буфера начальными значениями |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferInit(uint count, double value)
{
if(!Reserve(count))
return false;
m_data_total = (int)fmin(ArrayInitialize(m_data, value), count);
//---
return m_data_total == count;
}
//+------------------------------------------------------------------+
//| Метод получения значений буфера |
//+------------------------------------------------------------------+
int CBufferDouble::GetData(double &values[], bool load = true)
{
if(load && !BufferRead())
return -1;
return ArrayCopy(values, m_data, 0, 0, m_data_total);
}
//+------------------------------------------------------------------+
//| Метод получения значений буфера |
//+------------------------------------------------------------------+
int CBufferDouble::GetData(CArrayDouble *values, bool load = true)
{
if(CheckPointer(values) == POINTER_INVALID)
return -1;
if(load && !BufferRead())
return -1;
if(!values.AssignArray(GetPointer(this)))
return -1;
return values.m_data_total;
}
//+------------------------------------------------------------------+
//| Метод суммирования элементов двух буферов данных |
//+------------------------------------------------------------------+
bool CBufferDouble::SumArray(const CArrayDouble *src)
{
int num;
//--- Проверка массива исходных жанных
if(!CheckPointer(src))
return(false);
//--- Резервирование места в динамическом массиве для записи результатов
num = src.m_data_total;
if(m_data_max < num)
{
if(!Reserve(num))
return(false);
}
//--- Цикл сложения элементов массивов
for(int i = 0; i < num; i++)
{
if(m_data_total <= i)
m_data[i] = src.m_data[i];
else
m_data[i] += src.m_data[i];
}
m_sort_mode = src.SortMode();
m_data_total = (int)fmax(m_data_total, num);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Метод вычисления среднего значениия массива |
//+------------------------------------------------------------------+
double CBufferDouble::MathMean(void)
{
if(m_data_total <= 0)
return 0;
//---
double mean = 0;
for(int i = 0; i < m_data_total; i++)
mean += m_data[i];
//---
return mean / m_data_total;
}
//+------------------------------------------------------------------+
//| Получени индекса буфера в контексте OpenCL |
//+------------------------------------------------------------------+
int CBufferDouble::GetIndex(void)
{
if(CheckPointer(m_cOpenCL) == POINTER_INVALID || m_myIndex < 0)
{
m_myIndex = -1;
return m_myIndex;
}
//---
if(!m_cOpenCL.CheckBuffer(m_myIndex))
m_myIndex = BufferCreate(m_cOpenCL);
//---
return m_myIndex;
}
//+------------------------------------------------------------------+
//| Метод масштабирования данных (умножение на константу) |
//+------------------------------------------------------------------+
int CBufferDouble::Scaling(double value)
{
for(int i = 0; i < m_data_total; i++)
m_data[i] *= value;
//---
return m_data_total;
}
//+------------------------------------------------------------------+
//| Метод заполнения буфера из массива данных |
//+------------------------------------------------------------------+
bool CBufferDouble::UpdateArray(const int start_pos, const CArrayDouble *src, const int start_src, int count)
{
if(start_pos < 0 || start_src < 0)
return false;
if(CheckPointer(src) == POINTER_INVALID)
return false;
if(count < 0)
count = src.Total() - start_src;
if(count < 0 || src.Total() < (start_src + count))
return false;
if((start_pos + count) > m_data_max && !Reserve(start_pos + count))
return false;
//---
for(int i = 0; i < count; i++)
m_data[start_pos + i] = src[start_src + i];
//---
return true;
}
//+------------------------------------------------------------------+
//| Метод заполнения буфера из массива данных |
//+------------------------------------------------------------------+
bool CBufferDouble::UpdateArray(const int start_pos, const double &src[], const int start_src, int count)
{
if(start_pos < 0 || start_src < 0)
return false;
int src_total = ArraySize(src);
if(src_total <= 0)
return false;
if(count < 0)
count = src_total - start_src;
if(count < 0 || src_total < (start_src + count))
return false;
if((start_pos + count) > m_data_max && !Reserve(start_pos + count))
return false;
//---
for(int i = 0; i < count; i++)
m_data[start_pos + i] = src[start_src + i];
//---
return true;
}
//+------------------------------------------------------------------+