/* * Random variates from the hypergeometric distribution. * * Returns the number of white balls drawn when kk balls * are drawn at random from an urn containing nn1 white * and nn2 black balls. */ private static double RHyper(long kk, double nn1, double nn2, CoinFlipper coins) { var prng = new PRNG(coins); if (kk > 10) { return(HypergeometricHRUA(prng, nn1, nn2, kk)); } else { return(HypergeometricHYP(prng, nn1, nn2, kk)); } }
internal static long SampleUniform(ValueRange valueRange, CoinFlipper coins) { var currentRange = valueRange.Copy(); if (currentRange.Size() == 0) { throw new Exception(""); } while (currentRange.Size() > 1) { var mid = (currentRange.Start + currentRange.End) / 2; var bit = coins.GetCoin(); if (bit) { currentRange.Start = mid + 1; } else { currentRange.End = mid; } } return(currentRange.Start); }
public PRNG(CoinFlipper coins) { _coins = coins; }
/* * Get a sample from the hypergeometric distribution, using the provided bit list as a source of randomness */ internal static long SampleHGD(ValueRange inRange, ValueRange outRange, long mid, CoinFlipper coins) { var inSize = inRange.Size(); var outSize = outRange.Size(); if (inSize < 0 || outSize < 0 || inSize > outSize || !outRange.Contains(mid)) { throw new ArgumentException(); } var nSampleIndex = mid - outRange.Start + 1; if (inSize == outSize) { return(inRange.Start + nSampleIndex - 1); } double inSampleNum = RHyper(nSampleIndex, inSize, outSize - inSize, coins); if (inSampleNum == 0) { return(inRange.Start); } else { var inSample = inRange.Start + inSampleNum - 1; if (!inRange.Contains(Convert.ToInt32(inSample))) { throw new ArgumentException(); } return(Convert.ToInt32(inSample)); } }