Optimize Pollard Rho random sampling

This commit is contained in:
Marek Lemańczyk committed 2025-10-10 10:31:14 +02:00
1 parent 99a7ec5b70
commit 4ed9db7d0b
1 file changed
+31 -5
+31 -5
View File
@@ -1,9 +1,7 @@
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using PerfectNumbers.Core.Gpu;
@@ -18,6 +16,11 @@ public class MersenneDivisorCycles
// Lightweight read-mostly cache for small divisors (<= 4,000,000). 0 => unknown
private ulong[]? _smallCycles;
[ThreadStatic]
private static ulong _threadRandomState;
private static long _randomSeedCounter;
public static MersenneDivisorCycles Shared { get; } = new MersenneDivisorCycles();
public MersenneDivisorCycles()
@@ -594,9 +597,32 @@ public class MersenneDivisorCycles
private static ulong NextRandomUInt64()
{
Span<byte> buffer = stackalloc byte[8];
RandomNumberGenerator.Fill(buffer);
return BinaryPrimitives.ReadUInt64LittleEndian(buffer);
ulong state = _threadRandomState;
if (state == 0UL)
{
state = InitializeThreadRandomState();
}
state ^= state >> 12;
state ^= state << 25;
state ^= state >> 27;
_threadRandomState = state;
return state * 2685821657736338717UL;
}
private static ulong InitializeThreadRandomState()
{
ulong seed = (ulong)Interlocked.Increment(ref _randomSeedCounter);
seed += 0x9E3779B97F4A7C15UL;
seed = (seed ^ (seed >> 30)) * 0xBF58476D1CE4E5B9UL;
seed = (seed ^ (seed >> 27)) * 0x94D049BB133111EBUL;
seed ^= seed >> 31;
if (seed == 0UL)
{
seed = 0x9E3779B97F4A7C15UL;
}
return seed;
}
public readonly struct FactorCacheEntry