""" Implementation of method overloads for Generator objects. """ import numpy as np from numba.core import types from numba.core.extending import overload_method, register_jitable from numba.np.numpy_support import as_dtype, from_dtype from numba.np.random.generator_core import next_float, next_double from numba.np.numpy_support import is_nonelike from numba.core.errors import TypingError from numba.core.types.containers import Tuple, UniTuple from numba.np.random.distributions import \ (random_standard_exponential_inv_f, random_standard_exponential_inv, random_standard_exponential, random_standard_normal_f, random_standard_gamma, random_standard_normal, random_uniform, random_standard_exponential_f, random_standard_gamma_f, random_normal, random_exponential, random_gamma, random_beta, random_power, random_f,random_chisquare,random_standard_cauchy,random_pareto, random_weibull, random_laplace, random_logistic, random_lognormal, random_rayleigh, random_standard_t, random_wald, random_geometric, random_zipf, random_triangular, random_poisson, random_negative_binomial, random_logseries, random_noncentral_chisquare, random_noncentral_f, random_binomial) from numba.np.random import random_methods def _get_proper_func(func_32, func_64, dtype, dist_name="the given"): """ Most of the standard NumPy distributions that accept dtype argument only support either np.float32 or np.float64 as dtypes. This is a helper function that helps Numba select the proper underlying implementation according to provided dtype. """ if isinstance(dtype, types.Omitted): dtype = dtype.value np_dt = dtype if isinstance(dtype, type): nb_dt = from_dtype(np.dtype(dtype)) elif isinstance(dtype, types.NumberClass): nb_dt = dtype np_dt = as_dtype(nb_dt) if np_dt not in [np.float32, np.float64]: raise TypingError("Argument dtype is not one of the" + " expected type(s): " + " np.float32 or np.float64") if np_dt == np.float32: next_func = func_32 else: next_func = func_64 return next_func, nb_dt def check_size(size): if not any([isinstance(size, UniTuple) and isinstance(size.dtype, types.Integer), isinstance(size, Tuple) and size.count == 0, isinstance(size, types.Integer)]): raise TypingError("Argument size is not one of the" + " expected type(s): " + " an integer, an empty tuple or a tuple of integers") def check_types(obj, type_list, arg_name): """ Check if given object is one of the provided types. If not raises an TypeError """ if isinstance(obj, types.Omitted): obj = obj.value if not isinstance(type_list, (list, tuple)): type_list = [type_list] if not any([isinstance(obj, _type) for _type in type_list]): raise TypingError(f"Argument {arg_name} is not one of the" + f" expected type(s): {type_list}") # Overload the Generator().integers() @overload_method(types.NumPyRandomGeneratorType, 'integers') def NumPyRandomGeneratorType_integers(inst, low, high, size=None, dtype=np.int64, endpoint=False): check_types(low, [types.Integer, types.Boolean, bool, int], 'low') check_types(high, [types.Integer, types.Boolean, bool, int], 'high') check_types(endpoint, [types.Boolean, bool], 'endpoint') if isinstance(size, types.Omitted): size = size.value if isinstance(dtype, types.Omitted): dtype = dtype.value if isinstance(dtype, type): nb_dt = from_dtype(np.dtype(dtype)) _dtype = dtype elif isinstance(dtype, types.NumberClass): nb_dt = dtype _dtype = as_dtype(nb_dt) else: raise TypingError("Argument dtype is not one of the" + " expected type(s): " + "np.int32, np.int64, np.int16, np.int8, " "np.uint32, np.uint64, np.uint16, np.uint8, " "np.bool_") if _dtype == np.bool_: int_func = random_methods.random_bounded_bool_fill lower_bound = -1 upper_bound = 2 else: try: i_info = np.iinfo(_dtype) except ValueError: raise TypingError("Argument dtype is not one of the" + " expected type(s): " + "np.int32, np.int64, np.int16, np.int8, " "np.uint32, np.uint64, np.uint16, np.uint8, " "np.bool_") int_func = getattr(random_methods, f'random_bounded_uint{i_info.bits}_fill') lower_bound = i_info.min upper_bound = i_info.max if is_nonelike(size): def impl(inst, low, high, size=None, dtype=np.int64, endpoint=False): random_methods._randint_arg_check(low, high, endpoint, lower_bound, upper_bound) if not endpoint: high -= dtype(1) low = dtype(low) high = dtype(high) rng = high - low return int_func(inst.bit_generator, low, rng, 1, dtype)[0] else: low = dtype(low) high = dtype(high) rng = high - low return int_func(inst.bit_generator, low, rng, 1, dtype)[0] return impl else: check_size(size) def impl(inst, low, high, size=None, dtype=np.int64, endpoint=False): random_methods._randint_arg_check(low, high, endpoint, lower_bound, upper_bound) if not endpoint: high -= dtype(1) low = dtype(low) high = dtype(high) rng = high - low return int_func(inst.bit_generator, low, rng, size, dtype) else: low = dtype(low) high = dtype(high) rng = high - low return int_func(inst.bit_generator, low, rng, size, dtype) return impl # The following `shuffle` implementation is a direct translation from: # https://github.com/numpy/numpy/blob/95e3e7f445407e4f355b23d6a9991d8774f0eb0c/numpy/random/_generator.pyx#L4578 # Overload the Generator().shuffle() @overload_method(types.NumPyRandomGeneratorType, 'shuffle') def NumPyRandomGeneratorType_shuffle(inst, x, axis=0): check_types(x, [types.Array], 'x') check_types(axis, [int, types.Integer], 'axis') def impl(inst, x, axis=0): if axis < 0: axis = axis + x.ndim if axis > x.ndim - 1 or axis < 0: raise IndexError("Axis is out of bounds for the given array") z = np.swapaxes(x, 0, axis) buf = np.empty_like(z[0, ...]) for i in range(len(z) - 1, 0, -1): j = types.intp(random_methods.random_interval(inst.bit_generator, i)) if i == j: continue buf[...] = z[j, ...] z[j, ...] = z[i, ...] z[i, ...] = buf return impl # The following `permutation` implementation is a direct translation from: # https://github.com/numpy/numpy/blob/95e3e7f445407e4f355b23d6a9991d8774f0eb0c/numpy/random/_generator.pyx#L4710 # Overload the Generator().permutation() @overload_method(types.NumPyRandomGeneratorType, 'permutation') def NumPyRandomGeneratorType_permutation(inst, x, axis=0): check_types(x, [types.Array, types.Integer], 'x') check_types(axis, [int, types.Integer], 'axis') IS_INT = isinstance(x, types.Integer) def impl(inst, x, axis=0): if IS_INT: new_arr = np.arange(x) # NumPy ignores the axis argument when x is an integer inst.shuffle(new_arr) else: new_arr = x.copy() inst.shuffle(new_arr, axis=axis) return new_arr return impl # Overload the Generator().random() @overload_method(types.NumPyRandomGeneratorType, 'random') def NumPyRandomGeneratorType_random(inst, size=None, dtype=np.float64): dist_func, nb_dt = _get_proper_func(next_float, next_double, dtype, "random") if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, size=None, dtype=np.float64): return nb_dt(dist_func(inst.bit_generator)) return impl else: check_size(size) def impl(inst, size=None, dtype=np.float64): out = np.empty(size, dtype=dtype) out_f = out.flat for i in range(out.size): out_f[i] = dist_func(inst.bit_generator) return out return impl # Overload the Generator().standard_exponential() method @overload_method(types.NumPyRandomGeneratorType, 'standard_exponential') def NumPyRandomGeneratorType_standard_exponential(inst, size=None, dtype=np.float64, method='zig'): check_types(method, [types.UnicodeType, str], 'method') dist_func_inv, nb_dt = _get_proper_func( random_standard_exponential_inv_f, random_standard_exponential_inv, dtype ) dist_func, nb_dt = _get_proper_func(random_standard_exponential_f, random_standard_exponential, dtype) if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, size=None, dtype=np.float64, method='zig'): if method == 'zig': return nb_dt(dist_func(inst.bit_generator)) elif method == 'inv': return nb_dt(dist_func_inv(inst.bit_generator)) else: raise ValueError("Method must be either 'zig' or 'inv'") return impl else: check_size(size) def impl(inst, size=None, dtype=np.float64, method='zig'): out = np.empty(size, dtype=dtype) out_f = out.flat if method == 'zig': for i in range(out.size): out_f[i] = dist_func(inst.bit_generator) elif method == 'inv': for i in range(out.size): out_f[i] = dist_func_inv(inst.bit_generator) else: raise ValueError("Method must be either 'zig' or 'inv'") return out return impl # Overload the Generator().standard_normal() method @overload_method(types.NumPyRandomGeneratorType, 'standard_normal') def NumPyRandomGeneratorType_standard_normal(inst, size=None, dtype=np.float64): dist_func, nb_dt = _get_proper_func(random_standard_normal_f, random_standard_normal, dtype) if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, size=None, dtype=np.float64): return nb_dt(dist_func(inst.bit_generator)) return impl else: check_size(size) def impl(inst, size=None, dtype=np.float64): out = np.empty(size, dtype=dtype) out_f = out.flat for i in range(out.size): out_f[i] = dist_func(inst.bit_generator) return out return impl # Overload the Generator().standard_gamma() method @overload_method(types.NumPyRandomGeneratorType, 'standard_gamma') def NumPyRandomGeneratorType_standard_gamma(inst, shape, size=None, dtype=np.float64): check_types(shape, [types.Float, types.Integer, int, float], 'shape') dist_func, nb_dt = _get_proper_func(random_standard_gamma_f, random_standard_gamma, dtype) if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, shape, size=None, dtype=np.float64): return nb_dt(dist_func(inst.bit_generator, shape)) return impl else: check_size(size) def impl(inst, shape, size=None, dtype=np.float64): out = np.empty(size, dtype=dtype) out_f = out.flat for i in range(out.size): out_f[i] = dist_func(inst.bit_generator, shape) return out return impl # Overload the Generator().normal() method @overload_method(types.NumPyRandomGeneratorType, 'normal') def NumPyRandomGeneratorType_normal(inst, loc=0.0, scale=1.0, size=None): check_types(loc, [types.Float, types.Integer, int, float], 'loc') check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, loc=0.0, scale=1.0, size=None): return random_normal(inst.bit_generator, loc, scale) return impl else: check_size(size) def impl(inst, loc=0.0, scale=1.0, size=None): out = np.empty(size, dtype=np.float64) out_f = out.flat for i in range(out.size): out_f[i] = random_normal(inst.bit_generator, loc, scale) return out return impl # Overload the Generator().uniform() method @overload_method(types.NumPyRandomGeneratorType, 'uniform') def NumPyRandomGeneratorType_uniform(inst, low=0.0, high=1.0, size=None): check_types(low, [types.Float, types.Integer, int, float], 'low') check_types(high, [types.Float, types.Integer, int, float], 'high') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, low=0.0, high=1.0, size=None): return random_uniform(inst.bit_generator, low, high - low) return impl else: check_size(size) def impl(inst, low=0.0, high=1.0, size=None): out = np.empty(size, dtype=np.float64) out_f = out.flat for i in range(out.size): out_f[i] = random_uniform(inst.bit_generator, low, high - low) return out return impl # Overload the Generator().exponential() method @overload_method(types.NumPyRandomGeneratorType, 'exponential') def NumPyRandomGeneratorType_exponential(inst, scale=1.0, size=None): check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, scale=1.0, size=None): return random_exponential(inst.bit_generator, scale) return impl else: check_size(size) def impl(inst, scale=1.0, size=None): out = np.empty(size, dtype=np.float64) out_f = out.flat for i in range(out.size): out_f[i] = random_exponential(inst.bit_generator, scale) return out return impl # Overload the Generator().gamma() method @overload_method(types.NumPyRandomGeneratorType, 'gamma') def NumPyRandomGeneratorType_gamma(inst, shape, scale=1.0, size=None): check_types(shape, [types.Float, types.Integer, int, float], 'shape') check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, shape, scale=1.0, size=None): return random_gamma(inst.bit_generator, shape, scale) return impl else: check_size(size) def impl(inst, shape, scale=1.0, size=None): out = np.empty(size, dtype=np.float64) out_f = out.flat for i in range(out.size): out_f[i] = random_gamma(inst.bit_generator, shape, scale) return out return impl # Overload the Generator().beta() method @overload_method(types.NumPyRandomGeneratorType, 'beta') def NumPyRandomGeneratorType_beta(inst, a, b, size=None): check_types(a, [types.Float, types.Integer, int, float], 'a') check_types(b, [types.Float, types.Integer, int, float], 'b') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, a, b, size=None): return random_beta(inst.bit_generator, a, b) return impl else: check_size(size) def impl(inst, a, b, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_beta(inst.bit_generator, a, b) return out return impl # Overload the Generator().f() method @overload_method(types.NumPyRandomGeneratorType, 'f') def NumPyRandomGeneratorType_f(inst, dfnum, dfden, size=None): check_types(dfnum, [types.Float, types.Integer, int, float], 'dfnum') check_types(dfden, [types.Float, types.Integer, int, float], 'dfden') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, dfnum, dfden, size=None): return random_f(inst.bit_generator, dfnum, dfden) return impl else: check_size(size) def impl(inst, dfnum, dfden, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_f(inst.bit_generator, dfnum, dfden) return out return impl # Overload the Generator().chisquare() method @overload_method(types.NumPyRandomGeneratorType, 'chisquare') def NumPyRandomGeneratorType_chisquare(inst, df, size=None): check_types(df, [types.Float, types.Integer, int, float], 'df') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, df, size=None): return random_chisquare(inst.bit_generator, df) return impl else: check_size(size) def impl(inst, df, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_chisquare(inst.bit_generator, df) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'standard_cauchy') def NumPyRandomGeneratorType_standard_cauchy(inst, size=None): if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, size=None): return random_standard_cauchy(inst.bit_generator) return impl else: check_size(size) def impl(inst, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_standard_cauchy(inst.bit_generator) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'pareto') def NumPyRandomGeneratorType_pareto(inst, a, size=None): check_types(a, [types.Float, types.Integer, int, float], 'a') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, a, size=None): return random_pareto(inst.bit_generator, a) return impl else: check_size(size) def impl(inst, a, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_pareto(inst.bit_generator, a) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'weibull') def NumPyRandomGeneratorType_weibull(inst, a, size=None): check_types(a, [types.Float, types.Integer, int, float], 'a') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, a, size=None): return random_weibull(inst.bit_generator, a) return impl else: check_size(size) def impl(inst, a, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_weibull(inst.bit_generator, a) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'power') def NumPyRandomGeneratorType_power(inst, a, size=None): check_types(a, [types.Float, types.Integer, int, float], 'a') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, a, size=None): return random_power(inst.bit_generator, a) return impl else: check_size(size) def impl(inst, a, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_power(inst.bit_generator, a) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'laplace') def NumPyRandomGeneratorType_laplace(inst, loc=0.0, scale=1.0, size=None): check_types(loc, [types.Float, types.Integer, int, float], 'loc') check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, loc=0.0, scale=1.0, size=None): return random_laplace(inst.bit_generator, loc, scale) return impl else: check_size(size) def impl(inst, loc=0.0, scale=1.0, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_laplace(inst.bit_generator, loc, scale) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'logistic') def NumPyRandomGeneratorType_logistic(inst, loc=0.0, scale=1.0, size=None): check_types(loc, [types.Float, types.Integer, int, float], 'loc') check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, loc=0.0, scale=1.0, size=None): return random_logistic(inst.bit_generator, loc, scale) return impl else: check_size(size) def impl(inst, loc=0.0, scale=1.0, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_logistic(inst.bit_generator, loc, scale) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'lognormal') def NumPyRandomGeneratorType_lognormal(inst, mean=0.0, sigma=1.0, size=None): check_types(mean, [types.Float, types.Integer, int, float], 'mean') check_types(sigma, [types.Float, types.Integer, int, float], 'sigma') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, mean=0.0, sigma=1.0, size=None): return random_lognormal(inst.bit_generator, mean, sigma) return impl else: check_size(size) def impl(inst, mean=0.0, sigma=1.0, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_lognormal(inst.bit_generator, mean, sigma) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'rayleigh') def NumPyRandomGeneratorType_rayleigh(inst, scale=1.0, size=None): check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, scale=1.0, size=None): return random_rayleigh(inst.bit_generator, scale) return impl else: check_size(size) def impl(inst, scale=1.0, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_rayleigh(inst.bit_generator, scale) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'standard_t') def NumPyRandomGeneratorType_standard_t(inst, df, size=None): check_types(df, [types.Float, types.Integer, int, float], 'df') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, df, size=None): return random_standard_t(inst.bit_generator, df) return impl else: check_size(size) def impl(inst, df, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_standard_t(inst.bit_generator, df) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'wald') def NumPyRandomGeneratorType_wald(inst, mean, scale, size=None): check_types(mean, [types.Float, types.Integer, int, float], 'mean') check_types(scale, [types.Float, types.Integer, int, float], 'scale') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, mean, scale, size=None): return random_wald(inst.bit_generator, mean, scale) return impl else: check_size(size) def impl(inst, mean, scale, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_wald(inst.bit_generator, mean, scale) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'geometric') def NumPyRandomGeneratorType_geometric(inst, p, size=None): check_types(p, [types.Float, types.Integer, int, float], 'p') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, p, size=None): return np.int64(random_geometric(inst.bit_generator, p)) return impl else: check_size(size) def impl(inst, p, size=None): out = np.empty(size, dtype=np.int64) out_f = out.flat for i in range(out.size): out_f[i] = random_geometric(inst.bit_generator, p) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'zipf') def NumPyRandomGeneratorType_zipf(inst, a, size=None): check_types(a, [types.Float, types.Integer, int, float], 'a') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, a, size=None): return np.int64(random_zipf(inst.bit_generator, a)) return impl else: check_size(size) def impl(inst, a, size=None): out = np.empty(size, dtype=np.int64) out_f = out.flat for i in range(out.size): out_f[i] = random_zipf(inst.bit_generator, a) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'triangular') def NumPyRandomGeneratorType_triangular(inst, left, mode, right, size=None): check_types(left, [types.Float, types.Integer, int, float], 'left') check_types(mode, [types.Float, types.Integer, int, float], 'mode') check_types(right, [types.Float, types.Integer, int, float], 'right') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, left, mode, right, size=None): return random_triangular(inst.bit_generator, left, mode, right) return impl else: check_size(size) def impl(inst, left, mode, right, size=None): out = np.empty(size) out_f = out.flat for i in range(out.size): out_f[i] = random_triangular(inst.bit_generator, left, mode, right) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'poisson') def NumPyRandomGeneratorType_poisson(inst, lam , size=None): check_types(lam, [types.Float, types.Integer, int, float], 'lam') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, lam , size=None): return np.int64(random_poisson(inst.bit_generator, lam)) return impl else: check_size(size) def impl(inst, lam , size=None): out = np.empty(size, dtype=np.int64) out_f = out.flat for i in range(out.size): out_f[i] = random_poisson(inst.bit_generator, lam) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'negative_binomial') def NumPyRandomGeneratorType_negative_binomial(inst, n, p, size=None): check_types(n, [types.Float, types.Integer, int, float], 'n') check_types(p, [types.Float, types.Integer, int, float], 'p') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, n, p , size=None): return np.int64(random_negative_binomial(inst.bit_generator, n, p)) return impl else: check_size(size) def impl(inst, n, p , size=None): out = np.empty(size, dtype=np.int64) out_f = out.flat for i in range(out.size): out_f[i] = random_negative_binomial(inst.bit_generator, n, p) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'noncentral_chisquare') def NumPyRandomGeneratorType_noncentral_chisquare(inst, df, nonc, size=None): check_types(df, [types.Float, types.Integer, int, float], 'df') check_types(nonc, [types.Float, types.Integer, int, float], 'nonc') if isinstance(size, types.Omitted): size = size.value @register_jitable def check_arg_bounds(df, nonc): if df <= 0: raise ValueError("df <= 0") if nonc < 0: raise ValueError("nonc < 0") if is_nonelike(size): def impl(inst, df, nonc, size=None): check_arg_bounds(df, nonc) return np.float64(random_noncentral_chisquare(inst.bit_generator, df, nonc)) return impl else: check_size(size) def impl(inst, df, nonc, size=None): check_arg_bounds(df, nonc) out = np.empty(size, dtype=np.float64) out_f = out.flat for i in range(out.size): out_f[i] = random_noncentral_chisquare(inst.bit_generator, df, nonc) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'noncentral_f') def NumPyRandomGeneratorType_noncentral_f(inst, dfnum, dfden, nonc, size=None): check_types(dfnum, [types.Float, types.Integer, int, float], 'dfnum') check_types(dfden, [types.Float, types.Integer, int, float], 'dfden') check_types(nonc, [types.Float, types.Integer, int, float], 'nonc') if isinstance(size, types.Omitted): size = size.value @register_jitable def check_arg_bounds(dfnum, dfden, nonc): if dfnum <= 0: raise ValueError("dfnum <= 0") if dfden <= 0: raise ValueError("dfden <= 0") if nonc < 0: raise ValueError("nonc < 0") if is_nonelike(size): def impl(inst, dfnum, dfden, nonc, size=None): check_arg_bounds(dfnum, dfden, nonc) return np.float64(random_noncentral_f(inst.bit_generator, dfnum, dfden, nonc)) return impl else: check_size(size) def impl(inst, dfnum, dfden, nonc, size=None): check_arg_bounds(dfnum, dfden, nonc) out = np.empty(size, dtype=np.float64) out_f = out.flat for i in range(out.size): out_f[i] = random_noncentral_f(inst.bit_generator, dfnum, dfden, nonc) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'logseries') def NumPyRandomGeneratorType_logseries(inst, p, size=None): check_types(p, [types.Float, types.Integer, int, float], 'p') if isinstance(size, types.Omitted): size = size.value @register_jitable def check_arg_bounds(p): if p < 0 or p >= 1 or np.isnan(p): raise ValueError("p < 0, p >= 1 or p is NaN") if is_nonelike(size): def impl(inst, p, size=None): check_arg_bounds(p) return np.int64(random_logseries(inst.bit_generator, p)) return impl else: check_size(size) def impl(inst, p, size=None): check_arg_bounds(p) out = np.empty(size, dtype=np.int64) out_f = out.flat for i in range(out.size): out_f[i] = random_logseries(inst.bit_generator, p) return out return impl @overload_method(types.NumPyRandomGeneratorType, 'binomial') def NumPyRandomGeneratorType_binomial(inst, n, p, size=None): check_types(n, [types.Float, types.Integer, int, float], 'n') check_types(p, [types.Float, types.Integer, int, float], 'p') if isinstance(size, types.Omitted): size = size.value if is_nonelike(size): def impl(inst, n, p, size=None): return np.int64(random_binomial(inst.bit_generator, n, p)) return impl else: check_size(size) def impl(inst, n, p, size=None): out = np.empty(size, dtype=np.int64) for i in np.ndindex(size): out[i] = random_binomial(inst.bit_generator, n, p) return out return impl