diff --git a/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs b/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs
index 745894f5..e3b7d47b 100644
--- a/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs
+++ b/src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs
@@ -602,5 +602,242 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return rightSide.LeftMultiply(leftSide);
}
+
+ ///
+ /// Concatenates this matrix with the given matrix.
+ ///
+ /// The matrix to concatenate.
+ /// The combined matrix.
+ public virtual Matrix Append(Matrix right)
+ {
+ if (right == null)
+ {
+ throw new ArgumentNullException("right");
+ }
+
+ if (right.RowCount != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ Matrix result = CreateMatrix(RowCount, ColumnCount + right.ColumnCount);
+ Append(right, result);
+ return result;
+ }
+
+ ///
+ /// Concatenates this matrix with the given matrix and places the result into the result matrix.
+ ///
+ /// The matrix to concatenate.
+ /// The combined matrix.
+ public virtual void Append(Matrix right, Matrix result)
+ {
+ if (right == null)
+ {
+ throw new ArgumentNullException("right");
+ }
+
+ if (right.RowCount != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.ColumnCount != (ColumnCount + right.ColumnCount) || result.RowCount != RowCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ CommonParallel.For(
+ 0,
+ this.RowCount,
+ i =>
+ {
+ for (int j = 0; j < this.ColumnCount; j++)
+ {
+ result.At(i, j, At(i, j));
+ }
+ });
+
+ CommonParallel.For(
+ 0,
+ right.RowCount,
+ i =>
+ {
+ for (int j = 0; j < right.ColumnCount; j++)
+ {
+ result.At(i, j + ColumnCount, right.At(i, j));
+ }
+ });
+ }
+
+ ///
+ /// Stacks this matrix on top of the given matrix and places the result into the result matrix.
+ ///
+ /// The matrix to stack this matrix upon.
+ /// The combined matrix.
+ /// If lower is .
+ /// If upper.Columns != lower.Columns.
+ public virtual Matrix Stack(Matrix lower)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ if (lower.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException("lower", Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ Matrix result = CreateMatrix(RowCount + lower.RowCount, ColumnCount);
+ Stack(lower, result);
+ return result;
+ }
+
+ ///
+ /// Stacks this matrix on top of the given matrix and places the result into the result matrix.
+ ///
+ /// The matrix to stack this matrix upon.
+ /// The combined matrix.
+ /// If lower is .
+ /// If upper.Columns != lower.Columns.
+ public virtual void Stack(Matrix lower, Matrix result)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ if (lower.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException("lower", Resources.ArgumentMatrixSameColumnDimension);
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != (RowCount + lower.RowCount) || result.ColumnCount != ColumnCount)
+ {
+ throw new ArgumentException("result", Resources.ArgumentMatrixDimensions);
+ }
+
+ CommonParallel.For(
+ 0,
+ this.RowCount,
+ i =>
+ {
+ for (int j = 0; j < this.ColumnCount; j++)
+ {
+ result.At(i, j, At(i, j));
+ }
+ });
+
+ CommonParallel.For(
+ 0,
+ lower.RowCount,
+ i =>
+ {
+ for (int j = 0; j < lower.ColumnCount; j++)
+ {
+ result.At(i + RowCount, j, lower.At(i, j));
+ }
+ });
+ }
+
+ ///
+ /// Computes the trace of this matrix.
+ ///
+ /// The trace of this matrix
+ /// If the matrix is not square
+ public virtual double Trace()
+ {
+ if (RowCount != ColumnCount)
+ {
+ throw new ArgumentException(Resources.ArgumentMatrixSquare);
+ }
+
+ double t = 0.0;
+ for (int i = 0; i < RowCount; i++)
+ {
+ t += this[i, i];
+ }
+
+ return t;
+ }
+
+ ///
+ /// Diagonally stacks his matrix on top of the given matrix. The new matrix is a M-by-N matrix,
+ /// where M = this.Rows + lower.Rows and N = this.Columns + lower.Columns.
+ /// The values of off the off diagonal matrices/blocks are set to zero.
+ ///
+ /// The lower, right matrix.
+ /// If lower is .
+ /// the combined matrix
+ public virtual Matrix DiagonalStack(Matrix lower)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ Matrix result = CreateMatrix(RowCount + lower.RowCount, ColumnCount + lower.ColumnCount);
+ DiagonalStack(lower, result);
+ return result;
+ }
+
+ ///
+ /// Diagonally stacks his matrix on top of the given matrix and places the combined matrix into the result matrix.
+ ///
+ /// The lower, right matrix.
+ /// The combined matrix
+ /// If lower is .
+ /// If the result matrix is .
+ /// If the result matrix's dimensions are not (this.Rows + lower.rows) x (this.Columns + lower.Columns).
+ public virtual void DiagonalStack(Matrix lower, Matrix result)
+ {
+ if (lower == null)
+ {
+ throw new ArgumentNullException("lower");
+ }
+
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (result.RowCount != RowCount + lower.RowCount || result.ColumnCount != ColumnCount + lower.ColumnCount)
+ {
+ throw new ArgumentException("result", Resources.ArgumentMatrixDimensions);
+ }
+
+ CommonParallel.For(
+ 0,
+ this.RowCount,
+ i =>
+ {
+ for (var j = 0; j < this.ColumnCount; j++)
+ {
+ result.At(i, j, At(i, j));
+ }
+ });
+
+ CommonParallel.For(
+ 0,
+ lower.RowCount,
+ i =>
+ {
+ for (var j = 0; j < lower.ColumnCount; j++)
+ {
+ result.At(i + RowCount, j + ColumnCount, lower.At(i, j));
+ }
+ });
+ }
}
}
\ No newline at end of file
diff --git a/src/Numerics/LinearAlgebra/Double/Vector.cs b/src/Numerics/LinearAlgebra/Double/Vector.cs
index 774358ce..07adaa61 100644
--- a/src/Numerics/LinearAlgebra/Double/Vector.cs
+++ b/src/Numerics/LinearAlgebra/Double/Vector.cs
@@ -548,6 +548,66 @@ namespace MathNet.Numerics.LinearAlgebra.Double
result.Multiply(1.0 / scalar);
}
+ ///
+ /// Pointwise multiplies this vector with another vector.
+ ///
+ /// The vector to pointwise multiply with this one.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ /// A new vector that is the pointwise multiplication of this vector and .
+ public virtual Vector PointWiseMultiply(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ Vector result = CreateVector(Count);
+ PointWiseMultiply(other, result);
+ return result;
+ }
+
+ ///
+ /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
+ ///
+ /// The vector to pointwise multiply with this one.
+ /// The vector to store the result of the pointwise multiplication.
+ /// If the other vector is .
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ /// If this vector and are not the same size.
+ public virtual void PointWiseMultiply(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ CommonParallel.For(
+ 0,
+ this.Count,
+ index => result[index] = this[index] * other[index]);
+ }
#endregion
#region Arithmetic Operator Overloading
diff --git a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.Arithmetic.cs b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.Arithmetic.cs
index fbef83e7..ad5da2b2 100644
--- a/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.Arithmetic.cs
+++ b/src/UnitTests/LinearAlgebraTests/Double/MatrixTests.Arithmetic.cs
@@ -579,5 +579,238 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
Matrix target = CreateMatrix(matrix.RowCount + 1, matrix.ColumnCount);
matrix.Negate(target);
}
+
+ [Test]
+ public void Append()
+ {
+ Matrix left = testMatrices["Singular3x3"];
+ Matrix right = testMatrices["Tall3x2"];
+ Matrix result = left.Append(right);
+ Assert.AreEqual(left.ColumnCount + right.ColumnCount, result.ColumnCount);
+ Assert.AreEqual(left.RowCount, right.RowCount);
+
+ for (int i = 0; i < result.RowCount; i++)
+ {
+ for (int j = 0; j < result.ColumnCount; j++)
+ {
+ if (j < left.ColumnCount)
+ {
+ Assert.AreEqual(left[i, j], result[i, j]);
+ }
+ else
+ {
+ Assert.AreEqual(right[i, j - left.ColumnCount], result[i, j]);
+ }
+ }
+ }
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void AppendWithRightParameterNullShouldThrowException()
+ {
+ Matrix left = testMatrices["Square3x3"];
+ Matrix right = null;
+ left.Append(right);
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void AppendWithResultParameterNullShouldThrowException()
+ {
+ Matrix left = testMatrices["Square3x3"];
+ Matrix right = testMatrices["Tall3x2"];
+ Matrix result = null;
+ left.Append(right, result);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void AppendingTwoMatricesWithDifferentRowCountShouldThrowException()
+ {
+ Matrix left = testMatrices["Square3x3"];
+ Matrix right = testMatrices["Wide2x3"];
+ Matrix result = left.Append(right);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void AppendingWithInvalidResultMatrixColumnsShouldThrowException()
+ {
+ Matrix left = testMatrices["Square3x3"];
+ Matrix right = testMatrices["Tall3x2"];
+ Matrix result = CreateMatrix(3, 2);
+ left.Append(right, result);
+ }
+
+ [Test]
+ public void Stack()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix bottom = testMatrices["Wide2x3"];
+ Matrix result = top.Stack(bottom);
+ Assert.AreEqual(top.RowCount + bottom.RowCount, result.RowCount);
+ Assert.AreEqual(top.ColumnCount, result.ColumnCount);
+
+ for (int i = 0; i < result.RowCount; i++)
+ {
+ for (int j = 0; j < result.ColumnCount; j++)
+ {
+ if (i < top.RowCount)
+ {
+ Assert.AreEqual(result[i, j], top[i, j]);
+ }
+ else
+ {
+ Assert.AreEqual(result[i, j], bottom[i - top.RowCount, j]);
+ }
+ }
+ }
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void StackWithBottomParameterNullShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix bottom = null;
+ Matrix result = CreateMatrix(top.RowCount + top.RowCount, top.ColumnCount);
+ top.Stack(bottom, result);
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void StackWithResultParameterNullShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix bottom = testMatrices["Square3x3"];
+ Matrix result = null;
+ top.Stack(bottom, result);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void StackTwoMatricesWithDifferentColumnsShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix lower = testMatrices["Tall3x2"];
+ Matrix result = CreateMatrix(top.RowCount + lower.RowCount, top.ColumnCount);
+ top.Stack(lower, result);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void StackingWithInvalidResultMatrixRowsShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix bottom = testMatrices["Wide2x3"];
+ Matrix result = CreateMatrix(1, 3);
+ top.Stack(bottom, result);
+ }
+
+ [Test]
+ public void Trace()
+ {
+ Matrix matrix = testMatrices["Square3x3"];
+ double trace = matrix.Trace();
+ Assert.AreEqual(6.6, trace);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void TraceOfNonSquareMatrixShouldThrowException()
+ {
+ Matrix matrix = testMatrices["Wide2x3"];
+ double trace = matrix.Trace();
+ }
+
+ [Test]
+ public void DiagonalStack()
+ {
+ Matrix top = testMatrices["Tall3x2"];
+ Matrix bottom = testMatrices["Wide2x3"];
+ Matrix result = top.DiagonalStack(bottom);
+ Assert.AreEqual(top.RowCount + bottom.RowCount, result.RowCount);
+ Assert.AreEqual(top.ColumnCount + bottom.ColumnCount, result.ColumnCount);
+
+ for (int i = 0; i < result.RowCount; i++)
+ {
+ for (int j = 0; j < result.ColumnCount; j++)
+ {
+ if (i < top.RowCount && j < top.ColumnCount)
+ {
+ Assert.AreEqual(top[i, j], result[i, j]);
+ }
+ else if (i >= top.RowCount && j >= top.ColumnCount)
+ {
+ Assert.AreEqual(bottom[i - top.RowCount, j - top.ColumnCount], result[i, j]);
+ }
+ else
+ {
+ Assert.AreEqual(0, result[i, j]);
+ }
+ }
+ }
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void DiagonalStackWithLowerNullShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix lower = null;
+ top.DiagonalStack(lower);
+ }
+
+ [Test]
+ public void DiagonalStackWithPassingResult()
+ {
+ Matrix top = testMatrices["Tall3x2"];
+ Matrix bottom = testMatrices["Wide2x3"];
+ Matrix result = CreateMatrix(top.RowCount + bottom.RowCount, top.ColumnCount + bottom.ColumnCount);
+ top.DiagonalStack(bottom, result);
+ Assert.AreEqual(top.RowCount + bottom.RowCount, result.RowCount);
+ Assert.AreEqual(top.ColumnCount + bottom.ColumnCount, result.ColumnCount);
+
+ for (int i = 0; i < result.RowCount; i++)
+ {
+ for (int j = 0; j < result.ColumnCount; j++)
+ {
+ if (i < top.RowCount && j < top.ColumnCount)
+ {
+ Assert.AreEqual(top[i, j], result[i, j]);
+ }
+ else if (i >= top.RowCount && j >= top.ColumnCount)
+ {
+ Assert.AreEqual(bottom[i - top.RowCount, j - top.ColumnCount], result[i, j]);
+ }
+ else
+ {
+ Assert.AreEqual(0, result[i, j]);
+ }
+ }
+ }
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void DiagonalStackWithResultNullShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix lower = testMatrices["Wide2x3"];
+ Matrix result = null;
+ top.DiagonalStack(lower,result);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void DiagonalStackWithInvalidResultMatrixShouldThrowException()
+ {
+ Matrix top = testMatrices["Square3x3"];
+ Matrix lower = testMatrices["Wide2x3"];
+ Matrix result = CreateMatrix(top.RowCount + lower.RowCount + 2, top.ColumnCount + lower.ColumnCount);
+ top.DiagonalStack(lower, result);
+
+ }
}
}
\ No newline at end of file
diff --git a/src/UnitTests/LinearAlgebraTests/Double/VectorTests.Arithmetic.cs b/src/UnitTests/LinearAlgebraTests/Double/VectorTests.Arithmetic.cs
index f71a02d3..56dee3ae 100644
--- a/src/UnitTests/LinearAlgebraTests/Double/VectorTests.Arithmetic.cs
+++ b/src/UnitTests/LinearAlgebraTests/Double/VectorTests.Arithmetic.cs
@@ -726,5 +726,61 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
double d = dataA * dataB;
}
+
+ [Test]
+ public void PointWiseMultiply()
+ {
+ Vector vector1 = CreateVector(_data);
+ Vector vector2 = vector1.Clone();
+ Vector result = CreateVector(vector1.Count);
+ vector1.PointWiseMultiply(vector2, result);
+ for (int i = 0; i < vector1.Count; i++)
+ {
+ Assert.AreEqual(_data[i] * _data[i], result[i]);
+ }
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void PointWiseMultiplyWithOtherNullShouldThrowException()
+ {
+ Vector vector1 = CreateVector(_data);
+ Vector vector2 = null;
+ Vector result = CreateVector(vector1.Count);
+ vector1.PointWiseMultiply(vector2, result);
+ }
+
+ [Test]
+ [ExpectedArgumentNullException]
+ public void PointWiseMultiplyWithResultNullShouldThrowException()
+ {
+ Vector vector1 = CreateVector(_data);
+ Vector vector2 = vector1.Clone();
+ Vector result = null;
+ vector1.PointWiseMultiply(vector2, result);
+ }
+
+ [Test]
+ [ExpectedArgumentException]
+ public void PointWiseMultiplyWithInvalidResultLengthShouldThrowException()
+ {
+ Vector vector1 = CreateVector(_data);
+ Vector vector2 = vector1.Clone();
+ Vector result = CreateVector(vector1.Count + 1);
+ vector1.PointWiseMultiply(vector2, result);
+ }
+
+ [Test]
+ public void PointWiseMultiplyWithResult()
+ {
+ Vector vector1 = CreateVector(_data);
+ Vector vector2 = vector1.Clone();
+ Vector result = vector1.PointWiseMultiply(vector2);
+ for (int i = 0; i < vector1.Count; i++)
+ {
+ Assert.AreEqual(_data[i] * _data[i], result[i]);
+ }
+ }
+
}
}
\ No newline at end of file