26#if defined (HAVE_CONFIG_H)
36#include <unordered_map>
94 const std::string& distribution,
bool additional_arg =
false)
98 bool is_single =
false;
100 if (nargin > 0 && args(nargin-1).is_string ())
102 std::string s_arg = args(nargin-1).string_value ();
104 if (s_arg ==
"single")
109 else if (s_arg ==
"double")
116 error (
"%s: at least one argument is required", fcn);
117 else if (args(0).is_string ())
118 additional_arg =
false;
121 a = args(0).xarray_value (
"%s: dimension must be a scalar integer", fcn);
133 ([] (
const std::string& old_distribution)
168 else if (s_arg ==
"seed")
170 else if (s_arg ==
"state" || s_arg ==
"twister")
172 else if (s_arg ==
"uniform")
174 else if (s_arg ==
"normal")
176 else if (s_arg ==
"exponential")
178 else if (s_arg ==
"poisson")
180 else if (s_arg ==
"gamma")
183 error (
"%s: unrecognized string argument", fcn);
191 dims(0) = dims(1) = n;
200 error (
"%s: all elements of range must be integers", fcn);
212 dims(i) = (base >= 0 ? base : 0);
228 error (ee,
"%s: dimensions must be a scalar or array of integers", fcn);
239 dims(i) = (elt >=0 ? elt : 0);
259 if (args(idx+1).is_real_scalar ())
261 double d = args(idx+1).double_value ();
265 else if (args(idx+1).is_string ()
266 && args(idx+1).string_value () ==
"reset")
269 error (
"%s: seed must be a real scalar", fcn);
271 else if (ts ==
"state" || ts ==
"twister")
273 if (args(idx+1).is_string ()
274 && args(idx+1).string_value () ==
"reset")
279 =
ColumnVector (args(idx+1).vector_value (
false,
true));
284 if (math::isinf (s.
xelem (i)))
291 error (
"%s: unrecognized string argument", fcn);
297 for (
int i = 0; i < nargin; i++)
302 dims(i) = (elt >= 0 ? elt : 0);
326 if (a.
dims () != dims)
327 error (
"%s: mismatch in argument size", fcn);
331 float *v = m.rwdata ();
350 if (a.
dims () != dims)
351 error (
"%s: mismatch in argument size", fcn);
355 double *v = m.rwdata ();
472 return do_rand (args, args.
length (),
"rand",
"uniform");
624 return do_rand (args, args.
length (),
"randn",
"normal");
707 return do_rand (args, args.
length (),
"rande",
"exponential");
860 int nargin = args.
length ();
863 error (
"randg: insufficient arguments");
865 return do_rand (args, nargin,
"randg",
"gamma",
true);
1034DEFUN (randp, args, ,
1101 int nargin = args.
length ();
1104 error (
"randp: insufficient arguments");
1106 return do_rand (args, nargin,
"randp",
"poisson",
true);
1199DEFUN (randperm, args, ,
1215 int nargin = args.
length ();
1217 if (nargin < 1 || nargin > 2)
1221 octave_idx_type m = (nargin == 2) ? args(1).idx_type_value (
true) : n;
1224 error (
"randperm: M and N must be non-negative");
1227 error (
"randperm: M must be less than or equal to N");
1231 bool short_shuffle = m < n/5;
1235 double *rvec = r.
rwdata ();
1243 catch (
const std::bad_alloc&)
1248 short_shuffle =
true;
1259 std::unordered_map<octave_idx_type, octave_idx_type> map (m);
1273 std::swap (ivec[i], ivec[k]);
1277 if (map.find (k) == map.end ())
1280 std::swap (ivec[i], map[k]);
1293 std::swap (ivec[i], ivec[k]);
1299 rvec[i] = ivec[i] + 1;
1327template <
typename F>
1329 =
static_cast<F
> (std::uint64_t{1} << std::numeric_limits<F>::digits);
1333template <
typename T>
1337 constexpr double flintmax_val = flintmax_v<double>;
1339 const double rng = (imax - imin) + 1.0;
1340 const double K = std::floor (flintmax_val / rng);
1341 const double K_rng = K * rng;
1346 const double *rdata = rand_vals.
data ();
1349 T *data = result.
rwdata ();
1353 double r_prim = std::floor (rdata[i] * flintmax_val);
1356 while (r_prim >= K_rng)
1359 data[i] =
static_cast<T
> (imin + std::floor (r_prim / K));
1370 constexpr double flintmax_val = flintmax_v<double>;
1372 const double rng = (imax - imin) + 1.0;
1373 const double K = std::floor (flintmax_val / rng);
1374 const double K_rng = K * rng;
1380 double *data = result.
rwdata ();
1384 double r_prim = std::floor (data[i] * flintmax_val);
1387 while (r_prim >= K_rng)
1390 data[i] = imin + std::floor (r_prim / K);
1401 constexpr double flintmax_val = flintmax_v<double>;
1403 const double rng = (imax - imin) + 1.0;
1404 const double K = std::floor (flintmax_val / rng);
1405 const double K_rng = K * rng;
1412 const double *rdata = rand_vals.
data ();
1415 float *data = result.
rwdata ();
1419 double r_prim = std::floor (rdata[i] * flintmax_val);
1422 while (r_prim >= K_rng)
1425 data[i] =
static_cast<float> (imin + std::floor (r_prim / K));
1437 constexpr double flintmax_val = flintmax_v<double>;
1439 const double rng = (imax - imin) + 1.0;
1440 const double K = std::floor (flintmax_val / rng);
1441 const double K_rng = K * rng;
1446 const double *rdata = rand_vals.
data ();
1449 bool *data = result.
rwdata ();
1453 double r_prim = std::floor (rdata[i] * flintmax_val);
1455 while (r_prim >= K_rng)
1459 double value = imin + std::floor (r_prim / K);
1460 data[i] = value > 0.0;
1466DEFUN (randi, args, ,
1515 int nargin = args.
length ();
1520 constexpr double flintmax_dbl = flintmax_v<double>;
1526 error (
"randi: IMIN and IMAX must be integer bounds");
1528 if (bounds_arg.
numel () < 1 || bounds_arg.
numel () > 2)
1529 error (
"randi: first argument must be scalar IMIN or 2-element vector [IMIN, IMAX]");
1536 double val = bounds_array(i);
1537 if (val != std::trunc (val))
1538 error (
"randi: IMIN and IMAX must be integer bounds");
1543 if (bounds_array.
numel () == 1)
1546 imax = bounds_array(0);
1548 error (
"randi: IMAX must be >= 1");
1552 imin = bounds_array(0);
1553 imax = bounds_array(1);
1555 error (
"randi: IMIN must be <= IMAX");
1559 if (std::abs (imax) >= flintmax_dbl || std::abs (imin) >= flintmax_dbl)
1560 error (
"randi: IMIN and IMAX must be smaller than flintmax");
1562 if ((imax - imin) >= (flintmax_dbl - 1.0))
1563 error (
"randi: integer range must be smaller than flintmax-1");
1566 std::string rclass =
"double";
1567 int size_args_end = nargin;
1569 if (nargin > 1 && args(nargin - 1).is_string ())
1571 rclass = args(nargin - 1).string_value ();
1572 size_args_end = nargin - 1;
1577 int size_args_start = 1;
1579 if (size_args_end == size_args_start)
1586 else if (size_args_end == size_args_start + 1)
1599 dims(0) = (n >= 0 ? n : 0);
1600 dims(1) = (n >= 0 ? n : 0);
1611 error (ee,
"randi: dimensions must be a scalar or array of integers");
1620 dims(i) = (
d >= 0 ?
d : 0);
1624 error (
"randi: dimensions must be a scalar or array of integers");
1629 int ndims = size_args_end - size_args_start;
1632 for (
int i = 0; i < ndims; i++)
1635 dims(i) = (
d >= 0 ?
d : 0);
1642 constexpr double flintmax_sgl = flintmax_v<float>;
1644 double maxval, minval;
1645 std::string_view rclass_sv = rclass;
1650 if (rclass_sv ==
"double")
1652 maxval = flintmax_dbl;
1653 minval = -flintmax_dbl;
1656 else if (rclass_sv ==
"single")
1658 maxval = flintmax_sgl;
1659 minval = -flintmax_sgl;
1662 else if (rclass_sv ==
"int8")
1664 maxval = std::numeric_limits<int8_t>::max ();
1665 minval = std::numeric_limits<int8_t>::min ();
1666 generator = do_randi_array<octave_int8>;
1668 else if (rclass_sv ==
"int16")
1670 maxval = std::numeric_limits<int16_t>::max ();
1671 minval = std::numeric_limits<int16_t>::min ();
1672 generator = do_randi_array<octave_int16>;
1674 else if (rclass_sv ==
"int32")
1676 maxval = std::numeric_limits<int32_t>::max ();
1677 minval = std::numeric_limits<int32_t>::min ();
1678 generator = do_randi_array<octave_int32>;
1680 else if (rclass_sv ==
"uint8")
1682 maxval = std::numeric_limits<uint8_t>::max ();
1683 minval = std::numeric_limits<uint8_t>::min ();
1684 generator = do_randi_array<octave_uint8>;
1686 else if (rclass_sv ==
"uint16")
1688 maxval = std::numeric_limits<uint16_t>::max ();
1689 minval = std::numeric_limits<uint16_t>::min ();
1690 generator = do_randi_array<octave_uint16>;
1692 else if (rclass_sv ==
"uint32")
1694 maxval = std::numeric_limits<uint32_t>::max ();
1695 minval = std::numeric_limits<uint32_t>::min ();
1696 generator = do_randi_array<octave_uint32>;
1698 else if (rclass_sv ==
"logical")
1702 maxval = flintmax_dbl;
1703 minval = -flintmax_dbl;
1707 error (
"randi: unknown requested output CLASS '%s'", rclass.c_str ());
1710 warning (
"randi: integer IMAX exceeds requested type. "
1711 "Values might be truncated to requested type.");
1714 warning (
"randi: integer IMIN exceeds requested type. "
1715 "Values might be truncated to requested type.");
1717 return generator (dims, imin, imax);
1885OCTAVE_END_NAMESPACE(octave)
N Dimensional Array with copy-on-write semantics.
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
T & xelem(octave_idx_type n)
Size of the specified dimension.
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Vector representing the dimensions (size) of an Array.
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
void chop_trailing_singletons()
void resize(int n, int fill_value=0)
octave_idx_type length() const
bool is_scalar_type() const
octave_idx_type idx_type_value(bool req_int=false, bool frc_str_conv=false) const
octave_idx_type numel() const
std::string string_value(bool force=false) const
bool is_matrix_type() const
NDArray array_value(bool frc_str_conv=false) const
Array< octave_idx_type > octave_idx_type_vector_value(bool req_int=false, bool frc_str_conv=false, bool frc_vec_conv=false) const
octave::range< double > range_value() const
static FloatNDArray float_nd_array(const dim_vector &dims, float a=1.0)
static uint32NDArray state(const std::string &d="")
static NDArray nd_array(const dim_vector &dims, double a=1.0)
static void uniform_distribution()
static double scalar(double a=1.0)
static void exponential_distribution()
static float float_scalar(float a=1.0)
static void gamma_distribution()
static std::string distribution()
static void normal_distribution()
static void poisson_distribution()
bool all_elements_are_ints() const
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void warning(const char *fmt,...)
void error(const char *fmt,...)
void err_wrong_type_arg(const char *name, const char *s)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Array< bool > do_randi_array< bool >(const dim_vector &dims, double imin, double imax)
Array< float > do_randi_array< float >(const dim_vector &dims, double imin, double imax)
Array< double > do_randi_array< double >(const dim_vector &dims, double imin, double imax)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d