//+------------------------------------------------------------------+ //| BufferDouble.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Подключаем библиотеки | //+------------------------------------------------------------------+ #include #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; } //+------------------------------------------------------------------+