//+------------------------------------------------------------------+
//| Script program start function
//+------------------------------------------------------------------+
void OnStart() {
// Operations of addition and multiplication of matrices
CMatrix A(3),B(3),C();
// Prepare an array for rows
double a1[3]={1,2,3}, a2[3]={2,3,1}, a3[3]={3,1,2};
double b1[3]={3,2,1}, b2[3]={1,3,2}, b3[3]={2,1,3};
// Fill the matrices
A[0]=a1; A[1]=a2; A[2]=a3;
B[0]=b1; B[1]=b2; B[2]=b3;
// Output the matrices in the Experts log
Print("---- Elements of matrix A");
Print(A.String());
Print("---- Elements of matrix B");
Print(B.String());
// Addition of matrices
Print("---- Addition of matrices A and B");
C = A + B;
// Output the formatted string representation
Print(C.String());
// Multiplication of matrices
Print("---- Multiplication of matrices A and B");
C = A * B;
Print(C.String());
// Now we show how to get values in the style of dynamic arrays matrix[i][j]
Print("Output the values of matrix C elementwise");
// Go through the matrix rows - CRow objects - in a loop
for( int i=0; i < 3 ;i++) {
string com="| ";
//--- Form rows from the matrix for the value
for( int j=0; j < 3 ; j++) {
//--- Get the matrix element by the number of the row and column
double element=C[i][j];// [i] - Access to CRow in the array m_rows[] ,
// [j] - Overloaded operator of indexing in CRow
com=com+StringFormat("a(%d,%d)=%G ; ",i,j,element);
}
com+="|";
//--- Output the values of the row
Print(com);
}
}
//+------------------------------------------------------------------+
//| Class "Row"
//+------------------------------------------------------------------+
class CRow {
private:
double m_array[];
public:
// Constructors and a destructor
CRow(void) { ArrayResize(m_array,0); }
CRow(const CRow &r) { this=r; }
CRow(const double &array[]);
~CRow(void){};
// Number of elements in the row
int Size(void) const { return(ArraySize(m_array));}
// Returns a string with values
string String(void) const;
// Indexing operator
double operator[](int i) const { return(m_array[i]); }
// Assignment operators
void operator=(const double &array[]); // An array
void operator=(const CRow & r); // Another CRow object
double operator*(const CRow &o); // CRow object for multiplication
};
//+------------------------------------------------------------------+
//| Constructor for initializing a row with an array
//+------------------------------------------------------------------+
void CRow::CRow(const double &array[]) {
int size=ArraySize(array);
// If the array is not empty
if( size > 0 ) {
ArrayResize(m_array,size);
// Fill with values
for( int i=0; i < size ; i++) {
m_array[i]=array[i];
}
}
}
//+------------------------------------------------------------------+
//| Assignment operation for the array
//+------------------------------------------------------------------+
void CRow::operator=(const double &array[]) {
int size=ArraySize(array);
if(size==0) return;
// Fill the array with values
ArrayResize(m_array,size);
for( int i=0; i < size ; i++ ) {
m_array[i]=array[i];
}
}
//+------------------------------------------------------------------+
//| Assignment operation for CRow
//+------------------------------------------------------------------+
void CRow::operator=(const CRow &r) {
int size=r.Size();
if( size == 0 ) {
return;
}
// Fill the array with values
ArrayResize(m_array,size);
for( int i=0; i < size ; i++ ) {
m_array[i]=r[i];
}
}
//+------------------------------------------------------------------+
//| Operator of multiplication by another row
//+------------------------------------------------------------------+
double CRow::operator*(const CRow &o) {
double res=0;
// Verifications
int size = Size();
if( size != o.Size() || size == 0 ) {
Print(__FUNCSIG__,": Failed to multiply two matrices, their sizes are different");
return(res);
}
// Multiply arrays elementwise and add the products
for( int i=0 ; i < size ; i++ ) {
res += m_array[i] * o[i];
}
return(res);
}
//+------------------------------------------------------------------+
//| Returns a formatted string representation
//+------------------------------------------------------------------+
string CRow::String(void) const {
string out="";
// If the size of the array is greater than zero
int size=ArraySize(m_array);
// We work only with a non-zero number of array elements
if( size > 0 ) {
out="{";
for( int i=0; i < size ; i++ ) {
//--- Collect the values to a string
out += StringFormat(" %G;",m_array[i]);
}
out+=" }";
}
return(out);
}
//+------------------------------------------------------------------+
//| Class "Matrix"
//+------------------------------------------------------------------+
class CMatrix {
private:
CRow m_rows[];
public:
// Constructors and a destructor
CMatrix(void);
CMatrix(int rows) { ArrayResize(m_rows,rows); }
~CMatrix(void){};
// Get the matrix sizes
int Rows() const { return(ArraySize(m_rows)); }
int Cols() const { return(Rows() > 0? m_rows[0].Size():0); }
// Returns the value of the column in the form of a CRow row
CRow GetColumnAsRow(const int col_index) const;
// Returns a string with the matrix values
string String(void) const;
// The indexing operator returns a string by its number
CRow *operator[](int i) const { return(GetPointer(m_rows[i])); }
// Addition operator
CMatrix operator+(const CMatrix &m);
// Multiplication operator
CMatrix operator*(const CMatrix &m);
// Assignment operator
CMatrix *operator=(const CMatrix &m);
};
//+------------------------------------------------------------------+
//| Default constructor, create and array of rows of zero size
//+------------------------------------------------------------------+
CMatrix::CMatrix(void) {
// The zero number of rows in the matrix
ArrayResize(m_rows,0);
}
//+------------------------------------------------------------------+
//| Returns the column value in the form of CRow
//+------------------------------------------------------------------+
CRow CMatrix::GetColumnAsRow(const int col_index) const {
// A variable to get the values from the column
CRow row();
// The number of rows in the matrix
int rows=Rows();
// If the number of rows is greater than zero, execute the operation
if( rows > 0 ) {
// An array to receive the values of the column with index col_index
double array[];
ArrayResize(array,rows);
// Filling the array
for( int i = 0; i < rows ; i++) {
// Check the number of the column for row i - it may exceed the boundaries of the array
if( col_index >= this[i].Size()) {
Print( __FUNCSIG__ , ": Error! Column number ",col_index,"> row size ",i);
break; // row will be uninitialized object
}
array[i]=this[i][col_index];
}
// Create a CRow row based on the array values
row=array;
}
return(row);
}
//+------------------------------------------------------------------+
//| Addition of two matrices
//+------------------------------------------------------------------+
CMatrix CMatrix::operator+(const CMatrix &m) {
// The number of rows and columns in the passed matrix
int cols=m.Cols();
int rows=m.Rows();
// The matrix to receive the addition results
CMatrix res(rows);
// The sizes of the matrix must match
if( cols!=Cols() || rows!=Rows()) {
//--- Addition impossible
Print( __FUNCSIG__ ,": Failed to add two matrices, their sizes are different");
return(res);
}
// Auxiliary array
double arr[];
ArrayResize(arr,cols);
// Go through rows to add
for( int i = 0 ; i < rows ; i++ ) {
// Write the results of addition of matrix strings in the array
for( int k = 0 ; k < cols ; k++ ) {
arr[k]=this[i][k]+m[i][k];
}
// Place the array to the matrix row
res[i]=arr;
}
// return the result of addition of matrices
return(res);
}
//+------------------------------------------------------------------+
//| Multiplication of two matrices
//+------------------------------------------------------------------+
CMatrix CMatrix::operator*(const CMatrix &m) {
// Number of columns of the first matrix, number of rows passed in the matrix
int cols1=Cols();
int rows2=m.Rows();
int rows1=Rows();
int cols2=m.Cols();
// Matrix to receive the addition result
CMatrix res(rows1);
// Matrices should be coordinated
if( cols1 != rows2 ) {
//--- Multiplication impossible
Print(__FUNCSIG__,": Failed to multiply two matrices, format is not compatible "
"- number of columns in the first factor should be equal to the number of rows in the second");
return(res);
}
// Auxiliary array
double arr[];
ArrayResize(arr,cols1);
// Fill the rows in the multiplication matrix
for( int i = 0 ; i < rows1 ; i++ ) { // Go through rows
// Reset the receiving array
ArrayInitialize(arr,0);
// Go through elements in the row
for( int k = 0 ; k < cols1 ; k++ ) {
// Take values of column k of the matrix m in the for of CRow
CRow column=m.GetColumnAsRow(k);
// Multiply two rows and write the result of scalar multiplication of vectors in the i-th element
arr[k]=this[i]*column;
}
// place array arr[] in the i-th row of the matrix
res[i]=arr;
}
// Return the product of two matrices
return(res);
}
//+------------------------------------------------------------------+
//| Assignment operation
//+------------------------------------------------------------------+
CMatrix *CMatrix::operator=( const CMatrix &m) {
// Find and set the number of rows
int rows=m.Rows();
ArrayResize(m_rows,rows);
// Fill our rows with the values of rows of the passed matrix
for( int i = 0 ; i < rows ; i++) {
this[i]=m[i];
}
return(GetPointer(this));
}
//+------------------------------------------------------------------+
//| String representation of the matrix
//+------------------------------------------------------------------+
string CMatrix::String(void) const {
string out="";
int rows=Rows();
// Form string by string
for( int i = 0 ; i < rows ; i++ ) {
out=out+this[i].String()+"\r\n";
}
return(out);
}