From d5c60d5fdfea96f3743ab29a84f136bc50228f13 Mon Sep 17 00:00:00 2001
From: Ametov Artem <adametov@edu.hse.ru>
Date: Thu, 23 Jan 2025 22:39:45 +0300
Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F?=
 =?UTF-8?q?=D0=B5=D0=BC=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA?=
 =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8B=20=D0=BA=D0=BE=D0=BF=D0=B8=D1=80=D0=BE?=
 =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B8=D1=81=D0=B2?=
 =?UTF-8?q?=D0=B0=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=87=D0=B5?=
 =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B8=20=D0=BF=D0=B5=D1=80?=
 =?UTF-8?q?=D0=B5=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D1=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 matrix.hpp | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 209 insertions(+), 1 deletion(-)

diff --git a/matrix.hpp b/matrix.hpp
index cf39055..632d23b 100644
--- a/matrix.hpp
+++ b/matrix.hpp
@@ -62,6 +62,7 @@ namespace linalg {
         // Деструктор
         ~Matrix() noexcept;
 
+
         // Шаблонный оператор присваивания для матриц разных типов
         template<typename U>
         Matrix &operator=(const Matrix<U> &other);
@@ -70,6 +71,8 @@ namespace linalg {
         template<typename U>
         Matrix &operator=(Matrix<U> &&other) noexcept;
 
+        size_t size() const noexcept { return m_rows * m_columns; }
+
     private:
 
         // Указатель на данные матрицы
@@ -85,4 +88,209 @@ namespace linalg {
         template<typename U>
         void free(U *&ptr, size_t n) noexcept;
     };
-}
+
+    template<typename T>
+// Функция swap для обмена двух матриц местами (реализует семантику перемещения)
+    void swap(Matrix<T> &first, Matrix<T> &second) noexcept { first.swap(second); }
+
+// Конструктор для создания матрицы с заданным количеством строк (по умолчанию 1 столбец)
+    template<typename T>
+    Matrix<T>::Matrix(size_t rows) : m_rows(rows), m_columns(1), m_capacity(rows) {
+        // Выделяем память для элементов матрицы
+        m_ptr = reinterpret_cast<T *>(new std::byte[m_capacity * sizeof(T)]);
+
+        size_t i = 0;
+
+        try {
+            // Инициализируем элементы матрицы значениями по умолчанию
+            for (; i < rows; ++i) {
+                new(m_ptr + i) T();
+            }
+        } catch (...) {
+            // Освобождаем память в случае исключения
+            free<T>(m_ptr, i + 1);
+            this->~Matrix();
+            throw;
+        }
+    }
+
+// Конструктор для создания матрицы с заданным количеством строк и столбцов
+    template<typename T>
+    Matrix<T>::Matrix(size_t rows, size_t columns): m_rows(rows), m_columns(columns), m_capacity(rows * columns) {
+        // Выделяем память для элементов матрицы
+        m_ptr = reinterpret_cast<T *>(new std::byte[m_capacity * sizeof(T)]);
+
+        size_t i = 0;
+
+        try {
+            // Инициализируем элементы матрицы значениями по умолчанию
+            for (; i < rows * columns; ++i) {
+                new(m_ptr + i) T();
+            }
+        } catch (...) {
+            // Освобождаем память в случае исключения
+            free<T>(m_ptr, i + 1);
+            this->~Matrix();
+            throw;
+        }
+    }
+
+// Конструктор копирования для создания матрицы из другой матрицы другого типа
+    template<typename T>
+    template<typename U>
+    Matrix<T>::Matrix(const Matrix<U> &other) : m_rows(other.m_rows), m_columns(other.m_columns),
+                                                m_capacity(m_rows * m_columns) {
+        // Выделяем память для новой матрицы
+        m_ptr = reinterpret_cast<T *>(new std::byte[m_capacity * sizeof(T)]);
+
+        size_t i = 0;
+
+        try {
+            // Копируем элементы из другой матрицы
+            for (; i < m_rows * m_columns; ++i) {
+                new(m_ptr + i) T((other.m_ptr[i]));
+            }
+        } catch (...) {
+            // Освобождаем память в случае исключения
+            free<T>(m_ptr, i + 1);
+            this->~Matrix();
+            throw;
+        }
+    }
+
+// Перемещающий конструктор для создания матрицы из другой матрицы, переданной по rvalue-ссылке
+    template<typename T>
+    template<typename U>
+    Matrix<T>::Matrix(Matrix<U> &&other) noexcept : m_ptr(reinterpret_cast<T *>(other.m_ptr)), m_rows(other.m_rows),
+                                                    m_columns(other.m_columns), m_capacity(other.m_capacity) {
+        // Обнуляем исходную матрицу, чтобы она не владела ресурсами
+        other.m_ptr = nullptr;
+        other.m_columns = other.m_rows = other.m_capacity = 0;
+    }
+
+// Конструктор инициализации из одномерного списка значений
+    template<typename T>
+    template<typename U>
+    Matrix<T>::Matrix(std::initializer_list<U> lst) : m_rows(lst.size()), m_columns(1), m_capacity(lst.size()) {
+        // Выделяем память для элементов матрицы
+        m_ptr = reinterpret_cast<T *>(new std::byte[m_capacity * sizeof(T)]);
+
+        size_t i = 0;
+
+        try {
+            auto iter = lst.begin();
+            // Копируем значения из списка
+            for (; i < lst.size(); ++i) {
+                new(m_ptr + i) T(*iter);
+                ++iter;
+            }
+        } catch (...) {
+            // Освобождаем память в случае исключения
+            free<T>(m_ptr, i + 1);
+            this->~Matrix();
+            throw;
+        }
+    }
+
+// Конструктор инициализации из двумерного списка значений
+    template<typename T>
+    template<typename U>
+    Matrix<T>::Matrix(std::initializer_list<std::initializer_list<U>> lst) : m_rows(lst.size()),
+                                                                             m_columns(lst.begin()->size()),
+                                                                             m_capacity(m_rows * m_columns) {
+        // Выделяем память для элементов матрицы
+        m_ptr = reinterpret_cast<T *>(new std::byte[m_capacity * sizeof(T)]);
+
+        size_t i = 0;
+
+        try {
+            // Копируем значения из двумерного списка
+            for (const auto &row : lst) {
+                for (auto &elem : row) {
+                    new(m_ptr + i) T(elem);
+                    ++i;
+                }
+            }
+        } catch (...) {
+            // Освобождаем память в случае исключения
+            free<T>(m_ptr, i + 1);
+            this->~Matrix();
+            throw;
+        }
+    }
+
+// Деструктор матрицы для освобождения ресурсов
+    template<typename T>
+    Matrix<T>::~Matrix() noexcept {
+        if (m_ptr != nullptr) {
+            // Освобождаем память для всех элементов матрицы
+            free<T>(m_ptr, size());
+        }
+    }
+
+// Оператор копирующего присваивания для матриц разных типов
+    template<typename T>
+    template<typename U>
+    Matrix<T> &Matrix<T>::operator=(const Matrix<U> &other) {
+        if (&other == this) {
+            return *this;
+        }
+
+        // Если емкость текущей матрицы позволяет, обновляем существующие элементы
+        if (m_capacity >= other.size()) {
+            try {
+                for (size_t i = 0; i < size(); ++i) {
+                    m_ptr[i] = other.m_ptr[i];
+                }
+                for (size_t i = size(); i < other.size(); ++i) {
+                    new(m_ptr + i) T(other.m_ptr[i]);
+                }
+            } catch (...) {
+                throw;
+            }
+            for (size_t i = other.size(); i < size(); ++i) {
+                (m_ptr + i)->~T();
+            }
+            m_columns = other.m_columns;
+            m_rows = other.m_rows;
+            m_capacity = size();
+            return *this;
+        }
+
+        // Если емкость недостаточна, создаем копию матрицы и обмениваемся ресурсами
+        try {
+            Matrix<T> copy(other);
+            ::linalg::swap(copy, *this);
+        } catch (...) {
+            throw;
+        }
+
+        return *this;
+    }
+
+// Оператор перемещающего присваивания для матриц разных типов
+    template<typename T>
+    template<typename U>
+    Matrix<T> &Matrix<T>::operator=(Matrix<U> &&other) noexcept {
+        if (&other == this) {
+            return *this;
+        }
+
+        // Уничтожаем текущие элементы матрицы
+        for (size_t i = 0; i < size(); ++i) {
+            (m_ptr + i)->~T();
+        }
+
+        // Освобождаем выделенную память
+        delete[] reinterpret_cast<std::byte *>(m_ptr);
+        m_rows = other.m_rows;
+        m_columns = other.m_columns;
+        m_ptr = reinterpret_cast<T *>(other.m_ptr);
+
+        // Обнуляем другую матрицу
+        other.m_ptr = nullptr;
+        other.m_columns = other.m_rows = 0;
+
+        return *this;
+    }
+}
\ No newline at end of file
-- 
GitLab