diff options
Diffstat (limited to 'lib/stdlib/src/random.erl')
-rw-r--r-- | lib/stdlib/src/random.erl | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/stdlib/src/random.erl b/lib/stdlib/src/random.erl new file mode 100644 index 0000000000..01227c29b4 --- /dev/null +++ b/lib/stdlib/src/random.erl @@ -0,0 +1,124 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(random). + +%% Reasonable random number generator. +%% The method is attributed to B. A. Wichmann and I. D. Hill +%% See "An efficient and portable pseudo-random number generator", +%% Journal of Applied Statistics. AS183. 1982. Also Byte March 1987. + +-export([seed/0, seed/1, seed/3, uniform/0, uniform/1, + uniform_s/1, uniform_s/2, seed0/0]). + +%%----------------------------------------------------------------------- +%% The type of the state + +-type ran() :: {integer(), integer(), integer()}. + +%%----------------------------------------------------------------------- + +-spec seed0() -> ran(). + +seed0() -> + {3172, 9814, 20125}. + +%% seed() +%% Seed random number generation with default values + +-spec seed() -> ran(). + +seed() -> + reseed(seed0()). + +%% seed({A1, A2, A3}) +%% Seed random number generation + +-spec seed({integer(), integer(), integer()}) -> 'undefined' | ran(). + +seed({A1, A2, A3}) -> + seed(A1, A2, A3). + +%% seed(A1, A2, A3) +%% Seed random number generation + +-spec seed(integer(), integer(), integer()) -> 'undefined' | ran(). + +seed(A1, A2, A3) -> + put(random_seed, + {abs(A1) rem 30269, abs(A2) rem 30307, abs(A3) rem 30323}). + + +-spec reseed(ran()) -> ran(). + +reseed({A1, A2, A3}) -> + case seed(A1, A2, A3) of + undefined -> seed0(); + {_,_,_} = Tuple -> Tuple + end. + +%% uniform() +%% Returns a random float between 0 and 1. + +-spec uniform() -> float(). + +uniform() -> + {A1, A2, A3} = case get(random_seed) of + undefined -> seed0(); + Tuple -> Tuple + end, + B1 = (A1*171) rem 30269, + B2 = (A2*172) rem 30307, + B3 = (A3*170) rem 30323, + put(random_seed, {B1,B2,B3}), + R = A1/30269 + A2/30307 + A3/30323, + R - trunc(R). + +%% uniform(N) -> I +%% Given an integer N >= 1, uniform(N) returns a random integer +%% between 1 and N. + +-spec uniform(pos_integer()) -> pos_integer(). + +uniform(N) when is_integer(N), N >= 1 -> + trunc(uniform() * N) + 1. + + +%%% Functional versions + +%% uniform_s(State) -> {F, NewState} +%% Returns a random float between 0 and 1. + +-spec uniform_s(ran()) -> {float(), ran()}. + +uniform_s({A1, A2, A3}) -> + B1 = (A1*171) rem 30269, + B2 = (A2*172) rem 30307, + B3 = (A3*170) rem 30323, + R = A1/30269 + A2/30307 + A3/30323, + {R - trunc(R), {B1,B2,B3}}. + +%% uniform_s(N, State) -> {I, NewState} +%% Given an integer N >= 1, uniform(N) returns a random integer +%% between 1 and N. + +-spec uniform_s(pos_integer(), ran()) -> {integer(), ran()}. + +uniform_s(N, State0) when is_integer(N), N >= 1 -> + {F, State1} = uniform_s(State0), + {trunc(F * N) + 1, State1}. |