Browse Source

Linear Algebra: Started implement DenseVector

Signed-off-by: Marcus Cuda <marcus@cuda.net>
pull/36/head
Marcus Cuda 17 years ago
parent
commit
4abb536ea0
  1. 5
      src/Numerics/Constants.cs
  2. 196
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  3. 2
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  4. 38
      src/Numerics/LinearAlgebra/Double/Vector.cs
  5. 4
      src/Numerics/Numerics.csproj
  6. 11
      src/Numerics/Properties/Resources.Designer.cs
  7. 3
      src/Numerics/Properties/Resources.resx
  8. 25
      src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs
  9. 194
      src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs
  10. 2
      src/UnitTests/UnitTests.csproj

5
src/Numerics/Constants.cs

@ -159,5 +159,10 @@ namespace MathNet.Numerics
/// <summary>The Khinchin constant</summary>
/// <remarks>prod(k=1 -> inf){1+1/(k*(k+2))^log(k,2)}</remarks>
public const double Khinchin = 2.6854520010653064453097148354817956938203822939944629530511523455572188595371520028011d;
/// <summary>
/// The size of a double in bytes.
/// </summary>
public const int SizeOfDouble = sizeof(double);
}
}

196
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -0,0 +1,196 @@
// <copyright file="DenseVector.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
// Copyright (c) 2009 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.
// </copyright>
namespace MathNet.Numerics.LinearAlgebra.Double
{
using System;
using Properties;
/// <summary>
/// A vector using dense storage.
/// </summary>
public class DenseVector : Vector
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class with a given size.
/// </summary>
/// <param name="size">
/// the size of the vector.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size)
: base(size)
{
Data = new double[size];
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class with a given size
/// and each element set to the given value;
/// </summary>
/// <param name="size">
/// the size of the vector.
/// </param>
/// <param name="value">
/// the value to set each element to.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size, double value)
: this(size)
{
for (var index = 0; index < Data.Length; index++)
{
Data[index] = value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The matrix to create the new matrix from.
/// </param>
public DenseVector(Vector other)
: this(other.Count)
{
var vector = other as DenseVector;
if (vector == null)
{
// using enumerators since they will be more efficient for copying sparse matrices
foreach (var item in other.GetIndexedEnumerator())
{
Data[item.Key] = item.Value;
}
}
else
{
Buffer.BlockCopy(vector.Data, 0, Data, 0, Data.Length * Constants.SizeOfDouble);
}
}
/// <summary>
/// Gets the vector's data.
/// </summary>
/// <value>The vector's data.</value>
internal double[] Data
{
get;
private set;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override double this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
/// </summary>
/// <param name="rows">
/// The number of rows.
/// </param>
/// <param name="columns">
/// The number of columns.
/// </param>
/// <returns>
/// A matrix with the given dimensions.
/// </returns>
public override Matrix CreateMatrix(int rows, int columns)
{
throw new NotImplementedException();
}
/// <summary>
/// Creates a <strong>Vector</strong> of the given size using the same storage type
/// as this vector.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to create.
/// </param>
/// <returns>
/// The new <c>Vector</c>.
/// </returns>
public override Vector CreateVector(int size)
{
return new DenseVector(size);
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException("target", Resources.ArgumentVectorsSameLengths);
}
var otherVector = target as DenseVector;
if (otherVector == null)
{
for (var index = 0; index < Data.Length; index++)
{
target[index] = Data[index];
}
}
else
{
Buffer.BlockCopy(Data, 0, otherVector.Data, 0, Data.Length * Constants.SizeOfDouble);
}
}
}
}

2
src/Numerics/LinearAlgebra/Double/Matrix.cs

@ -29,7 +29,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
using MathNet.Numerics.Properties;
/// <summary>
/// A matrix class.
/// Defines the base class for <c>Matrix</c> classes.
/// </summary>
[Serializable]
public abstract class Matrix : IFormattable, ICloneable, IEquatable<Matrix>

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

@ -198,10 +198,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public abstract Matrix CreateMatrix(int rows, int columns);
/// <summary>
/// Returns an <see cref="IEnumerator{T}"/> that contains the position and value of the element.
/// Creates a <strong>Vector</strong> of the given size using the same storage type
/// as this vector.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to create.
/// </param>
/// <returns>
/// The new <c>Vector</c>.
/// </returns>
public abstract Vector CreateVector(int size);
/// <summary>
/// Returns an <see cref="IEnumerable{T}"/> that contains the position and value of the element.
/// </summary>
/// <returns>
/// An <see cref="IEnumerator{T}"/> over this vector that contains the position and value of each
/// An <see cref="IEnumerable{T}"/> over this vector that contains the position and value of each
/// non-zero element.
/// </returns>
/// <remarks>
@ -222,7 +234,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
/// <summary>
/// Returns an <see cref="IEnumerator{T}"/> over the specified elements.
/// Returns an <see cref="IEnumerable{T}"/> over the specified elements.
/// </summary>
/// <param name="startIndex">
/// The element to start copying from.
@ -231,7 +243,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// The number of elements to enumerate over.
/// </param>
/// <returns>
/// An <see cref="IEnumerator{T}"/> over a range of this vector.
/// An <see cref="IEnumerable{T}"/> over a range of this vector.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// If <paramref name="startIndex"/> or <paramref name="startIndex"/> + <paramref name="length"/>
@ -244,10 +256,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// being the value of the element at that index.
/// </remarks>
/// <seealso cref="KeyValuePair{T,K}"/>
/// <seealso cref="IEnumerator{T}"/>
/// <seealso cref="IEnumerable{T}"/>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "Needed to support sparse vectors.")]
public virtual IEnumerator<KeyValuePair<int, double>> GetIndexEnumerator(int startIndex, int length)
public virtual IEnumerable<KeyValuePair<int, double>> GetIndexedEnumerator(int startIndex, int length)
{
if (startIndex > Count)
{
@ -317,7 +329,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
/// <remarks>
/// For sparse vectors, <see cref="GetIndexedEnumerator"/> will perform better.
/// For sparse vectors, <see cref="GetIndexedEnumerator()"/> will perform better.
/// </remarks>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
Justification = "Needed to support sparse vectors.")]
@ -407,17 +419,5 @@ namespace MathNet.Numerics.LinearAlgebra.Double
#endregion
#endregion
/// <summary>
/// Creates a <strong>Vector</strong> of the given size using the same storage type
/// as this vector.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to create.
/// </param>
/// <returns>
/// The new <c>Vector</c>.
/// </returns>
protected internal abstract Vector CreateVector(int size);
}
}

4
src/Numerics/Numerics.csproj

@ -82,6 +82,9 @@
<Compile Include="Interpolation\IInterpolation.cs" />
<Compile Include="Interpolation\Interpolate.cs" />
<Compile Include="Interpolation\SplineBoundaryCondition.cs" />
<Compile Include="LinearAlgebra\Double\DenseVector.cs" />
<Compile Include="LinearAlgebra\Double\Matrix.cs" />
<Compile Include="LinearAlgebra\Double\Vector.cs" />
<Compile Include="NumberTheory\IntegerTheory.cs" />
<Compile Include="NumberTheory\IntegerTheory.Euclid.cs" />
<Compile Include="Precision.cs" />
@ -117,6 +120,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Distributions\Multivariate\" />
<Folder Include="LinearAlgebra\Algorithms\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

11
src/Numerics/Properties/Resources.Designer.cs

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4918
// Runtime Version:2.0.50727.4927
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -222,6 +222,15 @@ namespace MathNet.Numerics.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Value must not be positive..
/// </summary>
internal static string ArgumentMustBePositive {
get {
return ResourceManager.GetString("ArgumentMustBePositive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must neither be infinite nor NaN..
/// </summary>

3
src/Numerics/Properties/Resources.resx

@ -258,4 +258,7 @@
<data name="ArgumentLessThanOne" xml:space="preserve">
<value>Value must be greater than or equal to one.</value>
</data>
<data name="ArgumentMustBePositive" xml:space="preserve">
<value>Value must not be positive.</value>
</data>
</root>

25
src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs

@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
using LinearAlgebra.Double;
public class DenseVectorTests : VectorTests
{
protected override MathNet.Numerics.LinearAlgebra.Double.Vector CreateVector(int size)
{
return new DenseVector(size);
}
protected override Vector CreateVector(IList<double> data)
{
var vector = new DenseVector(data.Count);
for(var index = 0; index < data.Count; index++)
{
vector[index] = data[index];
}
return vector;
}
}
}

194
src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs

@ -0,0 +1,194 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="VectorTests.cs" company="">
// </copyright>
// <summary>
// vector tests.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
using System;
using System.Collections.Generic;
using MathNet.Numerics.LinearAlgebra.Double;
using MbUnit.Framework;
/// <summary>
/// The vector tests.
/// </summary>
public abstract class VectorTests
{
/// <summary>
/// The test data.
/// </summary>
private readonly double[] _data = { 1, 2, 3, 4, 5 };
/// <summary>
/// can clone vector.
/// </summary>
[Test]
public void CanCloneVector()
{
var vector = CreateVector(_data);
var clone = vector.Clone();
Assert.AreEqual(vector.Count, clone.Count);
for (var index = 0; index < _data.Length; index++)
{
Assert.AreEqual(vector[index], clone[index]);
}
}
/// <summary>
/// can convert vector to string.
/// </summary>
[Test]
public void CanConvertVectorToString()
{
var vector = CreateVector(_data);
var str = vector.ToString();
Assert.AreEqual("1,2,3,4,5", str);
}
/// <summary>
/// can copy partial vector to another.
/// </summary>
[Test]
[MultipleAsserts]
public void CanCopyPartialVectorToAnother()
{
var vector = CreateVector(_data);
var other = CreateVector(_data.Length);
vector.CopyTo(other, 2, 2, 2);
Assert.AreEqual(0.0, other[0]);
Assert.AreEqual(0.0, other[1]);
Assert.AreEqual(3.0, other[2]);
Assert.AreEqual(4.0, other[3]);
Assert.AreEqual(0.0, other[4]);
}
/// <summary>
/// can copy vector to another.
/// </summary>
[Test]
[MultipleAsserts]
public void CanCopyVectorToAnother()
{
var vector = CreateVector(_data);
var other = CreateVector(_data.Length);
vector.CopyTo(other);
for (var index = 0; index < _data.Length; index++)
{
Assert.AreEqual(vector[index], other[index]);
}
}
/// <summary>
/// can create matrix.
/// </summary>
[Test]
[Ignore]
public void CanCreateMatrix()
{
}
/// <summary>
/// can create vector.
/// </summary>
[Test]
public void CanCreateVector()
{
var expected = CreateVector(5);
var actual = expected.CreateVector(5);
Assert.AreEqual(expected.GetType(), actual.GetType(), "vectors are same type.");
}
/// <summary>
/// can enumerate over vector.
/// </summary>
[Test]
[MultipleAsserts]
public void CanEnumerateOverVector()
{
var vector = CreateVector(_data);
var index = 0;
foreach (var element in vector)
{
Assert.AreEqual(index + 1, element);
index++;
}
}
/// <summary>
/// can equate vectors.
/// </summary>
[Test]
[MultipleAsserts]
public void CanEquateVectors()
{
var vector1 = CreateVector(_data);
var vector2 = CreateVector(_data);
var vector3 = CreateVector(4);
Assert.IsTrue(vector1.Equals(vector1));
Assert.IsTrue(vector1.Equals(vector2));
Assert.IsFalse(vector1.Equals(vector3));
Assert.IsFalse(vector1.Equals(null));
}
/// <summary>
/// can get indexed enumerator.
/// </summary>
[Test]
[MultipleAsserts]
public void CanGetIndexedEnumerator()
{
var vector = CreateVector(_data);
var index = 0;
foreach (var pair in vector.GetIndexedEnumerator())
{
Assert.AreEqual(index, pair.Key);
Assert.AreEqual(++index, pair.Value);
}
}
/// <summary>
/// can get indexed enumerator over range.
/// </summary>
[Test]
[MultipleAsserts]
public void CanGetIndexedEnumeratorOverRange()
{
var vector = CreateVector(_data);
var index = 2;
foreach (var pair in vector.GetIndexedEnumerator(2, 2))
{
Assert.AreEqual(index, pair.Key);
Assert.AreEqual(++index, pair.Value);
}
}
/// <summary>
/// throws argument exception if size is not positive.
/// </summary>
[Test]
public void ThrowsArgumentExceptionIfSizeIsNotPositive()
{
Assert.Throws<ArgumentException>(() => CreateVector(-1));
Assert.Throws<ArgumentException>(() => CreateVector(0));
}
protected abstract Vector CreateVector(int size);
protected abstract Vector CreateVector(IList<double> data);
}
}

2
src/UnitTests/UnitTests.csproj

@ -72,6 +72,8 @@
<Compile Include="IntegrationTests\IntegrationTest.cs" />
<Compile Include="InterpolationTests\InterpolationContract.cs" />
<Compile Include="InterpolationTests\InterpolationTest.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseVectorTests.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.cs" />
<Compile Include="NumberTheoryTests\GcdRelatedTest.cs" />
<Compile Include="NumberTheoryTests\IntegerTheoryTest.cs" />
<Compile Include="PrecisionTest.cs" />

Loading…
Cancel
Save