public class Matrix
{
#region 基本域/属性
private readonly double[,] values;
public double this[int row, int columns]
{
get => values[row, columns];
set => values[row, columns] = value;
}
public int Rows => values.GetLength(0);
public int Columns => values.GetLength(1);
#endregion
public Matrix(int rows, int columns) => values = new double[rows, columns];
public Matrix(double[,] matrix) => values = (double[,])matrix.Clone();
#region 运算
#region 加法
public Matrix Add(Matrix other)
{
if (Rows != other.Rows || Columns != other.Columns) throw new ArithmeticException();
var ret = Copy();
ret.ByRowAndColumn((i, j) => ret[i, j] += other[i, j]);
return ret;
}
public static Matrix operator +(Matrix left, Matrix right) => left.Add(right);
#endregion
#region 减法
public Matrix Minus(Matrix other) => Add(-other);
public static Matrix operator -(Matrix left, Matrix right) => left.Minus(right);
public static Matrix operator -(Matrix matrix) => -1 * matrix;
#endregion
#region 数乘
public Matrix Multiply(double num)
{
var ret = Copy();
ret.ByRowAndColumn((i, j) => ret[i, j] *= num);
return ret;
}
public static Matrix operator *(double num, Matrix matrix) => matrix.Multiply(num);
public static Matrix operator *(Matrix matrix, double num) => matrix.Multiply(num);
#endregion
#region 转置
public Matrix Transpose()
{
var ret = new Matrix(Columns, Rows);
ByRowAndColumn((i, j) => ret[j, i] = this[i, j]);
return ret;
}
public Matrix T => Transpose();
#endregion
#region 乘法
public Matrix Multiply(Matrix other)
{
if (Columns != other.Rows) throw new ArithmeticException();
var ret = new Matrix(Rows, other.Columns);
ret.ByRowAndColumn((i, j) =>
{
for (int k = 0; k < Rows; k++)
ret[i, j] += this[i, k] * other[k, j];
});
return ret;
}
public static Matrix operator *(Matrix left, Matrix right) => left.Multiply(right);
#endregion
#endregion
private void ByRowAndColumn(Action<int, int> action)
{
for (var i = 0; i < Rows; i++) for (var j = 0; j < Columns; j++)
action(i, j);
}
public Matrix Copy() => new Matrix(values);
public static Matrix IdentityMatrix(int rank)
{
var ret = new Matrix(rank, rank);
for (var i = 0; i < rank; i++) ret[i, i] = 1;
return ret;
}
public Matrix I => IMethod();
private Matrix IMethod()
{
if (Rows != Columns) throw new ArithmeticException();
return IdentityMatrix(Rows);
}
}
public static class MatrixExtension
{
public static Matrix AsMatrix(this double[,] arr) => new Matrix(arr);
}