diff options
Diffstat (limited to 'lib/stdlib')
-rw-r--r-- | lib/stdlib/doc/src/rand.xml | 24 | ||||
-rw-r--r-- | lib/stdlib/src/rand.erl | 36 |
2 files changed, 36 insertions, 24 deletions
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml index 8745e16908..e7a5fb7fab 100644 --- a/lib/stdlib/doc/src/rand.xml +++ b/lib/stdlib/doc/src/rand.xml @@ -120,20 +120,28 @@ S0 = rand:seed_s(exsplus), {SND0, S2} = rand:normal_s(S1),</pre> <note> - <p>This random number generator is not cryptographically - strong. If a strong cryptographic random number generator is - needed, use one of functions in the - <seealso marker="crypto:crypto"><c>crypto</c></seealso> - module, for example, <seealso marker="crypto:crypto"> - <c>crypto:strong_rand_bytes/1</c></seealso>.</p> + <p>The builtin random number generator algorithms are not + cryptographically strong. If a cryptographically strong + random number generator is needed, use something like + <seealso marker="crypto:crypto#rand_seed-0"><c>crypto:rand_seed/0</c></seealso>. + </p> </note> </description> <datatypes> <datatype> + <name name="builtin_alg"/> + </datatype> + <datatype> <name name="alg"/> </datatype> <datatype> + <name name="alg_handler"/> + </datatype> + <datatype> + <name name="alg_seed"/> + </datatype> + <datatype> <name name="state"/> <desc><p>Algorithm-dependent state.</p></desc> </datatype> @@ -216,7 +224,7 @@ S0 = rand:seed_s(exsplus), <desc> <marker id="seed-1"/> <p>Seeds random number generation with the specifed algorithm and - time-dependent data if <anno>AlgOrExpState</anno> is an algorithm.</p> + time-dependent data if <anno>AlgOrStateOrExpState</anno> is an algorithm.</p> <p>Otherwise recreates the exported seed in the process dictionary, and returns the state. See also <seealso marker="#export_seed-0"><c>export_seed/0</c></seealso>.</p> @@ -237,7 +245,7 @@ S0 = rand:seed_s(exsplus), <fsummary>Seed random number generator.</fsummary> <desc> <p>Seeds random number generation with the specifed algorithm and - time-dependent data if <anno>AlgOrExpState</anno> is an algorithm.</p> + time-dependent data if <anno>AlgOrStateOrExpState</anno> is an algorithm.</p> <p>Otherwise recreates the exported seed and returns the state. See also <seealso marker="#export_seed-0"> <c>export_seed/0</c></seealso>.</p> diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl index 1f457b9e0e..3ff7aaf15f 100644 --- a/lib/stdlib/src/rand.erl +++ b/lib/stdlib/src/rand.erl @@ -45,20 +45,22 @@ %% ===================================================================== %% This depends on the algorithm handler function --type alg_seed() :: exs64_state() | exsplus_state() | exs1024_state(). +-type alg_seed() :: exs64_state() | exsplus_state() | exs1024_state() | term(). + %% This is the algorithm handler function within this module -type alg_handler() :: #{type := alg(), - max := integer(), - next := fun(), - uniform := fun(), - uniform_n := fun(), - jump := fun()}. - -%% Internal state --opaque state() :: {alg_handler(), alg_seed()}. --type alg() :: exs64 | exsplus | exs1024. --opaque export_state() :: {alg(), alg_seed()}. --export_type([alg/0, state/0, export_state/0]). + max := integer() | infinity, + next := fun((alg_seed()) -> {uint64(), alg_seed()}), + uniform := fun((state()) -> {float(), state()}), + uniform_n := fun((pos_integer(), state()) -> {pos_integer(), state()}), + jump := fun((state()) -> state())}. + +%% Algorithm state +-type state() :: {alg_handler(), alg_seed()}. +-type builtin_alg() :: exs64 | exsplus | exs1024. +-type alg() :: builtin_alg() | term(). +-type export_state() :: {alg(), alg_seed()}. +-export_type([builtin_alg/0, alg/0, alg_handler/0, alg_seed/0, state/0, export_state/0]). %% ===================================================================== %% API @@ -81,15 +83,17 @@ export_seed_s({#{type:=Alg}, Seed}) -> {Alg, Seed}. %% seed({Alg,Seed}) setup RNG with a previously exported seed %% and return the NEW state --spec seed(AlgOrExpState::alg() | export_state()) -> state(). +-spec seed(AlgOrStateOrExpState::builtin_alg() | state() | export_state()) -> state(). seed(Alg) -> seed_put(seed_s(Alg)). --spec seed_s(AlgOrExpState::alg() | export_state()) -> state(). +-spec seed_s(AlgOrStateOrExpState::builtin_alg() | state() | export_state()) -> state(). seed_s(Alg) when is_atom(Alg) -> seed_s(Alg, {erlang:phash2([{node(),self()}]), erlang:system_time(), erlang:unique_integer()}); +seed_s({AlgHandler, _Seed} = State) when is_map(AlgHandler) -> + State; seed_s({Alg0, Seed}) -> {Alg,_SeedFun} = mk_alg(Alg0), {Alg, Seed}. @@ -97,11 +101,11 @@ seed_s({Alg0, Seed}) -> %% seed/2: seeds RNG with the algorithm and given values %% and returns the NEW state. --spec seed(Alg :: alg(), {integer(), integer(), integer()}) -> state(). +-spec seed(Alg :: builtin_alg(), {integer(), integer(), integer()}) -> state(). seed(Alg0, S0) -> seed_put(seed_s(Alg0, S0)). --spec seed_s(Alg :: alg(), {integer(), integer(), integer()}) -> state(). +-spec seed_s(Alg :: builtin_alg(), {integer(), integer(), integer()}) -> state(). seed_s(Alg0, S0 = {_, _, _}) -> {Alg, Seed} = mk_alg(Alg0), AS = Seed(S0), |