354 lines
25 KiB
MQL5
354 lines
25 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\Array.mqh>
|
|
#ifndef Defines
|
|
#include "defines.mqh"
|
|
#endif
|
|
#include "opencl.mqh"
|
|
//+------------------------------------------------------------------+
|
|
//| Class CBufferDouble |
|
|
//| Назначение: Класс динамического буфера данных |
|
|
//+------------------------------------------------------------------+
|
|
class CBufferDouble : public CObject
|
|
{
|
|
protected:
|
|
CMyOpenCL *m_cOpenCL; // Объект контекста OpenCL
|
|
int m_myIndex; // Индекс буфера данных в контексте
|
|
public:
|
|
CBufferDouble(void);
|
|
~CBufferDouble(void);
|
|
//---
|
|
MATRIX m_mMatrix;
|
|
//--- Метод инициализации буфера начальными значениями
|
|
virtual bool BufferInit(const ulong rows, const ulong columns, const double value = 0);
|
|
//--- Сложение векторов
|
|
virtual bool SumArray(const CBufferDouble *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(MATRIX &values, bool load = true);
|
|
virtual int GetData(CBufferDouble *values, bool load = true);
|
|
//--- Рассчёт среднего значения буфера данных
|
|
virtual double MathMean(void);
|
|
//--- Масштабирование значений буфера
|
|
virtual int Scaling(double value);
|
|
//--- методы работы с файлами
|
|
virtual bool Save(const int file_handle);
|
|
virtual bool Load(const int file_handle);
|
|
//--- Идентификатор класса
|
|
virtual int Type(void) const { return defBufferDouble; }
|
|
|
|
ulong Rows(void) const { return m_mMatrix.Rows(); }
|
|
ulong Cols(void) const { return m_mMatrix.Cols(); }
|
|
uint Total(void) const { return (uint)(m_mMatrix.Rows() * m_mMatrix.Cols()); }
|
|
double At(uint index) const { return m_mMatrix.Flat(index); }
|
|
double operator[](ulong index) const { return m_mMatrix.Flat(index); }
|
|
|
|
bool Update(uint index, double value)
|
|
{
|
|
if(index >= Total())
|
|
return false;
|
|
m_mMatrix.Flat(index, value);
|
|
return true;
|
|
}
|
|
|
|
bool Update(uint row, uint col, double value)
|
|
{
|
|
if(row >= Rows() || col >= Cols())
|
|
return false;
|
|
m_mMatrix[row, col] = value;
|
|
return true;
|
|
}
|
|
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Конструктор класса |
|
|
//+------------------------------------------------------------------+
|
|
CBufferDouble::CBufferDouble(void) : m_myIndex(-1)
|
|
{
|
|
m_cOpenCL = NULL;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Деструктор класса |
|
|
//+------------------------------------------------------------------+
|
|
CBufferDouble::~CBufferDouble(void)
|
|
{
|
|
if(m_cOpenCL && m_myIndex >= 0)
|
|
{
|
|
if(m_cOpenCL.BufferFree(m_myIndex))
|
|
{
|
|
m_myIndex = -1;
|
|
m_cOpenCL = NULL;
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Созданиие нового буфера в контексте OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::BufferCreate(CMyOpenCL *opencl)
|
|
{
|
|
//--- Блок проверки исходных данных
|
|
if(!opencl)
|
|
{
|
|
BufferFree();
|
|
return false;
|
|
}
|
|
//--- Если полученный указатель совпадает с ранее сохранённым просто копируем содержимое буфера в память контекста
|
|
if(opencl == m_cOpenCL && m_myIndex >= 0)
|
|
{
|
|
if(!BufferWrite())
|
|
return false;
|
|
return true;
|
|
}
|
|
//--- Проверяем наличие ранее сохранённого указателя на контекст OpenCL
|
|
//--- При наличии, удаляем буфер из неиспользуемого контекста
|
|
if(m_cOpenCL && 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_mMatrix, 0, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR)) < 0)
|
|
return false;
|
|
m_cOpenCL = opencl;
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод удаления буфера из памяти контекста OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::BufferFree(void)
|
|
{
|
|
//--- Проверяем наличие ранее сохранённого указателя на контекст OpenCL
|
|
//--- При наличии, удаляем буфер из неиспользуемого контекста
|
|
if(m_cOpenCL && 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(!m_cOpenCL || m_myIndex < 0)
|
|
return false;
|
|
//---
|
|
if(!m_cOpenCL.BufferRead(m_myIndex, m_mMatrix, 0))
|
|
return false;
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод записи данных в буфера контекста OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::BufferWrite(void)
|
|
{
|
|
if(!m_cOpenCL || m_myIndex < 0)
|
|
return false;
|
|
//---
|
|
return m_cOpenCL.BufferWrite(m_myIndex, m_mMatrix, 0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод инициализации буфера начальными значениями |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::BufferInit(ulong rows, ulong columns, double value)
|
|
{
|
|
if(rows <= 0 || columns <= 0)
|
|
return false;
|
|
//---
|
|
if(!m_mMatrix.Init(rows, columns))
|
|
return false;
|
|
m_mMatrix.Fill(value);
|
|
if(m_cOpenCL)
|
|
return BufferCreate(m_cOpenCL);
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод получения значений буфера |
|
|
//+------------------------------------------------------------------+
|
|
int CBufferDouble::GetData(double &values[], bool load = true)
|
|
{
|
|
if(load && !BufferRead())
|
|
return -1;
|
|
if(ArraySize(values) != Total() &&
|
|
ArrayResize(values, Total()) <= 0)
|
|
return false;
|
|
//---
|
|
for(uint i = 0; i < Total(); i++)
|
|
values[i] = m_mMatrix.Flat(i);
|
|
return (int)Total();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод получения значений буфера |
|
|
//+------------------------------------------------------------------+
|
|
int CBufferDouble::GetData(MATRIX &values, bool load = true)
|
|
{
|
|
if(load && !BufferRead())
|
|
return -1;
|
|
//---
|
|
values = m_mMatrix;
|
|
return (int)Total();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод получения значений буфера |
|
|
//+------------------------------------------------------------------+
|
|
int CBufferDouble::GetData(CBufferDouble *values, bool load = true)
|
|
{
|
|
if(!values)
|
|
return -1;
|
|
if(load && !BufferRead())
|
|
return -1;
|
|
values.m_mMatrix.Copy(m_mMatrix);
|
|
return (int)values.Total();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод суммирования элементов двух буферов данных |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::SumArray(const CBufferDouble *src)
|
|
{
|
|
ulong num;
|
|
//--- Проверка массива исходных жанных
|
|
if(!src)
|
|
return(false);
|
|
//--- Резервирование места в динамическом массиве для записи результатов
|
|
num = src.m_mMatrix.Rows();
|
|
if(m_mMatrix.Rows() < num)
|
|
{
|
|
if(!m_mMatrix.Resize(num, m_mMatrix.Cols(), 0))
|
|
return(false);
|
|
}
|
|
num = src.m_mMatrix.Cols();
|
|
if(m_mMatrix.Cols() < num)
|
|
if(!m_mMatrix.Resize(m_mMatrix.Rows(), num, 0))
|
|
return(false);
|
|
//--- Cложения матриц
|
|
m_mMatrix += src.m_mMatrix;
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Метод вычисления среднего значениия массива |
|
|
//+------------------------------------------------------------------+
|
|
double CBufferDouble::MathMean(void)
|
|
{
|
|
return m_mMatrix.Mean();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Получени индекса буфера в контексте OpenCL |
|
|
//+------------------------------------------------------------------+
|
|
int CBufferDouble::GetIndex(void)
|
|
{
|
|
if(!m_cOpenCL || 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)
|
|
{
|
|
m_mMatrix *= value;
|
|
if(m_cOpenCL && !BufferWrite())
|
|
return false;
|
|
//---
|
|
return (int)Total();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::Save(const int file_handle)
|
|
{
|
|
if(file_handle == INVALID_HANDLE)
|
|
return false;
|
|
if(m_myIndex >= 0)
|
|
if(!BufferRead())
|
|
return false;
|
|
//---
|
|
if(FileWriteInteger(file_handle, Type()) < INT_VALUE)
|
|
return false;
|
|
if(FileWriteLong(file_handle, Rows()) < sizeof(long))
|
|
return false;
|
|
if(FileWriteLong(file_handle, Cols()) < sizeof(long))
|
|
return false;
|
|
//---
|
|
for(ulong r = 0; r < Rows(); r++)
|
|
for(ulong c = 0; c < Cols(); c++)
|
|
if(FileWriteDouble(file_handle, m_mMatrix[r, c]) < sizeof(double))
|
|
return false;
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
bool CBufferDouble::Load(const int file_handle)
|
|
{
|
|
if(file_handle == INVALID_HANDLE)
|
|
return false;
|
|
if(FileReadInteger(file_handle) != Type())
|
|
return false;
|
|
//---
|
|
ulong rows = FileReadLong(file_handle);
|
|
ulong cols = FileReadLong(file_handle);
|
|
if(!m_mMatrix.Init(rows, cols))
|
|
return false;
|
|
for(ulong r = 0; r < rows; r++)
|
|
for(ulong c = 0; c < cols; c++)
|
|
m_mMatrix[r, c] = FileReadDouble(file_handle);
|
|
//---
|
|
if(m_myIndex >= 0)
|
|
{
|
|
if(!BufferCreate(m_cOpenCL))
|
|
return false;
|
|
}
|
|
//---
|
|
return true;
|
|
}
|
|
//+------------------------------------------------------------------+
|