//
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 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.
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Complex;
using NUnit.Framework;
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
{
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
///
/// Abstract class with the common set of vector tests.
///
public abstract partial class VectorTests
{
///
/// Test vector values.
///
protected readonly Complex[] Data = { new Complex(1, 1), new Complex(2, 1), new Complex(3, 1), new Complex(4, 1), new Complex(5, 1) };
///
/// Can clone a vector.
///
[Test]
public void CanCloneVector()
{
var vector = CreateVector(Data);
var clone = vector.Clone();
Assert.AreNotSame(vector, clone);
Assert.AreEqual(vector.Count, clone.Count);
CollectionAssert.AreEqual(vector, clone);
}
#if !PORTABLE
///
/// Can clone a vector using IClonable interface method.
///
[Test]
public void CanCloneVectorUsingICloneable()
{
var vector = CreateVector(Data);
var clone = (Vector)((ICloneable)vector).Clone();
Assert.AreNotSame(vector, clone);
Assert.AreEqual(vector.Count, clone.Count);
CollectionAssert.AreEqual(vector, clone);
}
#endif
///
/// Can copy part of a vector to another vector.
///
[Test]
public void CanCopyPartialVectorToAnother()
{
var vector = CreateVector(Data);
var other = CreateVector(Data.Length);
vector.CopySubVectorTo(other, 2, 2, 2);
AssertHelpers.AlmostEqual(Complex.Zero, other[0]);
AssertHelpers.AlmostEqual(Complex.Zero, other[1]);
AssertHelpers.AlmostEqual(new Complex(3, 1), other[2]);
AssertHelpers.AlmostEqual(new Complex(4, 1), other[3]);
AssertHelpers.AlmostEqual(Complex.Zero, other[4]);
}
///
/// Can copy part of a vector to the same vector.
///
[Test]
public void CanCopyPartialVectorToSelf()
{
var vector = CreateVector(Data);
vector.CopySubVectorTo(vector, 0, 2, 2);
AssertHelpers.AlmostEqual(new Complex(1, 1), vector[0]);
AssertHelpers.AlmostEqual(new Complex(2, 1), vector[1]);
AssertHelpers.AlmostEqual(new Complex(1, 1), vector[2]);
AssertHelpers.AlmostEqual(new Complex(2, 1), vector[3]);
AssertHelpers.AlmostEqual(new Complex(5, 1), vector[4]);
}
///
/// Can copy a vector to another vector.
///
[Test]
public void CanCopyVectorToAnother()
{
var vector = CreateVector(Data);
var other = CreateVector(Data.Length);
vector.CopyTo(other);
CollectionAssert.AreEqual(vector, other);
}
///
/// Can create a matrix using instance of a vector.
///
[Test]
public void CanCreateMatrix()
{
var vector = CreateVector(Data);
var matrix = Matrix.Build.SameAs(vector, 10, 10);
Assert.AreEqual(matrix.RowCount, 10);
Assert.AreEqual(matrix.ColumnCount, 10);
}
///
/// Can create a vector using the instance of vector.
///
[Test]
public void CanCreateVector()
{
var expected = CreateVector(5);
var actual = Vector.Build.SameAs(expected, 5);
Assert.AreEqual(expected.Storage.IsDense, actual.Storage.IsDense, "vectors are same kind.");
}
///
/// Can enumerate over a vector.
///
[Test]
public void CanEnumerateOverVector()
{
var vector = CreateVector(Data);
for (var i = 0; i < Data.Length; i++)
{
Assert.AreEqual(Data[i], vector[i]);
}
}
///
/// Can enumerate over a vector using IEnumerable interface.
///
[Test]
public void CanEnumerateOverVectorUsingIEnumerable()
{
var enumerable = (IEnumerable)CreateVector(Data);
var index = 0;
foreach (var element in enumerable)
{
Assert.AreEqual(Data[index++], (Complex)element);
}
}
///
/// Can equate vectors.
///
[Test]
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));
Assert.IsFalse(vector1.Equals(2));
}
///
/// CreateVector throws ArgumentOutOfRangeException if size is not positive.
///
[Test]
public void SizeIsNotPositiveThrowsArgumentOutOfRangeException()
{
Assert.That(() => CreateVector(-1), Throws.TypeOf());
Assert.That(() => CreateVector(0), Throws.TypeOf());
}
///
/// Can equate vectors using Object.Equals.
///
[Test]
public void CanEquateVectorsUsingObjectEquals()
{
var vector1 = CreateVector(Data);
var vector2 = CreateVector(Data);
Assert.IsTrue(vector1.Equals((object)vector2));
}
///
/// Can get hash code of a vector.
///
[Test]
public void CanGetHashCode()
{
var vector = CreateVector(new[] { new Complex(1, 1), new Complex(2, 1), new Complex(3, 1), new Complex(4, 1), new Complex(5, 1) });
Assert.AreEqual(vector.GetHashCode(), vector.GetHashCode());
Assert.AreEqual(vector.GetHashCode(), CreateVector(new[] { new Complex(1, 1), new Complex(2, 1), new Complex(3, 1), new Complex(4, 1), new Complex(5, 1) }).GetHashCode());
Assert.AreNotEqual(vector.GetHashCode(), CreateVector(new[] { new Complex(1, 1) }).GetHashCode());
}
///
/// Can enumerate over a vector using indexed enumerator.
///
[Test]
public void CanEnumerateOverVectorUsingIndexedEnumerator()
{
var vector = CreateVector(Data);
foreach (var pair in vector.EnumerateIndexed())
{
Assert.AreEqual(Data[pair.Item1], pair.Item2);
}
}
///
/// Can enumerate over a vector using non-zero enumerator.
///
[Test]
public void CanEnumerateOverVectorUsingNonZeroEnumerator()
{
var vector = CreateVector(Data);
foreach (var pair in vector.EnumerateIndexed(Zeros.AllowSkip))
{
Assert.AreEqual(Data[pair.Item1], pair.Item2);
Assert.AreNotEqual(Complex.Zero, pair.Item2);
}
}
///
/// Can convert a vector to array.
///
[Test]
public void CanConvertVectorToArray()
{
var vector = CreateVector(Data);
var array = vector.ToArray();
CollectionAssert.AreEqual(array, vector);
}
///
/// Can convert a vector to column matrix.
///
[Test]
public void CanConvertVectorToColumnMatrix()
{
var vector = CreateVector(Data);
var matrix = vector.ToColumnMatrix();
Assert.AreEqual(vector.Count, matrix.RowCount);
Assert.AreEqual(1, matrix.ColumnCount);
for (var i = 0; i < vector.Count; i++)
{
Assert.AreEqual(vector[i], matrix[i, 0]);
}
}
///
/// Can convert a vector to row matrix.
///
[Test]
public void CanConvertVectorToRowMatrix()
{
var vector = CreateVector(Data);
var matrix = vector.ToRowMatrix();
Assert.AreEqual(vector.Count, matrix.ColumnCount);
Assert.AreEqual(1, matrix.RowCount);
for (var i = 0; i < vector.Count; i++)
{
Assert.AreEqual(vector[i], matrix[0, i]);
}
}
///
/// Can set values in vector.
///
[Test]
public void CanSetValues()
{
var vector = CreateVector(Data);
vector.SetValues(Data);
CollectionAssert.AreEqual(vector, Data);
}
///
/// Can get subvector from a vector.
///
/// The first element to begin copying from.
/// The number of elements to copy.
[TestCase(0, 5)]
[TestCase(2, 2)]
[TestCase(1, 4)]
public void CanGetSubVector(int index, int length)
{
var vector = CreateVector(Data);
var sub = vector.SubVector(index, length);
Assert.AreEqual(length, sub.Count);
for (var i = 0; i < length; i++)
{
Assert.AreEqual(vector[i + index], sub[i]);
}
}
///
/// Getting subvector using wrong parameters throw an exception.
///
/// The first element to begin copying from.
/// The number of elements to copy.
[TestCase(6, 10)]
[TestCase(1, -10)]
public void CanGetSubVectorWithWrongValuesShouldThrowException(int index, int length)
{
var vector = CreateVector(Data);
Assert.That(() => vector.SubVector(index, length), Throws.TypeOf());
}
///
/// Can find absolute minimum value index.
///
[Test]
public void CanFindAbsoluteMinimumIndex()
{
var source = CreateVector(Data);
const int Expected = 0;
var actual = source.AbsoluteMinimumIndex();
Assert.AreEqual(Expected, actual);
}
///
/// Can find absolute minimum value of a vector.
///
[Test]
public void CanFindAbsoluteMinimum()
{
var source = CreateVector(Data);
var expected = new Complex(1, 1).Magnitude;
var actual = source.AbsoluteMinimum();
Assert.AreEqual(expected, actual.Real);
}
///
/// Can find absolute maximum value index.
///
[Test]
public void CanFindAbsoluteMaximumIndex()
{
var source = CreateVector(Data);
const int Expected = 4;
var actual = source.AbsoluteMaximumIndex();
Assert.AreEqual(Expected, actual);
}
///
/// Can find absolute maximum value of a vector.
///
[Test]
public void CanFindAbsoluteMaximum()
{
var source = CreateVector(Data);
var expected = new Complex(5, 1).Magnitude;
var actual = source.AbsoluteMaximum();
Assert.AreEqual(expected, actual.Real);
}
///
/// Find maximum value index throws NotSupportedException.
///
[Test]
public void FindMaximumIndexThrowsNotSupportedException()
{
var vector = CreateVector(Data);
Assert.That(() => { var actual = vector.MaximumIndex(); }, Throws.TypeOf());
}
///
/// Find maximum value throws NotSupportedException.
///
[Test]
public void FindMaximumThrowsNotSupportedException()
{
var vector = CreateVector(Data);
Assert.That(() => { var actual = vector.Maximum(); }, Throws.TypeOf());
}
///
/// Find minimum value index throws NotSupportedException.
///
[Test]
public void FindMinimumIndexThrowsNotSupportedException()
{
var vector = CreateVector(Data);
Assert.That(() => { var actual = vector.MinimumIndex(); }, Throws.TypeOf());
}
///
/// Find minimum value throws NotSupportedException.
///
[Test]
public void FindMinimumThrowsNotSupportedException()
{
var vector = CreateVector(Data);
Assert.That(() => { var actual = vector.Minimum(); }, Throws.TypeOf());
}
///
/// Can compute the sum of a vector elements.
///
[Test]
public void CanSum()
{
Complex[] testData = { new Complex(-20, -1), new Complex(-10, -1), new Complex(10, 1), new Complex(20, 1), new Complex(30, 1) };
var vector = CreateVector(testData);
var actual = vector.Sum();
var expected = new Complex(30, 1);
Assert.AreEqual(expected, actual);
}
///
/// Can compute the sum of the absolute value a vector elements.
///
[Test]
public void CanSumMagnitudes()
{
Complex[] testData = { new Complex(-20, -1), new Complex(-10, -1), new Complex(10, 1), new Complex(20, 1), new Complex(30, 1) };
var vector = CreateVector(testData);
var actual = vector.SumMagnitudes();
var expected = testData.Sum(complex => complex.Magnitude);
Assert.AreEqual(expected, actual);
}
///
/// Set values with null parameter throw exception.
///
[Test]
public void SetValuesWithNullParameterThrowsArgumentException()
{
var vector = CreateVector(Data);
Assert.That(() => vector.SetValues(null), Throws.TypeOf());
}
///
/// Set values with non-equal data length throw exception.
///
[Test]
public void SetValuesWithNonEqualDataLengthThrowsArgumentException()
{
var vector = CreateVector(Data.Length + 2);
Assert.That(() => vector.SetValues(Data), Throws.TypeOf());
}
///
/// Generate a vector with number of elements less than zero throw an exception.
///
[Test]
public void RandomWithNumberOfElementsLessThanZeroThrowsArgumentException()
{
Assert.That(() => DenseVector.CreateRandom(-2, new ContinuousUniform()), Throws.TypeOf());
}
///
/// Can clear a vector.
///
[Test]
public void CanClearVector()
{
Complex[] testData = { new Complex(-20, -1), new Complex(-10, -1), new Complex(10, 1), new Complex(20, 1), new Complex(30, 1) };
var vector = CreateVector(testData);
vector.Clear();
foreach (var element in vector)
{
Assert.AreEqual(Complex.Zero, element);
}
}
///
/// Creates a new instance of the Vector class.
///
/// The size of the Vector to construct.
/// The new Vector.
protected abstract Vector CreateVector(int size);
///
/// Creates a new instance of the Vector class.
///
/// The array to create this vector from.
/// The new Vector.
protected abstract Vector CreateVector(IList data);
}
}