function [seed,whichGen] = ClockRandSeed(seed,whichGen) % [seed,whichGen] = ClockRandSeed([seed],[whichGen]) % ClockRandSeed seeds the random number from the time-of-day clock or another % "random enough" random source, e.g., high resolution time, or a true % random number source. If 'seed' is passed this is used instead of a % random source or clock time. % % 'whichGen' optionally allows selection of the random number generator. % If omitted, the recommended Mersenne-Twister will be used on both % Matlab and Octave. % % If supported, the rng() function will be used, with rng('shuffle') if % 'seed' is omitted. Otherwise the old rand()/randn() setup method is % used, with 'reset' on Octave for truly random init from /dev/urandom % or high resolution clock time. On Matlab the old seed = fix(1e6*sum(clock)) % will be used. % % NOTE: There is a page in the 2017 Matlab docs describing the issues around % random number generator selection and seeding. Type "help rand" and then % follow to the note on "Replace Discouraged Syntaxes of rand and randn" that % is at the end of the Description section. % % For reseeding on old Matlab versions, note the following: % % The multiplier 1e6 in fix(1e6*sum(clock)) is bigger than the 100 % suggested by Mathworks (see help RAND). They suggest 100*sum(clock), but % this would only change the seed once every 1/100 sec, which might % correspond to many iterations of a loop. With the bigger multiplier it's % pretty sure (depending only on clock grain) that two successive calls % will generate different seeds. % % Also unlike the Mathworks suggestion (see help RAND), we call FIX. This % has no effect on RAND and RANDN, but makes it easier to correctly print % the seed to a file. When a random seed generates an interesting result % one would like to be able to recreate the conditions that generated the % run. If the seed 1e6*sum(clock) is printed to a file, '%.0f' will often % round it differently than RAND would. % % See also: rng, rand, randn. % 10/15/93 dhb Made this a function. % 4/11/94 dhb Added randn seeding. % 8/9/97 dgp Update for more reliable seed. % dgp Gutted it to make version-dependence explicit. % 8/9/97 dhb Ungutted it to hide version-dependence. % 8/13/97 dhb Optional return of which generator used and passing of seed/generator. % 7/24/04 awi Cosmetic. % 1/29/05 dgp Cosmetic. % 06/15/17 dhb Added warning and help text that this is obsolete. % 9-Aug-17 mk Undid dhb's warning, as it promotes writing non-portable code % that only works on specific versions of Matlab, and thereby % creates vendor lock-in. Instead rewrote the function to call % equivalent methods to rng('shuffle') in current Octave and older % versions of Matlab, and rng('shuffle') in current Matlab and % future Octave. That was the whole point of having ClockRandSeed() % in the first place: Something that doesn't break each time that % Mathworks incompetent or careless software engineering breaks % backward compatibility. At least i don't want this to degrade to % Mathworks or Apples standards if possible. % 6-May-20 mk Take into account that recent rng() implementations can % return 'seed' as a struct consisting of seed and generator % type. Reported and suggested fix by Xiangrui Li, thanks! if nargin < 2 || isempty(whichGen) % Recommended generator on Matlab and Octave is 'twister' for Mersenne-Twister. % This is also the default startup generator of Octave and modern Matlab: whichGen = 'twister'; end if nargin < 1 || isempty(seed) % No seed specified. Let Matlab/Octave do the job: if exist('rng') % Reinit from system time or other appropriate source: rng('shuffle', whichGen); % Retrieve new seed after reinit: seed = rng; if isstruct(seed) whichGen = seed.Type; seed = seed.Seed; end else if IsOctave % Octave 'reset' will reinit from system time, or from the % truly random random number generator /dev/urandom if it % exists, e.g. on Linux: rand(whichGen, 'reset'); % Retrieve new seed after init: seed = rand(whichGen); % Apply it to the other randn() generator, so both operate % off the same 'seed': randn(whichGen, seed); else % Matlab: Manually reinit with clock time: seed = fix(1e6*sum(clock)); rand(whichGen, seed); randn(whichGen, seed); end end % Got our reinit and whichGen and seed contain the new selected % generator type and seed, so we are done: return; end % If we get to this point, then user wants total control: if exist('rng') rng(seed, whichGen); else rand(whichGen,seed); randn(whichGen,seed); end return;