1
0
Derivar 0
Warrior_EA/AI/BufferDouble.mqh
AnimateDread e4a154aa5e refactor(AI): split 8 self-contained classes out of the Network.mqh god-file
AI/Network.mqh was 5,805 lines / 18 classes in one file. Investigation
found method implementations for several classes (CNeuronBase/Pool/Conv,
CNeuronBaseOCL) hand-interleaved across thousands of lines - not safe to
split without risky manual reassembly. But 8 classes turned out to be
genuinely self-contained (declaration + every method body physically
contiguous, and only ever depended upon, never depending on anything
declared later): CConnection/CArrayCon, CNeuron, CDirectMLMy (+ its
WarriorDML.dll/WarriorCPU.dll #import blocks), CArrayLayer,
CLayerDescription, CBufferDouble, and CNeuronConvOCL/CNeuronPoolOCL.

Extracted each verbatim, via exact line-range extraction (not manual
retyping) to eliminate transcription risk, into its own AI/*.mqh file,
included from Network.mqh at the exact point each class used to sit -
preserving original declaration order exactly. Mathematically verified
byte-for-byte: reconstructing the original file from the 7 new files'
bodies + Network.mqh's remaining segments is line-for-line identical to
the pre-split git history. Compiled clean (MetaEditor, 0 errors/0
warnings) both before and after.

The remaining tangled classes (CNeuronBase, CNeuronPool, CNeuronConv,
CNet, CNeuronLSTM, CNeuronBaseOCL, CNeuronConvOCL/PoolOCL's shared base,
CNeuronLSTMOCL, COpenCLMy) stay in Network.mqh (now ~4,450 lines) -
splitting those safely needs deliberate per-method surgery, deferred to
a future dedicated pass rather than rushed into this one.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:13:03 -04:00

181 linhas
7,2 KiB
MQL5

//+------------------------------------------------------------------+
//| BufferDouble.mqh |
//| AnimateDread |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//| CBufferDouble - the OpenCL/DirectML-backed buffer wrapper every |
//| *OCL neuron class (AI\Network.mqh) uses for its weights/output/ |
//| gradient storage. Needs COpenCLMy (AI\Network.mqh) and |
//| CDirectMLMy (AI\NeuronDirectML.mqh) already declared. Extracted |
//| verbatim out of AI\Network.mqh (SOLID cleanup) - no logic changes.|
//+------------------------------------------------------------------+
#include "NeuronDirectML.mqh"
class CBufferDouble : public CArrayDouble
{
protected:
COpenCLMy *OpenCL;
CDirectMLMy *DirectML;
int m_myIndex;
//--- OpenCL device buffers are float32 (see AI\Network.cl's fp32 conversion) while this class's
//--- public CArrayDouble interface - and the DirectML backend's DLL boundary (DML_BufferRead/
//--- DML_BufferWrite, hardcoded to double[]) - stay double. This scratch array is the narrow/widen
//--- point: populated from m_data before an OpenCL write, copied back into m_data after an OpenCL
//--- read. Never touched on the DirectML or CPU-fallback paths.
float m_data_f[];
public:
CBufferDouble(void);
~CBufferDouble(void);
//---
virtual bool BufferInit(uint count, double value);
virtual bool BufferCreate(COpenCLMy *opencl);
virtual bool BufferCreate(CDirectMLMy *directml);
virtual bool BufferFree(void);
virtual bool BufferRead(void);
virtual bool BufferWrite(void);
virtual int GetData(double &values[]);
virtual int GetData(CArrayDouble *values);
virtual int GetIndex(void) { return m_myIndex; }
//---
virtual int Type(void) const { return defBufferDouble; }
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBufferDouble::CBufferDouble(void) : m_myIndex(-1)
{
OpenCL = NULL;
DirectML = NULL;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBufferDouble::~CBufferDouble(void)
{
BufferFree();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferCreate(COpenCLMy *opencl)
{
BufferFree();
//---
if(CheckPointer(opencl) == POINTER_INVALID)
return false;
if(ArrayResize(m_data_f, m_data_total) < 0)
return false;
for(int i = 0; i < m_data_total; i++)
m_data_f[i] = (float)m_data[i];
if((m_myIndex = opencl.AddBufferFromArray(m_data_f, 0, m_data_total, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR)) < 0)
return false;
OpenCL = opencl;
//---
return true;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferCreate(CDirectMLMy *directml)
{
BufferFree();
//---
if(CheckPointer(directml) == POINTER_INVALID)
return false;
if((m_myIndex = directml.BufferCreate(m_data_total)) < 0)
return false;
DirectML = directml;
return DirectML.BufferWrite(m_myIndex, m_data, m_data_total);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferFree(void)
{
if(CheckPointer(OpenCL) != POINTER_INVALID && m_myIndex >= 0)
{
if(!OpenCL.BufferFree(m_myIndex))
return false;
m_myIndex = -1;
OpenCL = NULL;
return true;
}
if(CheckPointer(DirectML) != POINTER_INVALID && m_myIndex >= 0)
{
DirectML.BufferFree(m_myIndex);
m_myIndex = -1;
DirectML = NULL;
return true;
}
//---
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferRead(void)
{
if(CheckPointer(OpenCL) != POINTER_INVALID && m_myIndex >= 0)
{
if(ArrayResize(m_data_f, m_data_total) < 0)
return false;
if(!OpenCL.BufferRead(m_myIndex, m_data_f, 0, 0, m_data_total))
return false;
for(int i = 0; i < m_data_total; i++)
m_data[i] = (double)m_data_f[i];
return true;
}
if(CheckPointer(DirectML) != POINTER_INVALID && m_myIndex >= 0)
return DirectML.BufferRead(m_myIndex, m_data, m_data_total);
//---
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBufferDouble::BufferWrite(void)
{
if(CheckPointer(OpenCL) != POINTER_INVALID && m_myIndex >= 0)
{
if(ArrayResize(m_data_f, m_data_total) < 0)
return false;
for(int i = 0; i < m_data_total; i++)
m_data_f[i] = (float)m_data[i];
return OpenCL.BufferWrite(m_myIndex, m_data_f, 0, 0, m_data_total);
}
if(CheckPointer(DirectML) != POINTER_INVALID && m_myIndex >= 0)
return DirectML.BufferWrite(m_myIndex, m_data, m_data_total);
//---
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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[])
{
if(!BufferRead())
return false;
return ArrayCopy(values, m_data, 0, 0, m_data_total);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int CBufferDouble::GetData(CArrayDouble *values)
{
if(!BufferRead())
return -1;
values.Clear();
if(!values.AddArray(GetPointer(this)))
return -1;
return m_data_total;
}