From 3c60340bde2c8980a197039e9183347f28790a53 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Wed, 20 Apr 2022 14:07:16 +0100 Subject: [PATCH] Add Product extension method Computes the element-wise product, optionally with a transformation delegate --- .../src/Core/EnumerableTests.Product.Byte.cs | 90 +++++++++++ .../Core/EnumerableTests.Product.Decimal.cs | 144 ++++++++++++++++++ .../Core/EnumerableTests.Product.Double.cs | 90 +++++++++++ .../src/Core/EnumerableTests.Product.Int16.cs | 90 +++++++++++ .../src/Core/EnumerableTests.Product.Int32.cs | 90 +++++++++++ .../src/Core/EnumerableTests.Product.Int64.cs | 90 +++++++++++ .../src/Core/EnumerableTests.Product.SByte.cs | 90 +++++++++++ .../Core/EnumerableTests.Product.Single.cs | 90 +++++++++++ .../Core/EnumerableTests.Product.UInt16.cs | 90 +++++++++++ .../Core/EnumerableTests.Product.UInt32.cs | 90 +++++++++++ .../Core/EnumerableTests.Product.UInt64.cs | 90 +++++++++++ X10D.Tests/src/Core/EnumerableTests.cs | 8 + .../EnumerableExtensions.Byte.cs | 51 +++++++ .../EnumerableExtensions.Decimal.cs | 27 ++++ .../EnumerableExtensions.Double.cs | 27 ++++ .../EnumerableExtensions.Int16.cs | 51 +++++++ .../EnumerableExtensions.Int32.cs | 52 +++++++ .../EnumerableExtensions.Int64.cs | 51 +++++++ .../EnumerableExtensions.Single.cs | 27 ++++ .../EnumerableExtensions.cs | 6 +- 20 files changed, 1341 insertions(+), 3 deletions(-) create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Byte.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Decimal.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Double.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Int16.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Int32.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Int64.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.SByte.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.Single.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.UInt16.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.UInt32.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.Product.UInt64.cs create mode 100644 X10D.Tests/src/Core/EnumerableTests.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Byte.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Decimal.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Double.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Int16.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Int32.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Int64.cs create mode 100644 X10D/src/EnumerableExtensions/EnumerableExtensions.Single.cs diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Byte.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Byte.cs new file mode 100644 index 0000000..3092751 --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Byte.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow((byte)0, (byte)1)] + [DataRow((byte)2, (byte)3, (byte)4)] + [DataRow((byte)1, (byte)2, (byte)3, (byte)4, (byte)5, (byte)6, (byte)7, (byte)8, (byte)9, (byte)10)] // 10! + public void ProductByte_Fixed(params byte[] source) + { + byte expected = 1; + foreach (byte item in source) + { + expected *= item; + } + + byte actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow((byte)0, (byte)1)] + [DataRow((byte)2, (byte)3, (byte)4)] + [DataRow((byte)1, (byte)2, (byte)3, (byte)4, (byte)5, (byte)6, (byte)7, (byte)8, (byte)9, (byte)10)] // 10! + public void ProductByte_Transformed_Fixed(params byte[] source) + { + byte expected = 1; + foreach (byte item in source) + { + expected *= (byte)(item * 2); + } + + byte actual = source.Product(n => (byte)(n * 2)); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductByte_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new byte[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (byte)random.Next(1, 100); + } + + byte expected = 1; + foreach (byte item in source) + { + expected *= item; + } + + byte actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductByte_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new byte[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (byte)random.Next(1, 100); + } + + byte expected = 1; + foreach (byte item in source) + { + expected *= (byte)(item * 2); + } + + byte actual = source.Product(n => (byte)(n * 2)); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Decimal.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Decimal.cs new file mode 100644 index 0000000..1e46673 --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Decimal.cs @@ -0,0 +1,144 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + // the Fixed methods in these tests can't use DataRow attribute because the use of a decimal literal compiles to an + // instantiation of the decimal struct, which is not a compile-time constant expression. + // thanks. I fucking hate it. + + [TestMethod] + public void ProductDecimal_Fixed() + { + { + var source = new[] {0m, 1m}; + var expected = 1m; + foreach (decimal item in source) + { + expected *= item; + } + + decimal actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + { + + var source = new[] {2m, 3m, 4m}; + var expected = 1m; + foreach (decimal item in source) + { + expected *= item; + } + + decimal actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + { + + var source = new[] {1m, 2m, 3m, 4m, 5m, 6m, 7m, 8m, 9m, 10m}; + var expected = 1m; + foreach (decimal item in source) + { + expected *= item; + } + + decimal actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductDecimal_Transformed_Fixed() + { + { + var source = new[] {0m, 1m}; + var expected = 1m; + foreach (decimal item in source) + { + expected *= item * 2; + } + + decimal actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + { + var source = new[] {2m, 3m, 4m}; + var expected = 1m; + foreach (decimal item in source) + { + expected *= item * 2; + } + + decimal actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + { + var source = new[] {1m, 2m, 3m, 4m, 5m, 6m, 7m, 8m, 9m, 10m}; + var expected = 1m; + foreach (decimal item in source) + { + expected *= item * 2; + } + + decimal actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductDecimal_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new decimal[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (decimal)random.NextDouble(); + } + + var expected = 1m; + foreach (decimal item in source) + { + expected *= item; + } + + decimal actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductDecimal_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new decimal[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (decimal)random.NextDouble(); + } + + var expected = 1m; + foreach (decimal item in source) + { + expected *= item * 2; + } + + decimal actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Double.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Double.cs new file mode 100644 index 0000000..3e1653b --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Double.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow(0.0, 1.0)] + [DataRow(2.0, 3.0, 4.0)] + [DataRow(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)] // 10! + public void ProductDouble_Fixed(params double[] source) + { + var expected = 1.0; + foreach (double item in source) + { + expected *= item; + } + + double actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow(0.0, 1.0)] + [DataRow(2.0, 3.0, 4.0)] + [DataRow(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)] // 10! + public void ProductDouble_Transformed_Fixed(params double[] source) + { + var expected = 1.0; + foreach (double item in source) + { + expected *= item * 2; + } + + double actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductDouble_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new double[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = random.NextDouble(); + } + + var expected = 1.0; + foreach (double item in source) + { + expected *= item; + } + + double actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductDouble_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new double[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = random.NextDouble(); + } + + var expected = 1.0; + foreach (double item in source) + { + expected *= item * 2; + } + + double actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Int16.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Int16.cs new file mode 100644 index 0000000..ac6c2a3 --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Int16.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow((short)0, (short)1)] + [DataRow((short)2, (short)3, (short)4)] + [DataRow((short)1, (short)2, (short)3, (short)4, (short)5, (short)6, (short)7, (short)8, (short)9, (short)10)] // 10! + public void ProductInt16_Fixed(params short[] source) + { + short expected = 1; + foreach (short item in source) + { + expected *= item; + } + + short actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow((short)0, (short)1)] + [DataRow((short)2, (short)3, (short)4)] + [DataRow((short)1, (short)2, (short)3, (short)4, (short)5, (short)6, (short)7, (short)8, (short)9, (short)10)] // 10! + public void ProductInt16_Transformed_Fixed(params short[] source) + { + short expected = 1; + foreach (short item in source) + { + expected *= (short)(item * 2); + } + + short actual = source.Product(n => (short)(n * 2)); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductInt16_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new short[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (short)random.Next(1, 100); + } + + short expected = 1; + foreach (short item in source) + { + expected *= item; + } + + short actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductInt16_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new short[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (short)random.Next(1, 100); + } + + short expected = 1; + foreach (short item in source) + { + expected *= (short)(item * 2); + } + + short actual = source.Product(n => (short)(n * 2)); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Int32.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Int32.cs new file mode 100644 index 0000000..d5327a5 --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Int32.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow(0, 1)] + [DataRow(2, 3, 4)] + [DataRow(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] // 10! + public void ProductInt32_Fixed(params int[] source) + { + var expected = 1; + foreach (int item in source) + { + expected *= item; + } + + int actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow(0, 1)] + [DataRow(2, 3, 4)] + [DataRow(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)] // 10! + public void ProductInt32_Transformed_Fixed(params int[] source) + { + var expected = 1; + foreach (int item in source) + { + expected *= item * 2; + } + + int actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductInt32_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new int[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = random.Next(1, 100); + } + + var expected = 1; + foreach (int item in source) + { + expected *= item; + } + + int actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductInt32_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new int[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = random.Next(1, 100); + } + + var expected = 1; + foreach (int item in source) + { + expected *= item * 2; + } + + int actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Int64.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Int64.cs new file mode 100644 index 0000000..b6fd43e --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Int64.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow(0L, 1L)] + [DataRow(2L, 3L, 4L)] + [DataRow(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L)] // 10! + public void ProductInt64_Fixed(params long[] source) + { + var expected = 1L; + foreach (long item in source) + { + expected *= item; + } + + long actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow(0L, 1L)] + [DataRow(2L, 3L, 4L)] + [DataRow(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L)] // 10! + public void ProductInt64_Transformed_Fixed(params long[] source) + { + var expected = 1L; + foreach (long item in source) + { + expected *= item * 2; + } + + long actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductInt64_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new long[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = random.NextInt64(1, 100); + } + + var expected = 1L; + foreach (long item in source) + { + expected *= item; + } + + long actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductInt64_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new long[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = random.NextInt64(1, 100); + } + + var expected = 1L; + foreach (long item in source) + { + expected *= item * 2; + } + + long actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.SByte.cs b/X10D.Tests/src/Core/EnumerableTests.Product.SByte.cs new file mode 100644 index 0000000..513cdca --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.SByte.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow((sbyte)0, (sbyte)1)] + [DataRow((sbyte)2, (sbyte)3, (sbyte)4)] + [DataRow((sbyte)1, (sbyte)2, (sbyte)3, (sbyte)4, (sbyte)5, (sbyte)6, (sbyte)7, (sbyte)8, (sbyte)9, (sbyte)10)] // 10! + public void ProductSByte_Fixed(params sbyte[] source) + { + sbyte expected = 1; + foreach (sbyte item in source) + { + expected *= item; + } + + sbyte actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow((sbyte)0, (sbyte)1)] + [DataRow((sbyte)2, (sbyte)3, (sbyte)4)] + [DataRow((sbyte)1, (sbyte)2, (sbyte)3, (sbyte)4, (sbyte)5, (sbyte)6, (sbyte)7, (sbyte)8, (sbyte)9, (sbyte)10)] // 10! + public void ProductSByte_Transformed_Fixed(params sbyte[] source) + { + sbyte expected = 1; + foreach (sbyte item in source) + { + expected *= (sbyte)(item * 2); + } + + sbyte actual = source.Product(n => (sbyte)(n * 2)); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductSByte_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new sbyte[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (sbyte)random.Next(1, 100); + } + + sbyte expected = 1; + foreach (sbyte item in source) + { + expected *= item; + } + + sbyte actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductSByte_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new sbyte[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (sbyte)random.Next(1, 100); + } + + sbyte expected = 1; + foreach (sbyte item in source) + { + expected *= (sbyte)(item * 2); + } + + sbyte actual = source.Product(n => (sbyte)(n * 2)); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.Single.cs b/X10D.Tests/src/Core/EnumerableTests.Product.Single.cs new file mode 100644 index 0000000..fb8adaf --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.Single.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow(0f, 1f)] + [DataRow(2f, 3f, 4f)] + [DataRow(1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f, 10f)] // 10! + public void ProductSingle_Fixed(params float[] source) + { + var expected = 1f; + foreach (float item in source) + { + expected *= item; + } + + float actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow(0f, 1f)] + [DataRow(2f, 3f, 4f)] + [DataRow(1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f, 10f)] // 10! + public void ProductSingle_Transformed_Fixed(params float[] source) + { + var expected = 1f; + foreach (float item in source) + { + expected *= item * 2; + } + + float actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductSingle_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new float[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (float)random.NextDouble(); + } + + var expected = 1f; + foreach (float item in source) + { + expected *= item; + } + + float actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductSingle_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new float[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (float)random.NextDouble(); + } + + var expected = 1f; + foreach (float item in source) + { + expected *= item * 2; + } + + float actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.UInt16.cs b/X10D.Tests/src/Core/EnumerableTests.Product.UInt16.cs new file mode 100644 index 0000000..46d9895 --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.UInt16.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow((ushort)0, (ushort)1)] + [DataRow((ushort)2, (ushort)3, (ushort)4)] + [DataRow((ushort)1, (ushort)2, (ushort)3, (ushort)4, (ushort)5, (ushort)6, (ushort)7, (ushort)8, (ushort)9, (ushort)10)] // 10! + public void ProductUInt16_Fixed(params ushort[] source) + { + ushort expected = 1; + foreach (ushort item in source) + { + expected *= item; + } + + ushort actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow((ushort)0, (ushort)1)] + [DataRow((ushort)2, (ushort)3, (ushort)4)] + [DataRow((ushort)1, (ushort)2, (ushort)3, (ushort)4, (ushort)5, (ushort)6, (ushort)7, (ushort)8, (ushort)9, (ushort)10)] // 10! + public void ProductUInt16_Transformed_Fixed(params ushort[] source) + { + ushort expected = 1; + foreach (ushort item in source) + { + expected *= (ushort)(item * 2); + } + + ushort actual = source.Product(n => (ushort)(n * 2)); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductUInt16_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new ushort[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (ushort)random.Next(1, 100); + } + + ushort expected = 1; + foreach (ushort item in source) + { + expected *= item; + } + + ushort actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductUInt16_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new ushort[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (ushort)random.Next(1, 100); + } + + ushort expected = 1; + foreach (ushort item in source) + { + expected *= (ushort)(item * 2); + } + + ushort actual = source.Product(n => (ushort)(n * 2)); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.UInt32.cs b/X10D.Tests/src/Core/EnumerableTests.Product.UInt32.cs new file mode 100644 index 0000000..d17355e --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.UInt32.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow(0u, 1u)] + [DataRow(2u, 3u, 4u)] + [DataRow(1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u)] // 10! + public void ProductUInt32_Fixed(params uint[] source) + { + var expected = 1u; + foreach (uint item in source) + { + expected *= item; + } + + uint actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow(0u, 1u)] + [DataRow(2u, 3u, 4u)] + [DataRow(1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u)] // 10! + public void ProductUInt32_Transformed_Fixed(params uint[] source) + { + var expected = 1u; + foreach (uint item in source) + { + expected *= item * 2; + } + + uint actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductUInt32_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new uint[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (uint) random.Next(1, 100); + } + + var expected = 1u; + foreach (uint item in source) + { + expected *= item; + } + + uint actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductUInt32_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new uint[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (uint) random.Next(1, 100); + } + + var expected = 1u; + foreach (uint item in source) + { + expected *= item * 2; + } + + uint actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.Product.UInt64.cs b/X10D.Tests/src/Core/EnumerableTests.Product.UInt64.cs new file mode 100644 index 0000000..99cf5bb --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.Product.UInt64.cs @@ -0,0 +1,90 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +public partial class EnumerableTests +{ + [TestMethod] + [DataRow(0UL, 1UL)] + [DataRow(2UL, 3UL, 4UL)] + [DataRow(1UL, 2UL, 3UL, 4UL, 5UL, 6UL, 7UL, 8UL, 9UL, 10UL)] // 10! + public void ProductUInt64_Fixed(params ulong[] source) + { + var expected = 1UL; + foreach (ulong item in source) + { + expected *= item; + } + + ulong actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [DataRow(0UL, 1UL)] + [DataRow(2UL, 3UL, 4UL)] + [DataRow(1UL, 2UL, 3UL, 4UL, 5UL, 6UL, 7UL, 8UL, 9UL, 10UL)] // 10! + public void ProductUInt64_Transformed_Fixed(params ulong[] source) + { + var expected = 1UL; + foreach (ulong item in source) + { + expected *= item * 2; + } + + ulong actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ProductUInt64_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new ulong[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (ulong) random.NextInt64(1, 100); + } + + var expected = 1UL; + foreach (ulong item in source) + { + expected *= item; + } + + ulong actual = source.Product(); + + Assert.AreEqual(expected, actual); + } + } + + [TestMethod] + public void ProductUInt64_Transformed_Random1000() + { + var random = new Random(); + + for (var i = 0; i < 1000; i++) + { + var source = new ulong[10]; + for (var j = 0; j < source.Length; j++) + { + source[j] = (ulong) random.NextInt64(1, 100); + } + + var expected = 1UL; + foreach (ulong item in source) + { + expected *= item * 2; + } + + ulong actual = source.Product(n => n * 2); + + Assert.AreEqual(expected, actual); + } + } +} diff --git a/X10D.Tests/src/Core/EnumerableTests.cs b/X10D.Tests/src/Core/EnumerableTests.cs new file mode 100644 index 0000000..97ae244 --- /dev/null +++ b/X10D.Tests/src/Core/EnumerableTests.cs @@ -0,0 +1,8 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace X10D.Tests.Core; + +[TestClass] +public partial class EnumerableTests +{ +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Byte.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Byte.cs new file mode 100644 index 0000000..912b0ac --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Byte.cs @@ -0,0 +1,51 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static byte Product(this IEnumerable source) + { + return source.Aggregate((byte)1, (current, value) => (byte) (current * value)); + } + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + [CLSCompliant(false)] + public static sbyte Product(this IEnumerable source) + { + return source.Aggregate((sbyte)1, (current, value) => (sbyte) (current * value)); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static byte Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + [CLSCompliant(false)] + public static sbyte Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Decimal.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Decimal.cs new file mode 100644 index 0000000..d3603ca --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Decimal.cs @@ -0,0 +1,27 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static decimal Product(this IEnumerable source) + { + return source.Aggregate(1m, (current, value) => (current * value)); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static decimal Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Double.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Double.cs new file mode 100644 index 0000000..d2e3079 --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Double.cs @@ -0,0 +1,27 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static double Product(this IEnumerable source) + { + return source.Aggregate(1.0, (current, value) => (current * value)); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static double Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Int16.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Int16.cs new file mode 100644 index 0000000..e6c5574 --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Int16.cs @@ -0,0 +1,51 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static short Product(this IEnumerable source) + { + return source.Aggregate((short)1, (current, value) => (short) (current * value)); + } + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + [CLSCompliant(false)] + public static ushort Product(this IEnumerable source) + { + return source.Aggregate((ushort)1, (current, value) => (ushort) (current * value)); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static short Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + [CLSCompliant(false)] + public static ushort Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Int32.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Int32.cs new file mode 100644 index 0000000..e54feee --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Int32.cs @@ -0,0 +1,52 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static int Product(this IEnumerable source) + { + return source.Aggregate(1, (current, value) => current * value); + } + + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + [CLSCompliant(false)] + public static uint Product(this IEnumerable source) + { + return source.Aggregate(1u, (current, value) => current * value); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static int Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + [CLSCompliant(false)] + public static uint Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Int64.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Int64.cs new file mode 100644 index 0000000..d51e9eb --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Int64.cs @@ -0,0 +1,51 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static long Product(this IEnumerable source) + { + return source.Aggregate(1L, (current, value) => current * value); + } + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + [CLSCompliant(false)] + public static ulong Product(this IEnumerable source) + { + return source.Aggregate(1UL, (current, value) => current * value); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static long Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + [CLSCompliant(false)] + public static ulong Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.Single.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.Single.cs new file mode 100644 index 0000000..d653823 --- /dev/null +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.Single.cs @@ -0,0 +1,27 @@ +namespace X10D; + +public static partial class EnumerableExtensions +{ + /// + /// Computes the product of a sequence of values. + /// + /// A sequence of values that are used to calculate the product. + /// The product the values in the sequence. + public static float Product(this IEnumerable source) + { + return source.Aggregate(1f, (current, value) => (current * value)); + } + + /// + /// Computes the product of a sequence of values that are obtained by invoking a transform function + /// on each element of the input sequence. + /// + /// A sequence of values that are used to calculate a product. + /// A transform function to apply to each element. + /// The type of the elements of . + /// The product of the projected values. + public static float Product(this IEnumerable source, Func selector) + { + return source.Select(selector).Product(); + } +} diff --git a/X10D/src/EnumerableExtensions/EnumerableExtensions.cs b/X10D/src/EnumerableExtensions/EnumerableExtensions.cs index 4e30505..65d5072 100644 --- a/X10D/src/EnumerableExtensions/EnumerableExtensions.cs +++ b/X10D/src/EnumerableExtensions/EnumerableExtensions.cs @@ -3,7 +3,7 @@ /// /// Extension methods for . /// -public static class EnumerableExtensions +public static partial class EnumerableExtensions { /// /// Reorganizes the elements in an enumerable by implementing a Fisher-Yates shuffle, and returns th shuffled result. @@ -36,11 +36,11 @@ public static class EnumerableExtensions } var buffer = new List(chunkSize); - + foreach (var item in source) { buffer.Add(item); - + if (buffer.Count >= chunkSize) { yield return buffer;