Extension methods benchmarked. Slower alternatives replaced.

This commit is contained in:
Marek Lemańczyk committed 2025-09-23 22:01:09 +02:00
1 parent 9becb8df67
commit 6e99ee39e3
40 files changed
+930 -1026

No files matched your search

@@ -1,5 +1,4 @@
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -15,38 +14,45 @@ public class Mod10UInt128Benchmarks
return Value % 10UL;
}
/// <summary>
/// Fastest
/// </summary>
[Benchmark]
public ulong ModWithHighLowModulo()
{
// Split and fold under mod 10: 2^64 ≡ 6 (mod 10)
ulong value = (ulong)Value;
ulong high = value >> 64;
ulong low = value;
ulong highRem = high % 10UL;
ulong lowRem = low % 10UL;
ulong combined = lowRem + highRem * 6UL;
return combined % 10UL;
return ModWithHighLowModuloHelper(Value);
}
[Benchmark]
public ulong ModWithLoopModulo()
{
UInt128 value = Value;
private static ulong ModWithHighLowModuloHelper(UInt128 value128)
{
// Split and fold under mod 10: 2^64 ≡ 6 (mod 10)
ulong value = (ulong)value128;
return ((value % 10UL) + ((value >> 64) % 10UL) * 6UL) % 10UL;
}
[Benchmark]
public ulong ModWithLoopModulo()
{
return ModWithLoopModuloHelper(Value);
}
private static ulong ModWithLoopModuloHelper(UInt128 value)
{
UInt128 zero = UInt128.Zero;
if (value == zero)
return 0UL;
ulong result = (ulong)value;
UInt128 high = value >> 64;
value >>= 64;
while (high != zero)
while (value != zero)
{
// 2^64 ≡ 6 (mod 10)
result = (result + (ulong)high * 6UL) % 10UL;
high >>= 64;
}
result = (result + (ulong)value * 6UL) % 10UL;
value >>= 64;
}
return result % 10UL;
}
return result % 10UL;
}
}
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -8,10 +9,16 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod10UIntBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod10(uint value) => value - (uint)((value * UIntExtensions.Mod5Mask) >> 35) * 10U;
[Params(10U, 2047U, 65535U, 2147483647U)]
public uint Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public uint ModuloOperator()
{
return Value % 10U;
@@ -20,7 +27,7 @@ public class Mod10UIntBenchmarks
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod10();
return Mod10(Value);
}
}
@@ -1,4 +1,3 @@
using System.Numerics;
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
@@ -16,7 +15,10 @@ public class Mod10ULongBenchmarks
return Value % 10UL;
}
[Benchmark]
/// <summary>
/// Fastest
/// </summary>
[Benchmark]
public ulong ModMethodModulo()
{
return Value.Mod10();
@@ -1,4 +1,3 @@
using System.Numerics;
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
@@ -10,7 +9,10 @@ public class Mod10_8_5_3Benchmarks
[Params(3UL, 8191UL, 131071UL, 2147483647UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModuloOperator()
{
ulong value = Value;
@@ -1,4 +1,3 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
@@ -36,10 +35,13 @@ public class Mod10_8_5_3PropertiesBenchmarks
return rem >= 5UL ? rem - 5UL : rem;
}
[Params(3UL, 8191UL, 131071UL, 2147483647UL)]
[Params(3UL, 6UL, 128UL, 256UL, 2_047UL, 8_191UL, 65_535UL, 131_071UL, 2_147_483_647UL, ulong.MaxValue - 1_024UL, ulong.MaxValue - 511UL, ulong.MaxValue - 255UL, ulong.MaxValue - 127UL, ulong.MaxValue - 63UL, ulong.MaxValue - 31UL, ulong.MaxValue - 17UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public (ulong Mod10, ulong Mod8, ulong Mod5, ulong Mod3) LegacyModulo()
{
UInt128 value = Value;
@@ -53,12 +55,7 @@ public class Mod10_8_5_3PropertiesBenchmarks
[Benchmark]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModMethodModulo()
{
Value.Mod10_8_5_3(out var mod10, out ulong mod8, out ulong mod5, out ulong mod3);
Mod10R = mod10;
Mod8R = mod8;
Mod5R = mod5;
Mod3R = mod3;
Value.Mod10_8_5_3(out Mod10R, out Mod8R, out Mod5R, out Mod3R);
return (Mod10R, Mod8R, Mod3R, Mod5R);
}
}
@@ -1,4 +1,3 @@
using System.Numerics;
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
@@ -14,19 +13,21 @@ public class Mod10_8_5_3StepsBenchmarks
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) LegacyModulo()
{
UInt128 value = Value;
ulong mod10 = (ulong)(value % 10UL) % 10UL;
ulong mod8 = (ulong)(value % 8UL);
ulong mod3 = (ulong)(value % 3UL);
ulong mod5 = (ulong)(value % 5UL);
ulong mod10 = (((ulong)(value % 10UL)) << 1) % 10UL;
ulong mod8 = (((ulong)(value & 7UL)) << 1) & 7UL;
ulong mod5 = (((ulong)(value % 5UL)) << 1) % 5UL;
ulong mod3 = (((ulong)(value % 3UL)) << 1) % 3UL;
return (mod10, mod8, mod3, mod5);
}
[Benchmark]
/// <summary>
/// Fastest
/// </summary>
[Benchmark]
public (ulong Mod10, ulong Mod8, ulong Mod3, ulong Mod5) ModMethodModulo()
{
Value.Mod10_8_5_3(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3);
Value.Mod10_8_5_3Steps(out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3);
// Step residues for q += 2*p
mod10 %= 10UL;
return (mod10, mod8, mod3, mod5);
}
}
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,10 +8,27 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod11UIntBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod11(uint value)
{
uint remainder = 0U;
while (value != 0U)
{
remainder += value & 1023U;
value >>= 10;
remainder -= 11U * (remainder / 11U);
}
return remainder;
}
[Params(11U, 2047U, 65535U, 2147483647U)]
public uint Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public uint ModuloOperator()
{
return Value % 11U;
@@ -20,7 +37,7 @@ public class Mod11UIntBenchmarks
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod11();
return Mod11(Value);
}
}
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,10 +8,25 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod11ULongBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod11(ulong value)
{
ulong remainder = ((uint)value % 11U) + ((uint)(value >> 32) % 11U) << 2;
while (remainder >= 11UL)
{
remainder -= 11UL;
}
return remainder;
}
[Params(11UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 127UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % 11UL;
@@ -20,7 +35,7 @@ public class Mod11ULongBenchmarks
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod11();
return Mod11(Value);
}
}
@@ -1,32 +1,92 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod11_7_5_3Benchmarks
{
private static readonly byte[] Mod7ByteCoefficients = [1, 4, 2, 1, 4, 2, 1, 4];
private static readonly byte[] Mod11ByteCoefficients = [1, 3, 9, 5, 4, 1, 3, 9];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong ReduceMod7(uint value)
{
while (value >= 7U)
{
value = (value >> 3) + (value & 7U);
if (value >= 7U && value < 14U)
{
value -= 7U;
}
}
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong ReduceMod11(uint value)
{
while (value >= 11U)
{
value = (value & 15U) + ((value >> 4) * 5U);
if (value >= 11U && value < 22U)
{
value -= 11U;
}
}
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Mod11_7_5_3(ulong value, out ulong mod11, out ulong mod7, out ulong mod5, out ulong mod3)
{
uint mod3And5Accumulator = 0U;
uint mod7Accumulator = 0U;
uint mod11Accumulator = 0U;
int index = 0;
byte current;
ulong temp = value;
byte[] mod7ByteCoefficients = Mod7ByteCoefficients;
byte[] mod11ByteCoefficients = Mod11ByteCoefficients;
do
{
current = (byte)temp;
mod3And5Accumulator += current;
mod7Accumulator += (uint)(current * mod7ByteCoefficients[index]);
mod11Accumulator += (uint)(current * mod11ByteCoefficients[index]);
temp >>= 8;
index++;
}
while (temp != 0UL);
mod3 = mod3And5Accumulator % 3;
mod5 = mod3And5Accumulator % 5;
mod7 = (uint)ReduceMod7(mod7Accumulator);
mod11 = (uint)ReduceMod11(mod11Accumulator);
}
[Params(3UL, 8191UL, 131071UL, 2147483647UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public (ulong Mod11, ulong Mod7, ulong Mod5, ulong Mod3) ModuloOperator()
{
ulong value = Value;
return (value % 11UL, value % 7UL, value % 5UL, value % 3UL);
}
[Benchmark]
public (ulong Mod11, ulong Mod7, ulong Mod5, ulong Mod3) ExtensionMethods()
{
ulong value = Value;
return (value.Mod11(), value.Mod7(), value.Mod5(), value.Mod3());
}
[Benchmark]
public (ulong Mod11, ulong Mod7, ulong Mod5, ulong Mod3) CombinedMethod()
{
Value.Mod11_7_5_3(out ulong mod11, out ulong mod7, out ulong mod5, out ulong mod3);
Mod11_7_5_3(Value, out ulong mod11, out ulong mod7, out ulong mod5, out ulong mod3);
return (mod11, mod7, mod5, mod3);
}
}
@@ -1,4 +1,3 @@
using System.Numerics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -12,12 +11,16 @@ public class Mod128UInt128Benchmarks
[Params(128UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 511UL)]
public UInt128 Value { get; set; }
[Benchmark(Baseline = true)]
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return (ulong)(Value % 128UL);
}
/// <summary>
/// Fastest
/// </summary>
/// <returns></returns>
[Benchmark]
public ulong ExtensionMethod()
{
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,10 +8,17 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod128UIntBenchmarks
{
[Params(128U, 2047U, 65535U, 2147483647U)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod128(uint value) => value & 127U;
[Params(3UL, 5UL, 6UL, 8UL, 10UL, 11UL, 32UL, 64UL, 128UL, 256UL, 2_047UL, 8_191UL, 65_535UL, 131_071UL, 2_147_483_647UL, uint.MaxValue - 1_024UL, uint.MaxValue - 511UL, uint.MaxValue - 255UL, uint.MaxValue - 127UL, uint.MaxValue - 63UL, uint.MaxValue - 31UL, uint.MaxValue - 17UL, uint.MaxValue)]
public uint Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest most of the times. It's usually much faster than it's slower.
/// </summary>
/// <returns></returns>
[Benchmark(Baseline = true)]
public uint ModuloOperator()
{
return Value % 128U;
@@ -20,7 +27,7 @@ public class Mod128UIntBenchmarks
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod128();
return Mod128(Value);
}
}
@@ -8,15 +8,19 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod128ULongBenchmarks
{
[Params(128UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 255UL)]
[Params(3UL, 5UL, 6UL, 8UL, 10UL, 11UL, 32UL, 64UL, 128UL, 256UL, 2_047UL, 8_191UL, 65_535UL, 131_071UL, 2_147_483_647UL, uint.MaxValue - 1_024UL, uint.MaxValue - 511UL, uint.MaxValue - 255UL, uint.MaxValue - 127UL, uint.MaxValue - 63UL, uint.MaxValue - 31UL, uint.MaxValue - 17UL, uint.MaxValue)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % 128UL;
}
/// <summary>
/// Usually fastest for high values. It's slower for some values and faster for other.
/// </summary>
/// <returns></returns>
[Benchmark]
public ulong ExtensionMethod()
{
@@ -20,7 +20,7 @@ public class Mod3UIntBenchmarks
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod3();
return UIntExtensions.Mod3(Value);
}
}
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -8,10 +9,22 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod3ULongBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Mod3(ulong value) =>
(
(uint)(value & ULongExtensions.WordBitMask) +
(uint)((value >> 16) & ULongExtensions.WordBitMask) +
(uint)((value >> 32) & ULongExtensions.WordBitMask) +
(uint)((value >> 48) & ULongExtensions.WordBitMask)
) % 3;
[Params(3UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 17UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % 3UL;
@@ -20,7 +33,7 @@ public class Mod3ULongBenchmarks
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod3();
return Mod3(Value);
}
}
@@ -8,7 +8,7 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod5UIntBenchmarks
{
[Params(5U, 2047U, 65535U, 2147483647U)]
[Params(3UL, 5UL, 6UL, 8UL, 10UL, 11UL, 32UL, 64UL, 128UL, 256UL, 2_047UL, 8_191UL, 65_535UL, 131_071UL, 2_147_483_647UL, uint.MaxValue - 1_024UL, uint.MaxValue - 511UL, uint.MaxValue - 255UL, uint.MaxValue - 127UL, uint.MaxValue - 63UL, uint.MaxValue - 31UL, uint.MaxValue - 17UL, uint.MaxValue)]
public uint Value { get; set; }
[Benchmark(Baseline = true)]
@@ -17,7 +17,10 @@ public class Mod5UIntBenchmarks
return Value % 5U;
}
[Benchmark]
/// <summary>
/// Mixed results. Sometimes it's faster, in higher ranges, sometimes it's slower.
/// </summary>
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod5();
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -8,10 +9,22 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod5ULongBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod5(ulong value) =>
(
(uint)(value & ULongExtensions.WordBitMask) +
(uint)((value >> 16) & ULongExtensions.WordBitMask) +
(uint)((value >> 32) & ULongExtensions.WordBitMask) +
(uint)((value >> 48) & ULongExtensions.WordBitMask)
) % 5;
[Params(5UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 31UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % 5UL;
@@ -20,7 +33,7 @@ public class Mod5ULongBenchmarks
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod5();
return Mod5(Value);
}
}
@@ -1,4 +1,4 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -9,6 +9,11 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod6ComparisonBenchmarks
{
private static readonly byte[] Mod6Lookup = [0, 3, 4, 1, 2, 5];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod6(ulong value) => Mod6Lookup[(int)(((value % 3UL) << 1) | (value & 1UL))];
private const int Iterations = 10_000_000;
private const ulong Divisor = 6UL;
private static readonly ulong FastDivMul = (ulong)(((UInt128)1 << 64) / Divisor);
@@ -71,7 +76,7 @@ public class Mod6ComparisonBenchmarks
for (int i = 0; i < Iterations; i++)
{
checksum += value.Mod6();
checksum += Mod6(value);
value += (ulong)((i & 15) + 1);
}
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,10 +8,18 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod6UIntBenchmarks
{
private static readonly byte[] Mod6Lookup = [0, 3, 4, 1, 2, 5];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod6(uint value) => Mod6Lookup[(int)(((value % 3U) << 1) | (value & 1U))];
[Params(6U, 2047U, 65535U, 2147483647U)]
public uint Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public uint ModuloOperator()
{
return Value % 6U;
@@ -20,7 +28,7 @@ public class Mod6UIntBenchmarks
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod6();
return Mod6(Value);
}
}
@@ -1,4 +1,4 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -9,13 +9,20 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod6ULongBenchmarks
{
private static readonly byte[] Mod6Lookup = [0, 3, 4, 1, 2, 5];
private static readonly ulong Divisor = 6UL;
private static readonly ulong FastDivMul = (ulong)(((UInt128)1 << 64) / Divisor);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod6(ulong value) => Mod6Lookup[(int)(((value % 3UL) << 1) | (value & 1UL))];
[Params(3UL, 131071UL, ulong.MaxValue)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % Divisor;
@@ -38,6 +45,6 @@ public class Mod6ULongBenchmarks
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod6();
return Mod6(Value);
}
}
@@ -17,7 +17,11 @@ public class Mod7UInt128Benchmarks
return (ulong)(Value % 7UL);
}
[Benchmark]
/// <summary>
/// Fastest
/// </summary>
/// <returns></returns>
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod7();
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,10 +8,30 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod7UIntBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint Mod7(uint value)
{
uint remainder = 0U;
while (value != 0U)
{
remainder += value & 7U;
value >>= 3;
if (remainder >= 7U)
{
remainder -= 7U;
}
}
return remainder >= 7U ? remainder - 7U : remainder;
}
[Params(7U, 2047U, 65535U, 2147483647U)]
public uint Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public uint ModuloOperator()
{
return Value % 7U;
@@ -20,7 +40,7 @@ public class Mod7UIntBenchmarks
[Benchmark]
public uint ExtensionMethod()
{
return Value.Mod7();
return Mod7(Value);
}
}
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,10 +8,25 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod7ULongBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod7(ulong value)
{
ulong remainder = ((uint)value % 7U) + (((uint)(value >> 32) % 7U) << 2);
while (remainder >= 7UL)
{
remainder -= 7UL;
}
return remainder;
}
[Params(7UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 63UL)]
public ulong Value { get; set; }
[Benchmark(Baseline = true)]
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % 7UL;
@@ -20,7 +35,7 @@ public class Mod7ULongBenchmarks
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod7();
return Mod7(Value);
}
}
@@ -1,4 +1,3 @@
using System.Numerics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
@@ -18,7 +17,10 @@ public class Mod8UInt128Benchmarks
return (ulong)(Value % 8UL);
}
[Benchmark]
/// <summary>
/// Fastest
/// </summary>
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod8();
@@ -17,6 +17,9 @@ public class Mod8UIntBenchmarks
return Value % 8U;
}
/// <summary>
/// Fastest
/// </summary>
[Benchmark]
public uint ExtensionMethod()
{
@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using PerfectNumbers.Core;
namespace EvenPerfectBitScanner.Benchmarks;
@@ -8,19 +8,25 @@ namespace EvenPerfectBitScanner.Benchmarks;
[MemoryDiagnoser]
public class Mod8ULongBenchmarks
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod8(ulong value) => value & 7UL;
[Params(8UL, 8191UL, 131071UL, 2147483647UL, ulong.MaxValue - 127UL)]
public ulong Value { get; set; }
/// <summary>
/// Fastest
/// </summary>
[Benchmark(Baseline = true)]
public ulong ModuloOperator()
{
return Value % 8UL;
}
[Benchmark]
[Benchmark]
public ulong ExtensionMethod()
{
return Value.Mod8();
return Mod8(Value);
}
}