diff --git a/src/libraries/System.Linq/src/System.Linq.csproj b/src/libraries/System.Linq/src/System.Linq.csproj
index 9040f668ab6f1d..9ffa540d03baca 100644
--- a/src/libraries/System.Linq/src/System.Linq.csproj
+++ b/src/libraries/System.Linq/src/System.Linq.csproj
@@ -98,6 +98,7 @@
+
diff --git a/src/libraries/System.Linq/src/System/Linq/Max.cs b/src/libraries/System.Linq/src/System/Linq/Max.cs
index 2c05d2dc29dbbb..d4adcc65ec1460 100644
--- a/src/libraries/System.Linq/src/System/Linq/Max.cs
+++ b/src/libraries/System.Linq/src/System/Linq/Max.cs
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
namespace System.Linq
{
@@ -15,6 +15,11 @@ public static int Max(this IEnumerable source)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
+ if (source.GetType() == typeof(int[]))
+ {
+ return Max((int[])source);
+ }
+
int value;
using (IEnumerator e = source.GetEnumerator())
{
@@ -37,6 +42,57 @@ public static int Max(this IEnumerable source)
return value;
}
+ private static int Max(int[] array)
+ {
+ if (array.Length == 0)
+ {
+ ThrowHelper.ThrowNoElementsException();
+ }
+
+ // Vectorize the search if possible.
+ int index, value;
+ if (Vector.IsHardwareAccelerated && array.Length >= Vector.Count * 2)
+ {
+ // The array is at least two vectors long. Create a vector from the first N elements,
+ // and then repeatedly compare that against the next vector from the array. At the end,
+ // the resulting vector will contain the maximum values found, and we then need only
+ // to find the max of those.
+ var maxes = new Vector(array);
+ index = Vector.Count;
+ do
+ {
+ maxes = Vector.Max(maxes, new Vector(array, index));
+ index += Vector.Count;
+ }
+ while (index + Vector.Count <= array.Length);
+
+ value = maxes[0];
+ for (int i = 1; i < Vector.Count; i++)
+ {
+ if (maxes[i] > value)
+ {
+ value = maxes[i];
+ }
+ }
+ }
+ else
+ {
+ value = array[0];
+ index = 1;
+ }
+
+ // Iterate through the remaining elements, comparing against the max.
+ for (int i = index; (uint)i < (uint)array.Length; i++)
+ {
+ if (array[i] > value)
+ {
+ value = array[i];
+ }
+ }
+
+ return value;
+ }
+
public static int? Max(this IEnumerable source)
{
if (source == null)
@@ -106,6 +162,11 @@ public static long Max(this IEnumerable source)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
+ if (source.GetType() == typeof(long[]))
+ {
+ return Max((long[])source);
+ }
+
long value;
using (IEnumerator e = source.GetEnumerator())
{
@@ -128,6 +189,58 @@ public static long Max(this IEnumerable source)
return value;
}
+ private static long Max(long[] array)
+ {
+ if (array.Length == 0)
+ {
+ ThrowHelper.ThrowNoElementsException();
+ }
+
+ // Vectorize the search if possible.
+ int index;
+ long value;
+ if (Vector.IsHardwareAccelerated && array.Length >= Vector.Count * 2)
+ {
+ // The array is at least two vectors long. Create a vector from the first N elements,
+ // and then repeatedly compare that against the next vector from the array. At the end,
+ // the resulting vector will contain the maximum values found, and we then need only
+ // to find the max of those.
+ var maxes = new Vector(array);
+ index = Vector.Count;
+ do
+ {
+ maxes = Vector.Max(maxes, new Vector(array, index));
+ index += Vector.Count;
+ }
+ while (index + Vector.Count <= array.Length);
+
+ value = maxes[0];
+ for (int i = 1; i < Vector.Count; i++)
+ {
+ if (maxes[i] > value)
+ {
+ value = maxes[i];
+ }
+ }
+ }
+ else
+ {
+ value = array[0];
+ index = 1;
+ }
+
+ // Iterate through the remaining elements, comparing against the max.
+ for (int i = index; (uint)i < (uint)array.Length; i++)
+ {
+ if (array[i] > value)
+ {
+ value = array[i];
+ }
+ }
+
+ return value;
+ }
+
public static long? Max(this IEnumerable source)
{
if (source == null)
diff --git a/src/libraries/System.Linq/src/System/Linq/Min.cs b/src/libraries/System.Linq/src/System/Linq/Min.cs
index 9f9266ff1bb83b..fc2e271f420ae1 100644
--- a/src/libraries/System.Linq/src/System/Linq/Min.cs
+++ b/src/libraries/System.Linq/src/System/Linq/Min.cs
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
namespace System.Linq
{
@@ -15,6 +15,11 @@ public static int Min(this IEnumerable source)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
+ if (source.GetType() == typeof(int[]))
+ {
+ return Min((int[])source);
+ }
+
int value;
using (IEnumerator e = source.GetEnumerator())
{
@@ -37,6 +42,57 @@ public static int Min(this IEnumerable source)
return value;
}
+ private static int Min(int[] array)
+ {
+ if (array.Length == 0)
+ {
+ ThrowHelper.ThrowNoElementsException();
+ }
+
+ // Vectorize the search if possible.
+ int index, value;
+ if (Vector.IsHardwareAccelerated && array.Length >= Vector.Count * 2)
+ {
+ // The array is at least two vectors long. Create a vector from the first N elements,
+ // and then repeatedly compare that against the next vector from the array. At the end,
+ // the resulting vector will contain the minimum values found, and we then need only
+ // to find the min of those.
+ var mins = new Vector(array);
+ index = Vector.Count;
+ do
+ {
+ mins = Vector.Min(mins, new Vector(array, index));
+ index += Vector.Count;
+ }
+ while (index + Vector.Count <= array.Length);
+
+ value = mins[0];
+ for (int i = 1; i < Vector.Count; i++)
+ {
+ if (mins[i] < value)
+ {
+ value = mins[i];
+ }
+ }
+ }
+ else
+ {
+ value = array[0];
+ index = 1;
+ }
+
+ // Iterate through the remaining elements, comparing against the min.
+ for (int i = index; (uint)i < (uint)array.Length; i++)
+ {
+ if (array[i] < value)
+ {
+ value = array[i];
+ }
+ }
+
+ return value;
+ }
+
public static int? Min(this IEnumerable source)
{
if (source == null)
@@ -88,6 +144,11 @@ public static long Min(this IEnumerable source)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
+ if (source.GetType() == typeof(long[]))
+ {
+ return Min((long[])source);
+ }
+
long value;
using (IEnumerator e = source.GetEnumerator())
{
@@ -110,6 +171,58 @@ public static long Min(this IEnumerable source)
return value;
}
+ private static long Min(long[] array)
+ {
+ if (array.Length == 0)
+ {
+ ThrowHelper.ThrowNoElementsException();
+ }
+
+ // Vectorize the search if possible.
+ int index;
+ long value;
+ if (Vector.IsHardwareAccelerated && array.Length >= Vector.Count * 2)
+ {
+ // The array is at least two vectors long. Create a vector from the first N elements,
+ // and then repeatedly compare that against the next vector from the array. At the end,
+ // the resulting vector will contain the minimum values found, and we then need only
+ // to find the min of those.
+ var mins = new Vector(array);
+ index = Vector.Count;
+ do
+ {
+ mins = Vector.Min(mins, new Vector(array, index));
+ index += Vector.Count;
+ }
+ while (index + Vector.Count <= array.Length);
+
+ value = mins[0];
+ for (int i = 1; i < Vector.Count; i++)
+ {
+ if (mins[i] < value)
+ {
+ value = mins[i];
+ }
+ }
+ }
+ else
+ {
+ value = array[0];
+ index = 1;
+ }
+
+ // Iterate through the remaining elements, comparing against the min.
+ for (int i = index; (uint)i < (uint)array.Length; i++)
+ {
+ if (array[i] < value)
+ {
+ value = array[i];
+ }
+ }
+
+ return value;
+ }
+
public static long? Min(this IEnumerable source)
{
if (source == null)
diff --git a/src/libraries/System.Linq/tests/MaxTests.cs b/src/libraries/System.Linq/tests/MaxTests.cs
index 78318b64b1194e..27313826b0df1d 100644
--- a/src/libraries/System.Linq/tests/MaxTests.cs
+++ b/src/libraries/System.Linq/tests/MaxTests.cs
@@ -40,6 +40,8 @@ public void Max_Int_EmptySource_ThrowsInvalidOpertionException()
{
Assert.Throws(() => Enumerable.Empty().Max());
Assert.Throws(() => Enumerable.Empty().Max(x => x));
+ Assert.Throws(() => Array.Empty().Max());
+ Assert.Throws(() => new List().Max());
}
public static IEnumerable