using System; namespace MatrixLibrary { public class MatrixException : Exception { public MatrixException() : base() { } public MatrixException(string message) : base(message) { } public MatrixException(string message, Exception innerException) : base(message, innerException) { } } public class Matrix : ICloneable { private readonly int rows; private readonly int columns; private readonly double[,] array; public int Rows => rows; public int Columns => columns; public double[,] Array => array; public Matrix(int rows, int columns) { if (rows <= 0 || columns <= 0) throw new ArgumentOutOfRangeException(rows <= 0 ? nameof(rows) : nameof(columns), "Matrix dimensions must be greater than zero."); this.rows = rows; this.columns = columns; this.array = new double[rows, columns]; } public Matrix(double[,] array) { if (array == null) throw new ArgumentNullException(nameof(array)); this.rows = array.GetLength(0); this.columns = array.GetLength(1); this.array = array; } public double this[int row, int column] { get { if (row < 0 || row >= rows || column < 0 || column >= columns) throw new ArgumentException("Index is out of range."); return array[row, column]; } set { if (row < 0 || row >= rows || column < 0 || column >= columns) throw new ArgumentException("Index is out of range."); array[row, column] = value; } } public object Clone() { return new Matrix((double[,])array.Clone()); } public static Matrix operator +(Matrix matrix1, Matrix matrix2) { if (matrix1 == null || matrix2 == null) throw new ArgumentNullException(matrix1 == null ? nameof(matrix1) : nameof(matrix2), "Matrix argument cannot be null."); if (matrix1.Rows != matrix2.Rows || matrix1.Columns != matrix2.Columns) throw new MatrixException("Matrices must have the same dimensions for addition."); double[,] resultArray = new double[matrix1.Rows, matrix1.Columns]; for (int i = 0; i < matrix1.Rows; i++) { for (int j = 0; j < matrix1.Columns; j++) { resultArray[i, j] = matrix1[i, j] + matrix2[i, j]; } } return new Matrix(resultArray); } public static Matrix operator -(Matrix matrix1, Matrix matrix2) { if (matrix1 == null || matrix2 == null) throw new ArgumentNullException(matrix1 == null ? nameof(matrix1) : nameof(matrix2), "Matrix argument cannot be null."); if (matrix1.Rows != matrix2.Rows || matrix1.Columns != matrix2.Columns) throw new MatrixException("Matrices must have the same dimensions for subtraction."); double[,] resultArray = new double[matrix1.Rows, matrix1.Columns]; for (int i = 0; i < matrix1.Rows; i++) { for (int j = 0; j < matrix1.Columns; j++) { resultArray[i, j] = matrix1[i, j] - matrix2[i, j]; } } return new Matrix(resultArray); } public static Matrix operator *(Matrix matrix1, Matrix matrix2) { if (matrix1 == null || matrix2 == null) throw new ArgumentNullException(matrix1 == null ? nameof(matrix1) : nameof(matrix2), "Matrix argument cannot be null."); if (matrix1.Columns != matrix2.Rows) throw new MatrixException("Number of columns in the first matrix must be equal to the number of rows in the second matrix for multiplication."); double[,] resultArray = new double[matrix1.Rows, matrix2.Columns]; for (int i = 0; i < matrix1.Rows; i++) { for (int j = 0; j < matrix2.Columns; j++) { double sum = 0; for (int k = 0; k < matrix1.Columns; k++) { sum += matrix1[i, k] * matrix2[k, j]; } resultArray[i, j] = sum; } } return new Matrix(resultArray); } public Matrix Add(Matrix matrix) { if (matrix == null) throw new ArgumentNullException(nameof(matrix), "Matrix argument cannot be null."); return this + matrix; } public Matrix Subtract(Matrix matrix) { return this - matrix; } public Matrix Multiply(Matrix matrix) { return this * matrix; } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) return false; Matrix other = (Matrix)obj; if (this.Rows != other.Rows || this.Columns != other.Columns) return false; for (int i = 0; i < this.Rows; i++) { for (int j = 0; j < this.Columns; j++) { if (this[i, j] != other[i, j]) return false; } } return true; } public override int GetHashCode() { return base.GetHashCode(); } } }