Packages
otpbp
5.10.0
7.18.0
7.16.1
7.15.0
7.14.0
7.13.0
7.12.0
7.11.0
7.10.2
7.9.3
7.9.2
7.9.1
7.8.7
7.8.6
7.8.5
7.8.4
7.7.1
7.7.0
7.6.3
7.6.2
7.6.1
7.6.0
7.5.1
7.5.0
7.4.0
7.3.4
7.3.3
7.3.2
7.3.1
7.3.0
7.2.0
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
6.26.0
6.25.0
6.24.0
6.23.0
6.22.2
6.21.3
6.21.2
6.21.1
6.20.2
6.19.1
6.19.0
6.18.3
6.18.2
6.18.1
6.18.0
6.17.1
6.17.0
6.16.0
6.15.4
6.15.3
6.15.2
6.15.1
6.15.0
6.14.0
6.13.5
6.13.4
6.13.3
6.13.2
6.13.1
6.13.0
6.12.0
6.11.2
6.11.1
6.10.0
6.9.2
6.9.1
6.9.0
6.8.0
6.7.1
6.7.0
6.6.4
6.6.3
6.6.2
6.6.1
6.6.0
6.5.0
6.4.0
6.3.3
6.3.2
6.3.1
6.3.0
6.2.1
6.2.0
6.1.0
6.0.0
5.39.0
5.38.0
5.37.0
5.36.0
5.35.2
5.34.3
5.34.2
5.34.1
5.33.1
5.32.1
5.32.0
5.31.3
5.31.2
5.31.1
5.31.0
5.30.1
5.30.0
5.29.0
5.28.4
5.28.3
5.28.2
5.28.1
5.28.0
5.27.0
5.26.5
5.26.4
5.26.3
5.26.2
5.26.1
5.26.0
5.25.0
5.24.2
5.24.1
5.23.0
5.22.2
5.22.1
5.22.0
5.21.0
5.20.1
5.20.0
5.19.4
5.19.3
5.19.2
5.19.1
5.19.0
5.18.0
5.17.0
5.16.3
5.16.1
5.16.0
5.15.1
5.15.0
5.14.0
5.13.1
5.13.0
5.12.1
5.12.0
5.11.2
5.11.1
5.10.1
5.10.0
5.9.0
5.8.0
5.7.0
5.6.1
5.6.0
5.5.0
5.4.2
5.4.1
5.4.0
5.3.0
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
4.79.0
4.78.0
4.77.0
4.76.2
4.75.3
4.75.2
4.75.1
4.74.0
4.73.1
4.73.0
4.72.3
4.72.2
4.72.1
4.72.0
4.71.1
4.71.0
4.70.0
4.69.4
4.69.3
4.69.2
4.69.1
4.69.0
4.68.0
4.67.5
4.67.4
4.67.3
4.67.2
4.67.0
4.66.0
4.65.2
4.65.1
4.64.0
4.63.2
4.63.1
4.63.0
4.62.0
4.61.1
4.61.0
4.60.4
4.60.3
4.60.2
4.60.1
4.60.0
4.59.0
4.58.0
4.57.2
4.57.1
4.57.0
4.56.2
4.56.1
4.56.0
4.55.0
4.54.0
4.53.0
4.52.1
4.52.0
4.51.3
4.51.2
4.51.0
4.50.0
4.49.3
4.49.2
OTP backports
Current section
Files
Jump to
Current section
Files
src/otpbp_rand.erl
-module(otpbp_rand).
-ifndef(HAVE_rand__jump_0).
% OTP 20.0
-export([jump/0]).
-endif.
-ifndef(HAVE_rand__jump_1).
% OTP 20.0
-export([jump/1]).
-endif.
-ifndef(HAVE_rand__normal_2).
% OTP 20.0
-export([normal/2]).
-endif.
-ifndef(HAVE_rand__normal_s_3).
% OTP 20.0
-export([normal_s/3]).
-endif.
-ifndef(HAVE_rand__uniform_real_0).
% OTP 21.0
-export([uniform_real/0]).
-endif.
-ifndef(HAVE_rand__uniform_real_s_1).
% OTP 21.0
-export([uniform_real_s/1]).
-endif.
-ifndef(HAVE_rand__splitmix64_next_1).
% OTP 25.0
-export([splitmix64_next/1]).
-endif.
-ifndef(HAVE_rand__exsp_next_1).
% OTP 25.0
-export([exsp_next/1]).
-endif.
-ifndef(HAVE_rand__exsp_jump_1).
% OTP 25.0
-export([exsp_jump/1]).
-endif.
-ifndef(HAVE_rand__mwc59_1).
% OTP 25.0
-export([mwc59/1]).
-endif.
-ifndef(HAVE_rand__mwc59_value32_1).
% OTP 25.0
-export([mwc59_value32/1]).
-endif.
-ifndef(HAVE_rand__mwc59_value_1).
% OTP 25.0
-export([mwc59_value/1]).
-endif.
-ifndef(HAVE_rand__mwc59_float_1).
% OTP 25.0
-export([mwc59_float/1]).
-endif.
-ifndef(HAVE_rand__mwc59_seed_0).
% OTP 25.0
-export([mwc59_seed/0]).
-endif.
-ifndef(HAVE_rand__mwc59_seed_1).
% OTP 25.0
-export([mwc59_seed/1]).
-endif.
-ifndef(HAVE_rand__bytes_1).
-ifndef(HAVE_rand__bytes_s_2).
-ifndef(NEED_rand__bytes_s_2).
-define(NEED_rand__bytes_s_2, true).
-endif.
-endif.
% OTP 24.0
-export([bytes/1]).
-endif.
-ifndef(HAVE_rand__bytes_s_2).
-ifndef(NEED_rand__bytes_s_2).
-define(NEED_rand__bytes_s_2, true).
-endif.
% OTP 24.0
-export([bytes_s/2]).
-endif.
-ifndef(HAVE_rand__jump_0).
-ifdef(HAVE_rand__jump_1).
-import(rand, [jump/1]).
-endif.
-endif.
-ifndef(HAVE_rand__normal_2).
-ifdef(HAVE_rand__normal_s_3).
-import(rand, [normal_s/3]).
-endif.
-endif.
-ifndef(HAVE_rand__uniform_real_0).
-ifdef(HAVE_rand__uniform_real_s_1).
-import(rand, [uniform_real_s/1]).
-endif.
-endif.
-ifndef(HAVE_rand__exsp_jump_1).
-ifdef(HAVE_rand__exsp_next_1).
-import(rand, [exsp_next/1]).
-endif.
-endif.
-define(SEED_DICT, rand_seed).
-define(BIT(Bits), (1 bsl (Bits))).
-define(MASK(Bits), (?BIT(Bits) - 1)).
-define(MASK(Bits, X), ((X) band ?MASK(Bits))).
-define(BSL(Bits, X, N), (?MASK((Bits) - (N), (X)) bsl (N))).
-define(MWC59_XS1, 4).
-define(MWC59_XS2, 27).
-ifndef(HAVE_rand__jump_1).
jump({#{jump := Jump}, _} = State) -> Jump(State);
jump({#{}, _}) -> error(not_implemented).
-endif.
-ifndef(HAVE_rand__jump_0).
jump() -> seed_put(jump(seed_get())).
-ifndef(NEED_seed_get_0).
-define(NEED_seed_get_0, true).
-endif.
-ifndef(NEED_seed_put_1).
-define(NEED_seed_put_1, true).
-endif.
-endif.
-ifndef(HAVE_rand__normal_2).
normal(Mean, Variance) -> Mean + math:sqrt(Variance) * rand:normal().
-endif.
-ifndef(HAVE_rand__normal_s_3).
normal_s(Mean, Variance, State0) when Variance > 0 ->
{X, State} = rand:normal_s(State0),
{Mean + math:sqrt(Variance) * X, State}.
-endif.
-ifndef(HAVE_rand__bytes_1).
bytes(N) ->
{Bytes, State} = bytes_s(N, seed_get()),
seed_put(State),
Bytes.
-ifndef(NEED_seed_get_0).
-define(NEED_seed_get_0, true).
-endif.
-ifndef(NEED_seed_put_1).
-define(NEED_seed_put_1, true).
-endif.
-endif.
-ifdef(NEED_rand__bytes_s_2).
bytes_s(N, {#{bits := Bits, next := Next} = AlgHandler, R}) when is_integer(N), 0 =< N ->
bytes_r(N, AlgHandler, Next, R, Bits, maps:get(weak_low_bits, AlgHandler, 0));
bytes_s(N, {#{max := Mask, next := Next} = AlgHandler, R}) when is_integer(N), 0 =< N, ?MASK(58) =< Mask ->
%% Old spec - assume 58 bits and 2 weak low bits
%% giving 56 bits i.e precisely 7 bytes per generated number
bytes_r(N, AlgHandler, Next, R, 58, 2).
-compile({inline, [bytes_r/6]}).
bytes_r(N, AlgHandler, Next, R, Bits, WeakLowBits) ->
%% We use whole bytes from each generator word,
%% GoodBytes: that number of bytes
GoodBytes = (Bits - WeakLowBits) bsr 3,
GoodBits = GoodBytes bsl 3,
%% Shift: how many bits of each generator word to waste by shifting right - we use the bits from the big end
bytes_r(N, AlgHandler, Next, R, <<>>, GoodBytes, GoodBits, Bits - GoodBits).
bytes_r(N0, AlgHandler, Next, R0, Bytes0, GoodBytes, GoodBits, Shift) when GoodBytes < N0 ->
{V, R1} = Next(R0),
bytes_r(N0 - GoodBytes, AlgHandler, Next, R1, <<Bytes0/binary, (V bsr Shift):GoodBits>>, GoodBytes, GoodBits, Shift);
bytes_r(N, AlgHandler, Next, R0, Bytes, _GoodBytes, GoodBits, _Shift) ->
{V, R1} = Next(R0),
Bits = N bsl 3,
%% Use the big end bits
{<<Bytes/binary, (V bsr (GoodBits - Bits)):Bits>>, {AlgHandler, R1}}.
-endif.
-ifndef(HAVE_rand__uniform_real_0).
uniform_real() ->
{X, Seed} = uniform_real_s(seed_get()),
seed_put(Seed),
X.
-ifndef(NEED_seed_get_0).
-define(NEED_seed_get_0, true).
-endif.
-ifndef(NEED_seed_put_1).
-define(NEED_seed_put_1, true).
-endif.
-endif.
-ifndef(HAVE_rand__uniform_real_s_1).
-define(BC(V, N), bc((V), ?BIT((N) - 1), N)).
uniform_real_s({#{next := Next} = Alg, R0}) ->
{V1, R1} = Next(R0),
uniform_real_s(Alg, V1, R1, Next).
-compile({inline, [uniform_real_s/5]}).
uniform_real_s(#{bits := Bits} = Alg, V1, R1, Next) ->
case V1 bsr (Bits - 56) of
M1 when ?BIT(55) =< M1 -> %% We have 56 bits - waste 3
{(M1 bsr 3) * math:pow(2.0, -53), {Alg, R1}};
M1 when ?BIT(54) =< M1 -> %% We have 55 bits - waste 2
{(M1 bsr 2) * math:pow(2.0, -54), {Alg, R1}};
M1 when ?BIT(53) =< M1 -> %% We have 54 bits - waste 1
{(M1 bsr 1) * math:pow(2.0, -55), {Alg, R1}};
M1 when ?BIT(52) =< M1 -> %% We have 53 bits - use all
{M1 * math:pow(2.0, -56), {Alg, R1}};
M1 -> %% Need more bits
{V2, R2} = Next(R1),
uniform_real_s(Alg, Next, M1, -56, R2, V2, Bits)
end;
uniform_real_s(#{max := _} = Alg, V1, R1, Next) ->
case ?MASK(56, V1) of
M1 when ?BIT(55) =< M1 -> %% We have 56 bits - waste 3
{(M1 bsr 3) * math:pow(2.0, -53), {Alg, R1}};
M1 when ?BIT(54) =< M1 -> %% We have 55 bits - waste 2
{(M1 bsr 2) * math:pow(2.0, -54), {Alg, R1}};
M1 when ?BIT(53) =< M1 -> %% We have 54 bits - waste 1
{(M1 bsr 1) * math:pow(2.0, -55), {Alg, R1}};
M1 when ?BIT(52) =< M1 -> %% We have 53 bits - use all
{M1 * math:pow(2.0, -56), {Alg, R1}};
M1 -> %% Need more bits
{V2, R2} = Next(R1),
uniform_real_s(Alg, Next, M1, -56, R2, V2, 56)
end.
uniform_real_s(Alg, _Next, M0, -1064, R1, V1, Bits) -> % 19*56
B0 = (53 - ?BC(M0, 52)), % Missing bits
{(((M0 bsl B0) bor (V1 bsr (Bits - B0))) * math:pow(2.0, -1064 - B0)), {Alg, R1}};
uniform_real_s(Alg, _Next, M0, BitNo, R1, V1, Bits) when ?BIT(51) =< M0 ->
{(((M0 bsl 1) bor (V1 bsr (Bits - 1))) * math:pow(2.0, BitNo - 1)), {Alg, R1}};
uniform_real_s(Alg, _Next, M0, BitNo, R1, V1, Bits) when ?BIT(50) =< M0 ->
{(((M0 bsl 2) bor (V1 bsr (Bits - 2))) * math:pow(2.0, BitNo - 2)), {Alg, R1}};
uniform_real_s(Alg, _Next, M0, BitNo, R1, V1, Bits) when ?BIT(49) =< M0 ->
{(((M0 bsl 3) bor (V1 bsr (Bits - 3))) * math:pow(2.0, BitNo - 3)), {Alg, R1}};
uniform_real_s(Alg, Next, 0, BitNo, R1, V1, Bits) ->
case V1 bsr (Bits - 56) of
M1 when ?BIT(55) =< M1 -> %% We have 56 bits - waste 3
{(M1 bsr 3) * math:pow(2.0, BitNo - 53), {Alg, R1}};
M1 when ?BIT(54) =< M1 -> %% We have 55 bits - waste 2
{(M1 bsr 2) * math:pow(2.0, BitNo - 54), {Alg, R1}};
M1 when ?BIT(53) =< M1 -> %% We have 54 bits - waste 1
{(M1 bsr 1) * math:pow(2.0, BitNo - 55), {Alg, R1}};
M1 when ?BIT(52) =< M1 -> %% We have 53 bits - use all
{M1 * math:pow(2.0, BitNo - 56), {Alg, R1}};
M1 when BitNo =/= -1008; ?BIT(42) =< M1 -> %% Need more bits; We have 43 bits - get the last bits
uniform_real_s(Alg, Next, M1, BitNo - 56, R1);
_ -> uniform_real_s({Alg, R1})
end;
uniform_real_s(Alg, _Next, M0, BitNo, R1, V1, Bits) ->
%% Fill up to 53 bits
B0 = 53 - ?BC(M0, 49), % Number of bits we need to append
{(((M0 bsl B0) bor (V1 bsr (Bits - B0))) * math:pow(2.0, BitNo - B0)), {Alg, R1}}.
uniform_real_s(Alg, Next, M0, BitNo, R0) ->
{V1, R1} = Next(R0),
case Alg of
#{bits := Bits} -> uniform_real_s(Alg, Next, M0, BitNo, R1, V1, Bits);
#{max := _} -> uniform_real_s(Alg, Next, M0, BitNo, R1, ?MASK(56, V1), 56)
end.
bc(V, B, N) when B =< V -> N;
bc(V, B, N) -> bc(V, B bsr 1, N - 1).
-endif.
-ifndef(HAVE_rand__splitmix64_next_1).
splitmix64_next(X_0) ->
X = ?MASK(64, X_0 + 16#9e3779b97f4a7c15),
Z_0 = ?MASK(64, (X bxor (X bsr 30)) * 16#bf58476d1ce4e5b9),
Z_1 = ?MASK(64, (Z_0 bxor (Z_0 bsr 27)) * 16#94d049bb133111eb),
{?MASK(64, Z_1 bxor (Z_1 bsr 31)), X}.
-endif.
-ifndef(HAVE_rand__exsp_next_1).
-define(exs_next(S0, S1, S1_b),
begin
S1_b = ?MASK(58, S1) bxor ?BSL(58, S1, 24),
S1_b bxor S0 bxor (S1_b bsr 11) bxor (S0 bsr 41)
end).
exsp_next([S1|S0]) ->
S0_1 = ?MASK(58, S0),
NewS1 = ?exs_next(S0_1, S1, S1_b),
{?MASK(58, S0_1 + NewS1), [S0_1|NewS1]}.
-endif.
-ifndef(HAVE_rand__exsp_jump_1).
-define(JUMPCONST1, 16#02f8ea6bc32c797).
-define(JUMPCONST2, 16#345d2a0f85f788c).
-define(JUMPELEMLEN, 58).
exsp_jump(S) ->
{S1, AS1} = exsplus_jump(S, [0|0], ?JUMPCONST1, ?JUMPELEMLEN),
{_, AS2} = exsplus_jump(S1, AS1, ?JUMPCONST2, ?JUMPELEMLEN),
AS2.
-dialyzer({no_improper_lists, exsplus_jump/4}).
exsplus_jump(S, AS, _, 0) -> {S, AS};
exsplus_jump(S, [AS0|AS1], J, N) ->
{_, NS} = exsp_next(S),
exsplus_jump(NS,
case ?MASK(1, J) of
1 ->
[S0|S1] = S,
[AS0 bxor S0|AS1 bxor S1];
0 -> [AS0|AS1]
end,
J bsr 1,
N - 1).
-endif.
-ifndef(HAVE_rand__mwc59_1).
-define(MWC59_A, 16#7fa6502).
-define(MWC59_B, 32).
mwc59(CX0) ->
CX = ?MASK(59, CX0),
?MWC59_A * ?MASK(?MWC59_B, CX) + CX bsr ?MWC59_B.
-endif.
-ifndef(HAVE_rand__mwc59_value32_1).
-define(MWC59_XS, 8).
mwc59_value32(CX1) ->
CX = ?MASK(32, CX1),
CX bxor ?BSL(32, CX, ?MWC59_XS).
-endif.
-ifndef(HAVE_rand__mwc59_value_1).
mwc59_value(CX1) ->
CX = ?MASK(59, CX1),
CX2 = CX bxor ?BSL(59, CX, ?MWC59_XS1),
CX2 bxor ?BSL(59, CX2, ?MWC59_XS2).
-endif.
-ifndef(HAVE_rand__mwc59_float_1).
-define(TWO_POW_MINUS53, 1.11022302462515657e-16).
mwc59_float(CX1) ->
CX = ?MASK(53, CX1),
CX2 = CX bxor ?BSL(53, CX, ?MWC59_XS1),
(CX2 bxor ?BSL(53, CX2, ?MWC59_XS2)) * ?TWO_POW_MINUS53.
-endif.
-ifndef(HAVE_rand__mwc59_seed_0).
mwc59_seed() ->
{A1, A2, A3} = default_seed(),
hash58(A1) bxor hash58(A2) bxor hash58(A3) + 1.
-compile({inline, default_seed/0}).
default_seed() -> {erlang:phash2([{node(), self()}]), erlang:system_time(), erlang:unique_integer()}.
-ifndef(NEED_hash58_1).
-define(NEED_hash58_1, true).
-endif.
-endif.
-ifndef(HAVE_rand__mwc59_seed_1).
mwc59_seed(S) when is_integer(S), 0 =< S, S =< ?MASK(58) -> hash58(S) + 1.
-ifndef(NEED_hash58_1).
-define(NEED_hash58_1, true).
-endif.
-endif.
-ifdef(NEED_seed_get_0).
-define(DEFAULT_ALG_HANDLER, exrop).
seed_get() ->
case get(?SEED_DICT) of
undefined -> rand:seed(?DEFAULT_ALG_HANDLER);
Old -> Old % no type checking here
end.
-endif.
-ifdef(NEED_seed_put_1).
seed_put(Seed) ->
put(?SEED_DICT, Seed),
Seed.
-endif.
-ifdef(NEED_hash58_1).
hash58(X) ->
X0 = ?MASK(58, X),
X1 = ?MASK(58, (X0 bxor (X0 bsr 29)) * 16#351afd7ed558ccd),
X2 = ?MASK(58, (X1 bxor (X1 bsr 29)) * 16#0ceb9fe1a85ec53),
X2 bxor (X2 bsr 29).
-endif.