From 4871cfa5287b81833b50db2ac3dd7675a30cbde1 Mon Sep 17 00:00:00 2001 From: Matthias Reitinger Date: Sun, 2 Oct 2022 16:23:40 +0200 Subject: [PATCH] Add missing tests and documentation in Utilities --- .../Extensions/DictionaryExtensionsTests.cs | 37 +++++ .../Extensions/MatrixExtensionsTests.cs | 28 ++++ .../Extensions/RandomExtensionsTests.cs | 21 +++ .../Extensions/VectorExtensionsTests.cs | 137 ++++++++++++++++++ Utilities/Extensions/DictionaryExtensions.cs | 13 +- Utilities/Extensions/RandomExtensions.cs | 6 + 6 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 Utilities.Tests/Extensions/DictionaryExtensionsTests.cs create mode 100644 Utilities.Tests/Extensions/RandomExtensionsTests.cs create mode 100644 Utilities.Tests/Extensions/VectorExtensionsTests.cs diff --git a/Utilities.Tests/Extensions/DictionaryExtensionsTests.cs b/Utilities.Tests/Extensions/DictionaryExtensionsTests.cs new file mode 100644 index 000000000..7d34d509e --- /dev/null +++ b/Utilities.Tests/Extensions/DictionaryExtensionsTests.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using FluentAssertions; +using NUnit.Framework; +using Utilities.Extensions; + +namespace Utilities.Tests.Extensions +{ + public class DictionaryExtensionsTests + { + [Test] + public void AddMany_ShouldThrowArgumentException_WhenKeyAlreadyExists() + { + var dictionary = new Dictionary { ["one"] = 1 }; + var enumerable = new[] { ("one", 1), ("two", 2) }; + + var action = () => dictionary.AddMany(enumerable); + + action.Should().Throw(); + } + + [Test] + public void AddMany_ShouldAddAllKeyValuePairs() + { + var dictionary = new Dictionary { ["one"] = 1 }; + var enumerable = new[] { ("two", 2), ("three", 3) }; + + dictionary.AddMany(enumerable); + + dictionary.Should().HaveCount(3); + + dictionary.Should().ContainKey("one").WhichValue.Should().Be(1); + dictionary.Should().ContainKey("two").WhichValue.Should().Be(2); + dictionary.Should().ContainKey("three").WhichValue.Should().Be(3); + } + } +} diff --git a/Utilities.Tests/Extensions/MatrixExtensionsTests.cs b/Utilities.Tests/Extensions/MatrixExtensionsTests.cs index 4fff17b3b..952dc2576 100644 --- a/Utilities.Tests/Extensions/MatrixExtensionsTests.cs +++ b/Utilities.Tests/Extensions/MatrixExtensionsTests.cs @@ -179,5 +179,33 @@ public void Subtract_ShouldCalculateSubtractionResult( double[,] operand, double[,] result) => source.Subtract(operand).Should().BeEquivalentTo(result); + + [Test] + public void RoundToNextInt_ShouldReturnRoundedMatrix() + { + var source = new[,] + { + { -1.9, 1.9 }, + { -1.5, 1.5 }, + { -1.1, 1.1 }, + { -0.9, 0.9 }, + { -0.5, 0.5 }, + { -0.1, 0.1 }, + }; + + var result = new double[,] + { + { -2, 2 }, + { -2, 2 }, + { -1, 1 }, + { -1, 1 }, + { 0, 0 }, + { 0, 0 }, + }; + + var actualResult = source.RoundToNextInt(); + + actualResult.Should().BeEquivalentTo(result); + } } } diff --git a/Utilities.Tests/Extensions/RandomExtensionsTests.cs b/Utilities.Tests/Extensions/RandomExtensionsTests.cs new file mode 100644 index 000000000..c3c5abb0e --- /dev/null +++ b/Utilities.Tests/Extensions/RandomExtensionsTests.cs @@ -0,0 +1,21 @@ +using System; +using FluentAssertions; +using NUnit.Framework; +using Utilities.Extensions; + +namespace Utilities.Tests.Extensions +{ + public class RandomExtensionsTests + { + [Test] + public void NextVector_ShouldReturnNormalizedVector() + { + var random = new Random(0); + + var result = random.NextVector(10); + + result.Length.Should().Be(10); + result.Magnitude().Should().BeApproximately(1.0, 1e-6); + } + } +} diff --git a/Utilities.Tests/Extensions/VectorExtensionsTests.cs b/Utilities.Tests/Extensions/VectorExtensionsTests.cs new file mode 100644 index 000000000..3c24de8a8 --- /dev/null +++ b/Utilities.Tests/Extensions/VectorExtensionsTests.cs @@ -0,0 +1,137 @@ +using System; +using FluentAssertions; +using NUnit.Framework; +using Utilities.Extensions; + +namespace Utilities.Tests.Extensions +{ + public class VectorExtensionsTests + { + [Test] + public void Copy_ShouldReturnCopyOfVector() + { + var vector = new double[] { 0, 1, 2, 3 }; + + var vectorCopy = vector.Copy(); + + vectorCopy.Should().BeEquivalentTo(vector); + vectorCopy.Should().NotBeSameAs(vector); + } + + [Test] + public void OuterProduct_ShouldCalculateOuterProduct() + { + var lhs = new double[] { -2, -1, 0, 1, 2 }; + var rhs = new double[] { 1, 2, 3 }; + + var result = new double[,] + { + { -2, -4, -6 }, + { -1, -2, -3 }, + { 0, 0, 0 }, + { 1, 2, 3 }, + { 2, 4, 6 }, + }; + + var actualResult = lhs.OuterProduct(rhs); + + actualResult.Should().BeEquivalentTo(result); + } + + [Test] + public void Dot_ShouldThrowArgumentException_WhenDimensionsDoNotMatch() + { + var lhs = new double[] { 1, 2, 3 }; + var rhs = new double[] { 1, 2, 3, 4 }; + + var func = () => lhs.Dot(rhs); + + func.Should().Throw() + .WithMessage("Dot product arguments must have same dimension"); + } + + [Test] + public void Dot_ShouldCalculateDotProduct() + { + var lhs = new double[] { 1, 2, 3 }; + var rhs = new double[] { 4, 5, 6 }; + + var actualResult = lhs.Dot(rhs); + + actualResult.Should().Be(32); + } + + [Test] + public void Magnitude_ShouldCalculateMagnitude() + { + var vector = new double[] { -3, 4 }; + + var actualResult = vector.Magnitude(); + + actualResult.Should().BeApproximately(5.0, 0.0001); + } + + [Test] + public void Scale_ShouldCalculateScale() + { + var vector = new double[] { -1, 0, 1 }; + var factor = 2; + + var result = new double[] { -2, 0, 2 }; + + var actualResult = vector.Scale(factor); + + actualResult.Should().BeEquivalentTo(result); + } + + [Test] + public void ToColumnVector_ShouldReturnColumnVector() + { + var vector = new double[] { 1, 2, 3, 4 }; + var result = new double[,] { { 1 }, { 2 }, { 3 }, { 4 } }; + + var actualResult = vector.ToColumnVector(); + + actualResult.Should().BeEquivalentTo(result); + } + + [Test] + public void ToRowVector_ShouldThrowInvalidOperationException_WhenSourceIsNotAColumnVector() + { + var source = new double[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } }; + + var func = () => source.ToRowVector(); + + func.Should().Throw() + .WithMessage("The column vector should have only 1 element in width."); + } + + [Test] + public void ToRowVector_ShouldReturnRowVector() + { + var source = new double[,] { { 1 }, { 2 }, { 3 }, { 4 } }; + var result = new double[] { 1, 2, 3, 4 }; + + var actualResult = source.ToRowVector(); + + actualResult.Should().BeEquivalentTo(result); + } + + [Test] + public void ToDiagonalMatrix_ShouldReturnDiagonalMatrix() + { + var source = new double[] { 1, 2, 3, 4 }; + var result = new double[,] + { + { 1, 0, 0, 0 }, + { 0, 2, 0, 0 }, + { 0, 0, 3, 0 }, + { 0, 0, 0, 4 }, + }; + + var actualResult = source.ToDiagonalMatrix(); + + actualResult.Should().BeEquivalentTo(result); + } + } +} diff --git a/Utilities/Extensions/DictionaryExtensions.cs b/Utilities/Extensions/DictionaryExtensions.cs index 632796faf..714232a16 100644 --- a/Utilities/Extensions/DictionaryExtensions.cs +++ b/Utilities/Extensions/DictionaryExtensions.cs @@ -1,9 +1,20 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Utilities.Extensions { public static class DictionaryExtensions { + /// + /// Adds the specified key value tuples to the dictionary. + /// + /// The dictionary. + /// The collection of key value tuples to add. + /// The type of the keys in the dictionary. + /// The type of the values in the dictionary. + /// + /// A key from the already exists in . + /// public static void AddMany( this Dictionary keys, IEnumerable<(TKey, TValue)> enumerable) where TKey : notnull diff --git a/Utilities/Extensions/RandomExtensions.cs b/Utilities/Extensions/RandomExtensions.cs index df7507034..871389576 100644 --- a/Utilities/Extensions/RandomExtensions.cs +++ b/Utilities/Extensions/RandomExtensions.cs @@ -5,6 +5,12 @@ namespace Utilities.Extensions { public static class RandomExtensions { + /// + /// Returns a random normalized vector of the specified size. + /// + /// The random number generator. + /// The size of the vector to return. + /// A random normalized vector. public static double[] NextVector(this Random rand, int size) { var vector = Enumerable.Range(0, size)