using System; using System.Threading; namespace PKHeX.Core; public static partial class Util { // Multithread safe rand, ha public static Random Rand => _local.Value; private static int randomSeed = Environment.TickCount; private static readonly ThreadLocal _local = new(() => { // threads should never really step on each other when starting, but we'll play it safe. var seed = Interlocked.Increment(ref randomSeed); var mix = (0x41C64E6D * seed) + 0x00006073; // why not return new Random(mix); }); public static uint Rand32() => Rand32(Rand); public static uint Rand32(this Random rnd) => ((uint)rnd.Next(1 << 30) << 2) | (uint)rnd.Next(1 << 2); public static ulong Rand64(this Random rnd) => rnd.Rand32() | ((ulong)rnd.Rand32() << 32); /// /// Shuffles the order of items within a collection of items. /// /// Item type /// Item collection public static void Shuffle(Span items) => Shuffle(items, 0, items.Length, Rand); /// /// Shuffles the order of items within a collection of items. /// /// Item type /// Item collection /// Starting position /// Ending position /// RNG object to use public static void Shuffle(Span items, int start, int end, Random rnd) { for (int i = start; i < end; i++) { int index = i + rnd.Next(end - i); (items[index], items[i]) = (items[i], items[index]); } } }