// // 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 MathNet.Numerics.Distributions; using MathNet.Numerics.LinearAlgebra.Storage; using MathNet.Numerics.Properties; using MathNet.Numerics.Threading; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace MathNet.Numerics.LinearAlgebra.Single { /// /// A matrix type for diagonal matrices. /// /// /// Diagonal matrices can be non-square matrices but the diagonal always starts /// at element 0,0. A diagonal matrix will throw an exception if non diagonal /// entries are set. The exception to this is when the off diagonal elements are /// 0.0 or NaN; these settings will cause no change to the diagonal matrix. /// [Serializable] [DebuggerDisplay("DiagonalMatrix {RowCount}x{ColumnCount}-Single")] public class DiagonalMatrix : Matrix { readonly DiagonalMatrixStorage _storage; /// /// Gets the matrix's data. /// /// The matrix's data. readonly float[] _data; /// /// Create a new diagonal matrix straight from an initialized matrix storage instance. /// The storage is used directly without copying. /// Intended for advanced scenarios where you're working directly with /// storage for performance or interop reasons. /// public DiagonalMatrix(DiagonalMatrixStorage storage) : base(storage) { _storage = storage; _data = _storage.Data; } /// /// Create a new square diagonal matrix with the given number of rows and columns. /// All cells of the matrix will be initialized to zero. /// Zero-length matrices are not supported. /// /// If the order is less than one. public DiagonalMatrix(int order) : this(new DiagonalMatrixStorage(order, order)) { } /// /// Create a new diagonal matrix with the given number of rows and columns. /// All cells of the matrix will be initialized to zero. /// Zero-length matrices are not supported. /// /// If the row or column count is less than one. public DiagonalMatrix(int rows, int columns) : this(new DiagonalMatrixStorage(rows, columns)) { } /// /// Create a new diagonal matrix with the given number of rows and columns. /// All diagonal cells of the matrix will be initialized to the provided value, all non-diagonal ones to zero. /// Zero-length matrices are not supported. /// /// If the row or column count is less than one. public DiagonalMatrix(int rows, int columns, float diagonalValue) : this(rows, columns) { for (var i = 0; i < _data.Length; i++) { _data[i] = diagonalValue; } } /// /// Create a new diagonal matrix with the given number of rows and columns directly binding to a raw array. /// The array is assumed to contain the diagonal elements only and is used directly without copying. /// Very efficient, but changes to the array and the matrix will affect each other. /// public DiagonalMatrix(int rows, int columns, float[] diagonalStorage) : this(new DiagonalMatrixStorage(rows, columns, diagonalStorage)) { } /// /// Create a new diagonal matrix as a copy of the given other matrix. /// This new matrix will be independent from the other matrix. /// The matrix to copy from must be diagonal as well. /// A new memory block will be allocated for storing the matrix. /// public static DiagonalMatrix OfMatrix(Matrix matrix) { return new DiagonalMatrix(DiagonalMatrixStorage.OfMatrix(matrix.Storage)); } /// /// Create a new diagonal matrix as a copy of the given two-dimensional array. /// This new matrix will be independent from the provided array. /// The array to copy from must be diagonal as well. /// A new memory block will be allocated for storing the matrix. /// public static DiagonalMatrix OfArray(float[,] array) { return new DiagonalMatrix(DiagonalMatrixStorage.OfArray(array)); } /// /// Create a new diagonal matrix and initialize each diagonal value from the provided indexed enumerable. /// Keys must be provided at most once, zero is assumed if a key is omitted. /// This new matrix will be independent from the enumerable. /// A new memory block will be allocated for storing the matrix. /// public static DiagonalMatrix OfIndexedDiagonal(int rows, int columns, IEnumerable> diagonal) { return new DiagonalMatrix(DiagonalMatrixStorage.OfIndexedEnumerable(rows, columns, diagonal)); } /// /// Create a new diagonal matrix and initialize each diagonal value from the provided enumerable. /// This new matrix will be independent from the enumerable. /// A new memory block will be allocated for storing the matrix. /// public static DiagonalMatrix OfDiagonal(int rows, int columns, IEnumerable diagonal) { return new DiagonalMatrix(DiagonalMatrixStorage.OfEnumerable(rows, columns, diagonal)); } /// /// Create a new diagonal matrix and initialize each diagonal value using the provided init function. /// public static DiagonalMatrix Create(int rows, int columns, Func init) { return new DiagonalMatrix(DiagonalMatrixStorage.OfInit(rows, columns, init)); } /// /// Create a new diagonal matrix with diagonal values sampled from the provided random distribution. /// public static DiagonalMatrix CreateRandom(int rows, int columns, IContinuousDistribution distribution) { return new DiagonalMatrix(DiagonalMatrixStorage.OfInit(rows, columns, i => (float) distribution.Sample())); } /// /// Creates a DiagonalMatrix for the given number of rows and columns. /// /// The number of rows. /// The number of columns. /// True if all fields must be mutable (e.g. not a diagonal matrix). /// /// A DiagonalMatrix with the given dimensions. /// public override Matrix CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) { return fullyMutable ? (Matrix) new SparseMatrix(numberOfRows, numberOfColumns) : new DiagonalMatrix(numberOfRows, numberOfColumns); } /// /// Creates a with a the given dimension. /// /// The size of the vector. /// True if all fields must be mutable. /// /// A with the given dimension. /// public override Vector CreateVector(int size, bool fullyMutable = false) { return new SparseVector(size); } #region Elementary operations /// /// Adds another matrix to this matrix. /// /// The matrix to add to this matrix. /// The result of the addition. /// If the other matrix is . /// If the two matrices don't have the same dimensions. public override Matrix Add(Matrix other) { if (other == null) { throw new ArgumentNullException("other"); } if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, other, "other"); } Matrix result; if (other is DiagonalMatrix) { result = new DiagonalMatrix(RowCount, ColumnCount); } else { result = new DenseMatrix(RowCount, ColumnCount); } Add(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 other matrix is . /// If the two matrices don't have the same dimensions. protected override void DoAdd(Matrix other, Matrix result) { var diagOther = other as DiagonalMatrix; var diagResult = result as DiagonalMatrix; if (diagOther == null || diagResult == null) { base.DoAdd(other, result); } else { Control.LinearAlgebraProvider.AddArrays(_data, diagOther._data, diagResult._data); } } /// /// Subtracts another matrix from this matrix. /// /// The matrix to subtract. /// The result of the subtraction. /// If the other matrix is . /// If the two matrices don't have the same dimensions. public override Matrix Subtract(Matrix other) { if (other == null) { throw new ArgumentNullException("other"); } if (other.RowCount != RowCount || other.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, other, "other"); } Matrix result; if (other is DiagonalMatrix) { result = new DiagonalMatrix(RowCount, ColumnCount); } else { result = new DenseMatrix(RowCount, ColumnCount); } Subtract(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 other matrix is . /// If the two matrices don't have the same dimensions. protected override void DoSubtract(Matrix other, Matrix result) { var diagOther = other as DiagonalMatrix; var diagResult = result as DiagonalMatrix; if (diagOther == null || diagResult == null) { base.DoSubtract(other, result); } else { Control.LinearAlgebraProvider.SubtractArrays(_data, diagOther._data, diagResult._data); } } /// /// Copies the values of the given array to the diagonal. /// /// The array to copy the values from. The length of the vector should be /// Min(Rows, Columns). /// If is . /// If the length of does not /// equal Min(Rows, Columns). /// For non-square matrices, the elements of are copied to /// this[i,i]. public override void SetDiagonal(float[] source) { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length != _data.Length) { throw new ArgumentException(Resources.ArgumentArraysSameLength, "source"); } Buffer.BlockCopy(source, 0, _data, 0, source.Length * Constants.SizeOfFloat); } /// /// Copies the values of the given to the diagonal. /// /// The vector to copy the values from. The length of the vector should be /// Min(Rows, Columns). /// If is . /// If the length of does not /// equal Min(Rows, Columns). /// For non-square matrices, the elements of are copied to /// this[i,i]. public override void SetDiagonal(Vector source) { var denseSource = source as DenseVector; if (denseSource == null) { base.SetDiagonal(source); return; } if (_data.Length != denseSource.Values.Length) { throw new ArgumentException(Resources.ArgumentVectorsSameLength, "source"); } Buffer.BlockCopy(denseSource.Values, 0, _data, 0, denseSource.Values.Length * Constants.SizeOfFloat); } /// /// 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 is . /// If the result matrix's dimensions are not the same as this matrix. protected override void DoMultiply(float scalar, Matrix result) { if (scalar == 0.0) { result.Clear(); return; } if (scalar == 1.0) { CopyTo(result); return; } var diagResult = result as DiagonalMatrix; if (diagResult == null) { base.DoMultiply(scalar, result); } else { if (!ReferenceEquals(this, result)) { CopyTo(diagResult); } Control.LinearAlgebraProvider.ScaleArray(scalar, _data, diagResult._data); } } /// /// 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 the other matrix is . /// If the result matrix is . /// If this.Columns != other.Rows. /// If the result matrix's dimensions are not the this.Rows x other.Columns. public override void Multiply(Matrix other, Matrix result) { if (other == null) { throw new ArgumentNullException("other"); } if (result == null) { throw new ArgumentNullException("result"); } if (ColumnCount != other.RowCount || result.RowCount != RowCount || result.ColumnCount != other.ColumnCount) { throw DimensionsDontMatch(this, other, result); } var m = other as DiagonalMatrix; var r = result as DiagonalMatrix; if (m == null || r == null) { base.Multiply(other, result); } else { var thisDataCopy = new float[r._data.Length]; var otherDataCopy = new float[r._data.Length]; Buffer.BlockCopy(_data, 0, thisDataCopy, 0, (r._data.Length > _data.Length) ? _data.Length * Constants.SizeOfFloat : r._data.Length * Constants.SizeOfFloat); Buffer.BlockCopy(m._data, 0, otherDataCopy, 0, (r._data.Length > m._data.Length) ? m._data.Length * Constants.SizeOfFloat : r._data.Length * Constants.SizeOfFloat); Control.LinearAlgebraProvider.PointWiseMultiplyArrays(thisDataCopy, otherDataCopy, r._data); } } /// /// Multiplies this matrix with another matrix and returns the result. /// /// The matrix to multiply with. /// If this.Columns != other.Rows. /// If the other matrix is . /// The result of multiplication. public override Matrix Multiply(Matrix other) { if (other == null) { throw new ArgumentNullException("other"); } if (ColumnCount != other.RowCount) { throw DimensionsDontMatch(this, other); } var result = other.CreateMatrix(RowCount, other.ColumnCount); Multiply(other, result); return result; } /// /// Multiplies this matrix with a vector and places the results into the result matrix. /// /// The vector to multiply with. /// The result of the multiplication. /// If is . /// If is . /// If result.Count != this.RowCount. /// If this.ColumnCount != .Count. public override void Multiply(Vector rightSide, Vector result) { if (rightSide == null) { throw new ArgumentNullException("rightSide"); } if (ColumnCount != rightSide.Count) { throw DimensionsDontMatch(this, rightSide, "rightSide"); } if (result == null) { throw new ArgumentNullException("result"); } if (RowCount != result.Count) { throw DimensionsDontMatch(this, result, "result"); } if (ReferenceEquals(rightSide, result)) { var tmp = result.CreateVector(result.Count); Multiply(rightSide, tmp); tmp.CopyTo(result); } else { // Clear the result vector result.Clear(); // Multiply the elements in the vector with the corresponding diagonal element in this. for (var r = 0; r < _data.Length; r++) { result[r] = _data[r] * rightSide[r]; } } } /// /// 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 is . /// If the result matrix is . /// If result.Count != this.ColumnCount. /// If this.RowCount != .Count. public override void LeftMultiply(Vector leftSide, Vector result) { if (leftSide == null) { throw new ArgumentNullException("leftSide"); } if (RowCount != leftSide.Count) { throw DimensionsDontMatch(this, leftSide, "leftSide"); } if (result == null) { throw new ArgumentNullException("result"); } if (ColumnCount != result.Count) { throw DimensionsDontMatch(this, result, "result"); } if (ReferenceEquals(leftSide, result)) { var tmp = result.CreateVector(result.Count); LeftMultiply(leftSide, tmp); tmp.CopyTo(result); } else { // Clear the result vector result.Clear(); // Multiply the elements in the vector with the corresponding diagonal element in this. for (var r = 0; r < _data.Length; r++) { result[r] = _data[r] * leftSide[r]; } } } /// /// Computes the determinant of this matrix. /// /// The determinant of this matrix. public override float Determinant() { if (RowCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare); } return _data.Aggregate(1.0f, (current, t) => current * t); } /// /// Returns the elements of the diagonal in a . /// /// The elements of the diagonal. /// For non-square matrices, the method returns Min(Rows, Columns) elements where /// i == j (i is the row index, and j is the column index). public override Vector Diagonal() { // TODO: Should we return reference to array? In current implementation we return copy of array, so changes in DenseVector will // not influence onto diagonal elements return new DenseVector((float[])_data.Clone()); } /// /// 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 the other matrix is . /// If the result matrix is . /// If this.Columns != other.Rows. /// If the result matrix's dimensions are not the this.Rows x other.Columns. public override void TransposeAndMultiply(Matrix other, Matrix result) { var otherDiagonal = other as DiagonalMatrix; var resultDiagonal = result as DiagonalMatrix; if (otherDiagonal == null || resultDiagonal == null) { base.TransposeAndMultiply(other, result); return; } Multiply(otherDiagonal.Transpose(), result); } /// /// Multiplies this matrix with transpose of another matrix and returns the result. /// /// The matrix to multiply with. /// If this.Columns != other.Rows. /// If the other matrix is . /// The result of multiplication. public override Matrix TransposeAndMultiply(Matrix other) { var otherDiagonal = other as DiagonalMatrix; if (otherDiagonal == null) { return base.TransposeAndMultiply(other); } if (ColumnCount != otherDiagonal.ColumnCount) { throw DimensionsDontMatch(this, otherDiagonal); } var result = other.CreateMatrix(RowCount, other.RowCount); TransposeAndMultiply(other, result); return result; } #endregion /// /// Returns the transpose of this matrix. /// /// The transpose of this matrix. public override Matrix Transpose() { var ret = new DiagonalMatrix(ColumnCount, RowCount); Buffer.BlockCopy(_data, 0, ret._data, 0, _data.Length * Constants.SizeOfFloat); return ret; } /// Calculates the L1 norm. /// The L1 norm of the matrix. public override float L1Norm() { return _data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t))); } /// Calculates the L2 norm. /// The L2 norm of the matrix. public override float L2Norm() { return _data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t))); } /// Calculates the Frobenius norm of this matrix. /// The Frobenius norm of this matrix. public override float FrobeniusNorm() { var norm = _data.Sum(t => t * t); return Convert.ToSingle(Math.Sqrt(norm)); } /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. public override float InfinityNorm() { return L1Norm(); } /// Calculates the condition number of this matrix. /// The condition number of the matrix. public override float ConditionNumber() { var maxSv = float.NegativeInfinity; var minSv = float.PositiveInfinity; foreach (var t in _data) { maxSv = Math.Max(maxSv, Math.Abs(t)); minSv = Math.Min(minSv, Math.Abs(t)); } return maxSv / minSv; } /// Computes the inverse of this matrix. /// If is not a square matrix. /// If is singular. /// The inverse of this matrix. public override Matrix Inverse() { if (RowCount != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare); } var inverse = (DiagonalMatrix)Clone(); for (var i = 0; i < _data.Length; i++) { if (_data[i] != 0.0) { inverse._data[i] = 1.0f / _data[i]; } else { throw new ArgumentException(Resources.ArgumentMatrixNotSingular); } } return inverse; } /// /// Returns a new matrix containing the lower triangle of this matrix. /// /// The lower triangle of this matrix. public override Matrix LowerTriangle() { return Clone(); } /// /// Puts the lower triangle of this matrix into the result matrix. /// /// Where to store the lower triangle. /// If is . /// If the result matrix's dimensions are not the same as this matrix. public override void LowerTriangle(Matrix result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } if (ReferenceEquals(this, result)) { return; } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, _data[i]); } } /// /// Returns a new matrix containing the lower triangle of this matrix. The new matrix /// does not contain the diagonal elements of this matrix. /// /// The lower triangle of this matrix. public override Matrix StrictlyLowerTriangle() { return new DiagonalMatrix(RowCount, ColumnCount); } /// /// Puts the strictly lower triangle of this matrix into the result matrix. /// /// Where to store the lower triangle. /// If is . /// If the result matrix's dimensions are not the same as this matrix. public override void StrictlyLowerTriangle(Matrix result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } result.Clear(); } /// /// Returns a new matrix containing the upper triangle of this matrix. /// /// The upper triangle of this matrix. public override Matrix UpperTriangle() { return Clone(); } /// /// Puts the upper triangle of this matrix into the result matrix. /// /// Where to store the lower triangle. /// If is . /// If the result matrix's dimensions are not the same as this matrix. public override void UpperTriangle(Matrix result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, _data[i]); } } /// /// Returns a new matrix containing the upper triangle of this matrix. The new matrix /// does not contain the diagonal elements of this matrix. /// /// The upper triangle of this matrix. public override Matrix StrictlyUpperTriangle() { return new DiagonalMatrix(RowCount, ColumnCount); } /// /// Puts the strictly upper triangle of this matrix into the result matrix. /// /// Where to store the lower triangle. /// If is . /// If the result matrix's dimensions are not the same as this matrix. public override void StrictlyUpperTriangle(Matrix result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch(this, result, "result"); } result.Clear(); } /// /// Creates a matrix that contains the values from the requested sub-matrix. /// /// The row to start copying from. /// The number of rows to copy. Must be positive. /// The column to start copying from. /// The number of columns to copy. Must be positive. /// The requested sub-matrix. /// If: is /// negative, or greater than or equal to the number of rows. /// is negative, or greater than or equal to the number /// of columns. /// (columnIndex + columnLength) >= Columns /// (rowIndex + rowLength) >= Rows /// If or /// is not positive. public override Matrix SubMatrix(int rowIndex, int rowCount, int columnIndex, int columnCount) { var target = rowIndex == columnIndex ? (Matrix)new DiagonalMatrix(rowCount, columnCount) : new SparseMatrix(rowCount, columnCount); Storage.CopySubMatrixTo(target.Storage, rowIndex, 0, rowCount, columnIndex, 0, columnCount, skipClearing: true); return target; } /// /// Creates a new and inserts the given column at the given index. /// /// The index of where to insert the column. /// The column to insert. /// A new with the inserted column. /// If is . /// If is < zero or > the number of columns. /// If the size of != the number of rows. public override Matrix InsertColumn(int columnIndex, Vector column) { if (column == null) { throw new ArgumentNullException("column"); } if (columnIndex < 0 || columnIndex > ColumnCount) { throw new ArgumentOutOfRangeException("columnIndex"); } if (column.Count != RowCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "column"); } var result = new SparseMatrix(RowCount, ColumnCount + 1); for (var i = 0; i < columnIndex; i++) { result.SetColumn(i, Column(i)); } result.SetColumn(columnIndex, column); for (var i = columnIndex + 1; i < ColumnCount + 1; i++) { result.SetColumn(i, Column(i - 1)); } return result; } /// /// Creates a new and inserts the given row at the given index. /// /// The index of where to insert the row. /// The row to insert. /// A new with the inserted column. /// If is . /// If is < zero or > the number of rows. /// If the size of != the number of columns. public override Matrix InsertRow(int rowIndex, Vector row) { if (row == null) { throw new ArgumentNullException("row"); } if (rowIndex < 0 || rowIndex > RowCount) { throw new ArgumentOutOfRangeException("rowIndex"); } if (row.Count != ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "row"); } var result = new SparseMatrix(RowCount + 1, ColumnCount); for (var i = 0; i < rowIndex; i++) { result.At(i, i, At(i, i)); } result.SetRow(rowIndex, row); for (var i = rowIndex + 1; i < result.RowCount; i++) { result.At(i, i - 1, At(i - 1, i - 1)); } return result; } /// /// Permute the columns of a matrix according to a permutation. /// /// The column permutation to apply to this matrix. /// Always thrown /// Permutation in diagonal matrix are senseless, because of matrix nature public override void PermuteColumns(Permutation p) { throw new InvalidOperationException("Permutations in diagonal matrix are not allowed"); } /// /// Permute the rows of a matrix according to a permutation. /// /// The row permutation to apply to this matrix. /// Always thrown /// Permutation in diagonal matrix are senseless, because of matrix nature public override void PermuteRows(Permutation p) { throw new InvalidOperationException("Permutations in diagonal matrix are not allowed"); } /// /// Gets a value indicating whether this matrix is symmetric. /// public override bool IsSymmetric { get { return true; } } /// /// Computes the modulus for each element of the matrix. /// /// The scalar denominator to use. /// Matrix to store the results in. protected override void DoModulus(float divisor, Matrix result) { var diagonalResult = result as DiagonalMatrix; if (diagonalResult == null) { base.DoModulus(divisor, result); return; } CommonParallel.For(0, _data.Length, 4096, (a, b) => { var r = diagonalResult._data; for (var i = a; i < b; i++) { r[i] = _data[i]%divisor; } }); } /// /// Computes the modulus for each element of the matrix. /// /// The scalar numerator to use. /// Matrix to store the results in. protected override void DoModulusByThis(float dividend, Matrix result) { var diagonalResult = result as DiagonalMatrix; if (diagonalResult == null) { base.DoModulusByThis(dividend, result); return; } CommonParallel.For(0, _data.Length, 4096, (a, b) => { var r = diagonalResult._data; for (var i = a; i < b; i++) { r[i] = dividend%_data[i]; } }); } #region Static constructors for special matrices. /// /// Initializes a square with all zero's except for ones on the diagonal. /// /// the size of the square matrix. /// A diagonal identity matrix. /// /// If is less than one. /// public static DiagonalMatrix Identity(int order) { var m = new DiagonalMatrix(order); for (var i = 0; i < order; i++) { m._data[i] = 1.0f; } return m; } #endregion } }