def random_poisson_ptrs(bitgen, lam): slam = np.sqrt(lam) loglam = np.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 (1): U = next_double(bitgen) - 0.5 V = next_double(bitgen) us = 0.5 - np.fabs(U) k = int((2 * a / us + b) * U + lam + 0.43) if ((us >= 0.07) and (V <= vr)): return k if ((k < 0) or ((us < 0.013) and (V > us))): continue # /* log(V) == log(0.0) ok here */ # /* if U==0.0 so that us==0.0, log is ok since always returns */ if ((np.log(V) + np.log(invalpha) - np.log(a / (us * us) + b)) <= (-lam + k * loglam - random_loggam(k + 1))): return k
def random_standard_normal(bitgen): while 1: r = next_uint64(bitgen) idx = r & 0xff r >>= 8 sign = r & 0x1 rabs = (r >> 1) & 0x000fffffffffffff x = rabs * wi_double[idx] if (sign & 0x1): x = -x if rabs < ki_double[idx]: return x if idx == 0: while 1: xx = -ziggurat_nor_inv_r * np.log1p(-next_double(bitgen)) yy = -np.log1p(-next_double(bitgen)) if (yy + yy > xx * xx): if ((rabs >> 8) & 0x1): return -(ziggurat_nor_r + xx) else: return ziggurat_nor_r + xx else: if (((fi_double[idx - 1] - fi_double[idx]) * next_double(bitgen) + fi_double[idx]) < np.exp(-0.5 * x * x)): return x
def random_standard_gamma(bitgen, shape): if (shape == 1.0): return random_standard_exponential(bitgen) elif (shape == 0.0): return 0.0 elif (shape < 1.0): while 1: U = next_double(bitgen) V = random_standard_exponential(bitgen) if (U <= 1.0 - shape): X = pow(U, 1. / shape) if (X <= V): return X else: Y = -np.log((1 - U) / shape) X = pow(1.0 - shape + shape * Y, 1. / shape) if (X <= (V + Y)): return X else: b = shape - 1. / 3. c = 1. / np.sqrt(9 * b) while 1: while 1: X = random_standard_normal(bitgen) V = 1.0 + c * X if (V > 0.0): break V = V * V * V U = next_double(bitgen) if (U < 1.0 - 0.0331 * (X * X) * (X * X)): return (b * V) if (np.log(U) < 0.5 * X * X + b * (1. - V + np.log(V))): return (b * V)
def random_laplace(bitgen, loc, scale): U = next_double(bitgen) while U <= 0: U = next_double(bitgen) if (U >= 0.5): U = loc - scale * np.log(2.0 - U - U) elif (U > 0.0): U = loc + scale * np.log(U + U) return U
def random_zipf(bitgen, a): am1 = a - 1.0 b = pow(2.0, am1) while 1: U = 1.0 - next_double(bitgen) V = next_double(bitgen) X = np.floor(pow(U, -1.0 / am1)) if (X > INT64_MAX or X < 1.0): continue T = pow(1.0 + 1.0 / X, am1) if (V * X * (T - 1.0) / (b - 1.0) <= T / b): return X
def random_standard_exponential(bitgen): while 1: ri = next_uint64(bitgen) ri >>= 3 idx = ri & 0xFF ri >>= 8 x = ri * we_double[idx] if (ri < ke_double[idx]): return x else: if idx == 0: return ziggurat_exp_r - np_log1p(-next_double(bitgen)) elif ((fe_double[idx - 1] - fe_double[idx]) * next_double(bitgen) + fe_double[idx] < np.exp(-x)): return x
def random_geometric_search(bitgen, p): X = 1 sum = prod = p q = 1.0 - p U = next_double(bitgen) while (U > sum): prod *= q sum += prod X = X + 1 return X
def random_wald(bitgen, mean, scale): mu_2l = mean / (2 * scale) Y = random_standard_normal(bitgen) Y = mean * Y * Y X = mean + mu_2l * (Y - np.sqrt(4 * scale * Y + Y * Y)) U = next_double(bitgen) if (U <= mean / (mean + X)): return X else: return mean * mean / X
def random_poisson_mult(bitgen, lam): enlam = np.exp(-lam) X = 0 prod = 1.0 while (1): U = next_double(bitgen) prod *= U if (prod > enlam): X += 1 else: return X
def random_triangular(bitgen, left, mode, right): base = right - left leftbase = mode - left ratio = leftbase / base leftprod = leftbase * base rightprod = (right - mode) * base U = next_double(bitgen) if (U <= ratio): return left + np.sqrt(U * leftprod) else: return right - np.sqrt((1.0 - U) * rightprod)
def random_beta(bitgen, a, b): if a <= 1.0 and b <= 1.0: while 1: U = next_double(bitgen) V = next_double(bitgen) X = pow(U, 1.0 / a) Y = pow(V, 1.0 / b) XpY = X + Y if XpY <= 1.0 and XpY > 0.0: if (X + Y > 0): return X / XpY else: logX = np.log(U) / a logY = np.log(V) / b logM = min(logX, logY) logX -= logM logY -= logM return np.exp(logX - np.log(np.exp(logX) + np.exp(logY))) else: Ga = random_standard_gamma(bitgen, a) Gb = random_standard_gamma(bitgen, b) return Ga / (Ga + Gb)
def random_rayleigh(bitgen, mode): return mode * np.sqrt(-2.0 * np.log(1.0 - next_double(bitgen)))
def random_logistic(bitgen, loc, scale): U = next_double(bitgen) while U <= 0.0: U = next_double(bitgen) return loc + scale * np.log(U / (1.0 - U))
def random_uniform(bitgen, lower, range): scaled_uniform = range * next_double(bitgen) return lower + scaled_uniform
def random_standard_exponential_inv(bitgen): return -np_log1p(-next_double(bitgen))