Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Pseudo-random-numbers-PCG32/00-META.yaml
Normal file
2
Task/Pseudo-random-numbers-PCG32/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Pseudo-random_numbers/PCG32
|
||||
71
Task/Pseudo-random-numbers-PCG32/00-TASK.txt
Normal file
71
Task/Pseudo-random-numbers-PCG32/00-TASK.txt
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
;Some definitions to help in the explanation:
|
||||
|
||||
:Floor operation<br>
|
||||
::https://en.wikipedia.org/wiki/Floor_and_ceiling_functions<br>
|
||||
::Greatest integer less than or equal to a real number.
|
||||
|
||||
:Bitwise Logical shift operators (c-inspired)<br>
|
||||
::https://en.wikipedia.org/wiki/Bitwise_operation#Bit_shifts<br>
|
||||
::Binary bits of value shifted left or right, with zero bits shifted in where appropriate.
|
||||
::Examples are shown for 8 bit binary numbers; most significant bit to the left.
|
||||
|
||||
:: '''<<''' Logical shift left by given number of bits.
|
||||
:::E.g Binary 00110101 '''<<''' 2 == Binary 11010100
|
||||
|
||||
:: '''>>''' Logical shift right by given number of bits.
|
||||
:::E.g Binary 00110101 '''>>''' 2 == Binary 00001101
|
||||
|
||||
:'''^''' Bitwise exclusive-or operator
|
||||
::https://en.wikipedia.org/wiki/Exclusive_or
|
||||
::Bitwise comparison for if bits differ
|
||||
:::E.g Binary 00110101 '''^''' Binary 00110011 == Binary 00000110
|
||||
|
||||
:'''|''' Bitwise or operator
|
||||
::https://en.wikipedia.org/wiki/Bitwise_operation#OR
|
||||
::Bitwise comparison gives 1 if any of corresponding bits are 1
|
||||
:::E.g Binary 00110101 '''|''' Binary 00110011 == Binary 00110111
|
||||
|
||||
|
||||
;[https://www.pcg-random.org/download.html#minimal-c-implementation| PCG32] Generator (pseudo-code):
|
||||
|
||||
PCG32 has two unsigned 64-bit integers of internal state:
|
||||
# '''state''': All 2**64 values may be attained.
|
||||
# '''sequence''': Determines which of 2**63 sequences that <code>state</code> iterates through. (Once set together with <code>state</code> at time of seeding will stay constant for this generators lifetime).
|
||||
|
||||
Values of <code>sequence</code> allow 2**63 ''different'' sequences of random numbers from the same <code>state</code>.
|
||||
|
||||
The algorithm is given 2 U64 inputs called <code>seed_state</code>, and <code>seed_sequence</code>. The algorithm proceeds in accordance with the following pseudocode:-
|
||||
<pre>
|
||||
const N<-U64 6364136223846793005
|
||||
const inc<-U64 (seed_sequence << 1) | 1
|
||||
state<-U64 ((inc+seed_state)*N+inc
|
||||
do forever
|
||||
xs<-U32 (((state>>18)^state)>>27)
|
||||
rot<-INT (state>>59)
|
||||
OUTPUT U32 (xs>>rot)|(xs<<((-rot)&31))
|
||||
state<-state*N+inc
|
||||
end do
|
||||
</pre>
|
||||
Note that this an [[wp:Anamorphism |anamorphism]] – dual to catamorphism, and encoded in some languages as a general higher-order `unfold` function, dual to `fold` or `reduce`.
|
||||
|
||||
;Task:
|
||||
|
||||
* Generate a class/set of functions that generates pseudo-random
|
||||
numbers using the above.
|
||||
|
||||
* Show that the first five integers generated with the seed <code>42, 54</code>
|
||||
are: 2707161783 2068313097 3122475824 2211639955 3215226955
|
||||
|
||||
|
||||
|
||||
* Show that for an initial seed of <code>987654321, 1</code> the counts of 100_000 repetitions of
|
||||
|
||||
floor(random_gen.next_float() * 5)
|
||||
|
||||
:Is as follows:
|
||||
|
||||
0: 20049, 1: 20022, 2: 20115, 3: 19809, 4: 20005
|
||||
|
||||
* Show your output here, on this page.
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
T PCG32
|
||||
UInt64 state, inc
|
||||
|
||||
F next_int()
|
||||
V old = .state
|
||||
.state = (old * 6364136223846793005) + .inc
|
||||
V shifted = UInt32(((old >> 18) (+) old) >> 27)
|
||||
V rot = UInt32(old >> 59)
|
||||
R (shifted >> rot) [|] (shifted << (((-)rot + 1) [&] 31))
|
||||
|
||||
F seed(UInt64 seed_state, seed_sequence)
|
||||
.state = 0
|
||||
.inc = (seed_sequence << 1) [|] 1
|
||||
.next_int()
|
||||
.state += seed_state
|
||||
.next_int()
|
||||
|
||||
F next_float()
|
||||
R Float(.next_int()) / (UInt64(1) << 32)
|
||||
|
||||
V random_gen = PCG32()
|
||||
random_gen.seed(42, 54)
|
||||
L 5
|
||||
print(random_gen.next_int())
|
||||
|
||||
random_gen.seed(987654321, 1)
|
||||
V hist = Dict(0.<5, i -> (i, 0))
|
||||
L 100'000
|
||||
hist[Int(random_gen.next_float() * 5)]++
|
||||
print(hist)
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
BEGIN # generate some pseudo random numbers using PCG32 #
|
||||
# note that although LONG INT is 64 bits in Algol 68G, LONG BITS is longer than 64 bits #
|
||||
LONG BITS state := LONG 16r853c49e6748fea9b;
|
||||
LONG INT inc := ABS LONG 16rda3e39cb94b95bdb;
|
||||
LONG BITS mask 64 = LONG 16rffffffffffffffff;
|
||||
LONG BITS mask 32 = LONG 16rffffffff;
|
||||
LONG BITS mask 31 = LONG 16r7fffffff;
|
||||
LONG INT one shl 32 = ABS ( LONG 16r1 SHL 32 );
|
||||
# XOR and assign convenience operator #
|
||||
PRIO XORAB = 1;
|
||||
OP XORAB = ( REF LONG BITS x, LONG BITS v )REF LONG BITS: x := ( x XOR v ) AND mask 64;
|
||||
# initialises the state to the specified seed #
|
||||
PROC seed = ( LONG INT seed state, seed sequence )VOID:
|
||||
BEGIN
|
||||
state := 16r0;
|
||||
inc := ABS ( ( ( BIN seed sequence SHL 1 ) OR 16r1 ) AND mask 64 );
|
||||
next int;
|
||||
state := SHORTEN ( BIN ( ABS state + seed state ) AND mask 64 );
|
||||
next int
|
||||
END # seed # ;
|
||||
# gets the next pseudo random integer #
|
||||
PROC next int = LONG INT:
|
||||
BEGIN
|
||||
LONG BITS old = state;
|
||||
LONG INT const = LONG 6364136223846793005;
|
||||
state := SHORTEN ( mask 64 AND BIN ( ( ABS old * LENG const ) + inc ) );
|
||||
LONG BITS x := old;
|
||||
x XORAB ( old SHR 18 );
|
||||
BITS xor shifted = SHORTEN ( mask 32 AND ( x SHR 27 ) );
|
||||
INT rot = SHORTEN ABS ( mask 32 AND ( old SHR 59 ) );
|
||||
INT rot 2 = IF rot = 0 THEN 0 ELSE 32 - rot FI;
|
||||
BITS xor shr := SHORTEN ( mask 32 AND LENG ( xor shifted SHR rot ) );
|
||||
BITS xor shl := xor shifted;
|
||||
TO rot 2 DO
|
||||
xor shl := SHORTEN ( ( mask 31 AND LENG xor shl ) SHL 1 )
|
||||
OD;
|
||||
ABS ( LENG xor shr OR LENG xor shl )
|
||||
END # next int # ;
|
||||
# gets the next pseudo random real #
|
||||
PROC next float = LONG REAL: next int / one shl 32;
|
||||
BEGIN # task test cases #
|
||||
seed( 42, 54 );
|
||||
print( ( whole( next int, 0 ), newline ) ); # 2707161783 #
|
||||
print( ( whole( next int, 0 ), newline ) ); # 2068313097 #
|
||||
print( ( whole( next int, 0 ), newline ) ); # 3122475824 #
|
||||
print( ( whole( next int, 0 ), newline ) ); # 2211639955 #
|
||||
print( ( whole( next int, 0 ), newline ) ); # 3215226955 #
|
||||
# count the number of occurances of 0..4 in a sequence of pseudo random reals scaled to be in [0..5) #
|
||||
seed( 987654321, 1 );
|
||||
[ 0 : 4 ]INT counts; FOR i FROM LWB counts TO UPB counts DO counts[ i ] := 0 OD;
|
||||
TO 100 000 DO counts[ SHORTEN ENTIER ( next float * 5 ) ] +:= 1 OD;
|
||||
FOR i FROM LWB counts TO UPB counts DO
|
||||
print( ( whole( i, -2 ), ": ", whole( counts[ i ], -6 ) ) )
|
||||
OD;
|
||||
print( ( newline ) )
|
||||
END
|
||||
END
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
with Interfaces; use Interfaces;
|
||||
|
||||
package random_pcg32 is
|
||||
function Next_Int return Unsigned_32;
|
||||
function Next_Float return Long_Float;
|
||||
procedure Seed (seed_state : Unsigned_64; seed_sequence : Unsigned_64);
|
||||
end random_pcg32;
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package body random_pcg32 is
|
||||
|
||||
State : Unsigned_64 := 0;
|
||||
inc : Unsigned_64 := 0;
|
||||
|
||||
----------------
|
||||
-- Next_State --
|
||||
----------------
|
||||
|
||||
procedure Next_State is
|
||||
N : constant Unsigned_64 := 6_364_136_223_846_793_005;
|
||||
begin
|
||||
State := State * N + inc;
|
||||
end Next_State;
|
||||
|
||||
--------------
|
||||
-- Next_Int --
|
||||
--------------
|
||||
|
||||
function Next_Int return Unsigned_32 is
|
||||
old : Unsigned_64 := State;
|
||||
shifted : Unsigned_32;
|
||||
Rot : Unsigned_64;
|
||||
answer : Unsigned_32;
|
||||
Mask32 : constant Unsigned_64 := Unsigned_64 (Unsigned_32'Last);
|
||||
begin
|
||||
shifted := Unsigned_32((((old / 2**18) xor old) / 2**27) and Mask32);
|
||||
Rot := old / 2**59;
|
||||
answer :=
|
||||
Shift_Right (shifted, Integer (Rot)) or
|
||||
Shift_Left (shifted, Integer ((not Rot + 1) and 31));
|
||||
Next_State;
|
||||
return answer;
|
||||
end Next_Int;
|
||||
|
||||
----------------
|
||||
-- Next_Float --
|
||||
----------------
|
||||
|
||||
function Next_Float return Long_Float is
|
||||
begin
|
||||
return Long_Float (Next_Int) / (2.0**32);
|
||||
end Next_Float;
|
||||
|
||||
----------
|
||||
-- Seed --
|
||||
----------
|
||||
|
||||
procedure Seed (seed_state : Unsigned_64; seed_sequence : Unsigned_64) is
|
||||
begin
|
||||
State := 0;
|
||||
inc := (2 * seed_sequence) or 1;
|
||||
Next_State;
|
||||
State := State + seed_state;
|
||||
Next_State;
|
||||
end Seed;
|
||||
|
||||
end random_pcg32;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
with Ada.Text_Io; use ADa.Text_io;
|
||||
with Interfaces; use Interfaces;
|
||||
with random_pcg32; use random_pcg32;
|
||||
|
||||
procedure Main_P is
|
||||
counts : array (0..4) of Natural := (Others => 0);
|
||||
J : Natural;
|
||||
begin
|
||||
seed(42, 54);
|
||||
for I in 1..5 loop
|
||||
Put_Line(Unsigned_32'Image(Next_Int));
|
||||
end loop;
|
||||
New_Line;
|
||||
|
||||
seed(987654321, 1);
|
||||
for I in 1..100_000 loop
|
||||
J := Natural(Long_Float'Floor(Next_Float * 5.0));
|
||||
Counts(J) := Counts(J) + 1;
|
||||
end loop;
|
||||
|
||||
for I in Counts'Range loop
|
||||
Put_Line(I'Image & " :" & Counts(I)'Image);
|
||||
end loop;
|
||||
|
||||
end Main_P;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#include <array>
|
||||
#include <iostream>
|
||||
|
||||
class PCG32 {
|
||||
private:
|
||||
const uint64_t N = 6364136223846793005;
|
||||
uint64_t state = 0x853c49e6748fea9b;
|
||||
uint64_t inc = 0xda3e39cb94b95bdb;
|
||||
public:
|
||||
uint32_t nextInt() {
|
||||
uint64_t old = state;
|
||||
state = old * N + inc;
|
||||
uint32_t shifted = (uint32_t)(((old >> 18) ^ old) >> 27);
|
||||
uint32_t rot = old >> 59;
|
||||
return (shifted >> rot) | (shifted << ((~rot + 1) & 31));
|
||||
}
|
||||
|
||||
double nextFloat() {
|
||||
return ((double)nextInt()) / (1LL << 32);
|
||||
}
|
||||
|
||||
void seed(uint64_t seed_state, uint64_t seed_sequence) {
|
||||
state = 0;
|
||||
inc = (seed_sequence << 1) | 1;
|
||||
nextInt();
|
||||
state = state + seed_state;
|
||||
nextInt();
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
auto r = new PCG32();
|
||||
|
||||
r->seed(42, 54);
|
||||
std::cout << r->nextInt() << '\n';
|
||||
std::cout << r->nextInt() << '\n';
|
||||
std::cout << r->nextInt() << '\n';
|
||||
std::cout << r->nextInt() << '\n';
|
||||
std::cout << r->nextInt() << '\n';
|
||||
std::cout << '\n';
|
||||
|
||||
std::array<int, 5> counts{ 0, 0, 0, 0, 0 };
|
||||
r->seed(987654321, 1);
|
||||
for (size_t i = 0; i < 100000; i++) {
|
||||
int j = (int)floor(r->nextFloat() * 5.0);
|
||||
counts[j]++;
|
||||
}
|
||||
|
||||
std::cout << "The counts for 100,000 repetitions are:\n";
|
||||
for (size_t i = 0; i < counts.size(); i++) {
|
||||
std::cout << " " << i << " : " << counts[i] << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const uint64_t N = 6364136223846793005;
|
||||
|
||||
static uint64_t state = 0x853c49e6748fea9b;
|
||||
static uint64_t inc = 0xda3e39cb94b95bdb;
|
||||
|
||||
uint32_t pcg32_int() {
|
||||
uint64_t old = state;
|
||||
state = old * N + inc;
|
||||
uint32_t shifted = (uint32_t)(((old >> 18) ^ old) >> 27);
|
||||
uint32_t rot = old >> 59;
|
||||
return (shifted >> rot) | (shifted << ((~rot + 1) & 31));
|
||||
}
|
||||
|
||||
double pcg32_float() {
|
||||
return ((double)pcg32_int()) / (1LL << 32);
|
||||
}
|
||||
|
||||
void pcg32_seed(uint64_t seed_state, uint64_t seed_sequence) {
|
||||
state = 0;
|
||||
inc = (seed_sequence << 1) | 1;
|
||||
pcg32_int();
|
||||
state = state + seed_state;
|
||||
pcg32_int();
|
||||
}
|
||||
|
||||
int main() {
|
||||
int counts[5] = { 0, 0, 0, 0, 0 };
|
||||
int i;
|
||||
|
||||
pcg32_seed(42, 54);
|
||||
printf("%u\n", pcg32_int());
|
||||
printf("%u\n", pcg32_int());
|
||||
printf("%u\n", pcg32_int());
|
||||
printf("%u\n", pcg32_int());
|
||||
printf("%u\n", pcg32_int());
|
||||
printf("\n");
|
||||
|
||||
pcg32_seed(987654321, 1);
|
||||
for (i = 0; i < 100000; i++) {
|
||||
int j = (int)floor(pcg32_float() * 5.0);
|
||||
counts[j]++;
|
||||
}
|
||||
|
||||
printf("The counts for 100,000 repetitions are:\n");
|
||||
for (i = 0; i < 5; i++) {
|
||||
printf(" %d : %d\n", i, counts[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import std.math;
|
||||
import std.stdio;
|
||||
|
||||
struct PCG32 {
|
||||
private:
|
||||
immutable ulong N = 6364136223846793005;
|
||||
ulong state = 0x853c49e6748fea9b;
|
||||
ulong inc = 0xda3e39cb94b95bdb;
|
||||
|
||||
public:
|
||||
void seed(ulong seed_state, ulong seed_sequence) {
|
||||
state = 0;
|
||||
inc = (seed_sequence << 1) | 1;
|
||||
nextInt();
|
||||
state = state + seed_state;
|
||||
nextInt();
|
||||
}
|
||||
|
||||
uint nextInt() {
|
||||
ulong old = state;
|
||||
state = old * N + inc;
|
||||
uint shifted = cast(uint)(((old >> 18) ^ old) >> 27);
|
||||
uint rot = old >> 59;
|
||||
return (shifted >> rot) | (shifted << ((~rot + 1) & 31));
|
||||
}
|
||||
|
||||
double nextFloat() {
|
||||
return (cast(double) nextInt()) / (1L << 32);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
auto r = PCG32();
|
||||
|
||||
r.seed(42, 54);
|
||||
writeln(r.nextInt());
|
||||
writeln(r.nextInt());
|
||||
writeln(r.nextInt());
|
||||
writeln(r.nextInt());
|
||||
writeln(r.nextInt());
|
||||
writeln;
|
||||
|
||||
auto counts = [0, 0, 0, 0, 0];
|
||||
r.seed(987654321, 1);
|
||||
foreach (_; 0..100_000) {
|
||||
int j = cast(int)floor(r.nextFloat() * 5.0);
|
||||
counts[j]++;
|
||||
}
|
||||
|
||||
writeln("The counts for 100,000 repetitions are:");
|
||||
foreach (i,v; counts) {
|
||||
writeln(" ", i, " : ", v);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
program PCG32_test;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
uses
|
||||
System.SysUtils,
|
||||
Velthuis.BigIntegers,
|
||||
System.Generics.Collections;
|
||||
|
||||
type
|
||||
TPCG32 = class
|
||||
public
|
||||
FState: BigInteger;
|
||||
FInc: BigInteger;
|
||||
mask64: BigInteger;
|
||||
mask32: BigInteger;
|
||||
k: BigInteger;
|
||||
constructor Create(seedState, seedSequence: BigInteger); overload;
|
||||
constructor Create(); overload;
|
||||
destructor Destroy; override;
|
||||
procedure Seed(seed_state, seed_sequence: BigInteger);
|
||||
function NextInt(): BigInteger;
|
||||
function NextIntRange(size: Integer): TArray<BigInteger>;
|
||||
function NextFloat(): Extended;
|
||||
end;
|
||||
|
||||
{ TPCG32 }
|
||||
|
||||
constructor TPCG32.Create(seedState, seedSequence: BigInteger);
|
||||
begin
|
||||
Create();
|
||||
Seed(seedState, seedSequence);
|
||||
end;
|
||||
|
||||
constructor TPCG32.Create;
|
||||
begin
|
||||
k := '6364136223846793005';
|
||||
mask64 := (BigInteger(1) shl 64) - 1;
|
||||
mask32 := (BigInteger(1) shl 32) - 1;
|
||||
FState := 0;
|
||||
FInc := 0;
|
||||
end;
|
||||
|
||||
destructor TPCG32.Destroy;
|
||||
begin
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TPCG32.NextFloat: Extended;
|
||||
begin
|
||||
Result := (NextInt.AsExtended / (BigInteger(1) shl 32).AsExtended);
|
||||
end;
|
||||
|
||||
function TPCG32.NextInt(): BigInteger;
|
||||
var
|
||||
old, xorshifted, rot, answer: BigInteger;
|
||||
begin
|
||||
old := FState;
|
||||
FState := ((old * k) + FInc) and mask64;
|
||||
xorshifted := (((old shr 18) xor old) shr 27) and mask32;
|
||||
rot := (old shr 59) and mask32;
|
||||
answer := (xorshifted shr rot.AsInteger) or (xorshifted shl ((-rot) and
|
||||
BigInteger(31)).AsInteger);
|
||||
Result := answer and mask32;
|
||||
end;
|
||||
|
||||
function TPCG32.NextIntRange(size: Integer): TArray<BigInteger>;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
SetLength(Result, size);
|
||||
if size = 0 then
|
||||
exit;
|
||||
|
||||
for i := 0 to size - 1 do
|
||||
Result[i] := NextInt;
|
||||
end;
|
||||
|
||||
procedure TPCG32.Seed(seed_state, seed_sequence: BigInteger);
|
||||
begin
|
||||
FState := 0;
|
||||
FInc := ((seed_sequence shl 1) or 1) and mask64;
|
||||
nextint();
|
||||
Fstate := (Fstate + seed_state);
|
||||
nextint();
|
||||
end;
|
||||
|
||||
var
|
||||
PCG32: TPCG32;
|
||||
i, key: Integer;
|
||||
count: TDictionary<Integer, Integer>;
|
||||
|
||||
begin
|
||||
PCG32 := TPCG32.Create(42, 54);
|
||||
|
||||
for i := 0 to 4 do
|
||||
Writeln(PCG32.NextInt().ToString);
|
||||
|
||||
PCG32.seed(987654321, 1);
|
||||
|
||||
count := TDictionary<Integer, Integer>.Create();
|
||||
|
||||
for i := 1 to 100000 do
|
||||
begin
|
||||
key := Trunc(PCG32.NextFloat * 5);
|
||||
if count.ContainsKey(key) then
|
||||
count[key] := count[key] + 1
|
||||
else
|
||||
count.Add(key, 1);
|
||||
end;
|
||||
|
||||
Writeln(#10'The counts for 100,000 repetitions are:');
|
||||
|
||||
for key in count.Keys do
|
||||
Writeln(key, ' : ', count[key]);
|
||||
|
||||
count.free;
|
||||
PCG32.free;
|
||||
Readln;
|
||||
end.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// PCG32. Nigel Galloway: August 13th., 2020
|
||||
let N=6364136223846793005UL
|
||||
let seed n g=let g=g<<<1|||1UL in (g,(g+n)*N+g)
|
||||
let pcg32=Seq.unfold(fun(n,g)->let rot,xs=uint32(g>>>59),uint32(((g>>>18)^^^g)>>>27) in Some(uint32((xs>>>(int rot))|||(xs<<<(-(int rot)&&&31))),(n,g*N+n)))
|
||||
let pcgFloat n=pcg32 n|>Seq.map(fun n-> (float n)/4294967296.0)
|
||||
|
|
@ -0,0 +1 @@
|
|||
pcg32(seed 42UL 54UL)|>Seq.take 5|>Seq.iter(printfn "%d")
|
||||
|
|
@ -0,0 +1 @@
|
|||
pcgFloat(seed 987654321UL 1UL)|>Seq.take 100000|>Seq.countBy(fun n->int(n*5.0))|>Seq.iter(printf "%A");printfn ""
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
USING: accessors kernel locals math math.bitwise math.statistics
|
||||
prettyprint sequences ;
|
||||
|
||||
CONSTANT: const 6364136223846793005
|
||||
|
||||
TUPLE: pcg32 state inc ;
|
||||
|
||||
: <pcg32> ( -- pcg32 )
|
||||
0x853c49e6748fea9b 0xda3e39cb94b95bdb pcg32 boa ;
|
||||
|
||||
:: next-int ( pcg -- n )
|
||||
pcg state>> :> old
|
||||
old const * pcg inc>> + 64 bits pcg state<<
|
||||
old -18 shift old bitxor -27 shift 32 bits :> shifted
|
||||
old -59 shift 32 bits :> r
|
||||
shifted r neg shift
|
||||
shifted r neg 31 bitand shift bitor 32 bits ;
|
||||
|
||||
: next-float ( pcg -- x ) next-int 1 32 shift /f ;
|
||||
|
||||
:: seed ( pcg st seq -- )
|
||||
0x0 pcg state<<
|
||||
seq 0x1 shift 1 bitor 64 bits pcg inc<<
|
||||
pcg next-int drop
|
||||
pcg state>> st + pcg state<<
|
||||
pcg next-int drop ;
|
||||
|
||||
! Task
|
||||
<pcg32> 42 54 [ seed ] keepdd 5 [ dup next-int . ] times
|
||||
|
||||
987654321 1 [ seed ] keepdd
|
||||
100,000 [ dup next-float 5 * >integer ] replicate nip
|
||||
histogram .
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
const CONST = 6364136223846793005
|
||||
|
||||
type Pcg32 struct{ state, inc uint64 }
|
||||
|
||||
func Pcg32New() *Pcg32 { return &Pcg32{0x853c49e6748fea9b, 0xda3e39cb94b95bdb} }
|
||||
|
||||
func (pcg *Pcg32) seed(seedState, seedSequence uint64) {
|
||||
pcg.state = 0
|
||||
pcg.inc = (seedSequence << 1) | 1
|
||||
pcg.nextInt()
|
||||
pcg.state = pcg.state + seedState
|
||||
pcg.nextInt()
|
||||
}
|
||||
|
||||
func (pcg *Pcg32) nextInt() uint32 {
|
||||
old := pcg.state
|
||||
pcg.state = old*CONST + pcg.inc
|
||||
pcgshifted := uint32(((old >> 18) ^ old) >> 27)
|
||||
rot := uint32(old >> 59)
|
||||
return (pcgshifted >> rot) | (pcgshifted << ((-rot) & 31))
|
||||
}
|
||||
|
||||
func (pcg *Pcg32) nextFloat() float64 {
|
||||
return float64(pcg.nextInt()) / (1 << 32)
|
||||
}
|
||||
|
||||
func main() {
|
||||
randomGen := Pcg32New()
|
||||
randomGen.seed(42, 54)
|
||||
for i := 0; i < 5; i++ {
|
||||
fmt.Println(randomGen.nextInt())
|
||||
}
|
||||
|
||||
var counts [5]int
|
||||
randomGen.seed(987654321, 1)
|
||||
for i := 0; i < 1e5; i++ {
|
||||
j := int(math.Floor(randomGen.nextFloat() * 5))
|
||||
counts[j]++
|
||||
}
|
||||
fmt.Println("\nThe counts for 100,000 repetitions are:")
|
||||
for i := 0; i < 5; i++ {
|
||||
fmt.Printf(" %d : %d\n", i, counts[i])
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import Data.Bits
|
||||
import Data.Word
|
||||
import System.Random
|
||||
import Data.List
|
||||
|
||||
data PCGen = PCGen !Word64 !Word64
|
||||
|
||||
mkPCGen state sequence =
|
||||
let
|
||||
n = 6364136223846793005 :: Word64
|
||||
inc = (sequence `shiftL` 1) .|. 1 :: Word64
|
||||
in PCGen ((inc + state)*n + inc) inc
|
||||
|
||||
instance RandomGen PCGen where
|
||||
next (PCGen state inc) =
|
||||
let
|
||||
n = 6364136223846793005 :: Word64
|
||||
xs = fromIntegral $ ((state `shiftR` 18) `xor` state) `shiftR` 27 :: Word32
|
||||
rot = fromIntegral $ state `shiftR` 59 :: Int
|
||||
in (fromIntegral $ (xs `shiftR` rot) .|. (xs `shiftL` ((-rot) .&. 31))
|
||||
, PCGen (state * n + inc) inc)
|
||||
|
||||
split _ = error "PCG32 is not splittable"
|
||||
|
||||
randoms' :: RandomGen g => g -> [Int]
|
||||
randoms' g = unfoldr (pure . next) g
|
||||
|
||||
toFloat n = fromIntegral n / (2^32 - 1)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
PCG32GEN=: {{
|
||||
g=. cocreate''
|
||||
'state0__g seq__g'=. m
|
||||
init__g=: {{
|
||||
max=: 2^64x
|
||||
u64=: &.((64#2x)&#:) NB. binary domain operation
|
||||
U64=: max&| NB. integer domain result
|
||||
U32=: (2^32)&(<.@|)
|
||||
and=: *. u64
|
||||
xor=: ~: u64
|
||||
or=: +. u64
|
||||
lsl=: max <.@| ] * 2x^[
|
||||
N=: 6364136223846793005x
|
||||
inc=: U64 1 2x p. seq
|
||||
state=: U64 inc+N*inc+state0
|
||||
}}
|
||||
next__g=: g {{ m[y
|
||||
xs=. U32 _27 lsl state xor _18 lsl state
|
||||
rot=. -_59 lsl state
|
||||
state=: U64 inc+N*state
|
||||
U32 (rot lsl xs) or (31 and rot) lsl xs
|
||||
}}
|
||||
init__g''
|
||||
(;'next_';(;g);'_')~
|
||||
}}
|
||||
|
||||
next_float=: %&(2^32)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
42 54 PCG32GEN ^:(1+i.5)''
|
||||
2707161776 2068313120 3122475824 2211639955 3215226955
|
||||
(~.,. #/.~) <.5*next_float 987654321 1 PCG32GEN^:(1+i.1e5) ''
|
||||
2 20115
|
||||
3 19809
|
||||
0 20049
|
||||
4 20005
|
||||
1 20022
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
public class PCG32 {
|
||||
private static final long N = 6364136223846793005L;
|
||||
|
||||
private long state = 0x853c49e6748fea9bL;
|
||||
private long inc = 0xda3e39cb94b95bdbL;
|
||||
|
||||
public void seed(long seedState, long seedSequence) {
|
||||
state = 0;
|
||||
inc = (seedSequence << 1) | 1;
|
||||
nextInt();
|
||||
state = state + seedState;
|
||||
nextInt();
|
||||
}
|
||||
|
||||
public int nextInt() {
|
||||
long old = state;
|
||||
state = old * N + inc;
|
||||
int shifted = (int) (((old >>> 18) ^ old) >>> 27);
|
||||
int rot = (int) (old >>> 59);
|
||||
return (shifted >>> rot) | (shifted << ((~rot + 1) & 31));
|
||||
}
|
||||
|
||||
public double nextFloat() {
|
||||
var u = Integer.toUnsignedLong(nextInt());
|
||||
return (double) u / (1L << 32);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
var r = new PCG32();
|
||||
|
||||
r.seed(42, 54);
|
||||
System.out.println(Integer.toUnsignedString(r.nextInt()));
|
||||
System.out.println(Integer.toUnsignedString(r.nextInt()));
|
||||
System.out.println(Integer.toUnsignedString(r.nextInt()));
|
||||
System.out.println(Integer.toUnsignedString(r.nextInt()));
|
||||
System.out.println(Integer.toUnsignedString(r.nextInt()));
|
||||
System.out.println();
|
||||
|
||||
int[] counts = {0, 0, 0, 0, 0};
|
||||
r.seed(987654321, 1);
|
||||
for (int i = 0; i < 100_000; i++) {
|
||||
int j = (int) Math.floor(r.nextFloat() * 5.0);
|
||||
counts[j]++;
|
||||
}
|
||||
|
||||
System.out.println("The counts for 100,000 repetitions are:");
|
||||
for (int i = 0; i < counts.length; i++) {
|
||||
System.out.printf(" %d : %d\n", i, counts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
const mask32, CONST = 0xffffffff, UInt(6364136223846793005)
|
||||
|
||||
mutable struct PCG32
|
||||
state::UInt64
|
||||
inc::UInt64
|
||||
PCG32(st=0x853c49e6748fea9b, i=0xda3e39cb94b95bdb) = new(st, i)
|
||||
end
|
||||
|
||||
"""return random 32 bit unsigned int"""
|
||||
function next_int!(x::PCG32)
|
||||
old = x.state
|
||||
x.state = (old * CONST) + x.inc
|
||||
xorshifted = (((old >> 18) ⊻ old) >> 27) & mask32
|
||||
rot = (old >> 59) & mask32
|
||||
return ((xorshifted >> rot) | (xorshifted << ((-rot) & 31))) & mask32
|
||||
end
|
||||
|
||||
"""return random float between 0 and 1"""
|
||||
next_float!(x::PCG32) = next_int!(x) / (1 << 32)
|
||||
|
||||
function seed!(x::PCG32, st, seq)
|
||||
x.state = 0x0
|
||||
x.inc = (UInt(seq) << 0x1) | 1
|
||||
next_int!(x)
|
||||
x.state = x.state + UInt(st)
|
||||
next_int!(x)
|
||||
end
|
||||
|
||||
function testPCG32()
|
||||
random_gen = PCG32()
|
||||
seed!(random_gen, 42, 54)
|
||||
for _ in 1:5
|
||||
println(next_int!(random_gen))
|
||||
end
|
||||
seed!(random_gen, 987654321, 1)
|
||||
hist = fill(0, 5)
|
||||
for _ in 1:100_000
|
||||
hist[Int(floor(next_float!(random_gen) * 5)) + 1] += 1
|
||||
end
|
||||
println(hist)
|
||||
for n in 1:5
|
||||
print(n - 1, ": ", hist[n], " ")
|
||||
end
|
||||
end
|
||||
|
||||
testPCG32()
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import kotlin.math.floor
|
||||
|
||||
class PCG32 {
|
||||
private var state = 0x853c49e6748fea9buL
|
||||
private var inc = 0xda3e39cb94b95bdbuL
|
||||
|
||||
fun nextInt(): UInt {
|
||||
val old = state
|
||||
state = old * N + inc
|
||||
val shifted = old.shr(18).xor(old).shr(27).toUInt()
|
||||
val rot = old.shr(59)
|
||||
return (shifted shr rot.toInt()) or shifted.shl((rot.inv() + 1u).and(31u).toInt())
|
||||
}
|
||||
|
||||
fun nextFloat(): Double {
|
||||
return nextInt().toDouble() / (1L shl 32)
|
||||
}
|
||||
|
||||
fun seed(seedState: ULong, seedSequence: ULong) {
|
||||
state = 0u
|
||||
inc = (seedSequence shl 1).or(1uL)
|
||||
nextInt()
|
||||
state += seedState
|
||||
nextInt()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val N = 6364136223846793005uL
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val r = PCG32()
|
||||
|
||||
r.seed(42u, 54u)
|
||||
println(r.nextInt())
|
||||
println(r.nextInt())
|
||||
println(r.nextInt())
|
||||
println(r.nextInt())
|
||||
println(r.nextInt())
|
||||
println()
|
||||
|
||||
val counts = Array(5) { 0 }
|
||||
r.seed(987654321u, 1u)
|
||||
for (i in 0 until 100000) {
|
||||
val j = floor(r.nextFloat() * 5.0).toInt()
|
||||
counts[j] += 1
|
||||
}
|
||||
|
||||
println("The counts for 100,000 repetitions are:")
|
||||
for (iv in counts.withIndex()) {
|
||||
println(" %d : %d".format(iv.index, iv.value))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
function uint32(n)
|
||||
return n & 0xffffffff
|
||||
end
|
||||
|
||||
function uint64(n)
|
||||
return n & 0xffffffffffffffff
|
||||
end
|
||||
|
||||
N = 6364136223846793005
|
||||
state = 0x853c49e6748fea9b
|
||||
inc = 0xda3e39cb94b95bdb
|
||||
|
||||
function pcg32_seed(seed_state, seed_sequence)
|
||||
state = 0
|
||||
inc = (seed_sequence << 1) | 1
|
||||
pcg32_int()
|
||||
state = state + seed_state
|
||||
pcg32_int()
|
||||
end
|
||||
|
||||
function pcg32_int()
|
||||
local old = state
|
||||
state = uint64(old * N + inc)
|
||||
local shifted = uint32(((old >> 18) ~ old) >> 27)
|
||||
local rot = uint32(old >> 59)
|
||||
return uint32((shifted >> rot) | (shifted << ((~rot + 1) & 31)))
|
||||
end
|
||||
|
||||
function pcg32_float()
|
||||
return 1.0 * pcg32_int() / (1 << 32)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
pcg32_seed(42, 54)
|
||||
print(pcg32_int())
|
||||
print(pcg32_int())
|
||||
print(pcg32_int())
|
||||
print(pcg32_int())
|
||||
print(pcg32_int())
|
||||
print()
|
||||
|
||||
counts = { 0, 0, 0, 0, 0 }
|
||||
pcg32_seed(987654321, 1)
|
||||
for i=1,100000 do
|
||||
local j = math.floor(pcg32_float() * 5.0) + 1
|
||||
counts[j] = counts[j] + 1
|
||||
end
|
||||
|
||||
print("The counts for 100,000 repetitions are:")
|
||||
for i=1,5 do
|
||||
print(" " .. (i - 1) .. ": " .. counts[i])
|
||||
end
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import algorithm, sequtils, strutils, tables
|
||||
|
||||
const N = 6364136223846793005u64
|
||||
|
||||
type PCG32 = object
|
||||
inc: uint64
|
||||
state: uint64
|
||||
|
||||
func seed(gen: var PCG32; seedState, seedSequence: uint64) =
|
||||
gen.inc = seedSequence shl 1 or 1
|
||||
gen.state = (gen.inc + seedState) * N + gen.inc
|
||||
|
||||
func nextInt(gen: var PCG32): uint32 =
|
||||
let xs = uint32((gen.state shr 18 xor gen.state) shr 27)
|
||||
let rot = int32(gen.state shr 59)
|
||||
result = uint32(xs shr rot or xs shl (-rot and 31))
|
||||
gen.state = gen.state * N + gen.inc
|
||||
|
||||
func nextFloat(gen: var PCG32): float =
|
||||
gen.nextInt().float / float(0xFFFFFFFFu32)
|
||||
|
||||
|
||||
when isMainModule:
|
||||
|
||||
var gen: PCG32
|
||||
|
||||
gen.seed(42, 54)
|
||||
for _ in 1..5:
|
||||
echo gen.nextInt()
|
||||
|
||||
echo ""
|
||||
gen.seed(987654321, 1)
|
||||
var counts: CountTable[int]
|
||||
for _ in 1..100_000:
|
||||
counts.inc int(gen.nextFloat() * 5)
|
||||
echo sorted(toSeq(counts.pairs)).mapIt($it[0] & ": " & $it[1]).join(", ")
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
let (>>) = Int64.shift_right_logical
|
||||
|
||||
let int32_bound n x =
|
||||
Int64.(to_int ((mul (logand (of_int32 x) 0xffffffffL) (of_int n)) >> 32))
|
||||
|
||||
let int32_rotate_right x n =
|
||||
Int32.(logor (shift_left x (-n land 31)) (shift_right_logical x n))
|
||||
|
||||
let pcg32_next inc st =
|
||||
Int64.(add (mul st 0x5851f42d4c957f2dL) inc)
|
||||
|
||||
let pcg32_output st =
|
||||
int32_rotate_right
|
||||
(Int32.logxor (Int64.to_int32 (st >> 27)) (Int64.to_int32 (st >> 45)))
|
||||
(Int64.to_int (st >> 59))
|
||||
|
||||
let seq_pcg32 (st, f) =
|
||||
let rec repeat st () = Seq.Cons (pcg32_output st, repeat (f st)) in
|
||||
repeat (f st)
|
||||
|
||||
let pcg32 seed_st seed_sq =
|
||||
let inc = Int64.(add (succ seed_sq) seed_sq) in
|
||||
Int64.add seed_st inc, pcg32_next inc
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
let () =
|
||||
pcg32 42L 54L |> seq_pcg32 |> Seq.take 5
|
||||
|> Seq.iter (Printf.printf " %lu") |> print_newline
|
||||
|
||||
let () =
|
||||
pcg32 987654321L 1L |> seq_pcg32 |> Seq.map (int32_bound 5) |> Seq.take 100000
|
||||
|> Seq.fold_left (fun a n -> a.(n) <- succ a.(n); a) (Array.make 5 0)
|
||||
|> Array.iteri (Printf.printf "%u: %u\n")
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use Math::AnyNum qw(:overload);
|
||||
|
||||
package PCG32 {
|
||||
|
||||
use constant {
|
||||
mask32 => 2**32 - 1,
|
||||
mask64 => 2**64 - 1,
|
||||
const => 6364136223846793005,
|
||||
};
|
||||
|
||||
sub new {
|
||||
my ($class, %opt) = @_;
|
||||
my $seed = $opt{seed} // 1;
|
||||
my $incr = $opt{incr} // 2;
|
||||
$incr = $incr << 1 | 1 & mask64;
|
||||
my $state = (($incr + $seed) * const + $incr) & mask64;
|
||||
bless {incr => $incr, state => $state}, $class;
|
||||
}
|
||||
|
||||
sub next_int {
|
||||
my ($self) = @_;
|
||||
my $state = $self->{state};
|
||||
my $shift = ($state >> 18 ^ $state) >> 27 & mask32;
|
||||
my $rotate = $state >> 59 & mask32;
|
||||
$self->{state} = ($state * const + $self->{incr}) & mask64;
|
||||
($shift >> $rotate) | $shift << (32 - $rotate) & mask32;
|
||||
}
|
||||
|
||||
sub next_float {
|
||||
my ($self) = @_;
|
||||
$self->next_int / 2**32;
|
||||
}
|
||||
}
|
||||
|
||||
say "Seed: 42, Increment: 54, first 5 values:";
|
||||
my $rng = PCG32->new(seed => 42, incr => 54);
|
||||
say $rng->next_int for 1 .. 5;
|
||||
|
||||
say "\nSeed: 987654321, Increment: 1, values histogram:";
|
||||
my %h;
|
||||
$rng = PCG32->new(seed => 987654321, incr => 1);
|
||||
$h{int 5 * $rng->next_float}++ for 1 .. 100_000;
|
||||
say "$_ $h{$_}" for sort keys %h;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"NB: These are not expected to match the task spec!\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">set_rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">42</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">5</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #7060A8;">set_rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">987654321</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">100000</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">rnd</span><span style="color: #0000FF;">()*</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">s</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
|
||||
<span style="color: #004080;">mpz</span> <span style="color: #000000;">cmult</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"6364136223846793005"</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0x853c49e6748fea9b"</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">inc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0xda3e39cb94b95bdb"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">/* Always odd */</span>
|
||||
<span style="color: #000000;">b64</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0x10000000000000000"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- (truncate to 64 bits)</span>
|
||||
<span style="color: #000000;">b32</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0x100000000"</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- (truncate to 32 bits)</span>
|
||||
<span style="color: #000000;">old</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
|
||||
<span style="color: #000000;">xorsh</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">seed</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">seed_state</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">seed_sequence</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seed_sequence</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- as per the talk page:
|
||||
-- state := remainder((inc+seed_state)*cmult+inc,b64)</span>
|
||||
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seed_state</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cmult</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">mpz_fdiv_r</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">state</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b64</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- state := remainder(state,b64) </span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">next_int</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">old</span><span style="color: #0000FF;">,</span><span style="color: #000000;">state</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- old := state</span>
|
||||
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">inc</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- state := inc</span>
|
||||
<span style="color: #7060A8;">mpz_addmul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">old</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cmult</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- state += old*cmult</span>
|
||||
<span style="color: #7060A8;">mpz_fdiv_r</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">state</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b64</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- state := remainder(state,b64) </span>
|
||||
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">old</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">18</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- xorsh := trunc(old/2^18)</span>
|
||||
<span style="color: #7060A8;">mpz_xor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">old</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- xorsh := xor_bits(xorsh,old)</span>
|
||||
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- xorsh := trunc(xorsh/2^27)</span>
|
||||
<span style="color: #7060A8;">mpz_fdiv_r</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">xorsh</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b32</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- xorsh := remainder(xorsh,b32) </span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">xorshifted</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_atom</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xorsh</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">old</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">old</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">59</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- old := trunc(old/2^59)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">rot</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">old</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bitsu</span><span style="color: #0000FF;">(</span><span style="color: #000000;">xorshifted</span> <span style="color: #0000FF;"><<</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">-</span><span style="color: #000000;">rot</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">#FFFFFFFF</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">xorshifted</span> <span style="color: #0000FF;">>></span> <span style="color: #000000;">rot</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">answer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">xor_bitsu</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">answer</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">next_float</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">next_int</span><span style="color: #0000FF;">()</span> <span style="color: #0000FF;">/</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">1</span> <span style="color: #0000FF;"><<</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #000000;">seed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">54</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">5</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">next_int</span><span style="color: #0000FF;">())</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #000000;">seed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">987654321</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">100000</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">next_float</span><span style="color: #0000FF;">()*</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">r</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
mask64 = (1 << 64) - 1
|
||||
mask32 = (1 << 32) - 1
|
||||
CONST = 6364136223846793005
|
||||
|
||||
|
||||
class PCG32():
|
||||
|
||||
def __init__(self, seed_state=None, seed_sequence=None):
|
||||
if all(type(x) == int for x in (seed_state, seed_sequence)):
|
||||
self.seed(seed_state, seed_sequence)
|
||||
else:
|
||||
self.state = self.inc = 0
|
||||
|
||||
def seed(self, seed_state, seed_sequence):
|
||||
self.state = 0
|
||||
self.inc = ((seed_sequence << 1) | 1) & mask64
|
||||
self.next_int()
|
||||
self.state = (self.state + seed_state)
|
||||
self.next_int()
|
||||
|
||||
def next_int(self):
|
||||
"return random 32 bit unsigned int"
|
||||
old = self.state
|
||||
self.state = ((old * CONST) + self.inc) & mask64
|
||||
xorshifted = (((old >> 18) ^ old) >> 27) & mask32
|
||||
rot = (old >> 59) & mask32
|
||||
answer = (xorshifted >> rot) | (xorshifted << ((-rot) & 31))
|
||||
answer = answer &mask32
|
||||
|
||||
return answer
|
||||
|
||||
def next_float(self):
|
||||
"return random float between 0 and 1"
|
||||
return self.next_int() / (1 << 32)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
random_gen = PCG32()
|
||||
random_gen.seed(42, 54)
|
||||
for i in range(5):
|
||||
print(random_gen.next_int())
|
||||
|
||||
random_gen.seed(987654321, 1)
|
||||
hist = {i:0 for i in range(5)}
|
||||
for i in range(100_000):
|
||||
hist[int(random_gen.next_float() *5)] += 1
|
||||
print(hist)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
def pcg32(seed_state=None, seed_sequence=None, as_int=True):
|
||||
def next_int():
|
||||
"return random 32 bit unsigned int"
|
||||
nonlocal state, inc
|
||||
|
||||
state, xorshifted, rot = (((state * CONST) + inc) & mask64,
|
||||
(((state >> 18) ^ state) >> 27) & mask32,
|
||||
(state >> 59) & mask32)
|
||||
answer = (((xorshifted >> rot) | (xorshifted << ((-rot) & 31)))
|
||||
& mask32)
|
||||
return answer
|
||||
|
||||
# Seed
|
||||
state = inc = 0
|
||||
if all(type(x) == int for x in (seed_state, seed_sequence)):
|
||||
inc = ((seed_sequence << 1) | 1) & mask64
|
||||
next_int()
|
||||
state += seed_state
|
||||
next_int()
|
||||
|
||||
while True:
|
||||
yield next_int() if as_int else next_int() / (1 << 32)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from itertools import islice
|
||||
|
||||
for i in islice(pcg32(42, 54), 5):
|
||||
print(i)
|
||||
hist = {i:0 for i in range(5)}
|
||||
for i in islice(pcg32(987654321, 1, as_int=False), 100_000):
|
||||
hist[int(i * 5)] += 1
|
||||
print(hist)
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
Numeric Digits 40
|
||||
N = 6364136223846793005
|
||||
state = x2d('853c49e6748fea9b',16)
|
||||
inc = x2d('da3e39cb94b95bdb',16)
|
||||
Call seed 42,54
|
||||
Do zz=1 To 5
|
||||
res=nextint()
|
||||
Say int2str(res)
|
||||
End
|
||||
Call seed 987654321,1
|
||||
cnt.=0
|
||||
Do i=1 To 100000
|
||||
z=nextfloat()
|
||||
cnt.z=cnt.z+1
|
||||
End
|
||||
Say ''
|
||||
Say 'The counts for 100,000 repetitions are:'
|
||||
Do z=0 To 4
|
||||
Say format(z,2) ':' format(cnt.z,5)
|
||||
End
|
||||
Exit
|
||||
|
||||
int2str: Procedure
|
||||
int=arg(1)
|
||||
intx=d2x(int,8)
|
||||
res=x2d(copies(0,8)intx,16)
|
||||
Return res
|
||||
|
||||
seed:
|
||||
Parse Arg seedState,seedSequence
|
||||
state=0
|
||||
inc=dshift(seedSequence,-1)
|
||||
inc=x2d(or(d2x(inc,16),d2x(1,16)),16)
|
||||
z=nextint()
|
||||
state=javaadd(state,seedState)
|
||||
z=nextint()
|
||||
Return
|
||||
|
||||
nextInt:
|
||||
old = state
|
||||
oldxN = javamult(old,n)
|
||||
statex= javaadd(oldxN,inc)
|
||||
state=statex
|
||||
oldx=d2x(old,16)
|
||||
oldb=x2b(oldx)
|
||||
oldb18=copies(0,18)left(oldb,64-18)
|
||||
oldb18o=bxor(oldb18,oldb)
|
||||
rb=copies(0,27)left(oldb18o,64-27)
|
||||
rx=b2x(rb)
|
||||
shifted=x2d(substr(rx,9),8)
|
||||
oldx=d2x(old,16)
|
||||
oldb=x2b(oldx)
|
||||
oldb2=copies(0,59)left(oldb,length(oldb)-59)
|
||||
oldx2=b2x(oldb2)
|
||||
rotx=x2d(substr(oldx2,9),8)
|
||||
t1=ishift(shifted,rotx,'L')
|
||||
t2=x2d(xneg(d2x(rotx,8)),8)
|
||||
t3=t2+1
|
||||
t4=x2d(xand(d2x(t3,8),d2x(31,8)),8)
|
||||
t5=dshift(shifted,-t4)
|
||||
t5x=d2x(t5,16)
|
||||
t5y=substr(t5x,9)
|
||||
t5z=x2d(t5y,16)
|
||||
t7=x2d(or(d2x(t1,16),d2x(t5z,16)),16)
|
||||
t8=long2int(t7)
|
||||
Return t8
|
||||
|
||||
nextfloat:
|
||||
ni=nextint()
|
||||
nix=d2x(ni,8)
|
||||
niz=copies(0,8)nix
|
||||
u=x2d(niz,16)
|
||||
uu=u/(2**32)
|
||||
z=uu*5%1
|
||||
Return z
|
||||
|
||||
javaadd: Procedure
|
||||
/**********************************************************************
|
||||
* Add two long integers and ignore the possible overflow
|
||||
**********************************************************************/
|
||||
Numeric Digits 40
|
||||
Parse Arg a,b
|
||||
r=a+b
|
||||
rx=d2x(r,18)
|
||||
res=right(rx,16)
|
||||
return x2d(res,16)
|
||||
|
||||
javamult: Procedure
|
||||
/**********************************************************************
|
||||
* Multiply java style
|
||||
**********************************************************************/
|
||||
Numeric Digits 40
|
||||
Parse Arg a,b
|
||||
m=d2x(a*b,16)
|
||||
res=x2d(m,16)
|
||||
Return res
|
||||
|
||||
bxor: Procedure
|
||||
/**********************************************************************
|
||||
* Exclusive Or two bit strings
|
||||
**********************************************************************/
|
||||
Parse arg a,b
|
||||
res=''
|
||||
Do i=1 To length(a)
|
||||
res=res||(substr(a,i,1)<>substr(b,i,1))
|
||||
End
|
||||
Return res
|
||||
|
||||
xxor: Procedure
|
||||
/**********************************************************************
|
||||
* Exclusive Or two hex strings
|
||||
**********************************************************************/
|
||||
Parse Arg u,v
|
||||
ub=x2b(u)
|
||||
vb=x2b(v)
|
||||
res=''
|
||||
Do i=1 To 64
|
||||
res=res||(substr(ub,i,1)<>substr(vb,i,1))
|
||||
End
|
||||
res=b2x(res)
|
||||
Return res
|
||||
|
||||
xand: Procedure
|
||||
/**********************************************************************
|
||||
* And two hex strings
|
||||
**********************************************************************/
|
||||
Parse Arg u,v
|
||||
ub=x2b(u)
|
||||
vb=x2b(v)
|
||||
res=''
|
||||
Do i=1 To length(ub)
|
||||
res=res||(substr(ub,i,1)&substr(vb,i,1))
|
||||
End
|
||||
res=b2x(res)
|
||||
Return res
|
||||
|
||||
or: Procedure
|
||||
/**********************************************************************
|
||||
* Or two hex strings
|
||||
**********************************************************************/
|
||||
Parse Arg u,v
|
||||
ub=x2b(u)
|
||||
vb=x2b(v)
|
||||
res=''
|
||||
Do i=1 To length(ub)
|
||||
res=res||(substr(ub,i,1)|substr(vb,i,1))
|
||||
End
|
||||
res=b2x(res)
|
||||
Return res
|
||||
|
||||
long2int: Procedure
|
||||
/**********************************************************************
|
||||
* Cast long to int
|
||||
**********************************************************************/
|
||||
Parse Arg long
|
||||
longx=d2x(long,16)
|
||||
int=x2d(substr(longx,9),8)
|
||||
Return int
|
||||
|
||||
xneg: Procedure
|
||||
/**********************************************************************
|
||||
* Negate a hex string
|
||||
**********************************************************************/
|
||||
Parse Arg s
|
||||
sb=x2b(s)
|
||||
res=''
|
||||
Do i=1 To length(sb)
|
||||
res=res||\substr(sb,i,1)
|
||||
End
|
||||
res=b2x(res)
|
||||
Return res
|
||||
|
||||
dshift: Procedure
|
||||
/**********************************************************************
|
||||
* Implement the shift operations for a long variable
|
||||
* r = dshift(long,shift[,mode]) >> Mode='L' logical right shift
|
||||
* >>> Mode='A' arithmetic right shift
|
||||
* << xhift<0 left shift
|
||||
********************************************`*************************/
|
||||
Parse Upper Arg n,s,o
|
||||
Numeric Digits 40
|
||||
If o='' Then o='L'
|
||||
nx=d2x(n,16)
|
||||
nb=x2b(nx)
|
||||
If s<0 Then Do
|
||||
s=abs(s)
|
||||
rb=substr(nb,s+1)||copies('0',s)
|
||||
rx=b2x(rb)
|
||||
r=x2d(rx,16)
|
||||
End
|
||||
Else Do
|
||||
If o='L' Then Do
|
||||
rb=left(copies('0',s)nb,length(nb))
|
||||
rx=b2x(rb)
|
||||
r=x2d(rx,16)
|
||||
End
|
||||
Else Do
|
||||
rb=left(copies(left(nb,1),s)nb,length(nb))
|
||||
rx=b2x(rb)
|
||||
r=x2d(rx,16)
|
||||
End
|
||||
End
|
||||
Return r
|
||||
|
||||
ishift: Procedure
|
||||
/**********************************************************************
|
||||
* Implement the shift operations for an int variable
|
||||
* r = dshift(int,shift[,mode]) >> Mode='L' logical right shift
|
||||
* >>> Mode='A' arithmetic right shift
|
||||
* << xhift<0 left shift
|
||||
********************************************`*************************/
|
||||
Parse Upper Arg n,s,o
|
||||
Numeric Digits 40
|
||||
If o='' Then o='L'
|
||||
nx=d2x(n,8)
|
||||
nb=x2b(nx)
|
||||
If s<0 Then Do
|
||||
s=abs(s)
|
||||
rb=substr(nb,s+1)||copies('0',s)
|
||||
rx=b2x(rb)
|
||||
r=x2d(rx,8)
|
||||
End
|
||||
Else Do
|
||||
If o='L' Then Do
|
||||
rb=left(copies('0',s)nb,length(nb))
|
||||
rx=b2x(rb)
|
||||
r=x2d(rx,8)
|
||||
End
|
||||
Else Do
|
||||
rb=left(copies(left(nb,1),s)nb,length(nb))
|
||||
rx=b2x(rb)
|
||||
r=x2d(rx,8)
|
||||
End
|
||||
End
|
||||
Return r
|
||||
|
||||
b2x: Procedure Expose x.
|
||||
/**********************************************************************
|
||||
* Convert a Bit string to a Hex stríng
|
||||
**********************************************************************/
|
||||
Parse Arg b
|
||||
z='0'; bits.z='0000'; y=bits.z; x.y=z
|
||||
z='1'; bits.z='0001'; y=bits.z; x.y=z
|
||||
z='2'; bits.z='0010'; y=bits.z; x.y=z
|
||||
z='3'; bits.z='0011'; y=bits.z; x.y=z
|
||||
z='4'; bits.z='0100'; y=bits.z; x.y=z
|
||||
z='5'; bits.z='0101'; y=bits.z; x.y=z
|
||||
z='6'; bits.z='0110'; y=bits.z; x.y=z
|
||||
z='7'; bits.z='0111'; y=bits.z; x.y=z
|
||||
z='8'; bits.z='1000'; y=bits.z; x.y=z
|
||||
z='9'; bits.z='1001'; y=bits.z; x.y=z
|
||||
z='A'; bits.z='1010'; y=bits.z; x.y=z
|
||||
z='B'; bits.z='1011'; y=bits.z; x.y=z
|
||||
z='C'; bits.z='1100'; y=bits.z; x.y=z
|
||||
z='D'; bits.z='1101'; y=bits.z; x.y=z
|
||||
z='E'; bits.z='1110'; y=bits.z; x.y=z
|
||||
z='F'; bits.z='1111'; y=bits.z; x.y=z
|
||||
x=''
|
||||
Do While b<>''
|
||||
Parse Var b b4 +4 b
|
||||
x=x||x.b4
|
||||
End
|
||||
Return x
|
||||
|
||||
x2b: Procedure Expose bits.
|
||||
/***********************************************************************
|
||||
* Convert a Hex string to a Bit stríng
|
||||
***********************************************************************/
|
||||
Parse Arg x
|
||||
z='0'; bits.z='0000'; y=bits.z; x.y=z
|
||||
z='1'; bits.z='0001'; y=bits.z; x.y=z
|
||||
z='2'; bits.z='0010'; y=bits.z; x.y=z
|
||||
z='3'; bits.z='0011'; y=bits.z; x.y=z
|
||||
z='4'; bits.z='0100'; y=bits.z; x.y=z
|
||||
z='5'; bits.z='0101'; y=bits.z; x.y=z
|
||||
z='6'; bits.z='0110'; y=bits.z; x.y=z
|
||||
z='7'; bits.z='0111'; y=bits.z; x.y=z
|
||||
z='8'; bits.z='1000'; y=bits.z; x.y=z
|
||||
z='9'; bits.z='1001'; y=bits.z; x.y=z
|
||||
z='A'; bits.z='1010'; y=bits.z; x.y=z
|
||||
z='B'; bits.z='1011'; y=bits.z; x.y=z
|
||||
z='C'; bits.z='1100'; y=bits.z; x.y=z
|
||||
z='D'; bits.z='1101'; y=bits.z; x.y=z
|
||||
z='E'; bits.z='1110'; y=bits.z; x.y=z
|
||||
z='F'; bits.z='1111'; y=bits.z; x.y=z
|
||||
b=''
|
||||
Do While x<>''
|
||||
Parse Var x c +1 x
|
||||
b=b||bits.c
|
||||
End
|
||||
Return b
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
class PCG32 {
|
||||
has $!state;
|
||||
has $!incr;
|
||||
constant mask32 = 2³² - 1;
|
||||
constant mask64 = 2⁶⁴ - 1;
|
||||
constant const = 6364136223846793005;
|
||||
|
||||
submethod BUILD (
|
||||
Int :$seed = 0x853c49e6748fea9b, # default seed
|
||||
Int :$incr = 0xda3e39cb94b95bdb # default increment
|
||||
) {
|
||||
$!incr = $incr +< 1 +| 1 +& mask64;
|
||||
$!state = (($!incr + $seed) * const + $!incr) +& mask64;
|
||||
}
|
||||
|
||||
method next-int {
|
||||
my $shift = ($!state +> 18 +^ $!state) +> 27 +& mask32;
|
||||
my $rotate = $!state +> 59 +& 31;
|
||||
$!state = ($!state * const + $!incr) +& mask64;
|
||||
($shift +> $rotate) +| ($shift +< (32 - $rotate) +& mask32)
|
||||
}
|
||||
|
||||
method next-rat { self.next-int / 2³² }
|
||||
}
|
||||
|
||||
|
||||
# Test next-int with custom seed and increment
|
||||
say 'Seed: 42, Increment: 54; first five Int values:';
|
||||
my $rng = PCG32.new( :seed(42), :incr(54) );
|
||||
.say for $rng.next-int xx 5;
|
||||
|
||||
|
||||
# Test next-rat (since these are rational numbers by default)
|
||||
say "\nSeed: 987654321, Increment: 1; first 1e5 Rat values histogram:";
|
||||
$rng = PCG32.new( :seed(987654321), :incr(1) );
|
||||
say ( ($rng.next-rat * 5).floor xx 100_000 ).Bag;
|
||||
|
||||
|
||||
# Test next-int with default seed and increment
|
||||
say "\nSeed: default, Increment: default; first five Int values:";
|
||||
$rng = PCG32.new;
|
||||
.say for $rng.next-int xx 5;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
class PCG32
|
||||
MASK64 = (1 << 64) - 1
|
||||
MASK32 = (1 << 32) - 1
|
||||
CONST = 6364136223846793005
|
||||
|
||||
def seed(seed_state, seed_sequence)
|
||||
@state = 0
|
||||
@inc = ((seed_sequence << 1) | 1) & MASK64
|
||||
next_int
|
||||
@state = @state + seed_state
|
||||
next_int
|
||||
end
|
||||
|
||||
def next_int
|
||||
old = @state
|
||||
@state = ((old * CONST) + @inc) & MASK64
|
||||
xorshifted = (((old >> 18) ^ old) >> 27) & MASK32
|
||||
rot = (old >> 59) & MASK32
|
||||
answer = (xorshifted >> rot) | (xorshifted << ((-rot) & 31))
|
||||
answer & MASK32
|
||||
end
|
||||
|
||||
def next_float
|
||||
next_int.fdiv(1 << 32)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
random_gen = PCG32.new
|
||||
random_gen.seed(42, 54)
|
||||
5.times{puts random_gen.next_int}
|
||||
|
||||
random_gen.seed(987654321, 1)
|
||||
p 100_000.times.each{(random_gen.next_float * 5).floor}.tally.sort.to_h
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
(import (scheme small) (srfi 33))
|
||||
|
||||
(define PCG-DEFAULT-MULTIPLIER 6364136223846793005)
|
||||
(define MASK64 (- (arithmetic-shift 1 64) 1))
|
||||
(define MASK32 (- (arithmetic-shift 1 32) 1))
|
||||
|
||||
(define-record-type <pcg32-random> (make-pcg32-random-record) pcg32?
|
||||
(state pcg32-state pcg32-state!)
|
||||
(inc pcg32-inc pcg32-inc!))
|
||||
|
||||
(define (make-pcg32)
|
||||
(define rng (make-pcg32-random-record))
|
||||
(pcg32-seed rng 31415926 535897932)
|
||||
rng)
|
||||
|
||||
(define (pcg32-seed rng init-state init-seq)
|
||||
(pcg32-state! rng 0)
|
||||
(pcg32-inc! rng
|
||||
(bitwise-and
|
||||
(bitwise-ior (arithmetic-shift init-seq 1) 1)
|
||||
MASK64))
|
||||
(pcg32-next-int rng)
|
||||
(pcg32-state! rng (bitwise-and (+ (pcg32-state rng) init-state) MASK64))
|
||||
(pcg32-next-int rng))
|
||||
|
||||
(define (pcg32-next-int rng)
|
||||
(define xorshifted 0)
|
||||
(define rot 0)
|
||||
(define answer 0)
|
||||
(define oldstate (pcg32-state rng))
|
||||
(pcg32-state! rng
|
||||
(bitwise-and
|
||||
(+ (* oldstate PCG-DEFAULT-MULTIPLIER) (pcg32-inc rng))
|
||||
MASK64))
|
||||
(set! xorshifted (bitwise-xor (arithmetic-shift oldstate -18) oldstate))
|
||||
(set! xorshifted (arithmetic-shift xorshifted -27))
|
||||
(set! xorshifted (bitwise-and xorshifted MASK32))
|
||||
(set! rot (bitwise-and (arithmetic-shift oldstate -59) MASK32))
|
||||
(set! answer (bitwise-ior
|
||||
(arithmetic-shift xorshifted (- rot))
|
||||
(arithmetic-shift xorshifted (bitwise-and (- rot) 31))))
|
||||
(set! answer (bitwise-and answer MASK32))
|
||||
answer)
|
||||
|
||||
(define (pcg32-next-float rng)
|
||||
(inexact (/ (pcg32-next-int rng) (arithmetic-shift 1 32))))
|
||||
|
||||
;; task
|
||||
|
||||
(define rng (make-pcg32))
|
||||
(pcg32-seed rng 42 54)
|
||||
(let lp ((i 0)) (when (< i 5)
|
||||
(display (pcg32-next-int rng))(newline)
|
||||
(lp (+ i 1))))
|
||||
(newline)
|
||||
|
||||
(pcg32-seed rng 987654321 1)
|
||||
(define vec (make-vector 5 0))
|
||||
(let lp ((i 0)) (when (< i 100000)
|
||||
(let ((j (exact (floor (* (pcg32-next-float rng) 5)))))
|
||||
(vector-set! vec j (+ (vector-ref vec j) 1)))
|
||||
(lp (+ i 1))))
|
||||
(let lp ((i 0)) (when (< i 5)
|
||||
(display i)
|
||||
(display " : ")
|
||||
(display (vector-ref vec i))
|
||||
(newline)
|
||||
(lp (+ i 1))))
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
class PCG32(seed, incr) {
|
||||
|
||||
has state
|
||||
|
||||
define (
|
||||
mask32 = (2**32 - 1),
|
||||
mask64 = (2**64 - 1),
|
||||
N = 6364136223846793005,
|
||||
)
|
||||
|
||||
method init {
|
||||
seed := 1
|
||||
incr := 2
|
||||
incr = (((incr << 1) | 1) & mask64)
|
||||
state = (((incr + seed)*N + incr) & mask64)
|
||||
}
|
||||
|
||||
method next_int {
|
||||
var shift = ((((state >> 18) ^ state) >> 27) & mask32)
|
||||
var rotate = ((state >> 59) & mask32)
|
||||
state = ((state*N + incr) & mask64)
|
||||
((shift >> rotate) | (shift << (32-rotate))) & mask32
|
||||
}
|
||||
|
||||
method next_float {
|
||||
self.next_int / (mask32+1)
|
||||
}
|
||||
}
|
||||
|
||||
say "Seed: 42, Increment: 54, first 5 values:";
|
||||
var rng = PCG32(seed: 42, incr: 54)
|
||||
say 5.of { rng.next_int }
|
||||
|
||||
say "\nSeed: 987654321, Increment: 1, values histogram:";
|
||||
var rng = PCG32(seed: 987654321, incr: 1)
|
||||
var histogram = Bag(1e5.of { floor(5*rng.next_float) }...)
|
||||
histogram.pairs.sort.each { .join(": ").say }
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
type pcg32 = LargeWord.word * LargeWord.word
|
||||
|
||||
local
|
||||
infix 5 >>
|
||||
val op >> = LargeWord.>>
|
||||
and m = 0w6364136223846793005 : LargeWord.word
|
||||
and rotate32 = fn a as (x, n) =>
|
||||
Word32.orb (Word32.>> a, Word32.<< (x, Word.andb (~ n, 0w31)))
|
||||
in
|
||||
fun pcg32Init (seed, seq) : pcg32 =
|
||||
let
|
||||
val inc = LargeWord.<< (LargeWord.fromInt seq, 0w1) + 0w1
|
||||
in
|
||||
((LargeWord.fromInt seed + inc) * m + inc, inc)
|
||||
end
|
||||
fun pcg32Random ((state, inc) : pcg32) : Word32.word * pcg32 = (
|
||||
rotate32 (
|
||||
Word32.xorb (
|
||||
Word32.fromLarge (state >> 0w27),
|
||||
Word32.fromLarge (state >> 0w45)),
|
||||
Word.fromLarge (state >> 0w59)),
|
||||
(state * m + inc, inc))
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
fun test1 (rand, state) =
|
||||
(print (Word32.fmt StringCvt.DEC rand ^ "\n"); state)
|
||||
|
||||
local
|
||||
val prependFormatted =
|
||||
fn (i, v, lst) => Int.toString i ^ ": " ^ Int.toString v :: lst
|
||||
and counts = IntArray.array (5, 0)
|
||||
in
|
||||
fun test2 (rand, state) =
|
||||
let
|
||||
val i = LargeWord.toInt (LargeWord.>> (0w5 * Word32.toLarge rand, 0w32))
|
||||
in
|
||||
IntArray.update (counts, i, IntArray.sub (counts, i) + 1); state
|
||||
end
|
||||
fun test2res () =
|
||||
IntArray.foldri prependFormatted [] counts
|
||||
end
|
||||
|
||||
fun doTimes (_, 0, state) = state
|
||||
| doTimes (f, n, state) = doTimes (f, n - 1, f state)
|
||||
|
||||
val _ = doTimes (test1 o pcg32Random, 5, pcg32Init (42, 54))
|
||||
|
||||
val _ = doTimes (test2 o pcg32Random, 100000, pcg32Init (987654321, 1))
|
||||
val () = print ("\n" ^ ((String.concatWith ", " o test2res) ()) ^ "\n")
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import "/big" for BigInt
|
||||
|
||||
var Const = BigInt.new("6364136223846793005")
|
||||
var Mask64 = (BigInt.one << 64) - BigInt.one
|
||||
var Mask32 = (BigInt.one << 32) - BigInt.one
|
||||
|
||||
class Pcg32 {
|
||||
construct new() {
|
||||
_state = BigInt.fromBaseString("853c49e6748fea9b", 16)
|
||||
_inc = BigInt.fromBaseString("da3e39cb94b95bdb", 16)
|
||||
}
|
||||
|
||||
seed(seedState, seedSequence) {
|
||||
_state = BigInt.zero
|
||||
_inc = ((seedSequence << BigInt.one) | BigInt.one) & Mask64
|
||||
nextInt
|
||||
_state = _state + seedState
|
||||
nextInt
|
||||
}
|
||||
|
||||
nextInt {
|
||||
var old = _state
|
||||
_state = (old*Const + _inc) & Mask64
|
||||
var xorshifted = (((old >> 18) ^ old) >> 27) & Mask32
|
||||
var rot = (old >> 59) & Mask32
|
||||
return ((xorshifted >> rot) | (xorshifted << ((-rot) & 31))) & Mask32
|
||||
}
|
||||
|
||||
nextFloat { nextInt.toNum / 2.pow(32) }
|
||||
}
|
||||
|
||||
var randomGen = Pcg32.new()
|
||||
randomGen.seed(BigInt.new(42), BigInt.new(54))
|
||||
for (i in 0..4) System.print(randomGen.nextInt)
|
||||
|
||||
var counts = List.filled(5, 0)
|
||||
randomGen.seed(BigInt.new(987654321), BigInt.one)
|
||||
for (i in 1..1e5) {
|
||||
var i = (randomGen.nextFloat * 5).floor
|
||||
counts[i] = counts[i] + 1
|
||||
}
|
||||
System.print("\nThe counts for 100,000 repetitions are:")
|
||||
for (i in 0..4) System.print(" %(i) : %(counts[i])")
|
||||
Loading…
Add table
Add a link
Reference in a new issue