GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
rand.cc
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////*
2//
3// Copyright (C) 1996-2026 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cmath>
31#include <complex>
32#include <cstdint>
33#include <functional>
34#include <limits>
35#include <string_view>
36#include <unordered_map>
37#include <string>
38
39#include "boolNDArray.h"
40#include "CNDArray.h"
41#include "fNDArray.h"
42#include "f77-fcn.h"
43#include "mappers.h"
44#include "oct-inttypes.h"
45#include "oct-rand.h"
46#include "quit.h"
47
48#include "defun.h"
49#include "error.h"
50#include "errwarn.h"
51#include "ovl.h"
52#include "unwind-prot.h"
53#include "utils.h"
54#include "ov-re-mat.h"
55
57
58/*
59%% Restore all rand* "seed" and "state" values in order, so that the
60%% new "state" algorithm remains active after these tests complete.
61%!function restore_rand_states (seed, state)
62%! rand ("seed", seed.rand);
63%! rande ("seed", seed.rande);
64%! randg ("seed", seed.randg);
65%! randn ("seed", seed.randn);
66%! randp ("seed", seed.randp);
67%! rand ("state", state.rand);
68%! rande ("state", state.rande);
69%! randg ("state", state.randg);
70%! randn ("state", state.randn);
71%! randp ("state", state.randp);
72%!endfunction
73
74%!shared __random_statistical_tests__, old_seed, old_state, restore_state
75%! ## Flag whether the statistical tests should be run in "make check" or not
76%! __random_statistical_tests__ = 0;
77%! ## Save and restore the states of each of the random number generators
78%! ## that are tested by the unit tests in this file.
79%! old_seed.rand = rand ("seed");
80%! old_seed.rande = rande ("seed");
81%! old_seed.randg = randg ("seed");
82%! old_seed.randn = randn ("seed");
83%! old_seed.randp = randp ("seed");
84%! old_state.rand = rand ("state");
85%! old_state.rande = rande ("state");
86%! old_state.randg = randg ("state");
87%! old_state.randn = randn ("state");
88%! old_state.randp = randp ("state");
89%! restore_state = onCleanup (@() restore_rand_states (old_seed, old_state));
90*/
91
92static octave_value
93do_rand (const octave_value_list& args, int nargin, const char *fcn,
94 const std::string& distribution, bool additional_arg = false)
95{
96 NDArray a;
97 int idx = 0;
98 bool is_single = false;
99
100 if (nargin > 0 && args(nargin-1).is_string ())
101 {
102 std::string s_arg = args(nargin-1).string_value ();
103
104 if (s_arg == "single")
105 {
106 is_single = true;
107 nargin--;
108 }
109 else if (s_arg == "double")
110 nargin--;
111 }
112
113 if (additional_arg)
114 {
115 if (nargin == 0)
116 error ("%s: at least one argument is required", fcn);
117 else if (args(0).is_string ())
118 additional_arg = false;
119 else
120 {
121 a = args(0).xarray_value ("%s: dimension must be a scalar integer", fcn);
122
123 idx++;
124 nargin--;
125 }
126 }
127
128 octave_value retval;
129 dim_vector dims;
130
131 // Restore current distribution on any exit.
132 unwind_action restore_distribution
133 ([] (const std::string& old_distribution)
134 {
135 rand::distribution (old_distribution);
136 }, rand::distribution ());
137
138 rand::distribution (distribution);
139
140 switch (nargin)
141 {
142 case 0:
143 {
144 if (additional_arg)
145 dims = a.dims ();
146 else
147 {
148 dims.resize (2);
149
150 dims(0) = 1;
151 dims(1) = 1;
152 }
153
154 goto gen_matrix;
155 }
156 break;
157
158 case 1:
159 {
160 octave_value tmp = args(idx);
161
162 if (tmp.is_string ())
163 {
164 std::string s_arg = tmp.string_value ();
165
166 if (s_arg == "dist")
167 retval = rand::distribution ();
168 else if (s_arg == "seed")
169 retval = rand::seed ();
170 else if (s_arg == "state" || s_arg == "twister")
171 retval = rand::state (fcn);
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")
182 else
183 error ("%s: unrecognized string argument", fcn);
184 }
185 else if (tmp.is_scalar_type ())
186 {
187 octave_idx_type n = tmp.idx_type_value (true);
188
189 dims.resize (2);
190
191 dims(0) = dims(1) = n;
192
193 goto gen_matrix;
194 }
195 else if (tmp.is_range ())
196 {
197 range<double> r = tmp.range_value ();
198
199 if (! r.all_elements_are_ints ())
200 error ("%s: all elements of range must be integers", fcn);
201
202 octave_idx_type n = r.numel ();
203
204 dims.resize (n);
205
206 octave_idx_type base = math::nint_big (r.base ());
207 octave_idx_type incr = math::nint_big (r.increment ());
208
209 for (octave_idx_type i = 0; i < n; i++)
210 {
211 // Negative dimensions treated as zero for Matlab compatibility
212 dims(i) = (base >= 0 ? base : 0);
213 base += incr;
214 }
215
216 goto gen_matrix;
217 }
218 else if (tmp.is_matrix_type ())
219 {
221
222 try
223 {
224 iv = tmp.octave_idx_type_vector_value (true);
225 }
226 catch (execution_exception& ee)
227 {
228 error (ee, "%s: dimensions must be a scalar or array of integers", fcn);
229 }
230
231 octave_idx_type len = iv.numel ();
232
233 dims.resize (len);
234
235 for (octave_idx_type i = 0; i < len; i++)
236 {
237 // Negative dimensions treated as zero for Matlab compatibility
238 octave_idx_type elt = iv(i);
239 dims(i) = (elt >=0 ? elt : 0);
240 }
241
242 goto gen_matrix;
243 }
244 else
245 err_wrong_type_arg ("rand", tmp);
246 }
247 break;
248
249 default:
250 {
251 octave_value tmp = args(idx);
252
253 if (nargin == 2 && tmp.is_string ())
254 {
255 std::string ts = tmp.string_value ();
256
257 if (ts == "seed")
258 {
259 if (args(idx+1).is_real_scalar ())
260 {
261 double d = args(idx+1).double_value ();
262
263 rand::seed (d);
264 }
265 else if (args(idx+1).is_string ()
266 && args(idx+1).string_value () == "reset")
267 rand::reset ();
268 else
269 error ("%s: seed must be a real scalar", fcn);
270 }
271 else if (ts == "state" || ts == "twister")
272 {
273 if (args(idx+1).is_string ()
274 && args(idx+1).string_value () == "reset")
275 rand::reset (fcn);
276 else
277 {
279 = ColumnVector (args(idx+1).vector_value (false, true));
280
281 // Backwards compatibility with previous versions of
282 // Octave which mapped Inf to 0.
283 for (octave_idx_type i = 0; i < s.numel (); i++)
284 if (math::isinf (s.xelem (i)))
285 s.xelem (i) = 0.0;
286
287 rand::state (s, fcn);
288 }
289 }
290 else
291 error ("%s: unrecognized string argument", fcn);
292 }
293 else
294 {
295 dims.resize (nargin);
296
297 for (int i = 0; i < nargin; i++)
298 {
299 octave_idx_type elt = args(idx+i).idx_type_value (true);
300
301 // Negative dimensions treated as zero for Matlab compatibility
302 dims(i) = (elt >= 0 ? elt : 0);
303 }
304
305 goto gen_matrix;
306 }
307 }
308 break;
309 }
310
311 // No "goto gen_matrix" in code path. Must be done processing.
312 return retval;
313
314gen_matrix:
315
317
318 if (is_single)
319 {
320 if (additional_arg)
321 {
322 if (a.numel () == 1)
323 return rand::float_nd_array (dims, a(0));
324 else
325 {
326 if (a.dims () != dims)
327 error ("%s: mismatch in argument size", fcn);
328
330 FloatNDArray m (dims);
331 float *v = m.rwdata ();
332
333 for (octave_idx_type i = 0; i < len; i++)
334 v[i] = rand::float_scalar (a(i));
335
336 return m;
337 }
338 }
339 else
340 return rand::float_nd_array (dims);
341 }
342 else
343 {
344 if (additional_arg)
345 {
346 if (a.numel () == 1)
347 return rand::nd_array (dims, a(0));
348 else
349 {
350 if (a.dims () != dims)
351 error ("%s: mismatch in argument size", fcn);
352
354 NDArray m (dims);
355 double *v = m.rwdata ();
356
357 for (octave_idx_type i = 0; i < len; i++)
358 v[i] = rand::scalar (a(i));
359
360 return m;
361 }
362 }
363 else
364 return rand::nd_array (dims);
365 }
366}
367
368DEFUN (rand, args, ,
369 doc: /* -*- texinfo -*-
370@deftypefn {} {@var{x} =} rand ()
371@deftypefnx {} {@var{x} =} rand (@var{n})
372@deftypefnx {} {@var{x} =} rand (@var{m}, @var{n}, @dots{})
373@deftypefnx {} {@var{x} =} rand ([@var{m}, @var{n}, @dots{}])
374@deftypefnx {} {@var{x} =} rand (@dots{}, @var{class})
375@c FIXME: Should implement "like" option for rand function
376@c @deftypefnx {} {@var{x} =} rand (@dots{}, "like", @var{var})
377@deftypefnx {} {@var{v} =} rand ("state")
378@deftypefnx {} {} rand ("state", @var{v})
379@deftypefnx {} {} rand ("state", "reset")
380@deftypefnx {} {@var{v} =} rand ("seed")
381@deftypefnx {} {} rand ("seed", @var{v})
382@deftypefnx {} {} rand ("seed", "reset")
383Return a scalar, matrix, or N-dimensional array whose elements are random
384numbers uniformly distributed on the interval (0, 1).
385
386If called with no arguments, return a scalar random value.
387
388If invoked with a single scalar integer argument @var{n}, return a square
389@nospell{NxN} matrix.
390
391If invoked with two or more scalar integer arguments, or a vector of integer
392values, return an array with the given dimensions.
393
394The optional argument @var{class} specifies the class of the return array.
395The only valid options are @qcode{"double"} (default) or @qcode{"single"}.
396
397Programming Note: Any negative dimensions are treated as zero, and any zero
398dimensions will result in an empty matrix. This odd behavior is for
399@sc{matlab} compatibility.
400
401The additional calling forms provide an interface to the underlying random
402number generator.
403
404You can query the state of the random number generator using the form
405
406@example
407v = rand ("state")
408@end example
409
410This returns a column vector @var{v} of length 625. Later, you can restore
411the random number generator to the state @var{v} using the form
412
413@example
414rand ("state", v)
415@end example
416
417@noindent
418You may also initialize the state vector from an arbitrary vector of length
419@leq{} 625 for @var{v}. The new state will be a hash based on the value of
420@var{v}, not @var{v} itself.
421
422By default, the generator is initialized by contributing entropy from the
423wall clock time, the CPU time, the current fraction of a second, the process
424ID and---if available---up to 1024 bits from the C++ random number source
425@code{random_device}, which might be non-deterministic (implementation
426specific). Note that this differs from @sc{matlab}, which always initializes
427the random number generator to the same state at startup. To obtain behavior
428comparable to @sc{matlab}, initialize with a deterministic state vector in
429Octave's startup files (@pxref{Startup Files}).
430
431Programming Notes: To compute the pseudo-random sequence, @code{rand} uses the
432Mersenne Twister with a period of @math{2^{19937}-1} (See
433@nospell{M. Matsumoto and T. Nishimura}, "Mersenne Twister: A
434623-dimensionally equidistributed uniform pseudorandom number generator",
435@cite{@nospell{ACM Trans.@: on Modeling and Computer Simulation}},
436@w{Vol.@: 8}, @w{No.@: 1}, @w{pp.@: 3}--30, January 1998,
437@url{http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html}).
438Do @strong{not} use for cryptography without securely hashing several returned
439values together, otherwise the generator state can be learned after reading 624
440consecutive values.
441
442Older versions of Octave used a different random number generator. The new
443generator is used by default as it is significantly faster than the old
444generator, and produces random numbers with a significantly longer cycle time.
445However, in some circumstances it might be desirable to obtain the same random
446sequences as produced by the old generators. To do this the keyword
447@qcode{"seed"} is used to specify that the old generators should be used, as in
448
449@example
450rand ("seed", val)
451@end example
452
453@noindent
454which sets the seed of the generator to @var{val}. The seed of the generator
455can be queried with
456
457@example
458s = rand ("seed")
459@end example
460
461However, it should be noted that querying the seed will not cause @code{rand}
462to use the old generators, only setting the seed will. To cause @code{rand} to
463once again use the new generators, the keyword @qcode{"state"} must be used
464to reset @code{rand} back to using the default generator.
465
466The state or seed of the generator can be reset to a new random value using
467the @qcode{"reset"} keyword.
468
469@seealso{randi, randn, rande, randg, randp}
470@end deftypefn */)
471{
472 return do_rand (args, args.length (), "rand", "uniform");
473}
474
475// FIXME: The old generator (selected when "seed" is set) will not
476// work properly if compiled to use 64-bit integers.
477
478/*
479%!test # "state" can be a scalar
480%! rand ("state", 12); x = rand (1,4);
481%! rand ("state", 12); y = rand (1,4);
482%! assert (x, y);
483%!test # "state" can be a vector
484%! rand ("state", [12,13]); x = rand (1,4);
485%! rand ("state", [12;13]); y = rand (1,4);
486%! assert (x, y);
487%!test # querying "state" returns a value which can be used later
488%! s = rand ("state"); x = rand (1,2);
489%! rand ("state", s); y = rand (1,2);
490%! assert (x, y);
491%!test # querying "state" doesn't disturb sequence
492%! rand ("state", 12); rand (1,2); x = rand (1,2);
493%! rand ("state", 12); rand (1,2); s = rand ("state"); y = rand (1,2);
494%! assert (x, y);
495%! rand ("state", s); z = rand (1,2);
496%! assert (x, z);
497%!test # "seed" must be a scalar
498%! rand ("seed", 12); x = rand (1,4);
499%! rand ("seed", 12); y = rand (1,4);
500%! assert (x, y);
501%!error <seed must be a real scalar> rand ("seed", [12,13])
502%!test # querying "seed" returns a value which can be used later
503%! s = rand ("seed"); x = rand (1,2);
504%! rand ("seed", s); y = rand (1,2);
505%! assert (x, y);
506%!test # querying "seed" doesn't disturb sequence
507%! rand ("seed", 12); rand (1,2); x = rand (1,2);
508%! rand ("seed", 12); rand (1,2); s = rand ("seed"); y = rand (1,2);
509%! assert (x, y);
510%! rand ("seed", s); z = rand (1,2);
511%! assert (x, z);
512*/
513
514/*
515%!test
516%! ## Test a known fixed state
517%! rand ("state", 1);
518%! assert (rand (1,6), [0.1343642441124013 0.8474337369372327 0.763774618976614 0.2550690257394218 0.495435087091941 0.4494910647887382], eps);
519%!test
520%! ## Test a known fixed seed
521%! rand ("seed", 1);
522%! assert (rand (1,6), [0.8668024251237512 0.9126510815694928 0.09366085007786751 0.1664607301354408 0.7408077004365623 0.7615650338120759], 1e-6);
523%!test
524%! if (__random_statistical_tests__)
525%! ## statistical tests may fail occasionally.
526%! rand ("state", 12);
527%! x = rand (100_000, 1);
528%! assert (min (x) > 0); #*** Please report this!!! ***
529%! assert (max (x) < 1); #*** Please report this!!! ***
530%! assert (mean (x), 0.5, 0.0024);
531%! assert (var (x), 1/48, 0.0632);
532%! assert (skewness (x), 0, 0.012);
533%! assert (kurtosis (x), -6/5, 0.0094);
534%! endif
535%!test
536%! if (__random_statistical_tests__)
537%! ## statistical tests may fail occasionally.
538%! rand ("seed", 12);
539%! x = rand (100_000, 1);
540%! assert (max (x) < 1); #*** Please report this!!! ***
541%! assert (min (x) > 0); #*** Please report this!!! ***
542%! assert (mean (x), 0.5, 0.0024);
543%! assert (var (x), 1/48, 0.0632);
544%! assert (skewness (x), 0, 0.012);
545%! assert (kurtosis (x), -6/5, 0.0094);
546%! endif
547*/
548
549/*
550## Test out-of-range values as rand() seeds.
551%!function v = __rand_sample__ (initval)
552%! rand ("state", initval);
553%! v = rand (1, 6);
554%!endfunction
555%!
556%!assert (__rand_sample__ (-1), __rand_sample__ (0))
557%!assert (__rand_sample__ (-Inf), __rand_sample__ (0))
558%!assert (__rand_sample__ (2^33), __rand_sample__ (intmax ("uint32")))
559%!assert (__rand_sample__ (Inf), __rand_sample__ (0))
560%!assert (__rand_sample__ (NaN), __rand_sample__ (0))
561*/
562
563/*
564## Note: Matlab compatibility requires using 0 for negative dimensions.
565%!assert (size (rand (1, -1, 2)), [1, 0, 2])
566
567## Test input validation
568%!error <conversion of 1.1 to.* failed> rand (1, 1.1)
569%!error <dimensions must be .* array of integers> rand ([1, 1.1])
570*/
571
572static std::string current_distribution = rand::distribution ();
573
574DEFUN (randn, args, ,
575 doc: /* -*- texinfo -*-
576@deftypefn {} {@var{x} =} randn ()
577@deftypefnx {} {@var{x} =} randn (@var{n})
578@deftypefnx {} {@var{x} =} randn (@var{m}, @var{n}, @dots{})
579@deftypefnx {} {@var{x} =} randn ([@var{m}, @var{n}, @dots{}])
580@deftypefnx {} {@var{x} =} randn (@dots{}, @var{class})
581@c FIXME: Should implement "like" option for randn function
582@c @deftypefnx {} {@var{x} =} randn (@dots{}, "like", @var{var})
583@deftypefnx {} {@var{v} =} randn ("state")
584@deftypefnx {} {} randn ("state", @var{v})
585@deftypefnx {} {} randn ("state", "reset")
586@deftypefnx {} {@var{v} =} randn ("seed")
587@deftypefnx {} {} randn ("seed", @var{v})
588@deftypefnx {} {} randn ("seed", "reset")
589Return a scalar, matrix, or N-dimensional array whose elements are random
590numbers from the standard normal distribution having a mean of @code{0} and a
591variance of @code{1}.
592
593If called with no arguments, return a scalar random value.
594
595If invoked with a single scalar integer argument @var{n}, return a square
596@nospell{NxN} matrix.
597
598If invoked with two or more scalar integer arguments, or a vector of integer
599values, return an array with the given dimensions.
600
601The optional argument @var{class} specifies the class of the return array.
602The only valid options are @qcode{"double"} (default) or @qcode{"single"}.
603
604Programming Note: Any negative dimensions are treated as zero, and any zero
605dimensions will result in an empty matrix. This odd behavior is for
606@sc{matlab} compatibility.
607
608The additional calling forms provide an interface to the underlying random
609number generator. See @ref{XREFrand,,@code{rand}} for documentation on
610querying and controlling the random number generator.
611
612Programming Note: By default, @code{randn} uses the
613@nospell{Marsaglia and Tsang} ``Ziggurat technique'' to transform from a
614uniform to a normal distribution.
615
616Reference: @nospell{G. Marsaglia and W.W. Tsang},
617"Ziggurat Method for Generating Random Variables",
618@cite{J.@tie{}Statistical Software}, @w{Vol.@: 5}, 2000,
619@url{https://www.jstatsoft.org/v05/i08/}
620
621@seealso{rand, randi, rande, randg, randp}
622@end deftypefn */)
623{
624 return do_rand (args, args.length (), "randn", "normal");
625}
626
627/*
628%!test
629%! ## Test a known fixed state
630%! randn ("state", 1);
631%! assert (randn (1, 6), [-2.666521678978671 -0.7381719971724564 1.507903992673601 0.6019427189162239 -0.450661261143348 -0.7054431351574116], 14*eps);
632%!test
633%! ## Test a known fixed seed
634%! randn ("seed", 1);
635%! assert (randn (1, 6), [-1.039402365684509 -1.25938892364502 0.1968704611063004 0.3874166905879974 -0.5976632833480835 -0.6615074276924133], 1e-6);
636%!test
637%! if (__random_statistical_tests__)
638%! ## statistical tests may fail occasionally.
639%! randn ("state", 12);
640%! x = randn (100_000, 1);
641%! assert (mean (x), 0, 0.01);
642%! assert (var (x), 1, 0.02);
643%! assert (skewness (x), 0, 0.02);
644%! assert (kurtosis (x), 0, 0.04);
645%! endif
646%!test
647%! if (__random_statistical_tests__)
648%! ## statistical tests may fail occasionally.
649%! randn ("seed", 12);
650%! x = randn (100_000, 1);
651%! assert (mean (x), 0, 0.01);
652%! assert (var (x), 1, 0.02);
653%! assert (skewness (x), 0, 0.02);
654%! assert (kurtosis (x), 0, 0.04);
655%! endif
656*/
657
658DEFUN (rande, args, ,
659 doc: /* -*- texinfo -*-
660@deftypefn {} {@var{x} =} rande ()
661@deftypefnx {} {@var{x} =} rande (@var{n})
662@deftypefnx {} {@var{x} =} rande (@var{m}, @var{n}, @dots{})
663@deftypefnx {} {@var{x} =} rande ([@var{m}, @var{n}, @dots{}])
664@deftypefnx {} {@var{x} =} rande (@dots{}, @var{class})
665@c FIXME: Should implement "like" option for rande function
666@c @deftypefnx {} {@var{x} =} rande (@dots{}, "like", @var{var})
667@deftypefnx {} {@var{v} =} rande ("state")
668@deftypefnx {} {} rande ("state", @var{v})
669@deftypefnx {} {} rande ("state", "reset")
670@deftypefnx {} {@var{v} =} rande ("seed")
671@deftypefnx {} {} rande ("seed", @var{v})
672@deftypefnx {} {} rande ("seed", "reset")
673Return a scalar, matrix, or N-dimensional array whose elements are random
674numbers from the exponential distribution with rate parameter @code{0}.
675
676If called with no arguments, return a scalar random value.
677
678If invoked with a single scalar integer argument @var{n}, return a square
679@nospell{NxN} matrix.
680
681If invoked with two or more scalar integer arguments, or a vector of integer
682values, return an array with the given dimensions.
683
684The optional argument @var{class} specifies the class of the return array.
685The only valid options are @qcode{"double"} (default) or @qcode{"single"}.
686
687Programming Note: Any negative dimensions are treated as zero, and any zero
688dimensions will result in an empty matrix. This odd behavior is for
689@sc{matlab} compatibility.
690
691The additional calling forms provide an interface to the underlying random
692number generator. See @ref{XREFrand,,@code{rand}} for documentation on
693querying and controlling the random number generator.
694
695Programming Note: By default, @code{rande} uses the
696@nospell{Marsaglia and Tsang} ``Ziggurat technique'' to transform from a
697uniform to an exponential distribution.
698
699Reference: @nospell{G. Marsaglia and W.W. Tsang},
700"Ziggurat Method for Generating Random Variables",
701@cite{J.@tie{}Statistical Software}, @w{Vol@: 5}, 2000,
702@url{https://www.jstatsoft.org/v05/i08/}
703
704@seealso{rand, randi, randn, randg, randp}
705@end deftypefn */)
706{
707 return do_rand (args, args.length (), "rande", "exponential");
708}
709
710/*
711%!test
712%! ## Test a known fixed state
713%! rande ("state", 1);
714%! assert (rande (1, 6), [3.602973885835625 0.1386190677555021 0.6743112889616958 0.4512830847258422 0.7255744741233175 0.3415969205292291], 2*eps);
715%!test
716%! ## Test a known fixed seed
717%! rande ("seed", 1);
718%! assert (rande (1, 6), [0.06492075175653866 1.717980206012726 0.4816154008731246 0.5231300676241517 0.103910739364359 1.668931916356087], 1e-6);
719%!test
720%! if (__random_statistical_tests__)
721%! ## statistical tests may fail occasionally
722%! rande ("state", 1);
723%! x = rande (100_000, 1);
724%! assert (min (x) > 0); # *** Please report this!!! ***
725%! assert (mean (x), 1, 0.01);
726%! assert (var (x), 1, 0.03);
727%! assert (skewness (x), 2, 0.06);
728%! assert (kurtosis (x), 6, 0.7);
729%! endif
730%!test
731%! if (__random_statistical_tests__)
732%! ## statistical tests may fail occasionally
733%! rande ("seed", 1);
734%! x = rande (100_000, 1);
735%! assert (min (x)>0); # *** Please report this!!! ***
736%! assert (mean (x), 1, 0.01);
737%! assert (var (x), 1, 0.03);
738%! assert (skewness (x), 2, 0.06);
739%! assert (kurtosis (x), 6, 0.7);
740%! endif
741*/
742
743DEFUN (randg, args, ,
744 doc: /* -*- texinfo -*-
745@deftypefn {} {@var{x} =} randg (@var{a})
746@deftypefnx {} {@var{x} =} randg (@var{a}, @var{n})
747@deftypefnx {} {@var{x} =} randg (@var{a}, @var{m}, @var{n}, @dots{})
748@deftypefnx {} {@var{x} =} randg (@var{a}, [@var{m}, @var{n}, @dots{}])
749@deftypefnx {} {@var{x} =} randg (@dots{}, @var{class})
750@c FIXME: Should implement "like" option for randg function
751@c @deftypefnx {} {@var{x} =} randg (@dots{}, "like", @var{var})
752@deftypefnx {} {@var{v} =} randg ("state")
753@deftypefnx {} {} randg ("state", @var{v})
754@deftypefnx {} {} randg ("state", "reset")
755@deftypefnx {} {@var{v} =} randg ("seed")
756@deftypefnx {} {} randg ("seed", @var{v})
757@deftypefnx {} {} randg ("seed", "reset")
758Return a scalar, matrix, or N-dimensional array whose elements are random
759numbers from the gamma distribution @code{gamma (@var{a},1)}.
760
761If called with no size arguments, return a scalar random value.
762
763If invoked with a single scalar size argument @var{n}, return a square
764@nospell{NxN} matrix.
765
766If invoked with two or more scalar integer size arguments, or a vector of
767integer values, return an array with the given dimensions.
768
769The optional argument @var{class} specifies the class of the return array.
770The only valid options are @qcode{"double"} (default) or @qcode{"single"}.
771
772Programming Note: Any negative dimensions are treated as zero, and any zero
773dimensions will result in an empty matrix. This odd behavior is for
774@sc{matlab} compatibility.
775
776The additional calling forms provide an interface to the underlying random
777number generator. See @ref{XREFrand,,@code{rand}} for documentation on
778querying and controlling the random number generator.
779
780Programming Notes: The gamma distribution can be used to generate many
781other distributions:
782
783@table @asis
784@item @code{gamma (a, b)} for @code{a > -1}, @code{b > 0}
785
786@example
787r = b * randg (a)
788@end example
789
790@item @code{beta (a, b)} for @code{a > -1}, @code{b > -1}
791
792@example
793@group
794r1 = randg (a, 1)
795r = r1 / (r1 + randg (b, 1))
796@end group
797@end example
798
799@item @code{Erlang (a, n)}
800
801@example
802r = a * randg (n)
803@end example
804
805@item @code{chisq (df)} for @code{df > 0}
806
807@example
808r = 2 * randg (df / 2)
809@end example
810
811@item @code{t (df)} for @code{0 < df < inf} (use randn if df is infinite)
812
813@example
814r = randn () / sqrt (2 * randg (df / 2) / df)
815@end example
816
817@item @code{F (n1, n2)} for @code{0 < n1}, @code{0 < n2}
818
819@example
820@group
821## r1 equals 1 if n1 is infinite
822r1 = 2 * randg (n1 / 2) / n1
823## r2 equals 1 if n2 is infinite
824r2 = 2 * randg (n2 / 2) / n2
825r = r1 / r2
826@end group
827@end example
828
829@item negative @code{binomial (n, p)} for @code{n > 0}, @code{0 < p <= 1}
830
831@example
832r = randp ((1 - p) / p * randg (n))
833@end example
834
835@item non-central @code{chisq (df, L)}, for @code{df >= 0} and @code{L > 0}
836(use chisq if @code{L = 0})
837
838@example
839@group
840r = randp (L / 2)
841r(r > 0) = 2 * randg (r(r > 0))
842r(df > 0) += 2 * randg (df(df > 0)/2)
843@end group
844@end example
845
846@item @code{Dirichlet (a1, @dots{} ak)}
847
848@example
849@group
850r = (randg (a1), @dots{}, randg (ak))
851r = r / sum (r)
852@end group
853@end example
854
855@end table
856
857@seealso{rand, randi, randn, rande, randp}
858@end deftypefn */)
859{
860 int nargin = args.length ();
861
862 if (nargin < 1)
863 error ("randg: insufficient arguments");
864
865 return do_rand (args, nargin, "randg", "gamma", true);
866}
867
868/*
869%!test
870%! randg ("state", 12);
871%! assert (randg ([-inf, -1, 0, inf, NaN]), [NaN, NaN, NaN, NaN, NaN]);
872
873%!test
874%! ## Test a known fixed state
875%! randg ("state", 1);
876%! assert (randg (0.1, 1, 6), [0.0103951513331241 8.335671459898252e-05 0.00138691397249762 0.000587308416993855 0.495590518784736 2.3921917414795e-12], eps);
877%!test
878%! ## Test a known fixed state
879%! randg ("state", 1);
880%! assert (randg (0.95, 1, 6), [3.099382433255327 0.3974529788871218 0.644367450750855 1.143261091802246 1.964111762696822 0.04011915547957939], 12*eps);
881%!test
882%! ## Test a known fixed state
883%! randg ("state", 1);
884%! assert (randg (1, 1, 6), [0.2273389379645993 1.288822625058359 0.2406335209340746 1.218869553370733 1.024649860162554 0.09631230343599533], 40*eps);
885%!test
886%! ## Test a known fixed state
887%! randg ("state", 1);
888%! assert (randg (10, 1, 6), [3.520369644331133 15.15369864472106 8.332112081991205 8.406211067432674 11.81193475187611 10.88792728177059], 56*eps);
889%!test
890%! ## Test a known fixed state
891%! randg ("state", 1);
892%! assert (randg (100, 1, 6), [75.34570255262264 115.4911985594699 95.23493031356388 95.48926019250911 106.2397448229803 103.4813150404118], 256*eps);
893%!test
894%! ## Test a known fixed seed
895%! randg ("seed", 1);
896%! assert (randg (0.1, 1, 6), [0.07144210487604141 0.460641473531723 0.4749028384685516 0.06823389977216721 0.000293838675133884 1.802567535340305e-12], 1e-6);
897%!test
898%! ## Test a known fixed seed
899%! randg ("seed", 1);
900%! assert (randg (0.95, 1, 6), [1.664905071258545 1.879976987838745 1.905677795410156 0.9948706030845642 0.5606933236122131 0.0766092911362648], 1e-6);
901%!test
902%! ## Test a known fixed seed
903%! randg ("seed", 1);
904%! assert (randg (1, 1, 6), [0.03512085229158401 0.6488978862762451 0.8114678859710693 0.1666885763406754 1.60791552066803 1.90356981754303], 1e-6);
905%!test
906%! ## Test a known fixed seed
907%! randg ("seed", 1);
908%! assert (randg (10, 1, 6), [6.566435813903809 10.11648464202881 10.73162078857422 7.747178077697754 6.278522491455078 6.240195751190186], 1e-5);
909%!test
910%! ## Test a known fixed seed
911%! randg ("seed", 1);
912%! assert (randg (100, 1, 6), [89.40208435058594 101.4734725952148 103.4020004272461 93.62763214111328 88.33104705810547 88.1871337890625], 1e-4);
913%!test
914%! ## Test out-of-bounds values produce NaN w/old-style generators & floats
915%! randg ("seed", 1);
916%! result = randg ([-2 Inf], "single");
917%! assert (result, single ([NaN NaN]));
918
919%!test
920%! if (__random_statistical_tests__)
921%! ## statistical tests may fail occasionally.
922%! randg ("state", 12);
923%! a = 0.1;
924%! x = randg (a, 100_000, 1);
925%! assert (mean (x), a, 0.01);
926%! assert (var (x), a, 0.01);
927%! assert (skewness (x), 2/sqrt (a), 1);
928%! assert (kurtosis (x), 6/a, 50);
929%! endif
930%!test
931%! if (__random_statistical_tests__)
932%! ## statistical tests may fail occasionally.
933%! randg ("state", 12);
934%! a = 0.95;
935%! x = randg (a, 100_000, 1);
936%! assert (mean (x), a, 0.01);
937%! assert (var (x), a, 0.04);
938%! assert (skewness (x), 2/sqrt (a), 0.2);
939%! assert (kurtosis (x), 6/a, 2);
940%! endif
941%!test
942%! if (__random_statistical_tests__)
943%! ## statistical tests may fail occasionally.
944%! randg ("state", 12);
945%! a = 1;
946%! x = randg (a, 100_000, 1);
947%! assert (mean (x), a, 0.01);
948%! assert (var (x), a, 0.04);
949%! assert (skewness (x), 2/sqrt (a), 0.2);
950%! assert (kurtosis (x), 6/a, 2);
951%! endif
952%!test
953%! if (__random_statistical_tests__)
954%! ## statistical tests may fail occasionally.
955%! randg ("state", 12);
956%! a = 10;
957%! x = randg (a, 100_000, 1);
958%! assert (mean (x), a, 0.1);
959%! assert (var (x), a, 0.5);
960%! assert (skewness (x), 2/sqrt (a), 0.1);
961%! assert (kurtosis (x), 6/a, 0.5);
962%! endif
963%!test
964%! if (__random_statistical_tests__)
965%! ## statistical tests may fail occasionally.
966%! randg ("state", 12);
967%! a = 100;
968%! x = randg (a, 100_000, 1);
969%! assert (mean (x), a, 0.2);
970%! assert (var (x), a, 2);
971%! assert (skewness (x), 2/sqrt (a), 0.05);
972%! assert (kurtosis (x), 6/a, 0.2);
973%! endif
974%!test
975%! randg ("seed", 12);
976%! assert (randg ([-inf, -1, 0, inf, NaN]), [NaN, NaN, NaN, NaN, NaN]);
977%!test
978%! if (__random_statistical_tests__)
979%! ## statistical tests may fail occasionally.
980%! randg ("seed", 12);
981%! a = 0.1;
982%! x = randg (a, 100_000, 1);
983%! assert (mean (x), a, 0.01);
984%! assert (var (x), a, 0.01);
985%! assert (skewness (x), 2/sqrt (a), 1);
986%! assert (kurtosis (x), 6/a, 50);
987%! endif
988%!test
989%! if (__random_statistical_tests__)
990%! ## statistical tests may fail occasionally.
991%! randg ("seed", 12);
992%! a = 0.95;
993%! x = randg (a, 100_000, 1);
994%! assert (mean (x), a, 0.01);
995%! assert (var (x), a, 0.04);
996%! assert (skewness (x), 2/sqrt (a), 0.2);
997%! assert (kurtosis (x), 6/a, 2);
998%! endif
999%!test
1000%! if (__random_statistical_tests__)
1001%! ## statistical tests may fail occasionally.
1002%! randg ("seed", 12);
1003%! a = 1;
1004%! x = randg (a, 100_000, 1);
1005%! assert (mean (x), a, 0.01);
1006%! assert (var (x), a, 0.04);
1007%! assert (skewness (x), 2/sqrt (a), 0.2);
1008%! assert (kurtosis (x), 6/a, 2);
1009%! endif
1010%!test
1011%! if (__random_statistical_tests__)
1012%! ## statistical tests may fail occasionally.
1013%! randg ("seed", 12);
1014%! a = 10;
1015%! x = randg (a, 100_000, 1);
1016%! assert (mean (x), a, 0.1);
1017%! assert (var (x), a, 0.5);
1018%! assert (skewness (x), 2/sqrt (a), 0.1);
1019%! assert (kurtosis (x), 6/a, 0.5);
1020%! endif
1021%!test
1022%! if (__random_statistical_tests__)
1023%! ## statistical tests may fail occasionally.
1024%! randg ("seed", 12);
1025%! a = 100;
1026%! x = randg (a, 100_000, 1);
1027%! assert (mean (x), a, 0.2);
1028%! assert (var (x), a, 2);
1029%! assert (skewness (x), 2/sqrt (a), 0.05);
1030%! assert (kurtosis (x), 6/a, 0.2);
1031%! endif
1032*/
1033
1034DEFUN (randp, args, ,
1035 doc: /* -*- texinfo -*-
1036@deftypefn {} {@var{x} =} randp (@var{l})
1037@deftypefnx {} {@var{x} =} randp (@var{l}, @var{n})
1038@deftypefnx {} {@var{x} =} randp (@var{l}, @var{m}, @var{n}, @dots{})
1039@deftypefnx {} {@var{x} =} randp (@var{l}, [@var{m}, @var{n}, @dots{}])
1040@deftypefnx {} {@var{x} =} randp (@dots{}, @var{class})
1041@c FIXME: Should implement "like" option for randp function
1042@c @deftypefnx {} {@var{x} =} randp (@dots{}, "like", @var{var})
1043@deftypefnx {} {@var{v} =} randp ("state")
1044@deftypefnx {} {} randp ("state", @var{v})
1045@deftypefnx {} {} randp ("state", "reset")
1046@deftypefnx {} {@var{v} =} randp ("seed")
1047@deftypefnx {} {} randp ("seed", @var{v})
1048@deftypefnx {} {} randp ("seed", "reset")
1049Return a scalar, matrix, or N-dimensional array whose elements are random
1050numbers from the Poisson distribution with mean value parameter @var{l}.
1051
1052If called with no size arguments, return a scalar random value.
1053
1054If invoked with a single scalar size argument @var{n}, return a square
1055@nospell{NxN} matrix.
1056
1057If invoked with two or more scalar integer size arguments, or a vector of
1058integer values, return an array with the given dimensions.
1059
1060The optional argument @var{class} specifies the class of the return array.
1061The only valid options are @qcode{"double"} (default) or @qcode{"single"}.
1062
1063Programming Note: Any negative dimensions are treated as zero, and any zero
1064dimensions will result in an empty matrix. This odd behavior is for
1065@sc{matlab} compatibility.
1066
1067The additional calling forms provide an interface to the underlying random
1068number generator. See @ref{XREFrand,,@code{rand}} for documentation on
1069querying and controlling the random number generator.
1070
1071Programming Notes: Five different algorithms are used depending on the range of
1072@var{l} and whether @var{l} is a scalar or a matrix.
1073
1074@table @asis
1075@item For scalar @var{l} @leq{} 12, use direct method.
1076@nospell{W.H.@tie{}Press}, et@tie{}al., @cite{Numerical Recipes in C},
1077Cambridge University Press, 1992.
1078
1079@item For scalar @var{l} > 12, use rejection method.[1]
1080@nospell{W.H.@tie{}Press}, et@tie{}al., @cite{Numerical Recipes in C},
1081Cambridge University Press, 1992.
1082
1083@item For matrix @var{l} @leq{} 10, use inversion method.[2]
1084@nospell{E.@tie{}Stadlober, et@tie{}al., WinRand source code}, available via
1085FTP.
1086
1087@item For matrix @var{l} > 10, use patchwork rejection method.
1088@nospell{E.@tie{}Stadlober, et@tie{}al., WinRand source code}, available via
1089FTP, or @nospell{H.@tie{}Zechner}, @cite{Efficient sampling from continuous and
1090discrete unimodal distributions}, Doctoral Dissertation, @w{pp.@: 156},
1091Technical University @nospell{Graz}, Austria, 1994.
1092
1093@item For @var{l} > 1e8, use normal approximation.
1094@nospell{L.@tie{}Montanet}, et@tie{}al., "Review of Particle Properties",
1095@cite{Physical Review@tie{}D}, 50, @w{p.@: 1284}, 1994.
1096@end table
1097
1098@seealso{rand, randi, randn, rande, randg}
1099@end deftypefn */)
1100{
1101 int nargin = args.length ();
1102
1103 if (nargin < 1)
1104 error ("randp: insufficient arguments");
1105
1106 return do_rand (args, nargin, "randp", "poisson", true);
1107}
1108
1109/*
1110%!test
1111%! randp ("state", 12);
1112%! assert (randp ([-inf, -1, 0, inf, NaN]), [NaN, NaN, 0, NaN, NaN]);
1113%!test
1114%! ## Test a known fixed state
1115%! randp ("state", 1);
1116%! assert (randp (5, 1, 6), [5 5 3 7 7 3]);
1117%!test
1118%! ## Test a known fixed state
1119%! randp ("state", 1);
1120%! assert (randp (15, 1, 6), [13 15 8 18 18 15]);
1121%!test
1122%! ## Test a known fixed state
1123%! randp ("state", 1);
1124%! assert (randp (1e9, 1, 6),
1125%! [999915677 999976657 1000047684 1000019035 999985749 999977692],
1126%! -1e-6);
1127%!test
1128%! ## Test a known fixed seed
1129%! randp ("seed", 1);
1130%! %%assert (randp (5, 1, 6), [8 2 3 6 6 8])
1131%! assert (randp (5, 1, 5), [8 2 3 6 6]);
1132%!test
1133%! ## Test a known fixed seed
1134%! randp ("seed", 1);
1135%! assert (randp (15, 1, 6), [15 16 12 10 10 12]);
1136%!test
1137%! ## Test a known fixed seed
1138%! randp ("seed", 1);
1139%! assert (randp (1e9, 1, 6),
1140%! [1000006208 1000012224 999981120 999963520 999963072 999981440],
1141%! -1e-6);
1142%!test
1143%! if (__random_statistical_tests__)
1144%! ## statistical tests may fail occasionally.
1145%! randp ("state", 12);
1146%! for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
1147%! x = randp (a (1), 100_000, 1);
1148%! assert (min (x) >= 0); # *** Please report this!!! ***
1149%! assert (mean (x), a(1), a(2));
1150%! assert (var (x), a(1), 0.02*a(1));
1151%! assert (skewness (x), 1/sqrt (a(1)), a(3));
1152%! assert (kurtosis (x), 1/a(1), 3*a(3));
1153%! endfor
1154%! endif
1155%!test
1156%! if (__random_statistical_tests__)
1157%! ## statistical tests may fail occasionally.
1158%! randp ("state", 12);
1159%! for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
1160%! x = randp (a(1)* ones (100_000, 1), 100_000, 1);
1161%! assert (min (x) >= 0); # *** Please report this!!! ***
1162%! assert (mean (x), a(1), a(2));
1163%! assert (var (x), a(1), 0.02*a(1));
1164%! assert (skewness (x), 1/sqrt (a(1)), a(3));
1165%! assert (kurtosis (x), 1/a(1), 3*a(3));
1166%! endfor
1167%! endif
1168%!test
1169%! randp ("seed", 12);
1170%! assert (randp ([-inf, -1, 0, inf, NaN]), [NaN, NaN, 0, NaN, NaN]);
1171%!test
1172%! if (__random_statistical_tests__)
1173%! ## statistical tests may fail occasionally.
1174%! randp ("seed", 12);
1175%! for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
1176%! x = randp (a(1), 100_000, 1);
1177%! assert (min (x) >= 0); # *** Please report this!!! ***
1178%! assert (mean (x), a(1), a(2));
1179%! assert (var (x), a(1), 0.02*a(1));
1180%! assert (skewness (x), 1/sqrt (a(1)), a(3));
1181%! assert (kurtosis (x), 1/a(1), 3*a(3));
1182%! endfor
1183%! endif
1184%!test
1185%! if (__random_statistical_tests__)
1186%! ## statistical tests may fail occasionally.
1187%! randp ("seed", 12);
1188%! for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
1189%! x = randp (a(1)* ones (100_000, 1), 100_000, 1);
1190%! assert (min (x) >= 0); # *** Please report this!!! ***
1191%! assert (mean (x), a(1), a(2));
1192%! assert (var (x), a(1), 0.02*a(1));
1193%! assert (skewness (x), 1/sqrt (a(1)), a(3));
1194%! assert (kurtosis (x), 1/a(1), 3*a(3));
1195%! endfor
1196%! endif
1197*/
1198
1199DEFUN (randperm, args, ,
1200 doc: /* -*- texinfo -*-
1201@deftypefn {} {@var{v} =} randperm (@var{n})
1202@deftypefnx {} {@var{v} =} randperm (@var{n}, @var{m})
1203Return a row vector containing a random permutation of @code{1:@var{n}}.
1204
1205If @var{m} is supplied, return @var{m} unique entries, sampled without
1206replacement from @code{1:@var{n}}.
1207
1208The complexity is O(@var{n}) in memory and O(@var{m}) in time, unless
1209@var{m} < @var{n}/5, in which case O(@var{m}) memory is used as well. The
1210randomization is performed using rand(). All permutations are equally
1211likely.
1212@seealso{perms}
1213@end deftypefn */)
1214{
1215 int nargin = args.length ();
1216
1217 if (nargin < 1 || nargin > 2)
1218 print_usage ();
1219
1220 octave_idx_type n = args(0).idx_type_value (true);
1221 octave_idx_type m = (nargin == 2) ? args(1).idx_type_value (true) : n;
1222
1223 if (m < 0 || n < 0)
1224 error ("randperm: M and N must be non-negative");
1225
1226 if (m > n)
1227 error ("randperm: M must be less than or equal to N");
1228
1229 // Quick and dirty heuristic to decide if we allocate or not the
1230 // whole vector for tracking the truncated shuffle.
1231 bool short_shuffle = m < n/5;
1232
1233 // Generate random numbers.
1234 NDArray r = rand::nd_array (dim_vector (1, m));
1235 double *rvec = r.rwdata ();
1236
1237 octave_idx_type idx_len = (short_shuffle ? m : n);
1239 try
1240 {
1241 idx = Array<octave_idx_type> (dim_vector (1, idx_len));
1242 }
1243 catch (const std::bad_alloc&)
1244 {
1245 // Looks like n is too big and short_shuffle is false.
1246 // Let's try again, but this time with the alternative.
1247 idx_len = m;
1248 short_shuffle = true;
1249 idx = Array<octave_idx_type> (dim_vector (1, idx_len));
1250 }
1251
1252 octave_idx_type *ivec = idx.rwdata ();
1253
1254 for (octave_idx_type i = 0; i < idx_len; i++)
1255 ivec[i] = i;
1256
1257 if (short_shuffle)
1258 {
1259 std::unordered_map<octave_idx_type, octave_idx_type> map (m);
1260
1261 // Perform the Knuth shuffle only keeping track of moved
1262 // entries in the map
1263 for (octave_idx_type i = 0; i < m; i++)
1264 {
1265 // rand() gives u in [0,1). For non-negative values, truncation is
1266 // equivalent to floor, so static_cast<octave_idx_type> (u * span)
1267 // is safe and avoids the cost of std::floor.
1268 octave_idx_type k = i + static_cast<octave_idx_type> (rvec[i] * (n - i));
1269
1270 // For shuffling first m entries, no need to use extra storage
1271 if (k < m)
1272 {
1273 std::swap (ivec[i], ivec[k]);
1274 }
1275 else
1276 {
1277 if (map.find (k) == map.end ())
1278 map[k] = k;
1279
1280 std::swap (ivec[i], map[k]);
1281 }
1282 }
1283 }
1284 else
1285 {
1286 // Perform the Knuth shuffle of the first m entries
1287 for (octave_idx_type i = 0; i < m; i++)
1288 {
1289 // rand() gives u in [0,1). For non-negative values, truncation is
1290 // equivalent to floor, so static_cast<octave_idx_type> (u * span)
1291 // is safe and avoids the cost of std::floor.
1292 octave_idx_type k = i + static_cast<octave_idx_type> (rvec[i] * (n - i));
1293 std::swap (ivec[i], ivec[k]);
1294 }
1295 }
1296
1297 // Convert to doubles, reusing r.
1298 for (octave_idx_type i = 0; i < m; i++)
1299 rvec[i] = ivec[i] + 1;
1300
1301 if (m < n)
1302 idx.resize (dim_vector (1, m));
1303
1304 // Now create an array object with a cached idx_vector.
1305 return ovl (new octave_matrix (r, idx_vector (idx)));
1306}
1307
1308/*
1309%!assert (sort (randperm (20)), 1:20)
1310%!assert (length (randperm (20,10)), 10)
1311
1312## Test biggish N
1313%!assert <*39378> (length (randperm (30_000^2, 100_000)), 100_000)
1314
1315%!test
1316%! rand ("seed", 0);
1317%! for i = 1:100
1318%! p = randperm (305, 30);
1319%! assert (length (unique (p)), 30);
1320%! endfor
1321*/
1322
1323// ================== port of randi.m ========================
1324
1325// flintmax: largest consecutive integer representable in floating point
1326// For IEEE 754 double: 2^53, for float: 2^24
1327template <typename F>
1328inline constexpr F flintmax_v
1329 = static_cast<F> (std::uint64_t{1} << std::numeric_limits<F>::digits);
1330
1331// Template function to fill array with random integers and cast to target type
1332// Uses rejection sampling to ensure unbiased results.
1333template <typename T>
1334static Array<T>
1335do_randi_array (const dim_vector& dims, double imin, double imax)
1336{
1337 constexpr double flintmax_val = flintmax_v<double>;
1338
1339 const double rng = (imax - imin) + 1.0;
1340 const double K = std::floor (flintmax_val / rng);
1341 const double K_rng = K * rng;
1342
1343 const octave_idx_type n = dims.numel ();
1344
1345 NDArray rand_vals = rand::nd_array (dims);
1346 const double *rdata = rand_vals.data ();
1347
1348 Array<T> result (dims);
1349 T *data = result.rwdata ();
1350
1351 for (octave_idx_type i = 0; i < n; i++)
1352 {
1353 double r_prim = std::floor (rdata[i] * flintmax_val);
1354
1355 // Rejection loop - rarely needed since K_rng is very close to flintmax
1356 while (r_prim >= K_rng)
1357 r_prim = std::floor (rand::scalar () * flintmax_val);
1358
1359 data[i] = static_cast<T> (imin + std::floor (r_prim / K));
1360 }
1361
1362 return result;
1363}
1364
1365// Specialization for double: work in-place to avoid extra allocation
1366template <>
1368do_randi_array<double> (const dim_vector& dims, double imin, double imax)
1369{
1370 constexpr double flintmax_val = flintmax_v<double>;
1371
1372 const double rng = (imax - imin) + 1.0;
1373 const double K = std::floor (flintmax_val / rng);
1374 const double K_rng = K * rng;
1375
1376 const octave_idx_type n = dims.numel ();
1377
1378 // Generate random values and transform in-place
1379 NDArray result = rand::nd_array (dims);
1380 double *data = result.rwdata ();
1381
1382 for (octave_idx_type i = 0; i < n; i++)
1383 {
1384 double r_prim = std::floor (data[i] * flintmax_val);
1385
1386 // Rejection loop - rarely needed since K_rng is very close to flintmax
1387 while (r_prim >= K_rng)
1388 r_prim = std::floor (rand::scalar () * flintmax_val);
1389
1390 data[i] = imin + std::floor (r_prim / K);
1391 }
1392
1393 return result;
1394}
1395
1396// Specialization for float: work in-place to avoid extra allocation
1397template <>
1399do_randi_array<float> (const dim_vector& dims, double imin, double imax)
1400{
1401 constexpr double flintmax_val = flintmax_v<double>;
1402
1403 const double rng = (imax - imin) + 1.0;
1404 const double K = std::floor (flintmax_val / rng);
1405 const double K_rng = K * rng;
1406
1407 const octave_idx_type n = dims.numel ();
1408
1409 // Generate random values in bulk, then transform
1410 // Use double precision for intermediate calculations to maintain accuracy
1411 NDArray rand_vals = rand::nd_array (dims);
1412 const double *rdata = rand_vals.data ();
1413
1414 FloatNDArray result (dims);
1415 float *data = result.rwdata ();
1416
1417 for (octave_idx_type i = 0; i < n; i++)
1418 {
1419 double r_prim = std::floor (rdata[i] * flintmax_val);
1420
1421 // Rejection loop - rarely needed since K_rng is very close to flintmax
1422 while (r_prim >= K_rng)
1423 r_prim = std::floor (rand::scalar () * flintmax_val);
1424
1425 data[i] = static_cast<float> (imin + std::floor (r_prim / K));
1426 }
1427
1428 return result;
1429}
1430
1431// Specialization for bool (logical): MATLAB uses value > 0, not value != 0
1432// so calls like randi ([-1, 0], 3, 3, 'logical') return all zeros.
1433template <>
1435do_randi_array<bool> (const dim_vector& dims, double imin, double imax)
1436{
1437 constexpr double flintmax_val = flintmax_v<double>;
1438
1439 const double rng = (imax - imin) + 1.0;
1440 const double K = std::floor (flintmax_val / rng);
1441 const double K_rng = K * rng;
1442
1443 const octave_idx_type n = dims.numel ();
1444
1445 NDArray rand_vals = rand::nd_array (dims);
1446 const double *rdata = rand_vals.data ();
1447
1448 boolNDArray result (dims);
1449 bool *data = result.rwdata ();
1450
1451 for (octave_idx_type i = 0; i < n; i++)
1452 {
1453 double r_prim = std::floor (rdata[i] * flintmax_val);
1454
1455 while (r_prim >= K_rng)
1456 r_prim = std::floor (rand::scalar () * flintmax_val);
1457
1458 // MATLAB logical: value > 0 gives true, otherwise false
1459 double value = imin + std::floor (r_prim / K);
1460 data[i] = value > 0.0;
1461 }
1462
1463 return result;
1464}
1465
1466DEFUN (randi, args, ,
1467 doc: /* -*- texinfo -*-
1468@deftypefn {} {@var{R} =} randi (@var{imax})
1469@deftypefnx {} {@var{R} =} randi (@var{imax}, @var{n})
1470@deftypefnx {} {@var{R} =} randi (@var{imax}, @var{m}, @var{n}, @dots{})
1471@deftypefnx {} {@var{R} =} randi (@var{imax}, [@var{m}, @var{n}, @dots{}])
1472@deftypefnx {} {@var{R} =} randi ([@var{imin}, @var{imax}], @dots{})
1473@deftypefnx {} {@var{R} =} randi (@dots{}, "@var{class}")
1474Return a scalar, matrix, or N-dimensional array whose elements are random
1475integers in the range @w{[1, @var{imax}]}.
1476
1477If called with no size arguments, return a scalar random value.
1478
1479If invoked with a single scalar size argument @var{n}, return a square
1480@nospell{NxN} matrix.
1481
1482If invoked with two or more scalar integer size arguments, or a vector of
1483integer values, return an array with the given dimensions.
1484
1485The integer range may optionally be described by a two-element matrix with a
1486lower and upper bound in which case the returned integers will be on the
1487interval @w{[@var{imin}, @var{imax}]}.
1488
1489The optional argument @var{class} will return a matrix of the requested type.
1490The default is @qcode{"double"}. Supported classes are: @qcode{"double"},
1491@qcode{"single"}, @qcode{"int8"}, @qcode{"int16"}, @qcode{"int32"},
1492@qcode{"uint8"}, @qcode{"uint16"}, @qcode{"uint32"}, and @qcode{"logical"}.
1493
1494Programming Notes: @code{randi} relies internally on @code{rand} which uses
1495class @qcode{"double"} to represent numbers. This limits the maximum integer
1496(@var{imax}) and range (@var{imax} - @var{imin}) to the value returned by the
1497@code{flintmax} function. For IEEE@tie{}754 floating point numbers this value
1498is @w{@math{2^{53} - 1}}.
1499
1500When the output class is @qcode{"logical"} the function constructs an array of
1501random integers as specified and then applies the test @w{@code{@var{x} > 0}}
1502to determine which elements will be true. Because the one-input form of the
1503function uses @code{1} for @var{imin} @code{randi} will always return a matrix
1504of all ones.
1505
1506Example: 150 integers in the range 1--10.
1507
1508@example
1509ri = randi (10, 150, 1)
1510@end example
1511
1512@seealso{rand, randn, rande, randg, randp}
1513@end deftypefn */)
1514{
1515 int nargin = args.length ();
1516
1517 if (nargin < 1)
1518 print_usage ();
1519
1520 constexpr double flintmax_dbl = flintmax_v<double>;
1521
1522 // Parse bounds argument
1523 octave_value bounds_arg = args(0);
1524
1525 if (! bounds_arg.isnumeric ())
1526 error ("randi: IMIN and IMAX must be integer bounds");
1527
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]");
1530
1531 NDArray bounds_array = bounds_arg.array_value ();
1532
1533 // Check that all bounds are integers
1534 for (octave_idx_type i = 0; i < bounds_array.numel (); i++)
1535 {
1536 double val = bounds_array(i);
1537 if (val != std::trunc (val))
1538 error ("randi: IMIN and IMAX must be integer bounds");
1539 }
1540
1541 double imin, imax;
1542
1543 if (bounds_array.numel () == 1)
1544 {
1545 imin = 1.0;
1546 imax = bounds_array(0);
1547 if (imax < 1)
1548 error ("randi: IMAX must be >= 1");
1549 }
1550 else
1551 {
1552 imin = bounds_array(0);
1553 imax = bounds_array(1);
1554 if (imax < imin)
1555 error ("randi: IMIN must be <= IMAX");
1556 }
1557
1558 // Check bounds against flintmax
1559 if (std::abs (imax) >= flintmax_dbl || std::abs (imin) >= flintmax_dbl)
1560 error ("randi: IMIN and IMAX must be smaller than flintmax");
1561
1562 if ((imax - imin) >= (flintmax_dbl - 1.0))
1563 error ("randi: integer range must be smaller than flintmax-1");
1564
1565 // Parse optional class argument (must be last if present)
1566 std::string rclass = "double";
1567 int size_args_end = nargin;
1568
1569 if (nargin > 1 && args(nargin - 1).is_string ())
1570 {
1571 rclass = args(nargin - 1).string_value ();
1572 size_args_end = nargin - 1;
1573 }
1574
1575 // Parse size arguments
1576 dim_vector dims;
1577 int size_args_start = 1;
1578
1579 if (size_args_end == size_args_start)
1580 {
1581 // No size arguments - return scalar
1582 dims.resize (2);
1583 dims(0) = 1;
1584 dims(1) = 1;
1585 }
1586 else if (size_args_end == size_args_start + 1)
1587 {
1588 // Single size argument
1589 octave_value size_arg = args(size_args_start);
1590
1591 if (size_arg.is_scalar_type ())
1592 {
1593 // FIXME: idx_type_value () produces a generic error
1594 // "conversion of XX to int64_t value failed".
1595 // It might be nicer at some point to use try/catch block to map
1596 // this to a nicer error message about dimensions must be integers.
1597 octave_idx_type n = size_arg.idx_type_value (true);
1598 dims.resize (2);
1599 dims(0) = (n >= 0 ? n : 0);
1600 dims(1) = (n >= 0 ? n : 0);
1601 }
1602 else if (size_arg.is_matrix_type () || size_arg.is_range ())
1603 {
1604 Array<octave_idx_type> size_vec;
1605 try
1606 {
1607 size_vec = size_arg.octave_idx_type_vector_value (true);
1608 }
1609 catch (execution_exception& ee)
1610 {
1611 error (ee, "randi: dimensions must be a scalar or array of integers");
1612 }
1613
1614 octave_idx_type len = size_vec.numel ();
1615 dims.resize (len);
1616
1617 for (octave_idx_type i = 0; i < len; i++)
1618 {
1619 octave_idx_type d = size_vec(i);
1620 dims(i) = (d >= 0 ? d : 0);
1621 }
1622 }
1623 else
1624 error ("randi: dimensions must be a scalar or array of integers");
1625 }
1626 else
1627 {
1628 // Multiple size arguments
1629 int ndims = size_args_end - size_args_start;
1630 dims.resize (ndims);
1631
1632 for (int i = 0; i < ndims; i++)
1633 {
1634 octave_idx_type d = args(size_args_start + i).idx_type_value (true);
1635 dims(i) = (d >= 0 ? d : 0);
1636 }
1637 }
1638
1640
1641 // Validate class and check for range warnings using numeric_limits
1642 constexpr double flintmax_sgl = flintmax_v<float>;
1643
1644 double maxval, minval;
1645 std::string_view rclass_sv = rclass;
1646
1647 // Dispatch table using lambdas for type-specific generation
1648 std::function<octave_value (const dim_vector&, double, double)> generator;
1649
1650 if (rclass_sv == "double")
1651 {
1652 maxval = flintmax_dbl;
1653 minval = -flintmax_dbl;
1654 generator = do_randi_array<double>;
1655 }
1656 else if (rclass_sv == "single")
1657 {
1658 maxval = flintmax_sgl;
1659 minval = -flintmax_sgl;
1660 generator = do_randi_array<float>;
1661 }
1662 else if (rclass_sv == "int8")
1663 {
1664 maxval = std::numeric_limits<int8_t>::max ();
1665 minval = std::numeric_limits<int8_t>::min ();
1666 generator = do_randi_array<octave_int8>;
1667 }
1668 else if (rclass_sv == "int16")
1669 {
1670 maxval = std::numeric_limits<int16_t>::max ();
1671 minval = std::numeric_limits<int16_t>::min ();
1672 generator = do_randi_array<octave_int16>;
1673 }
1674 else if (rclass_sv == "int32")
1675 {
1676 maxval = std::numeric_limits<int32_t>::max ();
1677 minval = std::numeric_limits<int32_t>::min ();
1678 generator = do_randi_array<octave_int32>;
1679 }
1680 else if (rclass_sv == "uint8")
1681 {
1682 maxval = std::numeric_limits<uint8_t>::max ();
1683 minval = std::numeric_limits<uint8_t>::min ();
1684 generator = do_randi_array<octave_uint8>;
1685 }
1686 else if (rclass_sv == "uint16")
1687 {
1688 maxval = std::numeric_limits<uint16_t>::max ();
1689 minval = std::numeric_limits<uint16_t>::min ();
1690 generator = do_randi_array<octave_uint16>;
1691 }
1692 else if (rclass_sv == "uint32")
1693 {
1694 maxval = std::numeric_limits<uint32_t>::max ();
1695 minval = std::numeric_limits<uint32_t>::min ();
1696 generator = do_randi_array<octave_uint32>;
1697 }
1698 else if (rclass_sv == "logical")
1699 {
1700 // No range warnings for logical.
1701 // Any value can be mapped to true (>0) or false (<=0)
1702 maxval = flintmax_dbl;
1703 minval = -flintmax_dbl;
1704 generator = do_randi_array<bool>;
1705 }
1706 else
1707 error ("randi: unknown requested output CLASS '%s'", rclass.c_str ());
1708
1709 if (imax > maxval)
1710 warning ("randi: integer IMAX exceeds requested type. "
1711 "Values might be truncated to requested type.");
1712
1713 if (imin < minval)
1714 warning ("randi: integer IMIN exceeds requested type. "
1715 "Values might be truncated to requested type.");
1716
1717 return generator (dims, imin, imax);
1718}
1719
1720/*
1721%!test
1722%! ri = randi (10, 1000, 1);
1723%! assert (ri, fix (ri));
1724%! assert (min (ri), 1);
1725%! assert (max (ri), 10);
1726%! assert (rows (ri), 1000);
1727%! assert (columns (ri), 1);
1728%! assert (class (ri), "double");
1729
1730%!test
1731%! ri = randi (int64 (100), 1, 1000);
1732%! assert (ri, fix (ri));
1733%! assert (min (ri), 1);
1734%! assert (max (ri), 100);
1735%! assert (rows (ri), 1);
1736%! assert (columns (ri), 1000);
1737%! assert (class (ri), "double");
1738
1739%!test
1740%! ri = randi ([-100, 100], 1000, 1);
1741%! assert (ri, fix (ri));
1742%! assert (min (ri) >= -100);
1743%! assert (max (ri) <= 100);
1744%! assert (class (ri), "double");
1745
1746%!test
1747%! ri = randi ([-5, 10], 1000, 1, "int8");
1748%! assert (ri, fix (ri));
1749%! assert (min (ri), int8 (-5));
1750%! assert (max (ri), int8 (10));
1751%! assert (class (ri), "int8");
1752
1753%!test
1754%! ri = randi ([-1000, 1000], 1000, 1, "int16");
1755%! assert (min (ri) >= int16 (-1000));
1756%! assert (max (ri) <= int16 (1000));
1757%! assert (class (ri), "int16");
1758
1759%!test
1760%! ri = randi ([-1e6, 1e6], 1000, 1, "int32");
1761%! assert (min (ri) >= int32 (-1e6));
1762%! assert (max (ri) <= int32 (1e6));
1763%! assert (class (ri), "int32");
1764
1765%!test
1766%! ri = randi ([0, 200], 1000, 1, "uint8");
1767%! assert (min (ri) >= uint8 (0));
1768%! assert (max (ri) <= uint8 (200));
1769%! assert (class (ri), "uint8");
1770
1771%!test
1772%! ri = randi ([100, 1000], 1000, 1, "uint16");
1773%! assert (min (ri) >= uint16 (100));
1774%! assert (max (ri) <= uint16 (1000));
1775%! assert (class (ri), "uint16");
1776
1777%!test
1778%! ri = randi ([1e5, 1e6], 1000, 1, "uint32");
1779%! assert (min (ri) >= uint32 (1e5));
1780%! assert (max (ri) <= uint32 (1e6));
1781%! assert (class (ri), "uint32");
1782
1783%!test
1784%! ri = randi ([-5; 10], 1000, 1, "single");
1785%! assert (ri, fix (ri));
1786%! assert (min (ri), single (-5));
1787%! assert (max (ri), single (10));
1788%! assert (class (ri), "single");
1789
1790## logical: MATLAB uses value > 0 for true, not value != 0
1791%!test
1792%! ri = randi ([0, 1], 1000, 1, "logical");
1793%! assert (islogical (ri));
1794%! assert (any (ri)); # at least one true (from 1s)
1795%! assert (! all (ri)); # at least one false (from 0s)
1796
1797%!test
1798%! ## [-1, 0] should give all false since neither > 0
1799%! ri = randi ([-1, 0], 1000, 1, "logical");
1800%! assert (islogical (ri));
1801%! assert (! any (ri)); # all false
1802
1803%!test
1804%! ## [-1, 1] gives ~1/3 true (only 1 > 0)
1805%! ri = randi ([-1, 1], 10000, 1, "logical");
1806%! assert (islogical (ri));
1807%! assert (any (ri)); # some true
1808%! assert (! all (ri)); # some false
1809%! assert (mean (ri), 1/3, 0.05); # approximately 1/3 true
1810
1811%!test
1812%! ## imax >= 1 always returns all true
1813%! ri = randi (10, 3, 3, "logical");
1814%! assert (islogical (ri));
1815%! assert (size (ri), [3, 3]);
1816%! assert (all (ri(:)));
1817
1818%!assert (size (randi (10, 3, 1, 2)), [3, 1, 2])
1819%!assert (size (randi (10, [3, 1, 2])), [3, 1, 2])
1820%!assert (size (randi ([1, 10], [3, 4])), [3, 4])
1821%!assert (size (randi ([1, 10], [3, 4], "int8")), [3, 4])
1822%!assert (class (randi ([1, 10], [3, 4], "int16")), "int16")
1823
1824%!shared max_int8, min_int8, max_uint8, min_uint8, max_single
1825%! max_int8 = double (intmax ("int8"));
1826%! min_int8 = double (intmin ("int8"));
1827%! max_uint8 = double (intmax ("uint8"));
1828%! min_uint8 = double (intmin ("uint8"));
1829%! max_single = double (flintmax ("single"));
1830
1831## Test that no warning thrown if IMAX is exactly on the limits of the range
1832%!function test_no_warning (fcn, varargin)
1833%! lastwarn ("");
1834%! fcn (varargin{:});
1835%! assert (lastwarn (), "");
1836%!endfunction
1837
1838%!test test_no_warning (@randi, max_int8, "int8");
1839%!test test_no_warning (@randi, max_uint8, "uint8");
1840%!test test_no_warning (@randi, max_single, "single");
1841%!test test_no_warning (@randi, [min_int8, max_int8], "int8");
1842%!test test_no_warning (@randi, [min_uint8, max_uint8], "uint8");
1843%!test test_no_warning (@randi, [-max_single, max_single], "single");
1844
1845## Test exceeding range
1846%!warning <exceeds requested type>
1847%! randi ([min_int8-1, max_int8], "int8");
1848%!warning <exceeds requested type>
1849%! randi ([min_uint8-1, max_uint8], "uint8");
1850%!warning <exceeds requested type>
1851%! randi ([min_int8, max_int8 + 1], "int8");
1852%!warning <exceeds requested type>
1853%! randi ([min_uint8, max_uint8 + 1], "uint8");
1854%!warning <exceeds requested type>
1855%! randi ([0, max_single + 1], "single");
1856%!warning <exceeds requested type>
1857%! ri = randi ([-5, 10], 1000, 1, "uint8");
1858%! assert (ri, fix (ri));
1859%! assert (min (ri), uint8 (-5));
1860%! assert (max (ri), uint8 (10));
1861%! assert (class (ri), "uint8");
1862
1863## Test input validation
1864%!error <Invalid call> randi ()
1865%!error <must be integer bounds> randi ("test")
1866%!error <must be integer bounds> randi (struct ("a", 1))
1867%!error <first argument must be scalar IMIN> randi ([])
1868%!error <first argument must be .* 2-element vector> randi ([1,2,3])
1869%!error <must be integer bounds> randi (1.5)
1870%!error <must be integer bounds> randi ([1.5, 2])
1871%!error <must be integer bounds> randi ([1, 2.5])
1872%!error <must be integer bounds> randi ([1.5, 2.5])
1873%!error <IMAX must be .= 1> randi (0)
1874%!error <IMIN must be <= IMAX> randi ([10, 1])
1875%!error <IMIN and IMAX must be smaller than flintmax> randi (flintmax ())
1876%!error <range must be smaller than flintmax-1> randi ([-1, flintmax() - 1])
1877%!error randi (10, 1.5)
1878%!error <dimensions must be .* array of integers> randi (10, [1.5, 2])
1879%!error <dimensions must be .* array of integers> randi (10, 1.5:0.5:3)
1880%!error <dimensions must be a scalar or array of integers> randi (10, {1, 2})
1881%!error randi (10, 1.5, 2)
1882%!error <unknown requested output CLASS 'foo'> randi (10, "foo")
1883*/
1884
1885OCTAVE_END_NAMESPACE(octave)
N Dimensional Array with copy-on-write semantics.
Definition Array-base.h:130
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition Array-base.h:529
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array-base.h:547
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
Definition Array-base.h:687
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array-base.h:440
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:92
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition dim-vector.h:341
void chop_trailing_singletons()
Definition dim-vector.h:162
void resize(int n, int fill_value=0)
Definition dim-vector.h:278
octave_idx_type length() const
Definition ovl.h:111
bool is_scalar_type() const
Definition ov.h:742
bool is_string() const
Definition ov.h:635
bool isnumeric() const
Definition ov.h:748
octave_idx_type idx_type_value(bool req_int=false, bool frc_str_conv=false) const
bool is_range() const
Definition ov.h:644
octave_idx_type numel() const
Definition ov.h:557
std::string string_value(bool force=false) const
Definition ov.h:981
bool is_matrix_type() const
Definition ov.h:745
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:863
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
Definition ov.h:992
static FloatNDArray float_nd_array(const dim_vector &dims, float a=1.0)
Definition oct-rand.h:179
static uint32NDArray state(const std::string &d="")
Definition oct-rand.h:80
static NDArray nd_array(const dim_vector &dims, double a=1.0)
Definition oct-rand.h:172
static void uniform_distribution()
Definition oct-rand.h:114
static double scalar(double a=1.0)
Definition oct-rand.h:145
static void exponential_distribution()
Definition oct-rand.h:126
static float float_scalar(float a=1.0)
Definition oct-rand.h:152
static void reset()
Definition oct-rand.h:73
static void gamma_distribution()
Definition oct-rand.h:138
static std::string distribution()
Definition oct-rand.h:101
static void normal_distribution()
Definition oct-rand.h:120
static double seed()
Definition oct-rand.h:59
static void poisson_distribution()
Definition oct-rand.h:132
bool all_elements_are_ints() const
Definition Range.cc:308
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
Definition defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition defun.h:56
void warning(const char *fmt,...)
Definition error.cc:1083
void error(const char *fmt,...)
Definition error.cc:1008
void err_wrong_type_arg(const char *name, const char *s)
Definition errwarn.cc:166
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217
constexpr F flintmax_v
Definition rand.cc:1329
Array< bool > do_randi_array< bool >(const dim_vector &dims, double imin, double imax)
Definition rand.cc:1435
Array< float > do_randi_array< float >(const dim_vector &dims, double imin, double imax)
Definition rand.cc:1399
Array< double > do_randi_array< double >(const dim_vector &dims, double imin, double imax)
Definition rand.cc:1368
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T len
Definition xerbla.cc:61