/// <summary> /// Puts the strictly upper triangle of this matrix into the result matrix. /// </summary> /// <param name="result">Where to store the lower triangle.</param> /// <exception cref="ArgumentNullException">If <paramref name="result"/> is <see langword="null" />.</exception> /// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception> public override void StrictlyUpperTriangle(Matrix <double> result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch <ArgumentException>(this, result, "result"); } result.Clear(); }
/// <summary> /// Negate each element of this matrix and place the results into the result matrix. /// </summary> /// <param name="result">The result of the negation.</param> protected override void DoNegate(Matrix <double> result) { if (result is DiagonalMatrix diagResult) { LinearAlgebraControl.Provider.ScaleArray(-1, _data, diagResult._data); return; } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, -_data[i]); } }
/// <summary> /// Multiplies the transpose of this matrix with another matrix and places the results into the result matrix. /// </summary> /// <param name="other">The matrix to multiply with.</param> /// <param name="result">The result of the multiplication.</param> protected override void DoTransposeThisAndMultiply(Matrix <double> other, Matrix <double> result) { var diagonalOther = other as DiagonalMatrix; var diagonalResult = result as DiagonalMatrix; if (diagonalOther != null && diagonalResult != null) { var thisDataCopy = new double[diagonalResult._data.Length]; var otherDataCopy = new double[diagonalResult._data.Length]; Array.Copy(_data, thisDataCopy, (diagonalResult._data.Length > _data.Length) ? _data.Length : diagonalResult._data.Length); Array.Copy(diagonalOther._data, otherDataCopy, (diagonalResult._data.Length > diagonalOther._data.Length) ? diagonalOther._data.Length : diagonalResult._data.Length); Control.LinearAlgebraProvider.PointWiseMultiplyArrays(thisDataCopy, otherDataCopy, diagonalResult._data); return; } var denseOther = other.Storage as DenseColumnMajorMatrixStorage <double>; if (denseOther != null) { var dense = denseOther.Data; var diagonal = _data; var d = Math.Min(denseOther.RowCount, ColumnCount); if (d < ColumnCount) { result.ClearSubMatrix(denseOther.RowCount, ColumnCount - denseOther.RowCount, 0, denseOther.ColumnCount); } int index = 0; for (int i = 0; i < denseOther.ColumnCount; i++) { for (int j = 0; j < d; j++) { result.At(j, i, dense[index] * diagonal[j]); index++; } index += (denseOther.RowCount - d); } return; } if (ColumnCount == RowCount) { other.Storage.MapIndexedTo(result.Storage, (i, j, x) => x * _data[i], Zeros.AllowSkip, ExistingData.Clear); } else { result.Clear(); other.Storage.MapSubMatrixIndexedTo(result.Storage, (i, j, x) => x * _data[i], 0, 0, other.RowCount, 0, 0, other.ColumnCount, Zeros.AllowSkip, ExistingData.AssumeZeros); } }
/// <summary> /// Create a new diagonal matrix with diagonal values sampled from the provided random distribution. /// </summary> /// <summary> /// Negate each element of this matrix and place the results into the result matrix. /// </summary> /// <param name="result">The result of the negation.</param> protected override void DoNegate(Matrix <double> result) { var diagResult = result as DiagonalMatrix; if (diagResult != null) { Map(x => - x, result, Zeros.AllowSkip); return; } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, -_data[i]); } }
/// <summary> /// Puts the lower triangle of this matrix into the result matrix. /// </summary> /// <param name="result">Where to store the lower triangle.</param> /// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception> public override void LowerTriangle(Matrix <double> result) { if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch <ArgumentException>(this, result, "result"); } if (ReferenceEquals(this, result)) { return; } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, _data[i]); } }
/// <summary> /// Puts the upper triangle of this matrix into the result matrix. /// </summary> /// <param name="result">Where to store the lower triangle.</param> /// <exception cref="ArgumentNullException">If <paramref name="result"/> is <see langword="null" />.</exception> /// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception> public override void UpperTriangle(Matrix <double> result) { if (result == null) { throw new ArgumentNullException("result"); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch <ArgumentException>(this, result, "result"); } result.Clear(); for (var i = 0; i < _data.Length; i++) { result.At(i, i, _data[i]); } }
/// <summary> /// Divides each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="divisor">The scalar to divide the matrix with.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivide(double divisor, Matrix <double> result) { if (divisor == 1.0) { CopyTo(result); return; } if (result is DiagonalMatrix diagResult) { LinearAlgebraControl.Provider.ScaleArray(1.0 / divisor, _data, diagResult._data); return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, _data[i] / divisor); } }
/// <summary> /// Divides a scalar by each element of the matrix and stores the result in the result matrix. /// </summary> /// <param name="dividend">The scalar to add.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivideByThis(double dividend, Matrix <double> result) { if (result is DiagonalMatrix diagResult) { var resultData = diagResult._data; CommonParallel.For(0, _data.Length, 4096, (a, b) => { for (int i = a; i < b; i++) { resultData[i] = dividend / _data[i]; } }); return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, dividend / _data[i]); } }
/// <summary> /// Divides a scalar by each element of the matrix and stores the result in the result matrix. /// </summary> /// <param name="dividend">The scalar to add.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivideByThis(double dividend, Matrix <double> result) { var diagResult = result as DiagonalMatrix; if (diagResult != null) { var resultData = diagResult._data; for (int i = 0; i < _data.Length; i++) { resultData[i] = dividend / _data[i]; } return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, dividend / _data[i]); } }
/// <summary> /// Divides each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="divisor">The scalar to divide the matrix with.</param> /// <param name="result">The matrix to store the result of the division.</param> protected override void DoDivide(double divisor, Matrix <double> result) { if (divisor == 1.0) { CopyTo(result); return; } var diagResult = result as DiagonalMatrix; if (diagResult != null) { Map(x => x / divisor, result, divisor == 0.0 ? Zeros.Include : Zeros.AllowSkip); return; } result.Clear(); for (int i = 0; i < _data.Length; i++) { result.At(i, i, _data[i] / divisor); } }
/// <summary> /// Multiplies each element of the matrix by a scalar and places results into the result matrix. /// </summary> /// <param name="scalar">The scalar to multiply the matrix with.</param> /// <param name="result">The matrix to store the result of the multiplication.</param> /// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception> protected override void DoMultiply(double scalar, Matrix <double> result) { if (scalar == 0.0) { result.Clear(); return; } if (scalar == 1.0) { CopyTo(result); return; } if (result is DiagonalMatrix diagResult) { LinearAlgebraControl.Provider.ScaleArray(scalar, _data, diagResult._data); } else { base.DoMultiply(scalar, result); } }
/// <summary> /// Puts the upper triangle of this matrix into the result matrix. /// </summary> /// <param name="result">Where to store the lower triangle.</param> /// <exceptioncreArgumentNullException">If /// /// <paramref name="result is /// /// <see langword="null" /> /// . /// </exception> /// <exceptioncreArgumentException">If the result matrix's dimensions are not the same as this matrix. /// /// </exception> public void UpperTriangle(Matrix <double> result) { if (result == null) { throw new ArgumentNullException(nameof(result)); } if (result.RowCount != RowCount || result.ColumnCount != ColumnCount) { throw DimensionsDontMatch <ArgumentException>(this, result, "result"); } if (ReferenceEquals(this, result)) { var tmp = Build.SameAs(result); UpperTriangle(tmp); tmp.CopyTo(result); } else { result.Clear(); UpperTriangleImpl(result); } }
/// <summary> /// Multiplies this matrix with another matrix and places the results into the result matrix. /// </summary> /// <param name="other">The matrix to multiply with.</param> /// <param name="result">The result of the multiplication.</param> protected override void DoMultiply(Matrix <double> other, Matrix <double> result) { var sparseOther = other as SparseMatrix; var sparseResult = result as SparseMatrix; if (sparseOther != null && sparseResult != null) { DoMultiplySparse(sparseOther, sparseResult); return; } var diagonalOther = other.Storage as DiagonalMatrixStorage <double>; if (diagonalOther != null && sparseResult != null) { var diagonal = diagonalOther.Data; if (other.ColumnCount == other.RowCount) { Storage.MapIndexedTo(result.Storage, (i, j, x) => x * diagonal[j], Zeros.AllowSkip, ExistingData.Clear); } else { result.Storage.Clear(); Storage.MapSubMatrixIndexedTo(result.Storage, (i, j, x) => x * diagonal[j], 0, 0, RowCount, 0, 0, ColumnCount, Zeros.AllowSkip, ExistingData.AssumeZeros); } return; } result.Clear(); var rowPointers = _storage.RowPointers; var columnIndices = _storage.ColumnIndices; var values = _storage.Values; var denseOther = other.Storage as DenseColumnMajorMatrixStorage <double>; if (denseOther != null) { // in this case we can directly address the underlying data-array for (var row = 0; row < RowCount; row++) { var startIndex = rowPointers[row]; var endIndex = rowPointers[row + 1]; if (startIndex == endIndex) { continue; } for (var column = 0; column < other.ColumnCount; column++) { var otherColumnStartPosition = column * other.RowCount; var sum = 0d; for (var index = startIndex; index < endIndex; index++) { sum += values[index] * denseOther.Data[otherColumnStartPosition + columnIndices[index]]; } result.At(row, column, sum); } } return; } var columnVector = new DenseVector(other.RowCount); for (var row = 0; row < RowCount; row++) { var startIndex = rowPointers[row]; var endIndex = rowPointers[row + 1]; if (startIndex == endIndex) { continue; } for (var column = 0; column < other.ColumnCount; column++) { // Multiply row of matrix A on column of matrix B other.Column(column, columnVector); var sum = 0d; for (var index = startIndex; index < endIndex; index++) { sum += values[index] * columnVector[columnIndices[index]]; } result.At(row, column, sum); } } }