Browse Source

Added Append, Stack, DiagonalStack, Trace to Matrix class.

Added PointWiseMultiply to abstract vector class.
la-knuth
Hani Medhat 17 years ago
committed by Marcus Cuda
parent
commit
24333feeb0
  1. 237
      src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs
  2. 60
      src/Numerics/LinearAlgebra/Double/Vector.cs
  3. 233
      src/UnitTests/LinearAlgebraTests/Double/MatrixTests.Arithmetic.cs
  4. 56
      src/UnitTests/LinearAlgebraTests/Double/VectorTests.Arithmetic.cs

237
src/Numerics/LinearAlgebra/Double/Matrix.Arithmetic.cs

@ -602,5 +602,242 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return rightSide.LeftMultiply(leftSide);
}
/// <summary>
/// Concatenates this matrix with the given matrix.
/// </summary>
/// <param name="right">The matrix to concatenate.</param>
/// <returns>The combined matrix.</returns>
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;
}
/// <summary>
/// Concatenates this matrix with the given matrix and places the result into the result matrix.
/// </summary>
/// <param name="right">The matrix to concatenate.</param>
/// <param name="result">The combined matrix.</param>
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));
}
});
}
/// <summary>
/// Stacks this matrix on top of the given matrix and places the result into the result matrix.
/// </summary>
/// <param name="lower">The matrix to stack this matrix upon.</param>
/// <returns>The combined matrix.</returns>
/// <exception cref="ArgumentNullException">If lower is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <strong>upper.Columns != lower.Columns</strong>.</exception>
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;
}
/// <summary>
/// Stacks this matrix on top of the given matrix and places the result into the result matrix.
/// </summary>
/// <param name="lower">The matrix to stack this matrix upon.</param>
/// <param name="result">The combined matrix.</param>
/// <exception cref="ArgumentNullException">If lower is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If <strong>upper.Columns != lower.Columns</strong>.</exception>
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));
}
});
}
/// <summary>
/// Computes the trace of this matrix.
/// </summary>
/// <returns>The trace of this matrix</returns>
/// <exception cref=">ArgumentException">If the matrix is not square</exception>
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;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="lower">The lower, right matrix.</param>
/// <exception cref="ArgumentNullException">If lower is <see langword="null" />.</exception>
/// <returns>the combined matrix</returns>
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;
}
/// <summary>
/// Diagonally stacks his matrix on top of the given matrix and places the combined matrix into the result matrix.
/// </summary>
/// <param name="lower">The lower, right matrix.</param>
/// <param name="result">The combined matrix</param>
/// <exception cref="ArgumentNullException">If lower is <see langword="null" />.</exception>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If the result matrix's dimensions are not (this.Rows + lower.rows) x (this.Columns + lower.Columns).</exception>
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));
}
});
}
}
}

60
src/Numerics/LinearAlgebra/Double/Vector.cs

@ -548,6 +548,66 @@ namespace MathNet.Numerics.LinearAlgebra.Double
result.Multiply(1.0 / scalar);
}
/// <summary>
/// Pointwise multiplies this vector with another vector.
/// </summary>
/// <param name="other">The vector to pointwise multiply with this one.</param>
/// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this vector and <paramref name="other"/> are not the same size.</exception>
/// <returns>A new vector that is the pointwise multiplication of this vector and <paramref name="other"/>.</returns>
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;
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
/// <exception cref="ArgumentNullException">If the other vector is <see langword="null" />.</exception>
/// <exception cref="ArgumentNullException">If the result vector is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this vector and <paramref name="other"/> are not the same size.</exception>
/// <exception cref="ArgumentException">If this vector and <paramref name="result"/> are not the same size.</exception>
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

233
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);
}
}
}

56
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]);
}
}
}
}
Loading…
Cancel
Save