חזור לתיקייה: wet

Matrix

חיפוש בתיקיה
Ctrl K
לחץ כאן או הקש Ctrl K כדי לחפש בכל התיקיה

    Matrix

    02340124

    מבוא לתכנות מערכות

    רשימות הרצאה לקריאה בשבת

    Matrix

    הופק מתוך תקיית התואר של שקד

    uni-folder.vercel.app

    matrix.cpp

    הערה (קובץ קוד)

    קובץ זה הוא קובץ קוד מסוג CPP.

    #include <cmath>
    #include "Matrix.h"
    #include "Utilities.h"
    
    #define GET_INDEX_AT(row, col, width) ((row*width) + col)
    
    Matrix::Matrix(int rows, int columns, int value) : mat(new int[rows * columns]()) {
        this->rows = rows;
        this->cols = columns;
        for (int i = 0; i < rows * columns; i++) {
            this->mat[i] = value;
        }
    }
    
    Matrix::Matrix(const Matrix& matrix) : mat(new int[matrix.rows * matrix.cols]) {
        this->rows = matrix.rows;
        this->cols = matrix.cols;
        for (int i = 0; i < rows * cols; i++) {
            this->mat[i] = matrix.mat[i];
        }
    }
    
    Matrix::~Matrix() {
        delete[] mat;
    }
    
    std::ostream& operator<<(std::ostream& ostream, const Matrix& matrix) {
        for (int i = 0; i < matrix.rows; i++) {
            for (int j = 0; j < matrix.cols; j++) {
                ostream << "|" << matrix(i, j);
            }
            ostream << "|" << std::endl;
        }
        return ostream;
    }
    
    Matrix& Matrix::operator=(const Matrix& matrix) {
        if (this == &matrix) {
            return *this;
        }
    
        cols = matrix.cols;
        rows = matrix.rows;
        delete[] mat;
        mat = new int[rows * cols];
        for (int i = 0; i < rows * cols; i++) {
            mat[i] = matrix.mat[i];
        }
        return *this;
    }
    
    int& Matrix::operator()(int row, int column) {
        if (row < 0 || row >= rows || column < 0 || column >= cols) {
            exitWithError(MatamErrorType::OutOfBounds);
        }
        return mat[GET_INDEX_AT(row, column, cols)];
    }
    
    int Matrix::operator()(int row, int column) const {
        if (row < 0 || row >= rows || column < 0 || column >= cols) {
            exitWithError(MatamErrorType::OutOfBounds);
        }
        return mat[GET_INDEX_AT(row, column, cols)];
    }
    
    Matrix& Matrix::operator+=(const Matrix& matrix) {
        if (rows != matrix.rows || cols != matrix.cols) {
            exitWithError(MatamErrorType::UnmatchedSizes);
        }
        for (int i = 0; i < (rows * cols); i++) {
            mat[i] += matrix.mat[i];
        }
    
        return *this;
    }
    
    Matrix& Matrix::operator-=(const Matrix& matrix) {
        if (rows != matrix.rows || cols != matrix.cols) {
            exitWithError(MatamErrorType::UnmatchedSizes);
        }
        for (int i = 0; i < (rows * cols); i++) {
            mat[i] -= matrix.mat[i];
        }
    
        return *this;
    }
    
    Matrix& Matrix::operator*=(const Matrix& matrix) {
        if (this->cols != matrix.rows) {
            exitWithError(MatamErrorType::UnmatchedSizes);
            return *this;
        }
    
        int* result = new int[rows * matrix.cols];
    
        // calculating the new matrix
        for (int i = 0; i < this->rows; i++) {
            for (int j = 0; j < matrix.cols; j++) {
                int sum = 0;
                for (int k = 0; k < this->cols; k++) {
                    sum += (*this)(i, k) * matrix(k, j);
                }
                result[GET_INDEX_AT(i, j, matrix.cols)] = sum;
            }
        }
    
        // reassigning the attributes
        delete[] mat;
        mat = result;
        cols = matrix.cols;
        return *this;
    }
    
    Matrix operator+(const Matrix& mat1, const Matrix& mat2) {
        Matrix result(mat1);
        return (result += mat2);
    }
    
    Matrix operator-(const Matrix& mat1, const Matrix& mat2) {
        Matrix result(mat1);
        return (result -= mat2);
    }
    
    Matrix operator*(const Matrix& mat1, const Matrix& mat2) {
        Matrix result(mat1);
        return (result *= mat2);
    }
    
    Matrix Matrix::operator-() const {
        Matrix result(this->rows, this->cols);
        return (result -= *this);
    }
    
    Matrix& Matrix::operator*=(int value) {
        for (int i = 0; i < (rows * cols); i++) {
            mat[i] *= value;
        }
    
        return *this;
    }
    
    Matrix operator*(const Matrix& mat, int value) {
        Matrix result(mat);
        return (result *= value);
    }
    
    Matrix operator*(int value, const Matrix& mat) {
        Matrix result(mat);
        return (result *= value);
    }
    
    bool Matrix::operator==(const Matrix& matrix) const {
        if (cols != matrix.cols || rows != matrix.rows) {
            return false;
        }
        for (int i = 0; i < rows * cols; i++) {
            if (this->mat[i] != matrix.mat[i]) {
                return false;
            }
        }
        return true;
    }
    
    bool Matrix::operator!=(const Matrix& matrix) const {
        return !(*this == matrix);
    }
    
    Matrix Matrix::rotateClockwise() const {
        Matrix result(cols, rows);
    
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result(j, rows - 1 - i) = (*this)(i, j);
            }
        }
    
        return result;
    }
    
    Matrix Matrix::rotateCounterClockwise() const {
        Matrix result(cols, rows);
    
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result(cols - 1 - j, i) = (*this)(i, j);
            }
        }
    
        return result;
    }
    
    Matrix Matrix::transpose() const {
        Matrix result(cols, rows);
    
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result(j, i) = (*this)(i, j);
            }
        }
    
        return result;
    }
    
    double Matrix::CalcFrobeniusNorm(const Matrix& mat) {
        double sum = 0;
        for (int i = 0; i < mat.cols * mat.rows; i++) {
            sum += (mat.mat[i] * mat.mat[i]);
        }
    
        return sqrt(sum);
    }
    
    int Matrix::CalcDeterminant(const Matrix& mat) {
        if (mat.rows != mat.cols) {
            exitWithError(MatamErrorType::NotSquareMatrix);
        }
        switch (mat.rows) {
            case 0:
                return 0;
            case 1:
                return mat(0, 0);
            case 2:
                return mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0);
            default: {
                int sum = 0, minus = 1;
                for (int i = 0; i < mat.rows; i++) {
                    Matrix minor = getMinor(mat, i);
                    sum += minus * mat(0, i) * CalcDeterminant(minor);
                    minus *= -1;
                }
                return sum;
            }
        }
    }
    
    Matrix Matrix::getMinor(const Matrix& mat, int index) {
        int size = mat.rows - 1;
        Matrix minor(size, size);
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                minor(i, j) = mat(i + 1, j >= index ? j + 1 : j);
            }
        }
        return minor;
    }