diff --git a/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebra.cs b/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebra.cs
index 2cc85450..ebc15ee2 100644
--- a/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebra.cs
+++ b/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebra.cs
@@ -30,10 +30,20 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
public interface ILinearAlgebra
{
///
- /// Adds the two arrays together: a += c.
+ /// Adds a scaled vector to another: y += alpha*x.
///
- /// One of the arrays to add.
- /// The other array to add.
- void AddArrays(double[] a, double[] b);
+ /// The vector to update.
+ /// The value to scale by.
+ /// The vector to add to .
+ /// This is equivalent to the AXPY BLAS routine.
+ void AddVectorToScaledVector(double[] y, double alpha, double[] x);
+
+ ///
+ /// Scales an array. Can be used to scale a vector and a matrix.
+ ///
+ /// The scalar.
+ /// The values to scale.
+ /// This is equivalent to the SCAL BLAS routine.
+ void ScaleArray(double alpha, double[] x);
}
}
diff --git a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebra.cs b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebra.cs
index 1749ef0a..22d5beae 100644
--- a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebra.cs
+++ b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebra.cs
@@ -31,37 +31,52 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra
///
internal class ManagedLinearAlgebra : ILinearAlgebra
{
- #region ILinearAlgebra Members
-
///
- /// Adds the two arrays together: a += c.
+ /// Adds a scaled vector to another: y += alpha*x.
///
- ///
- /// One of the arrays to add.
- ///
- ///
- /// The other array to add.
- ///
- public void AddArrays(double[] a, double[] b)
+ /// The vector to update.
+ /// The value to scale by.
+ /// The vector to add to .
+ /// This equivalent to the AXPY BLAS routine.
+ public void AddVectorToScaledVector(double[] y, double alpha, double[] x)
{
- if (a == null)
+ if (y == null)
{
- throw new ArgumentNullException("a");
+ throw new ArgumentNullException("y");
}
- if (b == null)
+ if (x == null)
{
- throw new ArgumentNullException("b");
+ throw new ArgumentNullException("x");
}
- if (a.Length != b.Length)
+ if (y.Length != x.Length)
{
throw new ArgumentException(Properties.Resources.ArgumentVectorsSameLength);
}
- Parallel.For(0, a.Length, i => a[i] += b[i]);
+ if (alpha.AlmostZero())
+ {
+ return;
+ }
+
+ if (alpha.AlmostEqual(1.0))
+ {
+ Parallel.For(0, y.Length, i => y[i] += x[i]);
+ }
+ else
+ {
+ Parallel.For(0, y.Length, i => y[i] += alpha * x[i]);
+ }
}
- #endregion
+ public void ScaleArray(double alpha, double[] x)
+ {
+ if (alpha.AlmostEqual(1.0))
+ {
+ return;
+ }
+ Parallel.For(0, x.Length, i => x[i] = alpha * x[i]);
+ }
}
}
\ No newline at end of file
diff --git a/src/Numerics/LinearAlgebra/Double/DenseVector.cs b/src/Numerics/LinearAlgebra/Double/DenseVector.cs
index 586fdb98..e846f644 100644
--- a/src/Numerics/LinearAlgebra/Double/DenseVector.cs
+++ b/src/Numerics/LinearAlgebra/Double/DenseVector.cs
@@ -265,7 +265,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
- _linearAlgebra.AddArrays(Data, denseVector.Data);
+ _linearAlgebra.AddVectorToScaledVector(Data, 1.0, denseVector.Data);
}
}
@@ -354,5 +354,169 @@ namespace MathNet.Numerics.LinearAlgebra.Double
ret.Add(rightSide);
return ret;
}
+
+ ///
+ /// Subtracts a scalar from each element of the vector.
+ ///
+ /// The scalar to subtract.
+ public override void Subtract(double scalar)
+ {
+ if (scalar.AlmostZero())
+ {
+ return;
+ }
+
+ Parallel.For(0, Count, i => Data[i] -= scalar);
+ }
+
+ ///
+ /// Subtracts a scalar from each element of the vector and stores the result in the result vector.
+ ///
+ /// The scalar to subtract.
+ /// The vector to store the result of the subtraction.
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ public override void Subtract(double scalar, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException("result", Resources.ArgumentVectorsSameLength);
+ }
+
+ CopyTo(result);
+ result.Subtract(scalar);
+ }
+
+ ///
+ /// Subtracts another vector from this vector.
+ ///
+ /// The vector to subtract from this one.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ public override void Subtract(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException("other", Resources.ArgumentVectorsSameLength);
+ }
+
+ var denseVector = other as DenseVector;
+
+ if (denseVector == null)
+ {
+ base.Subtract(other);
+ }
+ else
+ {
+ _linearAlgebra.AddVectorToScaledVector(Data, -1.0, denseVector.Data);
+ }
+ }
+
+ ///
+ /// Subtracts another vector to this vector and stores the result into the result vector.
+ ///
+ /// The vector to subtract from this one.
+ /// The vector to store the result of the subtraction.
+ /// 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 override void Subtract(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException("other", Resources.ArgumentVectorsSameLength);
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException("result", Resources.ArgumentVectorsSameLength);
+ }
+
+ if (ReferenceEquals(this, result) || ReferenceEquals(other, result))
+ {
+ var tmp = result.CreateVector(result.Count);
+ Subtract(other, tmp);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ CopyTo(result);
+ result.Subtract(other);
+ }
+ }
+
+ ///
+ /// Returns a Vector containing the negated values of rightSide.
+ ///
+ /// The vector to get the values from.
+ /// A vector containing the negated values as .
+ /// If is .
+ public static Vector operator -(DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return rightSide.Negate();
+ }
+
+ ///
+ /// Subtracts two Vectors and returns the results.
+ ///
+ /// The vector to subtract from.
+ /// The vector to subtract.
+ /// The result of the subtraction.
+ /// If and are not the same size.
+ /// If or is .
+ public static Vector operator -(DenseVector leftSide, DenseVector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.Count != rightSide.Count)
+ {
+ throw new ArgumentException("rightSide", Resources.ArgumentVectorsSameLength);
+ }
+
+ var ret = leftSide.Clone();
+ ret.Subtract(rightSide);
+ return ret;
+ }
+
+ ///
+ /// Returns a negated vector.
+ ///
+ /// The negated vector.
+ /// Added as an alternative to the unary negation operator.
+ public virtual Vector Negate()
+ {
+ var result = new DenseVector(Count);
+ Parallel.For(0, Count, i => result[i] = -Data[i]);
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/src/Numerics/LinearAlgebra/Double/Vector.cs b/src/Numerics/LinearAlgebra/Double/Vector.cs
index b1f579e6..fcb2625c 100644
--- a/src/Numerics/LinearAlgebra/Double/Vector.cs
+++ b/src/Numerics/LinearAlgebra/Double/Vector.cs
@@ -329,9 +329,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
///
- /// Returns a clone of this vector.
+ /// Returns this vector.
///
- /// A clone of this vector.
+ /// This vector.
/// Added as an alternative to the unary addition operator.
public virtual Vector Plus()
{
@@ -398,7 +398,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
///
/// This method is included for completeness.
/// The vector to get the values from.
- /// A vector containing a the same values as .
+ /// A vector containing the same values as .
/// If is .
public static Vector operator +(Vector rightSide)
{
@@ -440,6 +440,157 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return ret;
}
+ ///
+ /// Subtracts a scalar from each element of the vector.
+ ///
+ /// The scalar to subtract.
+ public virtual void Subtract(double scalar)
+ {
+ if (scalar.AlmostZero())
+ {
+ return;
+ }
+
+ Parallel.For(0, Count, i => this[i] -= scalar);
+ }
+
+ ///
+ /// Subtracts a scalar from each element of the vector and stores the result in the result vector.
+ ///
+ /// The scalar to subtract.
+ /// The vector to store the result of the subtraction.
+ /// If the result vector is .
+ /// If this vector and are not the same size.
+ public virtual void Subtract(double scalar, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ CopyTo(result);
+ result.Subtract(scalar);
+ }
+
+ ///
+ /// Returns a negated vector.
+ ///
+ /// The negated vector.
+ /// Added as an alternative to the unary negation operator.
+ public virtual Vector Negate()
+ {
+ var result = CreateVector(Count);
+ Parallel.For(0, Count, i => result[i] = -this[i]);
+ return result;
+ }
+
+ ///
+ /// Subtracts another vector from this vector.
+ ///
+ /// The vector to subtract from this one.
+ /// If the other vector is .
+ /// If this vector and are not the same size.
+ public virtual void Subtract(Vector other)
+ {
+ if (other == null)
+ {
+ throw new ArgumentNullException("other");
+ }
+
+ if (Count != other.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "other");
+ }
+
+ Parallel.For(0, Count, i => this[i] -= other[i]);
+ }
+
+ ///
+ /// Subtracts another vector to this vector and stores the result into the result vector.
+ ///
+ /// The vector to subtract from this one.
+ /// The vector to store the result of the subtraction.
+ /// 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 Subtract(Vector other, Vector result)
+ {
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
+ if (Count != result.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "result");
+ }
+
+ if (ReferenceEquals(this, result) || ReferenceEquals(other, result))
+ {
+ var tmp = result.CreateVector(result.Count);
+ Subtract(other, tmp);
+ tmp.CopyTo(result);
+ }
+ else
+ {
+ CopyTo(result);
+ result.Subtract(other);
+ }
+ }
+
+ ///
+ /// Returns a Vector containing the negated values of rightSide.
+ ///
+ /// The vector to get the values from.
+ /// A vector containing the negated values as .
+ /// If is .
+ public static Vector operator -(Vector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ return rightSide.Negate();
+ }
+
+ ///
+ /// Subtracts two Vectors and returns the results.
+ ///
+ /// The vector to subtract from.
+ /// The vector to subtract.
+ /// The result of the subtraction.
+ /// If and are not the same size.
+ /// If or is .
+ public static Vector operator -(Vector leftSide, Vector rightSide)
+ {
+ if (rightSide == null)
+ {
+ throw new ArgumentNullException("rightSide");
+ }
+
+ if (leftSide == null)
+ {
+ throw new ArgumentNullException("leftSide");
+ }
+
+ if (leftSide.Count != rightSide.Count)
+ {
+ throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
+ }
+
+ var ret = leftSide.Clone();
+ ret.Subtract(rightSide);
+ return ret;
+ }
+
+
#region Implemented Interfaces
#region ICloneable
diff --git a/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs b/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs
index 23cd89ca..f2e7bac6 100644
--- a/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs
+++ b/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs
@@ -6,7 +6,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public class DenseVectorTests : VectorTests
{
- protected override MathNet.Numerics.LinearAlgebra.Double.Vector CreateVector(int size)
+ protected override Vector CreateVector(int size)
{
return new DenseVector(size);
}
diff --git a/src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs b/src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs
index 0b4e0590..71dc7b02 100644
--- a/src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs
+++ b/src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs
@@ -346,7 +346,6 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
}
}
-
[Test]
[MultipleAsserts]
public void CanAddVectorToItselfUsingResultVector()
@@ -377,6 +376,231 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
}
}
+ [Test]
+ public void CanCallNegate()
+ {
+ var vector = CreateVector(_data);
+ var other = vector.Negate();
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(-_data[i], other[i]);
+ }
+ }
+
+ [Test]
+ public void OperatorNegateThrowsArgumentNullExceptionWhenCallOnNullVector()
+ {
+ Vector vector = null;
+ Vector other = null;
+ Assert.Throws(() => other = -vector);
+ }
+
+ [Test]
+ public void CanCallUnaryNegationOperator()
+ {
+ var vector = CreateVector(_data);
+ var other = -vector;
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(-_data[i], other[i]);
+ }
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractScalarFromVector()
+ {
+ var vector = CreateVector(_data);
+ vector.Subtract(2.0);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i] - 2.0, vector[i]);
+ }
+
+ vector.Subtract(0.0);
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i] - 2.0, vector[i]);
+ }
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractScalarFromVectorUsingResultVector()
+ {
+ var vector = CreateVector(_data);
+ var result = CreateVector(_data.Length);
+ vector.Subtract(2.0, result);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i], vector[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(_data[i] - 2.0, result[i]);
+ }
+
+ vector.Subtract(0.0, result);
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i], result[i]);
+ }
+ }
+
+ [Test]
+ public void ThrowsArgumentNullExceptionWhenSubtractingScalarWithNullResultVector()
+ {
+ var vector = CreateVector(_data.Length);
+ Assert.Throws(() => vector.Subtract(0.0, null));
+ }
+
+ [Test]
+ public void ThrowsArgumentExceptionWhenSubtractingScalarWithWrongSizeResultVector()
+ {
+ var vector = CreateVector(_data.Length);
+ var result = CreateVector(_data.Length + 1);
+ Assert.Throws(() => vector.Subtract(0.0, result));
+ }
+
+ [Test]
+ public void ThrowsArgumentNullExceptionWhenSubtractingTwoVectorsAndOneIsNull()
+ {
+ var vector = CreateVector(_data);
+ Assert.Throws(() => vector.Subtract(null));
+ }
+
+ [Test]
+ public void ThrowsArgumentExceptionWhenSubtractingTwoVectorsOfDifferingSize()
+ {
+ var vector = CreateVector(_data.Length);
+ var other = CreateVector(_data.Length + 1);
+ Assert.Throws(() => vector.Subtract(other));
+ }
+
+ [Test]
+ public void ThrowsArgumentNullExceptionWhenSubtractingTwoVectorsAndResultIsNull()
+ {
+ var vector = CreateVector(_data.Length);
+ var other = CreateVector(_data.Length + 1);
+ Assert.Throws(() => vector.Subtract(other, null));
+ }
+
+ [Test]
+ public void ThrowsArgumentExceptionWhenSubtractingTwoVectorsAndResultIsDifferentSize()
+ {
+ var vector = CreateVector(_data.Length);
+ var other = CreateVector(_data.Length);
+ var result = CreateVector(_data.Length + 1);
+ Assert.Throws(() => vector.Subtract(other, result));
+ }
+
+ [Test]
+ public void SubtractionOperatorThrowsArgumentNullExpectionIfAVectorIsNull()
+ {
+ Vector a = null;
+ var b = CreateVector(_data.Length);
+ Assert.Throws(() => a -= b);
+
+ a = b;
+ b = null;
+ Assert.Throws(() => a -= b);
+ }
+
+ [Test]
+ public void SubtractionOperatorThrowsArgumentExpectionIfVectorsAreDifferentSize()
+ {
+ var a = CreateVector(_data.Length);
+ var b = CreateVector(_data.Length + 1);
+ Assert.Throws(() => a -= b);
+ }
+
+ [Test]
+ public void CanSubtractTwoVectors()
+ {
+ var vector = CreateVector(_data);
+ var other = CreateVector(_data);
+ vector.Subtract(other);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(0.0, vector[i]);
+ }
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractTwoVectorsUsingResultVector()
+ {
+ var vector = CreateVector(_data);
+ var other = CreateVector(_data);
+ var result = CreateVector(_data.Length);
+ vector.Subtract(other, result);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i], vector[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(_data[i], other[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(0.0, result[i]);
+ }
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractTwoVectorsUsingOperator()
+ {
+ var vector = CreateVector(_data);
+ var other = CreateVector(_data);
+ var result = vector - other;
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i], vector[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(_data[i], other[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(0.0, result[i]);
+ }
+ }
+
+ [Test]
+ public void CanSubtractVectorFromItself()
+ {
+ var vector = CreateVector(_data);
+ vector.Subtract(vector);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(0.0, vector[i]);
+ }
+ }
+
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractVectorFromItselfUsingResultVector()
+ {
+ var vector = CreateVector(_data);
+ var result = CreateVector(_data.Length);
+ vector.Subtract(vector, result);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i], vector[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(0.0, result[i]);
+ }
+ }
+
+ [Test]
+ [MultipleAsserts]
+ public void CanSubtractTwoVectorsUsingItselfAsResultVector()
+ {
+ var vector = CreateVector(_data);
+ var other = CreateVector(_data);
+ vector.Subtract(other, vector);
+
+ for (var i = 0; i < _data.Length; i++)
+ {
+ Assert.AreEqual(_data[i], other[i], "Making sure the original vector wasn't modified.");
+ Assert.AreEqual(0.0, vector[i]);
+ }
+ }
protected abstract Vector CreateVector(int size);