using System; namespace FrostFS.SDK.ClientV2; internal sealed class Sampler { private readonly object _lock = new(); private Random random = new(); internal double[] Probabilities { get; set; } internal int[] Alias { get; set; } internal Sampler(double[] probabilities) { var small = new WorkList(); var large = new WorkList(); var n = probabilities.Length; // sampler.randomGenerator = rand.New(source) Probabilities = new double[n]; Alias = new int[n]; // Compute scaled probabilities. var p = new double[n]; for (int i = 0; i < n; i++) { p[i] = probabilities[i] * n; if (p[i] < 1) small.Add(i); else large.Add(i); } while (small.Length > 0 && large.Length > 0) { var l = small.Remove(); var g = large.Remove(); Probabilities[l] = p[l]; Alias[l] = g; p[g] = p[g] + p[l] - 1; if (p[g] < 1) small.Add(g); else large.Add(g); } while (large.Length > 0) { var g = large.Remove(); Probabilities[g] = 1; } while (small.Length > 0) { var l = small.Remove(); probabilities[l] = 1; } } internal int Next() { var n = Alias.Length; int i; double f; lock (_lock) { i = random.Next(0, n - 1); f = random.NextDouble(); } if (f < Probabilities[i]) { return i; } return Alias[i]; } }