Extension methods benchmarked. Slower alternatives replaced.
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user