Skip to content

Commit

Permalink
Improve performance of Sum()
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmada committed Jun 28, 2021
1 parent e3c97cf commit 185ede8
Show file tree
Hide file tree
Showing 72 changed files with 2,048 additions and 266 deletions.
49 changes: 45 additions & 4 deletions NetFabric.Hyperlinq.UnitTests/Aggregation/Sum.TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ namespace NetFabric.Hyperlinq
{
public static partial class TestData
{
public static TheoryData<double[]> Sum
public static TheoryData<double[]> SumDouble
=> new()
{
new double[] { },
new[] { double.NaN },
new[] { double.PositiveInfinity },
new[] { 1.0 },
new[] { 1.0, 2.0 },
new[] { 1.0, 2.0, 3.0 },
new[] { 1.0, 2.0, 3.0, 4.0 },
new[] { 1.0, 2.0, 3.0, 4.0, 5.0 },
new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 },
new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 },
new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 },
new[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 },
Expand All @@ -24,22 +29,58 @@ public static TheoryData<double[]> Sum
new[] { double.PositiveInfinity, double.PositiveInfinity }
};

public static TheoryData<double?[]> NullableSum
public static TheoryData<double?[]> SumNullableDouble
=> new()
{
new double?[] { },
new double?[] { default },
new double?[] { double.NaN },
new double?[] { double.PositiveInfinity },
new double?[] { 1 },
new double?[] { 1.0 },
new double?[] { 1.0, 2.0 },
new double?[] { 1.0, 2.0, 3.0 },
new double?[] { 1.0, 2.0, 3.0, 4.0 },
new double?[] { 1.0, 2.0, 3.0, 4.0, 5.0 },
new double?[] { default, default, default },
new double?[] { default, 2.0, double.NaN, 4.0, default },
new double?[] { default, 2.0, 3.0, 4.0, default },
new double?[] { 1.0, 2.0, default, 4.0, 5.0 },
new double?[] { 1.0, 2.0, 3.0, 4.0, 5.0 },
new double?[] { double.MaxValue, double.MaxValue },
new double?[] { double.PositiveInfinity, double.PositiveInfinity }
};

public static TheoryData<decimal[]> SumDecimal
=> new()
{
new decimal[] { },
new[] { 1.0M },
new[] { 1.0M, 2.0M },
new[] { 1.0M, 2.0M, 3.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M, 8.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M, 8.0M, 9.0M },
new[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M, 6.0M, 7.0M, 8.0M, 9.0M, 10.0M, 11.0M, 12.0M, 13.0M, 14.0M, 15.0M, 16.0M, 17.0M, 18.0M, 19.0M, 20.0M },
//new[] { decimal.MaxValue, decimal.MaxValue },
};


public static TheoryData<decimal?[]> SumNullableDecimal
=> new()
{
new decimal?[] { },
new decimal?[] { default },
new decimal?[] { 1.0M },
new decimal?[] { 1.0M, 2.0M },
new decimal?[] { 1.0M, 2.0M, 3.0M },
new decimal?[] { 1.0M, 2.0M, 3.0M, 4.0M },
new decimal?[] { 1.0M, 2.0M, 3.0M, 4.0M, 5.0M },
new decimal?[] { default, default, default },
new decimal?[] { default, 2.0M, 3.0M, 4.0M, default },
new decimal?[] { 1.0M, 2.0M, default, 4.0M, 5.0M },
//new decimal?[] { decimal.MaxValue, decimal.MaxValue },
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public class ArrayTests
{

[Theory]
[MemberData(nameof(TestData.Sum), MemberType = typeof(TestData))]
public void Sum_With_ValidData_Must_Succeed(double[] source)
[MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))]
public void Sum_With_Double_Must_Succeed(double[] source)
{
// Arrange
var wrapped = (ReadOnlySpan<double>)source.AsSpan();
Expand All @@ -27,8 +27,8 @@ public void Sum_With_ValidData_Must_Succeed(double[] source)
}

[Theory]
[MemberData(nameof(TestData.NullableSum), MemberType = typeof(TestData))]
public void Sum_With_Nullable_ValidData_Must_Succeed(double?[] source)
[MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))]
public void Sum_With_NullableDouble_Must_Succeed(double?[] source)
{
// Arrange
var wrapped = (ReadOnlySpan<double?>)source.AsSpan();
Expand All @@ -43,5 +43,42 @@ public void Sum_With_Nullable_ValidData_Must_Succeed(double?[] source)
_ = result.Must()
.BeEqualTo(expected!.Value);
}


[Theory]
[MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))]
public void Sum_With_Decimal_Must_Succeed(decimal[] source)
{
// Arrange
var wrapped = (ReadOnlySpan<decimal>)source.AsSpan();
var expected = source
.Sum();

// Act
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected);
}

[Theory]
[MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))]
public void Sum_With_NullableDecimal_ValidData_Must_Succeed(decimal?[] source)
{
// Arrange
var wrapped = (ReadOnlySpan<decimal?>)source.AsSpan();
var expected = source
.Sum();

// Act
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected!.Value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,71 @@ namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum
public class ValueEnumerableTests
{
[Theory]
[MemberData(nameof(TestData.Sum), MemberType = typeof(TestData))]
public void Sum_With_ValidData_Must_Succeed(double[] source)
[MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))]
public void Sum_With_Double_Must_Succeed(double[] source)
{
// Arrange
var wrapped = Wrap.AsValueEnumerable(source);
var expected = source
.Sum();

// Act
var result = wrapped
.Sum<Wrap.ValueEnumerableWrapper<double>, Wrap.Enumerator<double>, double, double>();
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected);
}

[Theory]
[MemberData(nameof(TestData.NullableSum), MemberType = typeof(TestData))]
public void Sum_With_Nullable_ValidData_Must_Succeed(double?[] source)
[MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))]
public void Sum_With_NullableDouble_Must_Succeed(double?[] source)
{
// Arrange
var wrapped = Wrap.AsValueEnumerable(source);
var expected = source
.Sum();

// Act
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected!.Value);
}

[Theory]
[MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))]
public void Sum_With_Decimal_Must_Succeed(decimal[] source)
{
// Arrange
var wrapped = Wrap.AsValueEnumerable(source);
var expected = source
.Sum();

// Act
var result = wrapped
.Sum<Wrap.ValueEnumerableWrapper<double?>, Wrap.Enumerator<double?>, double?, double>();
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected);
}

[Theory]
[MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))]
public void Sum_With_NullableDecimal_Must_Succeed(decimal?[] source)
{
// Arrange
var wrapped = Wrap.AsValueEnumerable(source);
var expected = source
.Sum();

// Act
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum
public class ValueReadOnlyCollectionTests
{
[Theory]
[MemberData(nameof(TestData.Sum), MemberType = typeof(TestData))]
public void Sum_With_ValidData_Must_Succeed(double[] source)
[MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))]
public void Sum_With_Double_Must_Succeed(double[] source)
{
// Arrange
var wrapped = Wrap.AsValueReadOnlyCollection(source);
Expand All @@ -26,8 +26,44 @@ public void Sum_With_ValidData_Must_Succeed(double[] source)
}

[Theory]
[MemberData(nameof(TestData.NullableSum), MemberType = typeof(TestData))]
public void Sum_With_Nullable_ValidData_Must_Succeed(double?[] source)
[MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))]
public void Sum_With_NullableDouble_Must_Succeed(double?[] source)
{
// Arrange
var wrapped = Wrap.AsValueReadOnlyCollection(source);
var expected = source
.Sum();

// Act
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected!.Value);
}

[Theory]
[MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))]
public void Sum_With_Decimal_Must_Succeed(decimal[] source)
{
// Arrange
var wrapped = Wrap.AsValueReadOnlyCollection(source);
var expected = source
.Sum();

// Act
var result = wrapped.AsValueEnumerable()
.Sum();

// Assert
_ = result.Must()
.BeEqualTo(expected);
}

[Theory]
[MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))]
public void Sum_With_NullableDecimal_Must_Succeed(decimal?[] source)
{
// Arrange
var wrapped = Wrap.AsValueReadOnlyCollection(source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace NetFabric.Hyperlinq.UnitTests.Aggregation.Sum
public class AsyncValueEnumerableTests
{
[Theory]
[MemberData(nameof(TestData.Sum), MemberType = typeof(TestData))]
public async ValueTask SumAsync_With_ValidData_Must_Succeed(double[] source)
[MemberData(nameof(TestData.SumDouble), MemberType = typeof(TestData))]
public async ValueTask SumAsync_With_Double_Must_Succeed(double[] source)
{
// Arrange
var wrapped = Wrap.AsAsyncValueEnumerable(source);
Expand All @@ -28,8 +28,46 @@ public async ValueTask SumAsync_With_ValidData_Must_Succeed(double[] source)
}

[Theory]
[MemberData(nameof(TestData.NullableSum), MemberType = typeof(TestData))]
public async ValueTask SumAsync_With_Nullable_ValidData_Must_Succeed(double?[] source)
[MemberData(nameof(TestData.SumNullableDouble), MemberType = typeof(TestData))]
public async ValueTask SumAsync_With_NullableDouble_Must_Succeed(double?[] source)
{
// Arrange
var wrapped = Wrap.AsAsyncValueEnumerable(source);
var expected = source
.Sum();

// Act
var result = await wrapped.AsAsyncValueEnumerable()
.SumAsync()
.ConfigureAwait(false);

// Assert
_ = result.Must()
.BeEqualTo(expected!.Value);
}

[Theory]
[MemberData(nameof(TestData.SumDecimal), MemberType = typeof(TestData))]
public async ValueTask SumAsync_With_Decimal_Must_Succeed(decimal[] source)
{
// Arrange
var wrapped = Wrap.AsAsyncValueEnumerable(source);
var expected = source
.Sum();

// Act
var result = await wrapped.AsAsyncValueEnumerable()
.SumAsync()
.ConfigureAwait(false);

// Assert
_ = result.Must()
.BeEqualTo(expected);
}

[Theory]
[MemberData(nameof(TestData.SumNullableDecimal), MemberType = typeof(TestData))]
public async ValueTask SumAsync_With_NullableDecimal_Must_Succeed(decimal?[] source)
{
// Arrange
var wrapped = Wrap.AsAsyncValueEnumerable(source);
Expand Down
6 changes: 3 additions & 3 deletions NetFabric.Hyperlinq/Aggregation/Sum/Sum.Range.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ static int SumRange(int start, int count)
}

for (index = 0; index < Vector<TResult>.Count; index++)
sum = GenericsOperator.Add(vectorSum[index], sum);
sum = Scalar.Add(vectorSum[index], sum);
}

if (start is 0)
{
for (; index < count; index++)
sum = GenericsOperator.Add(selector.Invoke(index), sum);
sum = Scalar.Add(selector.Invoke(index), sum);
}
else
{
for (; index < count; index++)
sum = GenericsOperator.Add(selector.Invoke(index + start), sum);
sum = Scalar.Add(selector.Invoke(index + start), sum);
}

return sum;
Expand Down
Loading

0 comments on commit 185ede8

Please sign in to comment.