// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // // Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // using System; using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra { /// /// Defines the base class for Matrix classes. /// public abstract partial class Matrix { /// /// The value of 1.0. /// public static readonly T One = BuilderInstance.Matrix.One; /// /// The value of 0.0. /// public static readonly T Zero = BuilderInstance.Matrix.Zero; /// /// Negate each element of this matrix and place the results into the result matrix. /// /// The result of the negation. protected abstract void DoNegate(Matrix result); /// /// Complex conjugates each element of this matrix and place the results into the result matrix. /// /// The result of the conjugation. protected abstract void DoConjugate(Matrix result); /// /// Add a scalar to each element of the matrix and stores the result in the result vector. /// /// The scalar to add. /// The matrix to store the result of the addition. protected abstract void DoAdd(T scalar, Matrix result); /// /// Adds another matrix to this matrix. /// /// The matrix to add to this matrix. /// The matrix to store the result of the addition. /// If the two matrices don't have the same dimensions. protected abstract void DoAdd(Matrix other, Matrix result); /// /// Subtracts a scalar from each element of the matrix and stores the result in the result matrix. /// /// The scalar to subtract. /// The matrix to store the result of the subtraction. protected abstract void DoSubtract(T scalar, Matrix result); /// /// Subtracts each element of the matrix from a scalar and stores the result in the result matrix. /// /// The scalar to subtract from. /// The matrix to store the result of the subtraction. protected void DoSubtractFrom(T scalar, Matrix result) { DoNegate(result); result.DoAdd(scalar, result); } /// /// Subtracts another matrix from this matrix. /// /// The matrix to subtract. /// The matrix to store the result of the subtraction. protected abstract void DoSubtract(Matrix other, Matrix result); /// /// Multiplies each element of the matrix by a scalar and places results into the result matrix. /// /// The scalar to multiply the matrix with. /// The matrix to store the result of the multiplication. protected abstract void DoMultiply(T scalar, Matrix result); /// /// Multiplies this matrix with a vector and places the results into the result vector. /// /// The vector to multiply with. /// The result of the multiplication. protected abstract void DoMultiply(Vector rightSide, Vector result); /// /// Multiplies this matrix with another matrix and places the results into the result matrix. /// /// The matrix to multiply with. /// The result of the multiplication. protected abstract void DoMultiply(Matrix other, Matrix result); /// /// Multiplies this matrix with transpose of another matrix and places the results into the result matrix. /// /// The matrix to multiply with. /// The result of the multiplication. protected abstract void DoTransposeAndMultiply(Matrix other, Matrix result); /// /// Multiplies the transpose of this matrix with a vector and places the results into the result vector. /// /// The vector to multiply with. /// The result of the multiplication. protected abstract void DoTransposeThisAndMultiply(Vector rightSide, Vector result); /// /// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix. /// /// The matrix to multiply with. /// The result of the multiplication. protected abstract void DoTransposeThisAndMultiply(Matrix other, Matrix result); /// /// Divides each element of the matrix by a scalar and places results into the result matrix. /// /// The scalar denominator to use. /// The matrix to store the result of the division. protected abstract void DoDivide(T divisor, Matrix result); /// /// Divides a scalar by each element of the matrix and stores the result in the result matrix. /// /// The scalar numerator to use. /// The matrix to store the result of the division. protected abstract void DoDivideByThis(T dividend, Matrix result); /// /// Computes the modulus for the given divisor each element of the matrix. /// /// The scalar denominator to use. /// Matrix to store the results in. protected abstract void DoModulus(T divisor, Matrix result); /// /// Computes the modulus for the given dividend for each element of the matrix. /// /// The scalar numerator to use. /// A vector to store the results in. protected abstract void DoModulusByThis(T dividend, Matrix result); /// /// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix. /// /// The matrix to pointwise multiply with this one. /// The matrix to store the result of the pointwise multiplication. protected abstract void DoPointwiseMultiply(Matrix other, Matrix result); /// /// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// /// The pointwise denominator matrix to use. /// The matrix to store the result of the pointwise division. protected abstract void DoPointwiseDivide(Matrix divisor, Matrix result); /// /// Pointwise modulus this matrix with another matrix and stores the result into the result matrix. /// /// The pointwise denominator matrix to use /// The result of the modulus. protected abstract void DoPointwiseModulus(Matrix divisor, Matrix result); /// /// Adds a scalar to each element of the matrix. /// /// The scalar to add. /// The result of the addition. /// If the two matrices don't have the same dimensions. public Matrix Add(T scalar) { if (scalar.Equals(Zero)) { return Clone(); } var result = CreateMatrix(RowCount, ColumnCount); DoAdd(scalar, result); return result; } /// /// Adds a scalar to each element of the matrix and stores the result in the result matrix. /// /// The scalar to add. /// The matrix to store the result of the addition. /// If the two matrices don't have the same dimensions. public void Add(T scalar, Matrix result) { if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } if (scalar.Equals(Zero)) { CopyTo(result); return; } DoAdd(scalar, result); } /// /// Adds another matrix to this matrix. /// /// The matrix to add to this matrix. /// The result of the addition. /// If the two matrices don't have the same dimensions. public virtual Matrix Add(Matrix other) { if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, other); } var result = CreateMatrix(RowCount, ColumnCount); DoAdd(other, result); return result; } /// /// Adds another matrix to this matrix. /// /// The matrix to add to this matrix. /// The matrix to store the result of the addition. /// If the two matrices don't have the same dimensions. public void Add(Matrix other, Matrix result) { if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, other, "other"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } DoAdd(other, result); } /// /// Subtracts a scalar from each element of the matrix. /// /// The scalar to subtract. /// A new matrix containing the subtraction of this matrix and the scalar. public Matrix Subtract(T scalar) { if (scalar.Equals(Zero)) { return Clone(); } var result = CreateMatrix(RowCount, ColumnCount); DoSubtract(scalar, result); return result; } /// /// Subtracts a scalar from each element of the matrix and stores the result in the result matrix. /// /// The scalar to subtract. /// The matrix to store the result of the subtraction. /// If this matrix and are not the same size. public void Subtract(T scalar, Matrix result) { if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } if (scalar.Equals(Zero)) { CopyTo(result); return; } DoSubtract(scalar, result); } /// /// Subtracts each element of the matrix from a scalar. /// /// The scalar to subtract from. /// A new matrix containing the subtraction of the scalar and this matrix. public Matrix SubtractFrom(T scalar) { var result = CreateMatrix(RowCount, ColumnCount); DoSubtractFrom(scalar, result); return result; } /// /// Subtracts each element of the matrix from a scalar and stores the result in the result matrix. /// /// The scalar to subtract from. /// The matrix to store the result of the subtraction. /// If this matrix and are not the same size. public void SubtractFrom(T scalar, Matrix result) { if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } DoSubtractFrom(scalar, result); } /// /// Subtracts another matrix from this matrix. /// /// The matrix to subtract. /// The result of the subtraction. /// If the two matrices don't have the same dimensions. public virtual Matrix Subtract(Matrix other) { if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, other); } var result = CreateMatrix(RowCount, ColumnCount); DoSubtract(other, result); return result; } /// /// Subtracts another matrix from this matrix. /// /// The matrix to subtract. /// The matrix to store the result of the subtraction. /// If the two matrices don't have the same dimensions. public void Subtract(Matrix other, Matrix result) { if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, other, "other"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } DoSubtract(other, result); } /// /// Multiplies each element of this matrix with a scalar. /// /// The scalar to multiply with. /// The result of the multiplication. public Matrix Multiply(T scalar) { if (scalar.Equals(One)) { return Clone(); } if (scalar.Equals(Zero)) { return CreateMatrix(RowCount, ColumnCount); } var result = CreateMatrix(RowCount, ColumnCount); DoMultiply(scalar, result); return result; } /// /// Multiplies each element of the matrix by a scalar and places results into the result matrix. /// /// The scalar to multiply the matrix with. /// The matrix to store the result of the multiplication. /// If the result matrix's dimensions are not the same as this matrix. public void Multiply(T scalar, Matrix result) { if (result.RowCount != RowCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "result"); } if (result.ColumnCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "result"); } if (scalar.Equals(One)) { CopyTo(result); return; } if (scalar.Equals(Zero)) { result.Clear(); return; } DoMultiply(scalar, result); } /// /// Divides each element of this matrix with a scalar. /// /// The scalar to divide with. /// The result of the division. public Matrix Divide(T scalar) { if (scalar.Equals(One)) { return Clone(); } if (scalar.Equals(Zero)) { throw new DivideByZeroException(); } var result = CreateMatrix(RowCount, ColumnCount); DoDivide(scalar, result); return result; } /// /// Divides each element of the matrix by a scalar and places results into the result matrix. /// /// The scalar to divide the matrix with. /// The matrix to store the result of the division. /// If the result matrix's dimensions are not the same as this matrix. public void Divide(T scalar, Matrix result) { if (result.RowCount != RowCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "result"); } if (result.ColumnCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "result"); } if (scalar.Equals(One)) { CopyTo(result); return; } if (scalar.Equals(Zero)) { throw new DivideByZeroException(); } DoDivide(scalar, result); } /// /// Divides a scalar by each element of the matrix. /// /// The scalar to divide. /// The result of the division. public Matrix DivideByThis(T scalar) { var result = CreateMatrix(RowCount, ColumnCount); DoDivideByThis(scalar, result); return result; } /// /// Divides a scalar by each element of the matrix and places results into the result matrix. /// /// The scalar to divide. /// The matrix to store the result of the division. /// If the result matrix's dimensions are not the same as this matrix. public void DivideByThis(T scalar, Matrix result) { if (result.RowCount != RowCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "result"); } if (result.ColumnCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "result"); } DoDivideByThis(scalar, result); } /// /// Multiplies this matrix by a vector and returns the result. /// /// The vector to multiply with. /// The result of the multiplication. /// If this.ColumnCount != rightSide.Count. public Vector Multiply(Vector rightSide) { if (ColumnCount != rightSide.Count) { throw DimensionsDontMatch(this, rightSide, "rightSide"); } var ret = CreateVector(RowCount); DoMultiply(rightSide, ret); return ret; } /// /// Multiplies this matrix with a vector and places the results into the result vector. /// /// The vector to multiply with. /// The result of the multiplication. /// If result.Count != this.RowCount. /// If this.ColumnCount != .Count. public virtual void Multiply(Vector rightSide, Vector result) { if (ColumnCount != rightSide.Count) { throw DimensionsDontMatch(this, rightSide, "rightSide"); } if (RowCount != result.Count) { throw DimensionsDontMatch(this, result, "result"); } if (ReferenceEquals(rightSide, result)) { var tmp = result.CreateVector(result.Count); DoMultiply(rightSide, tmp); tmp.CopyTo(result); } else { DoMultiply(rightSide, result); } } /// /// Left multiply a matrix with a vector ( = vector * matrix ). /// /// The vector to multiply with. /// The result of the multiplication. /// If this.RowCount != .Count. public Vector LeftMultiply(Vector leftSide) { if (RowCount != leftSide.Count) { throw DimensionsDontMatch(this, leftSide, "leftSide"); } var ret = CreateVector(ColumnCount); DoLeftMultiply(leftSide, ret); return ret; } /// /// Left multiply a matrix with a vector ( = vector * matrix ) and place the result in the result vector. /// /// The vector to multiply with. /// The result of the multiplication. /// If result.Count != this.ColumnCount. /// If this.RowCount != .Count. public virtual void LeftMultiply(Vector leftSide, Vector result) { if (RowCount != leftSide.Count) { throw DimensionsDontMatch(this, leftSide, "leftSide"); } if (ColumnCount != result.Count) { throw DimensionsDontMatch(this, result, "result"); } if (ReferenceEquals(leftSide, result)) { var tmp = result.CreateVector(result.Count); DoLeftMultiply(leftSide, tmp); tmp.CopyTo(result); } else { DoLeftMultiply(leftSide, result); } } /// /// Left multiply a matrix with a vector ( = vector * matrix ) and place the result in the result vector. /// /// The vector to multiply with. /// The result of the multiplication. protected void DoLeftMultiply(Vector leftSide, Vector result) { DoTransposeThisAndMultiply(leftSide, result); } /// /// Multiplies this matrix with another matrix and places the results into the result matrix. /// /// The matrix to multiply with. /// The result of the multiplication. /// If this.Columns != other.Rows. /// If the result matrix's dimensions are not the this.Rows x other.Columns. public virtual void Multiply(Matrix other, Matrix result) { if (ColumnCount != other.RowCount || result.RowCount != RowCount || result.ColumnCount != other.ColumnCount) { throw DimensionsDontMatch(this, other, result); } if (ReferenceEquals(this, result) || ReferenceEquals(other, result)) { var tmp = result.CreateMatrix(result.RowCount, result.ColumnCount); DoMultiply(other, tmp); tmp.CopyTo(result); } else { DoMultiply(other, result); } } /// /// Multiplies this matrix with another matrix and returns the result. /// /// The matrix to multiply with. /// If this.Columns != other.Rows. /// The result of the multiplication. public virtual Matrix Multiply(Matrix other) { if (ColumnCount != other.RowCount) { throw DimensionsDontMatch(this, other); } var result = CreateMatrix(RowCount, other.ColumnCount); DoMultiply(other, result); return result; } /// /// Multiplies this matrix with transpose of another matrix and places the results into the result matrix. /// /// The matrix to multiply with. /// The result of the multiplication. /// If this.Columns != other.ColumnCount. /// If the result matrix's dimensions are not the this.RowCount x other.RowCount. public virtual void TransposeAndMultiply(Matrix other, Matrix result) { if (ColumnCount != other.ColumnCount || result.RowCount != RowCount || result.ColumnCount != other.RowCount) { throw DimensionsDontMatch(this, other, result); } if (ReferenceEquals(this, result) || ReferenceEquals(other, result)) { var tmp = result.CreateMatrix(result.RowCount, result.ColumnCount); DoTransposeAndMultiply(other, tmp); tmp.CopyTo(result); } else { DoTransposeAndMultiply(other, result); } } /// /// Multiplies this matrix with transpose of another matrix and returns the result. /// /// The matrix to multiply with. /// If this.Columns != other.ColumnCount. /// The result of the multiplication. public virtual Matrix TransposeAndMultiply(Matrix other) { if (ColumnCount != other.ColumnCount) { throw DimensionsDontMatch(this, other); } var result = CreateMatrix(RowCount, other.RowCount); DoTransposeAndMultiply(other, result); return result; } /// /// Multiplies the transpose of this matrix by a vector and returns the result. /// /// The vector to multiply with. /// The result of the multiplication. /// If this.RowCount != rightSide.Count. public Vector TransposeThisAndMultiply(Vector rightSide) { if (RowCount != rightSide.Count) { throw DimensionsDontMatch(this, rightSide, "rightSide"); } var ret = CreateVector(ColumnCount); DoTransposeThisAndMultiply(rightSide, ret); return ret; } /// /// Multiplies the transpose of this matrix with a vector and places the results into the result vector. /// /// The vector to multiply with. /// The result of the multiplication. /// If result.Count != this.ColumnCount. /// If this.RowCount != .Count. public void TransposeThisAndMultiply(Vector rightSide, Vector result) { if (RowCount != rightSide.Count) { throw DimensionsDontMatch(this, rightSide, "rightSide"); } if (ColumnCount != result.Count) { throw DimensionsDontMatch(this, result, "result"); } if (ReferenceEquals(rightSide, result)) { var tmp = result.CreateVector(result.Count); DoTransposeThisAndMultiply(rightSide, tmp); tmp.CopyTo(result); } else { DoTransposeThisAndMultiply(rightSide, result); } } /// /// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix. /// /// The matrix to multiply with. /// The result of the multiplication. /// If this.Rows != other.RowCount. /// If the result matrix's dimensions are not the this.ColumnCount x other.ColumnCount. public void TransposeThisAndMultiply(Matrix other, Matrix result) { if (RowCount != other.RowCount || result.RowCount != ColumnCount || result.ColumnCount != other.ColumnCount) { throw DimensionsDontMatch(this, other, result); } if (ReferenceEquals(this, result) || ReferenceEquals(other, result)) { var tmp = result.CreateMatrix(result.RowCount, result.ColumnCount); DoTransposeThisAndMultiply(other, tmp); tmp.CopyTo(result); } else { DoTransposeThisAndMultiply(other, result); } } /// /// Multiplies the transpose of this matrix with another matrix and returns the result. /// /// The matrix to multiply with. /// If this.Rows != other.RowCount. /// The result of the multiplication. public Matrix TransposeThisAndMultiply(Matrix other) { if (RowCount != other.RowCount) { throw DimensionsDontMatch(this, other); } var result = CreateMatrix(ColumnCount, other.ColumnCount); DoTransposeThisAndMultiply(other, result); return result; } /// /// Negate each element of this matrix. /// /// A matrix containing the negated values. public Matrix Negate() { var result = CreateMatrix(RowCount, ColumnCount); DoNegate(result); return result; } /// /// Negate each element of this matrix and place the results into the result matrix. /// /// The result of the negation. /// if the result matrix's dimensions are not the same as this matrix. public void Negate(Matrix result) { if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result); } DoNegate(result); } /// /// Complex conjugate each element of this matrix. /// /// A matrix containing the conjugated values. public Matrix Conjugate() { var result = CreateMatrix(RowCount, ColumnCount); DoConjugate(result); return result; } /// /// Complex conjugate each element of this matrix and place the results into the result matrix. /// /// The result of the conjugation. /// if the result matrix's dimensions are not the same as this matrix. public void Conjugate(Matrix result) { if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result); } DoConjugate(result); } /// /// Computes the modulus (matrix % divisor) for each element of the matrix. /// /// The scalar denominator to use. /// A matrix containing the results. public Matrix Modulus(T divisor) { var result = CreateMatrix(RowCount, ColumnCount); DoModulus(divisor, result); return result; } /// /// Computes the modulus (matrix % divisor) for each element of the matrix. /// /// The scalar denominator to use. /// Matrix to store the results in. public void Modulus(T divisor, Matrix result) { if (ColumnCount != result.ColumnCount || RowCount != result.RowCount) { throw DimensionsDontMatch(this, result); } DoModulus(divisor, result); } /// /// Computes the modulus (dividend % matrix) for each element of the matrix. /// /// The scalar numerator to use. /// A matrix containing the results. public Matrix ModulusByThis(T dividend) { var result = CreateMatrix(RowCount, ColumnCount); DoModulusByThis(dividend, result); return result; } /// /// Computes the modulus (dividend % matrix) for each element of the matrix. /// /// The scalar numerator to use. /// Matrix to store the results in. public void ModulusByThis(T dividend, Matrix result) { if (ColumnCount != result.ColumnCount || RowCount != result.RowCount) { throw DimensionsDontMatch(this, result); } DoModulusByThis(dividend, result); } /// /// Pointwise multiplies this matrix with another matrix. /// /// The matrix to pointwise multiply with this one. /// If this matrix and are not the same size. /// A new matrix that is the pointwise multiplication of this matrix and . public Matrix PointwiseMultiply(Matrix other) { if (ColumnCount != other.ColumnCount || RowCount != other.RowCount) { throw DimensionsDontMatch(this, other, "other"); } var result = CreateMatrix(RowCount, ColumnCount); DoPointwiseMultiply(other, result); return result; } /// /// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix. /// /// The matrix to pointwise multiply with this one. /// The matrix to store the result of the pointwise multiplication. /// If this matrix and are not the same size. /// If this matrix and are not the same size. public void PointwiseMultiply(Matrix other, Matrix result) { if (ColumnCount != result.ColumnCount || RowCount != result.RowCount || ColumnCount != other.ColumnCount || RowCount != other.RowCount) { throw DimensionsDontMatch(this, other, result); } DoPointwiseMultiply(other, result); } /// /// Pointwise divide this matrix by another matrix. /// /// The pointwise denominator matrix to use. /// If this matrix and are not the same size. /// A new matrix that is the pointwise division of this matrix and . public Matrix PointwiseDivide(Matrix divisor) { if (ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount) { throw DimensionsDontMatch(this, divisor); } var result = CreateMatrix(RowCount, ColumnCount); DoPointwiseDivide(divisor, result); return result; } /// /// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// /// The pointwise denominator matrix to use. /// The matrix to store the result of the pointwise division. /// If this matrix and are not the same size. /// If this matrix and are not the same size. public void PointwiseDivide(Matrix divisor, Matrix result) { if (ColumnCount != result.ColumnCount || RowCount != result.RowCount || ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount) { throw DimensionsDontMatch(this, divisor, result); } DoPointwiseDivide(divisor, result); } /// /// Pointwise modulus this matrix by another matrix. /// /// The pointwise denominator matrix to use. /// If this matrix and are not the same size. /// A new matrix that is the pointwise modulus of this matrix and . public Matrix PointwiseModulus(Matrix divisor) { if (ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount) { throw DimensionsDontMatch(this, divisor); } var result = CreateMatrix(RowCount, ColumnCount); DoPointwiseModulus(divisor, result); return result; } /// /// Pointwise modulus this matrix by another matrix and stores the result into the result matrix. /// /// The pointwise denominator matrix to use. /// The matrix to store the result of the pointwise modulus. /// If this matrix and are not the same size. /// If this matrix and are not the same size. public void PointwiseModulus(Matrix divisor, Matrix result) { if (ColumnCount != result.ColumnCount || RowCount != result.RowCount || ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount) { throw DimensionsDontMatch(this, divisor, result); } DoPointwiseModulus(divisor, result); } /// /// Computes the trace of this matrix. /// /// The trace of this matrix /// If the matrix is not square public abstract T Trace(); /// /// Calculates the rank of the matrix /// /// effective numerical rank, obtained from SVD public virtual int Rank() { return Svd(false).Rank; } /// Calculates the condition number of this matrix. /// The condition number of the matrix. /// The condition number is calculated using singular value decomposition. public virtual T ConditionNumber() { return Svd(false).ConditionNumber; } /// Computes the determinant of this matrix. /// The determinant of this matrix. public virtual T Determinant() { if (RowCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare); } return LU().Determinant; } /// Computes the inverse of this matrix. /// The inverse of this matrix. public virtual Matrix Inverse() { if (RowCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare); } return LU().Inverse(); } /// /// Computes the Kronecker product of this matrix with the given matrix. The new matrix is M-by-N /// with M = this.Rows * lower.Rows and N = this.Columns * lower.Columns. /// /// The other matrix. /// The kronecker product of the two matrices. public Matrix KroneckerProduct(Matrix other) { var result = CreateMatrix(RowCount*other.RowCount, ColumnCount*other.ColumnCount); KroneckerProduct(other, result); return result; } /// /// Computes the Kronecker product of this matrix with the given matrix. The new matrix is M-by-N /// with M = this.Rows * lower.Rows and N = this.Columns * lower.Columns. /// /// The other matrix. /// The kronecker product of the two matrices. /// If the result matrix's dimensions are not (this.Rows * lower.rows) x (this.Columns * lower.Columns). public virtual void KroneckerProduct(Matrix other, Matrix result) { if (result.RowCount != (RowCount*other.RowCount) || result.ColumnCount != (ColumnCount*other.ColumnCount)) { throw DimensionsDontMatch(this, other, result); } for (var j = 0; j < ColumnCount; j++) { for (var i = 0; i < RowCount; i++) { result.SetSubMatrix(i*other.RowCount, other.RowCount, j*other.ColumnCount, other.ColumnCount, At(i, j)*other); } } } /// /// Normalizes the columns of a matrix. /// /// The norm under which to normalize the columns under. /// A normalized version of the matrix. /// If the parameter p is not positive. public Matrix NormalizeColumns(int p) { if (p < 1) { throw new ArgumentOutOfRangeException("p", Resources.ArgumentMustBePositive); } var ret = CreateMatrix(RowCount, ColumnCount); for (var index = 0; index < ColumnCount; index++) { ret.SetColumn(index, Column(index).Normalize(p)); } return ret; } /// /// Normalizes the rows of a matrix. /// /// The norm under which to normalize the rows under. /// A normalized version of the matrix. /// If the parameter p is not positive. public Matrix NormalizeRows(int p) { if (p < 1) { throw new ArgumentOutOfRangeException("p", Resources.ArgumentMustBePositive); } var ret = CreateMatrix(RowCount, ColumnCount); for (var index = 0; index < RowCount; index++) { ret.SetRow(index, Row(index).Normalize(p)); } return ret; } #region Exceptions - possibly move elsewhere? internal static Exception DimensionsDontMatch(Matrix left, Matrix right, Matrix result, string paramName = null) where TException : Exception { var message = string.Format(Resources.ArgumentMatrixDimensions3, left.RowCount + "x" + left.ColumnCount, right.RowCount + "x" + right.ColumnCount, result.RowCount + "x" + result.ColumnCount); return CreateException(message, paramName); } internal static Exception DimensionsDontMatch(Matrix left, Matrix right, string paramName = null) where TException : Exception { var message = string.Format(Resources.ArgumentMatrixDimensions2, left.RowCount + "x" + left.ColumnCount, right.RowCount + "x" + right.ColumnCount); return CreateException(message, paramName); } internal static Exception DimensionsDontMatch(Matrix matrix) where TException : Exception { var message = string.Format(Resources.ArgumentMatrixDimensions1, matrix.RowCount + "x" + matrix.ColumnCount); return CreateException(message); } internal static Exception DimensionsDontMatch(Matrix left, Vector right, Vector result, string paramName = null) where TException : Exception { return DimensionsDontMatch(left, right.ToColumnMatrix(), result.ToColumnMatrix(), paramName); } internal static Exception DimensionsDontMatch(Matrix left, Vector right, string paramName = null) where TException : Exception { return DimensionsDontMatch(left, right.ToColumnMatrix(), paramName); } internal static Exception DimensionsDontMatch(Vector left, Matrix right, string paramName = null) where TException : Exception { return DimensionsDontMatch(left.ToColumnMatrix(), right, paramName); } internal static Exception DimensionsDontMatch(Vector left, Vector right, string paramName = null) where TException : Exception { return DimensionsDontMatch(left.ToColumnMatrix(), right.ToColumnMatrix(), paramName); } static Exception CreateException(string message, string paramName = null) where TException : Exception { if (typeof (TException) == typeof (ArgumentException)) { return new ArgumentException(message, paramName); } if (typeof (TException) == typeof (ArgumentOutOfRangeException)) { return new ArgumentOutOfRangeException(paramName, message); } return new Exception(message); } #endregion } }