aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/random.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/src/random.erl')
-rw-r--r--lib/stdlib/src/random.erl124
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}.