Копирование матриц, векторов и массивов

Наиболее простой и привычный способ копирования матриц и векторов — через оператор присваивания '='.

matrix a = {{22}, {33}, {44}};
matrix b = a + 2;
matrix c;
Print("matrix a \n"a);
Print("matrix b \n"b);
c.Assign(b);
Print("matrix c \n"c);

Данный фрагмент генерирует в журнале такие записи:

matrix a
[[2,2]
 [3,3]
 [4,4]]
matrix b
[[4,4]
 [5,5]
 [6,6]]
matrix c
[[4,4]
 [5,5]
 [6,6]]

Однако для копирования матриц и векторов предназначена и пара методов: Copy и Assign. Отличие метода Assign от Copy в том, что он позволяет копировать не только матрицы, но и массивы.

bool matrix<T>::Copy(const matrix<T> &source)

bool matrix<T>::Assign(const matrix<T> &source)

bool matrix<T>::Assign(const T &array[])

Аналогичные по действию и прототипам методы реализованы и для векторов.

Через Assign возможна запись вектора в матрицу: результатом будет однострочная матрица.

bool matrix<T>::Assign(const vector<T> &v)

Также вектору можно назначить матрицу: будет выполнена её развёртка, то есть все строки матрицы выстраиваются в один ряд (эквивалентно вызову метода Flat).

bool vector<T>::Assign(const matrix<T> &m)

На момент написания данной главы в MQL5 не существует метода для экспорта матрицы или вектора в массив, хотя есть механизм для "переноса" данных (см. далее метод Swap).

Пример ниже показывает, как целочисленный массив int_arr копируется в матрицу типа double. При этом результирующая матрица автоматически подстраивается под размеры копируемого массива.

matrix double_matrix = matrix::Full(2103.14);
Print("double_matrix before Assign() \n"double_matrix);
int int_arr[5][5] = {{12}, {34}, {56}};
Print("int_arr: ");
ArrayPrint(int_arr);
double_matrix.Assign(int_arr);
Print("double_matrix after Assign(int_arr) \n"double_matrix);

Получим в журнале следующий вывод.

double_matrix before Assign() 
[[3.14,3.14,3.14,3.14,3.14,3.14,3.14,3.14,3.14,3.14]
 [3.14,3.14,3.14,3.14,3.14,3.14,3.14,3.14,3.14,3.14]]
 
int_arr: 
    [,0][,1][,2][,3][,4]
[0,]   1   2   0   0   0
[1,]   3   4   0   0   0
[2,]   5   6   0   0   0
[3,]   0   0   0   0   0
[4,]   0   0   0   0   0
 
double_matrix after Assign(int_arr) 
[[1,2,0,0,0]
 [3,4,0,0,0]
 [5,6,0,0,0]
 [0,0,0,0,0]
 [0,0,0,0,0]]

Таким образом, метод Assign позволяет переходить в коде от массивов к матрицам с автоматическим приведением размера и типа.

Более эффективно (быстро и без копирования) можно переносить данные между матрицами, векторами и массивами с помощью методов Swap.

bool matrix<T>::Swap(vector<T> &vec)

bool matrix<T>::Swap(matrix<T> &vec)

bool matrix<T>::Swap(T &arr[])

bool vector<T>::Swap(vector<T> &vec)

bool vector<T>::Swap(matrix<T> &vec)

bool vector<T>::Swap(T &arr[])

Они работают по такому же принципу, как и функция ArraySwap: местами меняются внутренние указатели на буфера с данными внутри двух объектов. В результате, элементы матрицы или вектора исчезают в исходном объекте и появляются в принимающем массиве, или наоборот "перетекают" из массива в матрицу или вектор.

Метод Swap позволяет работать с динамическими массивами, в том числе и с многомерными. На константные размеры старших измерений многомерного массива (array[][N1][N2]...) налагается условие: произведение этих размеров должно быть кратно размеру матрицы или вектора. Так массив с геометрией [][2][3] перераспределяется блоками по 6 элементов. Следовательно, он совместим по обмену с матрицами и векторами размерами 6, 12, 18 и т.д.