# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1381862928 14400 # Node ID 0b7f5c56f8531471a5e42a4f9f306b11a1998964 # Parent 1978a6c76aa9ce181c61d51906efd0f6e08fc221 Allow randperm to work with bigger inputs (bug #39378) * rand.cc (Frandperm): Remove restriction on maximum size of m. Wrap the allocation of idx in a try-catch block. Allocate a smaller idx in the catch block. Add a test. diff -r 1978a6c76aa9 -r 0b7f5c56f853 libinterp/corefcn/rand.cc --- a/libinterp/corefcn/rand.cc Tue Oct 15 11:09:07 2013 -0700 +++ b/libinterp/corefcn/rand.cc Tue Oct 15 14:48:48 2013 -0400 @@ -1157,7 +1157,7 @@ // Quick and dirty heuristic to decide if we allocate or not the // whole vector for tracking the truncated shuffle. - bool short_shuffle = m < n/5 && m < 1e5; + bool short_shuffle = m < n/5; if (! error_state) { @@ -1166,7 +1166,20 @@ double *rvec = r.fortran_vec (); octave_idx_type idx_len = short_shuffle ? m : n; - Array idx (dim_vector (1, idx_len)); + Array idx; + try + { + idx = Array (dim_vector (1, idx_len)); + } + catch(std::bad_alloc) + { + // Looks like n is too big and short_shuffle is false. + // Let's try again, but this time with the alternative. + idx_len = m; + short_shuffle = true; + idx = Array (dim_vector (1, idx_len)); + } + octave_idx_type *ivec = idx.fortran_vec (); for (octave_idx_type i = 0; i < idx_len; i++) @@ -1231,6 +1244,9 @@ %!assert (sort (randperm (20)), 1:20) %!assert (length (randperm (20,10)), 10) +## Test biggish N (bug #39378) +%!assert (length (randperm(30000^2, 100000)), 100000); + %!test %! rand ("seed", 0); %! for i = 1:100