rand.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2009 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <ctime>
00029 #if defined (HAVE_UNORDERED_MAP)
00030 #include <unordered_map>
00031 #elif defined (HAVE_TR1_UNORDERED_MAP)
00032 #include <tr1/unordered_map>
00033 #endif
00034 #include <string>
00035 
00036 #include "f77-fcn.h"
00037 #include "lo-mappers.h"
00038 #include "oct-rand.h"
00039 #include "quit.h"
00040 
00041 #include "defun-dld.h"
00042 #include "error.h"
00043 #include "gripes.h"
00044 #include "oct-obj.h"
00045 #include "unwind-prot.h"
00046 #include "utils.h"
00047 #include "ov-re-mat.h"
00048 
00049 /*
00050 %!shared __random_statistical_tests__
00051 %! % Flag whether the statistical tests should be run in "make check" or not
00052 %! __random_statistical_tests__ = 0;
00053 */
00054 
00055 static octave_value
00056 do_rand (const octave_value_list& args, int nargin, const char *fcn,
00057          const std::string& distribution, bool additional_arg = false)
00058 {
00059   octave_value retval;
00060   NDArray a;
00061   int idx = 0;
00062   dim_vector dims;
00063 
00064   unwind_protect frame;
00065   // Restore current distribution on any exit.
00066   frame.add_fcn (octave_rand::distribution,
00067                  octave_rand::distribution ());
00068 
00069   octave_rand::distribution (distribution);
00070 
00071   if (additional_arg)
00072     {
00073       if (nargin == 0)
00074         {
00075           error ("%s: expecting at least one argument", fcn);
00076           goto done;
00077         }
00078       else if (args(0).is_string())
00079         additional_arg = false;
00080       else
00081         {
00082           a = args(0).array_value ();
00083           if (error_state)
00084             {
00085               error ("%s: expecting scalar or matrix arguments", fcn);
00086               goto done;
00087             }
00088           idx++;
00089           nargin--;
00090         }
00091     }
00092 
00093   switch (nargin)
00094     {
00095     case 0:
00096       {
00097         if (additional_arg)
00098           dims = a.dims ();
00099         else
00100           {
00101             dims.resize (2);
00102 
00103             dims(0) = 1;
00104             dims(1) = 1;
00105           }
00106         goto gen_matrix;
00107       }
00108       break;
00109 
00110     case 1:
00111       {
00112         octave_value tmp = args(idx);
00113 
00114         if (tmp.is_string ())
00115           {
00116             std::string s_arg = tmp.string_value ();
00117 
00118             if (s_arg == "dist")
00119               {
00120                 retval = octave_rand::distribution ();
00121               }
00122             else if (s_arg == "seed")
00123               {
00124                 retval = octave_rand::seed ();
00125               }
00126             else if (s_arg == "state" || s_arg == "twister")
00127               {
00128                 retval = octave_rand::state (fcn);
00129               }
00130             else if (s_arg == "uniform")
00131               {
00132                 octave_rand::uniform_distribution ();
00133               }
00134             else if (s_arg == "normal")
00135               {
00136                 octave_rand::normal_distribution ();
00137               }
00138             else if (s_arg == "exponential")
00139               {
00140                 octave_rand::exponential_distribution ();
00141               }
00142             else if (s_arg == "poisson")
00143               {
00144                 octave_rand::poisson_distribution ();
00145               }
00146             else if (s_arg == "gamma")
00147               {
00148                 octave_rand::gamma_distribution ();
00149               }
00150             else
00151               error ("%s: unrecognized string argument", fcn);
00152           }
00153         else if (tmp.is_scalar_type ())
00154           {
00155             double dval = tmp.double_value ();
00156 
00157             if (xisnan (dval))
00158               {
00159                 error ("%s: NaN is invalid matrix dimension", fcn);
00160               }
00161             else
00162               {
00163                 dims.resize (2);
00164 
00165                 dims(0) = NINTbig (tmp.double_value ());
00166                 dims(1) = NINTbig (tmp.double_value ());
00167 
00168                 if (! error_state)
00169                   goto gen_matrix;
00170               }
00171           }
00172         else if (tmp.is_range ())
00173           {
00174             Range r = tmp.range_value ();
00175 
00176             if (r.all_elements_are_ints ())
00177               {
00178                 octave_idx_type n = r.nelem ();
00179 
00180                 dims.resize (n);
00181 
00182                 octave_idx_type base = NINTbig (r.base ());
00183                 octave_idx_type incr = NINTbig (r.inc ());
00184 
00185                 for (octave_idx_type i = 0; i < n; i++)
00186                   {
00187                     //Negative dimensions are treated as zero for Matlab
00188                     //compatibility
00189                     dims(i) = base >= 0 ? base : 0;
00190                     base += incr;
00191                   }
00192 
00193                 goto gen_matrix;
00194 
00195               }
00196             else
00197               error ("%s: all elements of range must be integers",
00198                      fcn);
00199           }
00200         else if (tmp.is_matrix_type ())
00201           {
00202             Array<int> iv = tmp.int_vector_value (true);
00203 
00204             if (! error_state)
00205               {
00206                 octave_idx_type len = iv.length ();
00207 
00208                 dims.resize (len);
00209 
00210                 for (octave_idx_type i = 0; i < len; i++)
00211                   {
00212                     //Negative dimensions are treated as zero for Matlab
00213                     //compatibility
00214                     octave_idx_type elt = iv(i);
00215                     dims(i) = elt >=0 ? elt : 0;
00216                   }
00217 
00218                 goto gen_matrix;
00219               }
00220             else
00221               error ("%s: expecting integer vector", fcn);
00222           }
00223         else
00224           {
00225             gripe_wrong_type_arg ("rand", tmp);
00226             return retval;
00227           }
00228       }
00229       break;
00230 
00231     default:
00232       {
00233         octave_value tmp = args(idx);
00234 
00235         if (nargin == 2 && tmp.is_string ())
00236           {
00237             std::string ts = tmp.string_value ();
00238 
00239             if (ts == "seed")
00240               {
00241                 if (args(idx+1).is_real_scalar ())
00242                   {
00243                     double d = args(idx+1).double_value ();
00244 
00245                     if (! error_state)
00246                       octave_rand::seed (d);
00247                   }
00248                 else if (args(idx+1).is_string ()
00249                          && args(idx+1).string_value() == "reset")
00250                   octave_rand::reset ();
00251                 else
00252                   error ("%s: seed must be a real scalar", fcn);
00253               }
00254             else if (ts == "state" || ts == "twister")
00255               {
00256                 if (args(idx+1).is_string ()
00257                     && args(idx+1).string_value() == "reset")
00258                   octave_rand::reset (fcn);
00259                 else
00260                   {
00261                     ColumnVector s =
00262                       ColumnVector (args(idx+1).vector_value(false, true));
00263 
00264                     if (! error_state)
00265                       octave_rand::state (s, fcn);
00266                   }
00267               }
00268             else
00269               error ("%s: unrecognized string argument", fcn);
00270           }
00271         else
00272           {
00273             dims.resize (nargin);
00274 
00275             for (int i = 0; i < nargin; i++)
00276               {
00277                 octave_idx_type elt = args(idx+i).int_value ();
00278                 if (error_state)
00279                   {
00280                     error ("%s: expecting integer arguments", fcn);
00281                     goto done;
00282                   }
00283                 //Negative is zero for Matlab compatibility
00284                 dims(i) = elt >= 0 ? elt : 0;
00285               }
00286 
00287             goto gen_matrix;
00288           }
00289       }
00290       break;
00291     }
00292 
00293  done:
00294 
00295   return retval;
00296 
00297  gen_matrix:
00298 
00299   dims.chop_trailing_singletons ();
00300 
00301   if (additional_arg)
00302     {
00303       if (a.length() == 1)
00304         return octave_rand::nd_array (dims, a(0));
00305       else
00306         {
00307           if (a.dims() != dims)
00308             {
00309               error ("%s: mismatch in argument size", fcn);
00310               return retval;
00311             }
00312           octave_idx_type len = a.length ();
00313           NDArray m (dims);
00314           double *v = m.fortran_vec ();
00315           for (octave_idx_type i = 0; i < len; i++)
00316             v[i] = octave_rand::scalar (a(i));
00317           return m;
00318         }
00319     }
00320   else
00321     return octave_rand::nd_array (dims);
00322 }
00323 
00324 DEFUN_DLD (rand, args, ,
00325   "-*- texinfo -*-\n\
00326 @deftypefn  {Loadable Function} {} rand (@var{n})\n\
00327 @deftypefnx {Loadable Function} {} rand (@var{n}, @var{m}, @dots{})\n\
00328 @deftypefnx {Loadable Function} {} rand ([@var{n} @var{m} @dots{}])\n\
00329 @deftypefnx {Loadable Function} {@var{v} =} rand (\"state\")\n\
00330 @deftypefnx {Loadable Function} {} rand (\"state\", @var{v})\n\
00331 @deftypefnx {Loadable Function} {} rand (\"state\", \"reset\")\n\
00332 @deftypefnx {Loadable Function} {@var{v} =} rand (\"seed\")\n\
00333 @deftypefnx {Loadable Function} {} rand (\"seed\", @var{v})\n\
00334 @deftypefnx {Loadable Function} {} rand (\"seed\", \"reset\")\n\
00335 Return a matrix with random elements uniformly distributed on the\n\
00336 interval (0, 1).  The arguments are handled the same as the arguments\n\
00337 for @code{eye}.\n\
00338 \n\
00339 You can query the state of the random number generator using the\n\
00340 form\n\
00341 \n\
00342 @example\n\
00343 v = rand (\"state\")\n\
00344 @end example\n\
00345 \n\
00346 This returns a column vector @var{v} of length 625.  Later, you can\n\
00347 restore the random number generator to the state @var{v}\n\
00348 using the form\n\
00349 \n\
00350 @example\n\
00351 rand (\"state\", v)\n\
00352 @end example\n\
00353 \n\
00354 @noindent\n\
00355 You may also initialize the state vector from an arbitrary vector of\n\
00356 length @leq{} 625 for @var{v}.  This new state will be a hash based on the\n\
00357 value of @var{v}, not @var{v} itself.\n\
00358 \n\
00359 By default, the generator is initialized from @code{/dev/urandom} if it is\n\
00360 available, otherwise from CPU time, wall clock time, and the current\n\
00361 fraction of a second.\n\
00362 \n\
00363 To compute the pseudo-random sequence, @code{rand} uses the Mersenne\n\
00364 Twister with a period of @math{2^{19937}-1} (See M. Matsumoto and\n\
00365 T. Nishimura,\n\
00366 @cite{Mersenne Twister: A 623-dimensionally equidistributed uniform\n\
00367 pseudorandom number generator}, ACM Trans. on\n\
00368 Modeling and Computer Simulation Vol. 8, No. 1, pp. 3-30, January 1998,\n\
00369 @url{http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html}).\n\
00370 Do @strong{not} use for cryptography without securely hashing\n\
00371 several returned values together, otherwise the generator state\n\
00372 can be learned after reading 624 consecutive values.\n\
00373 \n\
00374 Older versions of Octave used a different random number generator.\n\
00375 The new generator is used by default\n\
00376 as it is significantly faster than the old generator, and produces\n\
00377 random numbers with a significantly longer cycle time.  However, in\n\
00378 some circumstances it might be desirable to obtain the same random\n\
00379 sequences as used by the old generators.  To do this the keyword\n\
00380 \"seed\" is used to specify that the old generators should be use,\n\
00381 as in\n\
00382 \n\
00383 @example\n\
00384 rand (\"seed\", val)\n\
00385 @end example\n\
00386 \n\
00387 @noindent\n\
00388 which sets the seed of the generator to @var{val}.  The seed of the\n\
00389 generator can be queried with\n\
00390 \n\
00391 @example\n\
00392 s = rand (\"seed\")\n\
00393 @end example\n\
00394 \n\
00395 However, it should be noted that querying the seed will not cause\n\
00396 @code{rand} to use the old generators, only setting the seed will.\n\
00397 To cause @code{rand} to once again use the new generators, the\n\
00398 keyword \"state\" should be used to reset the state of the @code{rand}.\n\
00399 \n\
00400 The state or seed of the generator can be reset to a new random value\n\
00401 using the \"reset\" keyword.\n\
00402 @seealso{randn, rande, randg, randp}\n\
00403 @end deftypefn")
00404 {
00405   octave_value retval;
00406 
00407   int nargin = args.length ();
00408 
00409   retval = do_rand (args, nargin, "rand", "uniform");
00410 
00411   return retval;
00412 }
00413 
00414 // FIXME -- The old generator (selected when "seed" is set) will not
00415 // work properly if compiled to use 64-bit integers.
00416 
00417 /*
00418 %!test # 'state' can be a scalar
00419 %! rand('state',12); x = rand(1,4);
00420 %! rand('state',12); y = rand(1,4);
00421 %! assert(x,y);
00422 %!test # 'state' can be a vector
00423 %! rand('state',[12,13]); x=rand(1,4);
00424 %! rand('state',[12;13]); y=rand(1,4);
00425 %! assert(x,y);
00426 %!test # querying 'state' doesn't disturb sequence
00427 %! rand('state',12); rand(1,2); x=rand(1,2);
00428 %! rand('state',12); rand(1,2);
00429 %! s=rand('state'); y=rand(1,2);
00430 %! assert(x,y);
00431 %! rand('state',s); z=rand(1,2);
00432 %! assert(x,z);
00433 %!test # 'seed' must be a scalar
00434 %! rand('seed',12); x = rand(1,4);
00435 %! rand('seed',12); y = rand(1,4);
00436 %! assert(x,y);
00437 %!error(rand('seed',[12,13]))
00438 %!test # querying 'seed' returns a value which can be used later
00439 %! s=rand('seed'); x=rand(1,2);
00440 %! rand('seed',s); y=rand(1,2);
00441 %! assert(x,y);
00442 %!test # querying 'seed' doesn't disturb sequence
00443 %! rand('seed',12); rand(1,2); x=rand(1,2);
00444 %! rand('seed',12); rand(1,2);
00445 %! s=rand('seed'); y=rand(1,2);
00446 %! assert(x,y);
00447 %! rand('seed',s); z=rand(1,2);
00448 %! assert(x,z);
00449 */
00450 
00451 /*
00452 %!test
00453 %! % Test fixed state
00454 %! rand("state",1);
00455 %! assert (rand(1,6), [0.1343642441124013 0.8474337369372327 0.763774618976614 0.2550690257394218 0.495435087091941 0.4494910647887382],1e-6);
00456 %!test
00457 %! % Test fixed seed
00458 %! rand("seed",1);
00459 %! assert (rand(1,6), [0.8668024251237512 0.9126510815694928 0.09366085007786751 0.1664607301354408 0.7408077004365623 0.7615650338120759],1e-6);
00460 %!test
00461 %! if (__random_statistical_tests__)
00462 %!   % statistical tests may fail occasionally.
00463 %!   rand("state",12);
00464 %!   x = rand(100000,1);
00465 %!   assert(max(x)<1.); %*** Please report this!!! ***
00466 %!   assert(min(x)>0.); %*** Please report this!!! ***
00467 %!   assert(mean(x),0.5,0.0024);
00468 %!   assert(var(x),1/48,0.0632);
00469 %!   assert(skewness(x),0,0.012);
00470 %!   assert(kurtosis(x),-6/5,0.0094);
00471 %! endif
00472 %!test
00473 %! if (__random_statistical_tests__)
00474 %!   % statistical tests may fail occasionally.
00475 %!   rand("seed",12);
00476 %!   x = rand(100000,1);
00477 %!   assert(max(x)<1.); %*** Please report this!!! ***
00478 %!   assert(min(x)>0.); %*** Please report this!!! ***
00479 %!   assert(mean(x),0.5,0.0024);
00480 %!   assert(var(x),1/48,0.0632);
00481 %!   assert(skewness(x),0,0.012);
00482 %!   assert(kurtosis(x),-6/5,0.0094);
00483 %! endif
00484 */
00485 
00486 
00487 static std::string current_distribution = octave_rand::distribution ();
00488 
00489 DEFUN_DLD (randn, args, ,
00490   "-*- texinfo -*-\n\
00491 @deftypefn  {Loadable Function} {} randn (@var{n})\n\
00492 @deftypefnx {Loadable Function} {} randn (@var{n}, @var{m}, @dots{})\n\
00493 @deftypefnx {Loadable Function} {} randn ([@var{n} @var{m} @dots{}])\n\
00494 @deftypefnx {Loadable Function} {@var{v} =} randn (\"state\")\n\
00495 @deftypefnx {Loadable Function} {} randn (\"state\", @var{v})\n\
00496 @deftypefnx {Loadable Function} {} randn (\"state\", \"reset\")\n\
00497 @deftypefnx {Loadable Function} {@var{v} =} randn (\"seed\")\n\
00498 @deftypefnx {Loadable Function} {} randn (\"seed\", @var{v})\n\
00499 @deftypefnx {Loadable Function} {} randn (\"seed\", \"reset\")\n\
00500 Return a matrix with normally distributed random\n\
00501 elements having zero mean and variance one.  The arguments are\n\
00502 handled the same as the arguments for @code{rand}.\n\
00503 \n\
00504 By default, @code{randn} uses the Marsaglia and Tsang ``Ziggurat technique''\n\
00505 to transform from a uniform to a normal distribution.\n\
00506 \n\
00507 Reference: G. Marsaglia and W.W. Tsang,\n\
00508 @cite{Ziggurat Method for Generating Random Variables},\n\
00509 J. Statistical Software, vol 5, 2000,\n\
00510 @url{http://www.jstatsoft.org/v05/i08/})\n\
00511 \n\
00512 @seealso{rand, rande, randg, randp}\n\
00513 @end deftypefn")
00514 {
00515   octave_value retval;
00516 
00517   int nargin = args.length ();
00518 
00519   retval = do_rand (args, nargin, "randn", "normal");
00520 
00521   return retval;
00522 }
00523 
00524 /*
00525 %!test
00526 %! % Test fixed state
00527 %! randn("state",1);
00528 %! assert (randn(1,6), [-2.666521678978671 -0.7381719971724564 1.507903992673601 0.6019427189162239 -0.450661261143348 -0.7054431351574116],1e-6);
00529 %!test
00530 %! % Test fixed seed
00531 %! randn("seed",1);
00532 %! assert (randn(1,6), [-1.039402365684509 -1.25938892364502 0.1968704611063004 0.3874166905879974 -0.5976632833480835 -0.6615074276924133],1e-6);
00533 %!test
00534 %! if (__random_statistical_tests__)
00535 %!   % statistical tests may fail occasionally.
00536 %!   randn("state",12);
00537 %!   x = randn(100000,1);
00538 %!   assert(mean(x),0,0.01);
00539 %!   assert(var(x),1,0.02);
00540 %!   assert(skewness(x),0,0.02);
00541 %!   assert(kurtosis(x),0,0.04);
00542 %! endif
00543 %!test
00544 %! if (__random_statistical_tests__)
00545 %!   % statistical tests may fail occasionally.
00546 %!   randn("seed",12);
00547 %!   x = randn(100000,1);
00548 %!   assert(mean(x),0,0.01);
00549 %!   assert(var(x),1,0.02);
00550 %!   assert(skewness(x),0,0.02);
00551 %!   assert(kurtosis(x),0,0.04);
00552 %! endif
00553 */
00554 
00555 DEFUN_DLD (rande, args, ,
00556   "-*- texinfo -*-\n\
00557 @deftypefn  {Loadable Function} {} rande (@var{n})\n\
00558 @deftypefnx {Loadable Function} {} rande (@var{n}, @var{m}, @dots{})\n\
00559 @deftypefnx {Loadable Function} {} rande ([@var{n} @var{m} @dots{}])\n\
00560 @deftypefnx {Loadable Function} {@var{v} =} rande (\"state\")\n\
00561 @deftypefnx {Loadable Function} {} rande (\"state\", @var{v})\n\
00562 @deftypefnx {Loadable Function} {} rande (\"state\", \"reset\")\n\
00563 @deftypefnx {Loadable Function} {@var{v} =} rande (\"seed\")\n\
00564 @deftypefnx {Loadable Function} {} rande (\"seed\", @var{v})\n\
00565 @deftypefnx {Loadable Function} {} rande (\"seed\", \"reset\")\n\
00566 Return a matrix with exponentially distributed random elements.  The\n\
00567 arguments are handled the same as the arguments for @code{rand}.\n\
00568 \n\
00569 By default, @code{randn} uses the Marsaglia and Tsang ``Ziggurat technique''\n\
00570 to transform from a uniform to an exponential distribution.\n\
00571 \n\
00572 Reference: G. Marsaglia and W.W. Tsang,\n\
00573 @cite{Ziggurat Method for Generating Random Variables},\n\
00574 J. Statistical Software, vol 5, 2000,\n\
00575 @url{http://www.jstatsoft.org/v05/i08/})\n\
00576 \n\
00577 @seealso{rand, randn, randg, randp}\n\
00578 @end deftypefn")
00579 {
00580   octave_value retval;
00581 
00582   int nargin = args.length ();
00583 
00584   retval = do_rand (args, nargin, "rande", "exponential");
00585 
00586   return retval;
00587 }
00588 
00589 /*
00590 %!test
00591 %! % Test fixed state
00592 %! rande("state",1);
00593 %! assert (rande(1,6), [3.602973885835625 0.1386190677555021 0.6743112889616958 0.4512830847258422 0.7255744741233175 0.3415969205292291],1e-6);
00594 %!test
00595 %! % Test fixed seed
00596 %! rande("seed",1);
00597 %! assert (rande(1,6), [0.06492075175653866 1.717980206012726 0.4816154008731246 0.5231300676241517 0.103910739364359 1.668931916356087],1e-6);
00598 %!test
00599 %! if (__random_statistical_tests__)
00600 %!   % statistical tests may fail occasionally
00601 %!   rande("state",1);
00602 %!   x = rande(100000,1);
00603 %!   assert(min(x)>0); % *** Please report this!!! ***
00604 %!   assert(mean(x),1,0.01);
00605 %!   assert(var(x),1,0.03);
00606 %!   assert(skewness(x),2,0.06);
00607 %!   assert(kurtosis(x),6,0.7);
00608 %! endif
00609 %!test
00610 %! if (__random_statistical_tests__)
00611 %!   % statistical tests may fail occasionally
00612 %!   rande("seed",1);
00613 %!   x = rande(100000,1);
00614 %!   assert(min(x)>0); % *** Please report this!!! ***
00615 %!   assert(mean(x),1,0.01);
00616 %!   assert(var(x),1,0.03);
00617 %!   assert(skewness(x),2,0.06);
00618 %!   assert(kurtosis(x),6,0.7);
00619 %! endif
00620 */
00621 
00622 DEFUN_DLD (randg, args, ,
00623   "-*- texinfo -*-\n\
00624 @deftypefn  {Loadable Function} {} randg (@var{n})\n\
00625 @deftypefnx {Loadable Function} {} randg (@var{n}, @var{m}, @dots{})\n\
00626 @deftypefnx {Loadable Function} {} randg ([@var{n} @var{m} @dots{}])\n\
00627 @deftypefnx {Loadable Function} {@var{v} =} randg (\"state\")\n\
00628 @deftypefnx {Loadable Function} {} randg (\"state\", @var{v})\n\
00629 @deftypefnx {Loadable Function} {} randg (\"state\", \"reset\")\n\
00630 @deftypefnx {Loadable Function} {@var{v} =} randg (\"seed\")\n\
00631 @deftypefnx {Loadable Function} {} randg (\"seed\", @var{v})\n\
00632 @deftypefnx {Loadable Function} {} randg (\"seed\", \"reset\")\n\
00633 Return a matrix with @code{gamma(@var{a},1)} distributed random elements.\n\
00634 The arguments are handled the same as the arguments for @code{rand},\n\
00635 except for the argument @var{a}.\n\
00636 \n\
00637 This can be used to generate many distributions:\n\
00638 \n\
00639 @table @asis\n\
00640 @item @code{gamma (a, b)} for @code{a > -1}, @code{b > 0}\n\
00641 \n\
00642 @example\n\
00643 r = b * randg (a)\n\
00644 @end example\n\
00645 \n\
00646 @item @code{beta (a, b)} for @code{a > -1}, @code{b > -1}\n\
00647 \n\
00648 @example\n\
00649 @group\n\
00650 r1 = randg (a, 1)\n\
00651 r = r1 / (r1 + randg (b, 1))\n\
00652 @end group\n\
00653 @end example\n\
00654 \n\
00655 @item @code{Erlang (a, n)}\n\
00656 \n\
00657 @example\n\
00658 r = a * randg (n)\n\
00659 @end example\n\
00660 \n\
00661 @item @code{chisq (df)} for @code{df > 0}\n\
00662 \n\
00663 @example\n\
00664 r = 2 * randg (df / 2)\n\
00665 @end example\n\
00666 \n\
00667 @item @code{t (df)} for @code{0 < df < inf} (use randn if df is infinite)\n\
00668 \n\
00669 @example\n\
00670 r = randn () / sqrt (2 * randg (df / 2) / df)\n\
00671 @end example\n\
00672 \n\
00673 @item @code{F (n1, n2)} for @code{0 < n1}, @code{0 < n2}\n\
00674 \n\
00675 @example\n\
00676 @group\n\
00677 ## r1 equals 1 if n1 is infinite\n\
00678 r1 = 2 * randg (n1 / 2) / n1\n\
00679 ## r2 equals 1 if n2 is infinite\n\
00680 r2 = 2 * randg (n2 / 2) / n2\n\
00681 r = r1 / r2\n\n\
00682 @end group\n\
00683 @end example\n\
00684 \n\
00685 @item negative @code{binomial (n, p)} for @code{n > 0}, @code{0 < p <= 1}\n\
00686 \n\
00687 @example\n\
00688 r = randp ((1 - p) / p * randg (n))\n\
00689 @end example\n\
00690 \n\
00691 @item non-central @code{chisq (df, L)}, for @code{df >= 0} and @code{L > 0}\n\
00692 (use chisq if @code{L = 0})\n\
00693 \n\
00694 @example\n\
00695 @group\n\
00696 r = randp (L / 2)\n\
00697 r(r > 0) = 2 * randg (r(r > 0))\n\
00698 r(df > 0) += 2 * randg (df(df > 0)/2)\n\
00699 @end group\n\
00700 @end example\n\
00701 \n\
00702 @item @code{Dirichlet (a1, @dots{} ak)}\n\
00703 \n\
00704 @example\n\
00705 @group\n\
00706 r = (randg (a1), @dots{}, randg (ak))\n\
00707 r = r / sum (r)\n\
00708 @end group\n\
00709 @end example\n\
00710 \n\
00711 @end table\n\
00712 @seealso{rand, randn, rande, randp}\n\
00713 @end deftypefn")
00714 {
00715   octave_value retval;
00716 
00717   int nargin = args.length ();
00718 
00719   if (nargin < 1)
00720     error ("randg: insufficient arguments");
00721   else
00722     retval = do_rand (args, nargin, "randg", "gamma", true);
00723 
00724   return retval;
00725 }
00726 
00727 /*
00728 %!test
00729 %! randg("state",12)
00730 %!assert(randg([-inf,-1,0,inf,nan]),[nan,nan,nan,nan,nan]) % *** Please report
00731 
00732 
00733 %!test
00734 %! % Test fixed state
00735 %! randg("state",1);
00736 %! assert (randg(0.1,1,6), [0.0103951513331241 8.335671459898252e-05 0.00138691397249762 0.000587308416993855 0.495590518784736 2.3921917414795e-12],1e-6);
00737 %!test
00738 %! % Test fixed state
00739 %! randg("state",1);
00740 %! assert (randg(0.95,1,6), [3.099382433255327 0.3974529788871218 0.644367450750855 1.143261091802246 1.964111762696822 0.04011915547957939],1e-6);
00741 %!test
00742 %! % Test fixed state
00743 %! randg("state",1);
00744 %! assert (randg(1,1,6), [0.2273389379645993 1.288822625058359 0.2406335209340746 1.218869553370733 1.024649860162554 0.09631230343599533],1e-6);
00745 %!test
00746 %! % Test fixed state
00747 %! randg("state",1);
00748 %! assert (randg(10,1,6), [3.520369644331133 15.15369864472106 8.332112081991205 8.406211067432674 11.81193475187611 10.88792728177059],1e-5);
00749 %!test
00750 %! % Test fixed state
00751 %! randg("state",1);
00752 %! assert (randg(100,1,6), [75.34570255262264 115.4911985594699 95.23493031356388 95.48926019250911 106.2397448229803 103.4813150404118],1e-4);
00753 %!test
00754 %! % Test fixed seed
00755 %! randg("seed",1);
00756 %! assert (randg(0.1,1,6), [0.07144210487604141 0.460641473531723 0.4749028384685516 0.06823389977216721 0.000293838675133884 1.802567535340305e-12],1e-6);
00757 %!test
00758 %! % Test fixed seed
00759 %! randg("seed",1);
00760 %! assert (randg(0.95,1,6), [1.664905071258545 1.879976987838745 1.905677795410156 0.9948706030845642 0.5606933236122131 0.0766092911362648],1e-6);
00761 %!test
00762 %! % Test fixed seed
00763 %! randg("seed",1);
00764 %! assert (randg(1,1,6), [0.03512085229158401 0.6488978862762451 0.8114678859710693 0.1666885763406754 1.60791552066803 1.90356981754303],1e-6);
00765 %!test
00766 %! % Test fixed seed
00767 %! randg("seed",1);
00768 %! assert (randg(10,1,6), [6.566435813903809 10.11648464202881 10.73162078857422 7.747178077697754 6.278522491455078 6.240195751190186],1e-5);
00769 %!test
00770 %! % Test fixed seed
00771 %! randg("seed",1);
00772 %! assert (randg(100,1,6), [89.40208435058594 101.4734725952148 103.4020004272461 93.62763214111328 88.33104705810547 88.1871337890625],1e-4);
00773 %!test
00774 %! if (__random_statistical_tests__)
00775 %!   % statistical tests may fail occasionally.
00776 %!   randg("state",12)
00777 %!   a=0.1; x = randg(a,100000,1);
00778 %!   assert(mean(x),    a,         0.01);
00779 %!   assert(var(x),     a,         0.01);
00780 %!   assert(skewness(x),2/sqrt(a), 1.);
00781 %!   assert(kurtosis(x),6/a,       50.);
00782 %! endif
00783 %!test
00784 %! if (__random_statistical_tests__)
00785 %!   % statistical tests may fail occasionally.
00786 %!   randg("state",12)
00787 %!   a=0.95; x = randg(a,100000,1);
00788 %!   assert(mean(x),    a,         0.01);
00789 %!   assert(var(x),     a,         0.04);
00790 %!   assert(skewness(x),2/sqrt(a), 0.2);
00791 %!   assert(kurtosis(x),6/a,       2.);
00792 %! endif
00793 %!test
00794 %! if (__random_statistical_tests__)
00795 %!   % statistical tests may fail occasionally.
00796 %!   randg("state",12)
00797 %!   a=1; x = randg(a,100000,1);
00798 %!   assert(mean(x),a,             0.01);
00799 %!   assert(var(x),a,              0.04);
00800 %!   assert(skewness(x),2/sqrt(a), 0.2);
00801 %!   assert(kurtosis(x),6/a,       2.);
00802 %! endif
00803 %!test
00804 %! if (__random_statistical_tests__)
00805 %!   % statistical tests may fail occasionally.
00806 %!   randg("state",12)
00807 %!   a=10; x = randg(a,100000,1);
00808 %!   assert(mean(x),    a,         0.1);
00809 %!   assert(var(x),     a,         0.5);
00810 %!   assert(skewness(x),2/sqrt(a), 0.1);
00811 %!   assert(kurtosis(x),6/a,       0.5);
00812 %! endif
00813 %!test
00814 %! if (__random_statistical_tests__)
00815 %!   % statistical tests may fail occasionally.
00816 %!   randg("state",12)
00817 %!   a=100; x = randg(a,100000,1);
00818 %!   assert(mean(x),    a,         0.2);
00819 %!   assert(var(x),     a,         2.);
00820 %!   assert(skewness(x),2/sqrt(a), 0.05);
00821 %!   assert(kurtosis(x),6/a,       0.2);
00822 %! endif
00823 %!test
00824 %! randg("seed",12)
00825 %!assert(randg([-inf,-1,0,inf,nan]),[nan,nan,nan,nan,nan]) % *** Please report
00826 %!test
00827 %! if (__random_statistical_tests__)
00828 %!   % statistical tests may fail occasionally.
00829 %!   randg("seed",12)
00830 %!   a=0.1; x = randg(a,100000,1);
00831 %!   assert(mean(x),    a,         0.01);
00832 %!   assert(var(x),     a,         0.01);
00833 %!   assert(skewness(x),2/sqrt(a), 1.);
00834 %!   assert(kurtosis(x),6/a,       50.);
00835 %! endif
00836 %!test
00837 %! if (__random_statistical_tests__)
00838 %!   % statistical tests may fail occasionally.
00839 %!   randg("seed",12)
00840 %!   a=0.95; x = randg(a,100000,1);
00841 %!   assert(mean(x),    a,         0.01);
00842 %!   assert(var(x),     a,         0.04);
00843 %!   assert(skewness(x),2/sqrt(a), 0.2);
00844 %!   assert(kurtosis(x),6/a,       2.);
00845 %! endif
00846 %!test
00847 %! if (__random_statistical_tests__)
00848 %!   % statistical tests may fail occasionally.
00849 %!   randg("seed",12)
00850 %!   a=1; x = randg(a,100000,1);
00851 %!   assert(mean(x),a,             0.01);
00852 %!   assert(var(x),a,              0.04);
00853 %!   assert(skewness(x),2/sqrt(a), 0.2);
00854 %!   assert(kurtosis(x),6/a,       2.);
00855 %! endif
00856 %!test
00857 %! if (__random_statistical_tests__)
00858 %!   % statistical tests may fail occasionally.
00859 %!   randg("seed",12)
00860 %!   a=10; x = randg(a,100000,1);
00861 %!   assert(mean(x),    a,         0.1);
00862 %!   assert(var(x),     a,         0.5);
00863 %!   assert(skewness(x),2/sqrt(a), 0.1);
00864 %!   assert(kurtosis(x),6/a,       0.5);
00865 %! endif
00866 %!test
00867 %! if (__random_statistical_tests__)
00868 %!   % statistical tests may fail occasionally.
00869 %!   randg("seed",12)
00870 %!   a=100; x = randg(a,100000,1);
00871 %!   assert(mean(x),    a,         0.2);
00872 %!   assert(var(x),     a,         2.);
00873 %!   assert(skewness(x),2/sqrt(a), 0.05);
00874 %!   assert(kurtosis(x),6/a,       0.2);
00875 %! endif
00876 */
00877 
00878 
00879 DEFUN_DLD (randp, args, ,
00880   "-*- texinfo -*-\n\
00881 @deftypefn  {Loadable Function} {} randp (@var{l}, @var{n})\n\
00882 @deftypefnx {Loadable Function} {} randp (@var{l}, @var{n}, @var{m}, @dots{})\n\
00883 @deftypefnx {Loadable Function} {} randp (@var{l}, [@var{n} @var{m} @dots{}])\n\
00884 @deftypefnx {Loadable Function} {@var{v} =} randp (\"state\")\n\
00885 @deftypefnx {Loadable Function} {} randp (\"state\", @var{v})\n\
00886 @deftypefnx {Loadable Function} {} randp (\"state\", \"reset\")\n\
00887 @deftypefnx {Loadable Function} {@var{v} =} randp (\"seed\")\n\
00888 @deftypefnx {Loadable Function} {} randp (\"seed\", @var{v})\n\
00889 @deftypefnx {Loadable Function} {} randp (\"seed\", \"reset\")\n\
00890 Return a matrix with Poisson distributed random elements with mean value\n\
00891 parameter given by the first argument, @var{l}.  The arguments\n\
00892 are handled the same as the arguments for @code{rand}, except for the\n\
00893 argument @var{l}.\n\
00894 \n\
00895 Five different algorithms are used depending on the range of @var{l}\n\
00896 and whether or not @var{l} is a scalar or a matrix.\n\
00897 \n\
00898 @table @asis\n\
00899 @item For scalar @var{l} @leq{} 12, use direct method.\n\
00900 W.H. Press, et al., @cite{Numerical Recipes in C},\n\
00901 Cambridge University Press, 1992.\n\
00902 \n\
00903 @item For scalar @var{l} > 12, use rejection method.[1]\n\
00904 W.H. Press, et al., @cite{Numerical Recipes in C},\n\
00905 Cambridge University Press, 1992.\n\
00906 \n\
00907 @item For matrix @var{l} @leq{} 10, use inversion method.[2]\n\
00908 E. Stadlober, et al., WinRand source code, available via FTP.\n\
00909 \n\
00910 @item For matrix @var{l} > 10, use patchwork rejection method.\n\
00911 E. Stadlober, et al., WinRand source code, available via FTP, or\n\
00912 H. Zechner, @cite{Efficient sampling from continuous and discrete\n\
00913 unimodal distributions}, Doctoral Dissertation, 156pp., Technical\n\
00914 University Graz, Austria, 1994.\n\
00915 \n\
00916 @item For @var{l} > 1e8, use normal approximation.\n\
00917 L. Montanet, et al., @cite{Review of Particle Properties}, Physical Review\n\
00918 D 50 p1284, 1994.\n\
00919 @end table\n\
00920 @seealso{rand, randn, rande, randg}\n\
00921 @end deftypefn")
00922 {
00923   octave_value retval;
00924 
00925   int nargin = args.length ();
00926 
00927   if (nargin < 1)
00928     error ("randp: insufficient arguments");
00929   else
00930     retval = do_rand (args, nargin, "randp", "poisson", true);
00931 
00932   return retval;
00933 }
00934 
00935 /*
00936 %!test
00937 %! randp("state",12)
00938 %!assert(randp([-inf,-1,0,inf,nan]),[nan,nan,0,nan,nan]); % *** Please report
00939 %!test
00940 %! % Test fixed state
00941 %! randp("state",1);
00942 %! assert(randp(5,1,6),[5 5 3 7 7 3])
00943 %!test
00944 %! % Test fixed state
00945 %! randp("state",1);
00946 %! assert(randp(15,1,6),[13 15 8 18 18 15])
00947 %!test
00948 %! % Test fixed state
00949 %! randp("state",1);
00950 %! assert(randp(1e9,1,6),[999915677 999976657 1000047684 1000019035 999985749 999977692],-1e-6)
00951 %!test
00952 %! % Test fixed state
00953 %! randp("seed",1);
00954 %! %%assert(randp(5,1,6),[8 2 3 6 6 8])
00955 %! assert(randp(5,1,5),[8 2 3 6 6])
00956 %!test
00957 %! % Test fixed state
00958 %! randp("seed",1);
00959 %! assert(randp(15,1,6),[15 16 12 10 10 12])
00960 %!test
00961 %! % Test fixed state
00962 %! randp("seed",1);
00963 %! assert(randp(1e9,1,6),[1000006208 1000012224 999981120 999963520 999963072 999981440],-1e-6)
00964 %!test
00965 %! if (__random_statistical_tests__)
00966 %!   % statistical tests may fail occasionally.
00967 %!   randp("state",12)
00968 %!   for a=[5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
00969 %!     x = randp(a(1),100000,1);
00970 %!     assert(min(x)>=0); % *** Please report this!!! ***
00971 %!     assert(mean(x),a(1),a(2));
00972 %!     assert(var(x),a(1),0.02*a(1));
00973 %!     assert(skewness(x),1/sqrt(a(1)),a(3));
00974 %!     assert(kurtosis(x),1/a(1),3*a(3));
00975 %!   endfor
00976 %! endif
00977 %!test
00978 %! if (__random_statistical_tests__)
00979 %!   % statistical tests may fail occasionally.
00980 %!   randp("state",12)
00981 %!   for a=[5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
00982 %!     x = randp(a(1)*ones(100000,1),100000,1);
00983 %!     assert(min(x)>=0); % *** Please report this!!! ***
00984 %!     assert(mean(x),a(1),a(2));
00985 %!     assert(var(x),a(1),0.02*a(1));
00986 %!     assert(skewness(x),1/sqrt(a(1)),a(3));
00987 %!     assert(kurtosis(x),1/a(1),3*a(3));
00988 %!   endfor
00989 %! endif
00990 %!test
00991 %! randp("seed",12)
00992 %!assert(randp([-inf,-1,0,inf,nan]),[nan,nan,0,nan,nan]); % *** Please report
00993 %!test
00994 %! if (__random_statistical_tests__)
00995 %!   % statistical tests may fail occasionally.
00996 %!   randp("seed",12)
00997 %!   for a=[5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
00998 %!     x = randp(a(1),100000,1);
00999 %!     assert(min(x)>=0); % *** Please report this!!! ***
01000 %!     assert(mean(x),a(1),a(2));
01001 %!     assert(var(x),a(1),0.02*a(1));
01002 %!     assert(skewness(x),1/sqrt(a(1)),a(3));
01003 %!     assert(kurtosis(x),1/a(1),3*a(3));
01004 %!   endfor
01005 %! endif
01006 %!test
01007 %! if (__random_statistical_tests__)
01008 %!   % statistical tests may fail occasionally.
01009 %!   randp("seed",12)
01010 %!   for a=[5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03]
01011 %!     x = randp(a(1)*ones(100000,1),100000,1);
01012 %!     assert(min(x)>=0); % *** Please report this!!! ***
01013 %!     assert(mean(x),a(1),a(2));
01014 %!     assert(var(x),a(1),0.02*a(1));
01015 %!     assert(skewness(x),1/sqrt(a(1)),a(3));
01016 %!     assert(kurtosis(x),1/a(1),3*a(3));
01017 %!   endfor
01018 %! endif
01019 */
01020 
01021 DEFUN_DLD (randperm, args, ,
01022   "-*- texinfo -*-\n\
01023 @deftypefn  {Loadable Function} {} randperm (@var{n})\n\
01024 @deftypefnx {Loadable Function} {} randperm (@var{n}, @var{m})\n\
01025 Return a row vector containing a random permutation of @code{1:@var{n}}.\n\
01026 If @var{m} is supplied, return @var{m} unique entries, sampled without\n\
01027 replacement from @code{1:@var{n}}.  The complexity is O(@var{n}) in\n\
01028 memory and O(@var{m}) in time, unless @var{m} < @var{n}/5, in which case\n\
01029 O(@var{m}) memory is used as well.  The randomization is performed using\n\
01030 rand(). All permutations are equally likely.\n\
01031 @seealso{perms}\n\
01032 @end deftypefn")
01033 {
01034 
01035 #ifdef USE_UNORDERED_MAP_WITH_TR1
01036 using std::tr1::unordered_map;
01037 #else
01038 using std::unordered_map;
01039 #endif
01040 
01041   int nargin = args.length ();
01042   octave_value retval;
01043 
01044   if (nargin == 1 || nargin == 2)
01045     {
01046       octave_idx_type n, m;
01047 
01048       n = args(0).idx_type_value (true);
01049 
01050       if (nargin == 2)
01051         m = args(1).idx_type_value (true);
01052       else
01053         m = n;
01054 
01055       if (m < 0 || n < 0)
01056         error ("randperm: M and N must be non-negative");
01057 
01058       if (m > n)
01059         error ("randperm: M must be less than or equal to N");
01060 
01061       // Quick and dirty heuristic to decide if we allocate or not the
01062       // whole vector for tracking the truncated shuffle.
01063       bool short_shuffle = m < n/5 && m < 1e5;
01064 
01065       if (! error_state)
01066         {
01067           // Generate random numbers.
01068           NDArray r = octave_rand::nd_array (dim_vector (1, m));
01069           double *rvec = r.fortran_vec ();
01070 
01071           octave_idx_type idx_len = short_shuffle ? m : n;
01072           Array<octave_idx_type> idx (dim_vector (1, idx_len));
01073           octave_idx_type *ivec = idx.fortran_vec ();
01074 
01075           for (octave_idx_type i = 0; i < idx_len; i++)
01076             ivec[i] = i;
01077 
01078           if (short_shuffle)
01079             {
01080               unordered_map<octave_idx_type, octave_idx_type> map (m);
01081 
01082               // Perform the Knuth shuffle only keeping track of moved
01083               // entries in the map
01084               for (octave_idx_type i = 0; i < m; i++)
01085                 {
01086                   octave_idx_type k = i +
01087                     gnulib::floor (rvec[i] * (n - i));
01088 
01089                   //For shuffling first m entries, no need to use extra
01090                   //storage
01091                   if (k < m)
01092                     {
01093                       std::swap (ivec[i], ivec[k]);
01094                     }
01095                   else
01096                     {
01097                       if (map.find (k) == map.end ())
01098                         map[k] = k;
01099 
01100                       std::swap (ivec[i], map[k]);
01101                     }
01102                 }
01103             }
01104           else
01105             {
01106 
01107               // Perform the Knuth shuffle of the first m entries
01108               for (octave_idx_type i = 0; i < m; i++)
01109                 {
01110                   octave_idx_type k = i +
01111                     gnulib::floor (rvec[i] * (n - i));
01112                   std::swap (ivec[i], ivec[k]);
01113                 }
01114             }
01115 
01116           // Convert to doubles, reusing r.
01117           for (octave_idx_type i = 0; i < m; i++)
01118             rvec[i] = ivec[i] + 1;
01119 
01120           if (m < n)
01121             idx.resize (dim_vector (1, m));
01122 
01123           // Now create an array object with a cached idx_vector.
01124           retval = new octave_matrix (r, idx_vector (idx));
01125         }
01126     }
01127   else
01128     print_usage ();
01129 
01130   return retval;
01131 }
01132 
01133 /*
01134 %!assert (sort (randperm (20)), 1:20)
01135 %!assert (length (randperm (20,10)), 10)
01136 
01137 %!test
01138 %! rand ("seed", 0);
01139 %! for i = 1:100
01140 %!   p = randperm (305, 30);
01141 %!   assert (length (unique (p)), 30);
01142 %! endfor
01143 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines