diff --git a/PerfectNumbers.Core/MersenneDivisorCycles.cs b/PerfectNumbers.Core/MersenneDivisorCycles.cs index d8eb5ed..1827fea 100644 --- a/PerfectNumbers.Core/MersenneDivisorCycles.cs +++ b/PerfectNumbers.Core/MersenneDivisorCycles.cs @@ -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 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