;+ ; NAME: ; shuffle ; ; PURPOSE: ; This function shuffles the values in an array. ; ; CATEGORY: ; Array, Optimal Detection Package v3.1.1 ; ; CALLING SEQUENCE: ; result = shuffle( x ) ; ; INPUTS: ; X: An array of any type, of size N_X. ; ; KEYWORD PARAMETERS: ; INDEX: Returns the index values of the shuffled array. ; N_OUT: An optional scalar integer specifying the number of values to ; output. The default is N_X. If REPLACE is not set, then N_OUT cannot ; be larger than N_X. ; REPLACE: If set, the function shuffles with replacement. The default is ; without replacement. ; SEED: A seed for the random number generator to use. ; ; OUTPUTS: ; Result: Returns the shuffled version of array X. ; INDEX: See above. ; SEED: See above. Also returns a seed for the next implementation of the ; random number generator. ; ; PROCEDURE: ; This function used the RANDOMU IDL function to produce an array of random ; index values. ; ; EXAMPLE: ; Define a vector. ; x = [0,1,2,3,4] ; Shuffle the vector with replacement. ; result = shuffle( x, replace=1, seed=1 ) ; This should give result = [2,0,3,2,4]. ; ; MODIFICATION HISTORY: ; Written by: Daithi Stone (stoned@atm.ox.ac.uk), 2001-07-18. ; Modified: DAS, 2002-11-21 (added seed initialisation). ; Modified: DAS, 2003-02-17 (allowed input of very long vectors) ; Modified: DAS, 2005-01-03 (added SEED keyword) ; Modified: DAS, 2011-03-16 (corrected bug when long vectors are input; ; modified formating) ; Modified: DAS, 2011-11-06 (Inclusion in Optimal Detection Package ; category) ; Modified: DAS, 2019-10-31 (Add N_OUT keyword input; Added more efficient ; calculation when REPLACE=1) ;- ;*********************************************************************** FUNCTION SHUFFLE, $ X, $ INDEX=index, $ N_OUT=n_out, $ REPLACE=replace_opt, $ SEED=seed ;*********************************************************************** ; Constants and Variables ; Number of values input n_x = n_elements( x ) ; The number of values to output if not( keyword_set( n_out ) ) then n_out = n_x ; Whether we need to worry about long integer indices long_opt = max( [ n_x, n_out ] ) gt 32000 if long_opt eq 1 then begin zero = 0l endif else begin zero = 0 endelse ; Index of shuffled values if long_opt eq 1 then begin index = lonarr( n_out ) endif else begin index = intarr( n_out ) endelse ; Replacement option replace_opt = keyword_set( replace_opt ) if ( replace_opt eq 0 ) and ( n_out gt n_x ) then stop ; Working vector of index input values (needed only if shuffling without ; replacement) if replace_opt eq 0 then begin if long_opt eq 1 then begin id_left = lindgen( n_x + 2 ) - 1 endif else begin id_left = indgen( n_x + 2 ) - 1 endelse n_left = n_elements( id_left ) endif ; Initialise the random number generator if not( keyword_set( seed ) ) then seed = long( systime( seconds=1 ) ) ;*********************************************************************** ; Shuffle Values ; If we are shuffling without replacement if replace_opt eq 0 then begin ; Iterate through output values for i_out = zero, n_out - 1 do begin ; Determine how many values left to shuffle n_left = n_elements( id_left ) ; Generate a random index value ind = floor( randomu( seed, uniform=1 ) * ( n_left - 2 ) ) + 1 index[i_out] = id_left[ind] ; Remove the value from availability for later selection id_left = [ id_left[0:ind-1], id_left[ind+1:n_left-1] ] endfor ; If we are shuffling with replacement endif else begin ; Generate random index values index = floor( randomu( seed, n_out, uniform=1 ) * n_x ) id = where( index eq n_x, n_id ) ; Ensure no illegal values (from randomu()=1) while n_id gt 0 do begin index[id] = floor( randomu( seed, n_id, uniform=1 ) * n_x ) id = where( index eq n_x, n_id ) endwhile endelse ; Create shuffled array y = x[index] ; Reform output if n_out eq n_x then begin x_dim = ( size( x ) )[1:n_elements(size(x))-3] y = reform( y , x_dim ) index = reform( index, x_dim ) endif ;*********************************************************************** ; The End return, y END