Skip to content

Instantly share code, notes, and snippets.

@tannergooding
Last active April 23, 2026 15:11
Show Gist options
  • Select an option

  • Save tannergooding/37e69efe58a478ad573b2d3ce3260e08 to your computer and use it in GitHub Desktop.

Select an option

Save tannergooding/37e69efe58a478ad573b2d3ce3260e08 to your computer and use it in GitHub Desktop.
public static int Sum(ReadOnlySpan<int> x)
{
if (Vector128.IsHardwareAccelerated)
{
int result;
if (x.Length >= Vector128<int>.Count)
{
result = Vectorized128(x);
}
else
{
result = VectorizedSmall(x);
}
return result;
}
else
{
return SoftwareFallback(x);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static int SoftwareFallback(ReadOnlySpan<int> x)
{
int result = 0;
for (int i = 0; i < x.Length; i++)
{
result += x[i];
}
return result;
}
static int Vectorized128(ReadOnlySpan<int> x)
{
Vector128<int> vresult = Vector128<int>.Zero;
Vector128<int> beg = Vector128.Create(x);
Vector128<int> end = Vector128.Create(x[^Vector128<int>.Count..]);
if (x.Length > (Vector128<int>.Count * 4))
{
x = x[Vector128<int>.Count..];
Vector128<int> vector1;
Vector128<int> vector2;
Vector128<int> vector3;
Vector128<int> vector4;
while (x.Length >= (Vector128<int>.Count * 4))
{
vector1 = Vector128.Create(x[(Vector128<int>.Count * 0)..]);
vector2 = Vector128.Create(x[(Vector128<int>.Count * 1)..]);
vector3 = Vector128.Create(x[(Vector128<int>.Count * 2)..]);
vector4 = Vector128.Create(x[(Vector128<int>.Count * 3)..]);
vresult += vector1;
vresult += vector2;
vresult += vector3;
vresult += vector4;
x = x[(Vector128<int>.Count * 4)..];
}
}
vresult += beg;
(int blocks, int trailing) = Math.DivRem(x.Length, Vector128<int>.Count);
x = x[..^trailing];
switch (blocks)
{
case 3:
{
Vector128<int> vector = Vector128.Create(x[^(Vector128<int>.Count * 3)..]);
vresult += vector;
goto case 2;
}
case 2:
{
Vector128<int> vector = Vector128.Create(x[^(Vector128<int>.Count * 2)..]);
vresult += vector;
goto case 1;
}
case 1:
{
Vector128<int> vector = Vector128.Create(x[^(Vector128<int>.Count * 1)..]);
vresult += vector;
goto case 0;
}
case 0:
{
end = Vector128.ConditionalSelect(CreateRemainderMaskVector128(trailing), end, Vector128<int>.Zero);
vresult += end;
break;
}
}
return Vector128.Sum(vresult);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static int VectorizedSmall(ReadOnlySpan<int> x)
{
int result = 0;
switch (x.Length)
{
case 3:
{
result += x[2];
goto case 2;
}
case 2:
{
result += x[1];
goto case 1;
}
case 1:
{
result += x[0];
goto case 0;
}
case 0:
{
break;
}
}
return result;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector128<int> CreateRemainderMaskVector128(int count)
{
return Vector128.Create(RemainderMask[(count * Vector128<int>.Count)..]);
}
private static ReadOnlySpan<int> RemainderMask =>
[
+0, +0, +0, +0,
+0, +0, +0, -1,
+0, +0, -1, -1,
+0, -1, -1, -1,
-1, -1, -1, -1,
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment