205 строки
4.3 KiB
Plaintext
205 строки
4.3 KiB
Plaintext
% 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)];
|
|
}
|
|
|