Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,2 @@
---
from: http://rosettacode.org/wiki/Pseudo-random_numbers/PCG32

View 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.

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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)

View file

@ -0,0 +1 @@
pcg32(seed 42UL 54UL)|>Seq.take 5|>Seq.iter(printfn "%d")

View file

@ -0,0 +1 @@
pcgFloat(seed 987654321UL 1UL)|>Seq.take 100000|>Seq.countBy(fun n->int(n*5.0))|>Seq.iter(printf "%A");printfn ""

View file

@ -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 .

View file

@ -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])
}
}

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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]);
}
}
}

View file

@ -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()

View file

@ -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))
}
}

View file

@ -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

View file

@ -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(", ")

View file

@ -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

View file

@ -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")

View file

@ -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;

View file

@ -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>
<!--

View file

@ -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>
<!--

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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))))

View file

@ -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 }

View file

@ -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

View file

@ -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")

View file

@ -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])")