internal static ulong rk_interval(ulong max, rk_state state) { ulong mask = max, value; if (max == 0) { return(0); } /* Smallest bit mask >= max */ mask |= mask >> 1; mask |= mask >> 2; mask |= mask >> 4; mask |= mask >> 8; mask |= mask >> 16; mask |= mask >> 32; /* Search a random value in [0..mask] <= max */ if (max <= 0xffffffffUL) { while ((value = (rk_random(state) & mask)) > max) { ; } } else { while ((value = (rk_ulong(state) & mask)) > max) { ; } } return(value); }
static long rk_poisson_ptrs(rk_state state, double lam) { long k; double U, V, slam, loglam, a, b, invalpha, vr, us; slam = Math.Sqrt(lam); loglam = Math.Log(lam); b = 0.931 + 2.53 * slam; a = -0.059 + 0.02483 * b; invalpha = 1.1239 + 1.1328 / (b - 3.4); vr = 0.9277 - 3.6224 / (b - 2); while (true) { U = rk_double(state) - 0.5; V = rk_double(state); us = 0.5 - Math.Abs(U); k = (long)Math.Floor((2 * a / us + b) * U + lam + 0.43); if ((us >= 0.07) && (V <= vr)) { return(k); } if ((k < 0) || ((us < 0.013) && (V > us))) { continue; } if ((Math.Log(V) + Math.Log(invalpha) - Math.Log(a / (us * us) + b)) <= (-lam + k * loglam - loggam(k + 1))) { return(k); } } }
internal static long rk_logseries(rk_state state, double p) { double q, r, U, V; long result; r = Math.Log(1.0 - p); while (true) { V = rk_double(state); if (V >= p) { return(1); } U = rk_double(state); q = 1.0 - Math.Exp(r * U); if (V <= q * q) { result = (long)Math.Floor(1 + Math.Log(V) / Math.Log(q)); if (result < 1) { continue; } else { return(result); } } if (V >= q) { return(1); } return(2); } }
internal static double rk_logistic(rk_state state, double loc, double scale) { double U; U = rk_double(state); return(loc + scale * Math.Log(U / (1.0 - U))); }
internal static double rk_gumbel(rk_state state, double loc, double scale) { double U; U = 1.0 - rk_double(state); return(loc - scale * Math.Log(-Math.Log(U))); }
internal static long rk_negative_binomial(rk_state state, double n, double p) { double Y; Y = rk_gamma(state, n, (1 - p) / p); return(rk_poisson(state, Y)); }
internal static double rk_gauss(rk_state state) { if (state.has_gauss) { double tmp = state.gauss; state.gauss = 0; state.has_gauss = false; return(tmp); } else { double f, x1, x2, r2; do { x1 = 2.0 * rk_double(state) - 1.0; x2 = 2.0 * rk_double(state) - 1.0; r2 = x1 * x1 + x2 * x2; }while (r2 >= 1.0 || r2 == 0.0); /* Box-Muller transform */ f = Math.Sqrt(-2.0 * Math.Log(r2) / r2); /* Keep for next call */ state.gauss = f * x1; state.has_gauss = true; return(f * x2); } }
static UInt64 rk_uint64(rk_state state) { UInt64 upper = (UInt64)rk_random(state) << 32; UInt64 lower = (UInt64)rk_random(state); return(upper | lower); }
internal static long rk_zipf(rk_state state, double a) { double am1, b; am1 = a - 1.0; b = Math.Pow(2.0, am1); while (true) { double T, U, V, X; U = 1.0 - rk_double(state); V = rk_double(state); X = Math.Floor(Math.Pow(U, -1.0 / am1)); /* * The real result may be above what can be represented in a signed * long. Since this is a straightforward rejection algorithm, we can * just reject this value. This function then models a Zipf * distribution truncated to sys.maxint. */ if (X > Int64.MaxValue || X < 1.0) { continue; } T = Math.Pow(1.0 + 1.0 / X, am1); if (V * X * (T - 1.0) / (b - 1.0) <= T / b) { return((long)X); } } }
/* * Fills an array with cnt random npy_bool between off and off + rng * inclusive. */ internal static void rk_random_bool(bool off, bool rng, npy_intp cnt, bool[] _out, rk_state state) { npy_intp i; UInt32 buf = 0; int bcnt = 0; if (rng == false) { for (i = 0; i < cnt; i++) { _out[i] = off; } return; } /* If we reach here rng and mask are one and off is zero */ System.Diagnostics.Debug.Assert(rng == true && off == false); for (i = 0; i < cnt; i++) { if (bcnt == 0) { buf = rk_uint32(state); bcnt = 31; } else { buf >>= 1; bcnt--; } _out[i] = (buf & 0x00000001) != 0; } }
/* * Fills an array with cnt random npy_uint32 between off and off + rng * inclusive. The numbers wrap if rng is sufficiently large. */ internal static void rk_random_uint32(UInt32 off, UInt32 rng, npy_intp cnt, UInt32[] _out, rk_state state) { UInt32 val, mask = rng; npy_intp i; if (rng == 0) { for (i = 0; i < cnt; i++) { _out[i] = off; } return; } /* Smallest bit mask >= max */ mask |= mask >> 1; mask |= mask >> 2; mask |= mask >> 4; mask |= mask >> 8; mask |= mask >> 16; for (i = 0; i < cnt; i++) { while ((val = (rk_uint32(state) & mask)) > rng) { ; } _out[i] = off + val; } }
static long rk_hypergeometric_hyp(rk_state state, long good, long bad, long sample) { long d1, K, Z; double d2, U, Y; d1 = bad + good - sample; d2 = (double)Math.Min(bad, good); Y = d2; K = sample; while (Y > 0.0) { U = rk_double(state); Y -= (long)Math.Floor(U + Y / (d1 + K)); K--; if (K == 0) { break; } } Z = (long)(d2 - Y); if (good > bad) { Z = sample - Z; } return(Z); }
static Int64 rk_int64(rk_state state) { Int64 upper = (Int64)rk_random(state) << 32; Int64 lower = (Int64)rk_random(state); return(upper | lower); }
internal static long rk_binomial(rk_state state, long n, double p) { double q; if (p <= 0.5) { if (p * n <= 30.0) { return(rk_binomial_inversion(state, n, p)); } else { return(rk_binomial_btpe(state, n, p)); } } else { q = 1.0 - p; if (q * n <= 30.0) { return(n - rk_binomial_inversion(state, n, q)); } else { return(n - rk_binomial_btpe(state, n, q)); } } }
internal static void rk_fill(byte[] buffer, Int32 size, rk_state state) { ulong r; int index = 0; for (; size >= 4; size -= 4) { r = rk_random(state); buffer[index++] = (byte)(r & 0xFF); buffer[index++] = (byte)((r >> 8) & 0xFF); buffer[index++] = (byte)((r >> 16) & 0xFF); buffer[index++] = (byte)((r >> 24) & 0xFF); } if (size <= 0) { return; } r = rk_random(state); for (; size > 0; r >>= 8, size--) { buffer[index++] = (byte)(r & 0xFF); } }
internal static double rk_standard_gamma(rk_state state, double shape) { double b, c; double U, V, X, Y; if (shape == 1.0) { return(rk_standard_exponential(state)); } else if (shape < 1.0) { for (; ;) { U = rk_double(state); V = rk_standard_exponential(state); if (U <= 1.0 - shape) { X = Math.Pow(U, 1.0 / shape); if (X <= V) { return(X); } } else { Y = -Math.Log((1 - U) / shape); X = Math.Pow(1.0 - shape + shape * Y, 1.0 / shape); if (X <= (V + Y)) { return(X); } } } } else { b = shape - 1.0 / 3.0; c = 1.0 / Math.Sqrt(9 * b); for (; ;) { do { X = rk_gauss(state); V = 1.0 + c * X; } while (V <= 0.0); V = V * V * V; U = rk_double(state); if (U < 1.0 - 0.0331 * (X * X) * (X * X)) { return(b * V); } if (Math.Log(U) < 0.5 * X * X + b * (1.0 - V + Math.Log(V))) { return(b * V); } } } }
public static void rk_seed(ulong seed, rk_state state) { state.gauss = 0; state.has_gauss = false; state.has_binomial = false; state.rndGenerator.Seed(seed, state); }
internal static double rk_weibull(rk_state state, double a) { if (a == 0.0) { return(0.0); } return(Math.Pow(rk_standard_exponential(state), 1.0 / a)); }
internal static double rk_standard_t(rk_state state, double df) { double N, G, X; N = rk_gauss(state); G = rk_standard_gamma(state, df / 2); X = Math.Sqrt(df / 2) * N / Math.Sqrt(G); return(X); }
internal static long rk_hypergeometric(rk_state state, long good, long bad, long sample) { if (sample > 10) { return(rk_hypergeometric_hrua(state, good, bad, sample)); } else { return(rk_hypergeometric_hyp(state, good, bad, sample)); } }
internal static long rk_geometric(rk_state state, double p) { if (p >= 0.333333333333333333333333) { return(rk_geometric_search(state, p)); } else { return(rk_geometric_inversion(state, p)); } }
internal static double rk_laplace(rk_state state, double loc, double scale) { double U; U = rk_double(state); if (U < 0.5) { U = loc + scale * Math.Log(U + U); } else { U = loc - scale * Math.Log(2.0 - U - U); } return(U); }
internal static long rk_poisson(rk_state state, double lam) { if (lam >= 10) { return(rk_poisson_ptrs(state, lam)); } else if (lam == 0) { return(0); } else { return(rk_poisson_mult(state, lam)); } }
static long rk_geometric_search(rk_state state, double p) { double U; long X; double sum, prod, q; X = 1; sum = prod = p; q = 1.0 - p; U = rk_double(state); while (U > sum) { prod *= q; sum += prod; X++; } return(X); }
internal static double rk_noncentral_chisquare(rk_state state, double df, double nonc) { if (nonc == 0) { return(rk_chisquare(state, df)); } if (1 < df) { double Chi2 = rk_chisquare(state, df - 1); double N = rk_gauss(state) + Math.Sqrt(nonc); return(Chi2 + N * N); } else { long i = rk_poisson(state, nonc / 2.0); return(rk_chisquare(state, df + 2 * i)); } }
static long rk_binomial_inversion(rk_state state, long n, double p) { double q, qn, np, px, U; long X, bound; if (!(state.has_binomial) || (state.nsave != n) || (state.psave != p)) { state.nsave = n; state.psave = p; state.has_binomial = true; state.q = q = 1.0 - p; state.r = qn = Math.Exp(n * Math.Log(q)); state.c = np = n * p; state.m = bound = (npy_intp)Math.Min(n, np + 10.0 * Math.Sqrt(np * q + 1)); } else { q = state.q; qn = state.r; np = state.c; bound = state.m; } X = 0; px = qn; U = rk_double(state); while (U > px) { X++; if (X > bound) { X = 0; px = qn; U = rk_double(state); } else { U -= px; px = ((n - X + 1) * p * px) / (X * q); } } return(X); }
/* * Fills an array with cnt random npy_int64 between off and off + rng * inclusive. The numbers wrap if rng is sufficiently large. */ internal static void rk_random_int64(Int64 off, Int64 rng, npy_intp cnt, Int64[] _out, rk_state state) { Int64 val, mask = rng; npy_intp i; if (rng == 0) { for (i = 0; i < cnt; i++) { _out[i] = off; } return; } /* Smallest bit mask >= max */ mask |= mask >> 1; mask |= mask >> 2; mask |= mask >> 4; mask |= mask >> 8; mask |= mask >> 16; mask |= mask >> 32; for (i = 0; i < cnt; i++) { if (rng <= 0xffffffffL) { while ((val = (rk_int32(state) & mask)) > rng) { ; } } else { while ((val = (rk_int64(state) & mask)) > rng) { ; } } _out[i] = off + val; } }
internal static double rk_wald(rk_state state, double mean, double scale) { double U, X, Y; double mu_2l; mu_2l = mean / (2 * scale); Y = rk_gauss(state); Y = mean * Y * Y; X = mean + mu_2l * (Y - Math.Sqrt(4 * scale * Y + Y * Y)); U = rk_double(state); if (U <= mean / (mean + X)) { return(X); } else { return(mean * mean / X); } }
/* * Fills an array with cnt random npy_uint16 between off and off + rng * inclusive. The numbers wrap if rng is sufficiently large. */ internal static void rk_random_uint16(UInt16 off, UInt16 rng, npy_intp cnt, UInt16[] _out, rk_state state) { UInt16 val, mask = rng; npy_intp i; UInt32 buf = 0; int bcnt = 0; if (rng == 0) { for (i = 0; i < cnt; i++) { _out[i] = off; } return; } /* Smallest bit mask >= max */ mask |= (UInt16)(mask >> 1); mask |= (UInt16)(mask >> 2); mask |= (UInt16)(mask >> 4); mask |= (UInt16)(mask >> 8); for (i = 0; i < cnt; i++) { do { if (bcnt == 0) { buf = rk_uint32(state); bcnt = 1; } else { buf >>= 16; bcnt--; } val = (UInt16)(buf & mask); } while (val > rng); _out[i] = (UInt16)(off + val); } }
internal static double rk_beta(rk_state state, double a, double b) { double Ga, Gb; if ((a <= 1.0) && (b <= 1.0)) { double U, V, X, Y; /* Use Johnk's algorithm */ while (true) { U = rk_double(state); V = rk_double(state); X = Math.Pow(U, 1.0 / a); Y = Math.Pow(V, 1.0 / b); if ((X + Y) <= 1.0) { if (X + Y > 0) { return(X / (X + Y)); } else { double logX = Math.Log(U) / a; double logY = Math.Log(V) / b; double logM = logX > logY ? logX : logY; logX -= logM; logY -= logM; return(Math.Exp(logX - Math.Log(Math.Exp(logX) + Math.Exp(logY)))); } } } } else { Ga = rk_standard_gamma(state, a); Gb = rk_standard_gamma(state, b); return(Ga / (Ga + Gb)); } }