View file File name : rand.sl Content :% Copyright (C) 2012-2017,2018 John E. Davis % % This file is part of the S-Lang Library and may be distributed under the % terms of the GNU General Public License. See the file COPYING for % more information. %--------------------------------------------------------------------------- import ("rand"); private define get_generator_args (nargs, num_parms, parmsp, rtp, nump, usage_str) { @rtp = NULL; @nump = NULL; if (nargs == num_parms) { @parmsp = __pop_list (num_parms); return; } if (nargs == num_parms + 1) { @nump = (); variable parms = __pop_list (num_parms); if (typeof (parms[0]) == Rand_Type) { @rtp = list_pop (parms); list_append (parms, @nump); @nump = NULL; } @parmsp = parms; return; } if (nargs == num_parms + 2) { @nump = (); @parmsp = __pop_list (num_parms); variable rt = (); if (typeof (rt) == Rand_Type) { @rtp = rt; return; } } else _pop_n (nargs); usage (usage_str); } private define call_rand_func () { variable num = (); variable args = __pop_list (_NARGS-3); variable rt, func; (func, rt) = (); if (rt == NULL) { if (num == NULL) return (@func) (__push_list(args)); return (@func) (__push_list(args), num); } if (num == NULL) return (@func)(rt, __push_list(args)); return (@func)(rt, __push_list(args), num); } define rand_flat () { variable parms, rt, num; get_generator_args (_NARGS, 2, &parms, &rt, &num, "r = rand_flat ([Rand_Type,] xmin, xmax [,num])"); variable r = call_rand_func (&rand_uniform, rt, num); return parms[0] + (parms[1] - parms[0])*__tmp(r); } define rand_chisq () { variable parms, rt, num; get_generator_args (_NARGS, 1, &parms, &rt, &num, "r = rand_chisq ([Rand_Type,] nu [,num])"); return 2.0 * call_rand_func (&rand_gamma, rt, 0.5*parms[0], 1.0, num); } define rand_fdist () { variable parms, rt, num; get_generator_args (_NARGS, 2, &parms, &rt, &num, "r = rand_fdist ([Rand_Type,] nu1, nu2 [,num])"); variable nu1 = parms[0], nu2 = parms[1]; return (call_rand_func (&rand_gamma, rt, 0.5*nu1, 1.0, num)/nu1) / (call_rand_func(&rand_gamma, rt, 0.5*nu2, 1.0, num)/nu2); } define rand_tdist () { variable parms, rt, num; get_generator_args (_NARGS, 1, &parms, &rt, &num, "r = rand_tdist ([Rand_Type,] nu, [,num])"); variable nu = parms[0]; return call_rand_func (&rand_gauss, rt, 1.0, num) / sqrt(call_rand_func(&rand_chisq, rt, nu, num)/nu); } define rand_int () { variable parms, rt, num; get_generator_args (_NARGS, 2, &parms, &rt, &num, "r = rand_int ([Rand_Type,] imin, imax [,num])"); variable imin = typecast (parms[0], Int32_Type), imax = typecast (parms[1], Int32_Type), di; if (imin > imax) throw InvalidParmError, "rand_int: imax < imin"; di = typecast (imax - imin, UInt32_Type); variable r = call_rand_func (&rand, rt, num); if (di + 1 != 0) % UINT32_MAX does not exist r = __tmp(r) mod (di + 1); return typecast (imin + r, Int32_Type); } define rand_exp () { variable parms, rt, num; get_generator_args (_NARGS, 1, &parms, &rt, &num, "r = rand_exp ([Rand_Type,] beta [,num])"); return (-parms[0]) * log (call_rand_func (&rand_uniform_pos, rt, num)); } private define make_indices (a, d, i) { _for (0, length(array_shape(a))-1, 1) { variable j = (); if (j == d) i; else [:]; } } define rand_sample () { if (_NARGS < 2) { _pop_n (_NARGS); usage ("(B1 [,B2,...]) = rand_sample ([Rand_Type,] A1 [A2,...], num)"); } variable num = (); variable arrays = __pop_list (_NARGS-1); variable rt = NULL; if (typeof (arrays[0]) == Rand_Type) rt = list_pop (arrays); variable n0 = NULL, dim0; variable a, indices; foreach a (arrays) { dim0 = array_shape (a)[0]; if (n0 == NULL) { n0 = dim0; continue; } if (n0 != dim0) throw TypeMismatchError, "The arrays passed to rand_sample must have the same leading dimension"; } if (num > n0) num = n0; if (rt == NULL) indices = rand_permutation (n0); else indices = rand_permutation (rt, n0); if (num < n0) indices = indices[[0:num-1]]; foreach a (arrays) a[make_indices(a, 0, indices)]; }