Pseudo-random numbers/PCG32: Difference between revisions
m
→{{header|Wren}}: Minor tidy
m (→{{header|Wren}}: Minor tidy) |
|||
(38 intermediate revisions by 16 users not shown) | |||
Line 49:
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:
Line 71:
* Show your output here, on this page.
=={{header|11l}}==
{{trans|Python}}
<syntaxhighlight lang="11l">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)</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
[0 = 20049, 1 = 20022, 2 = 20115, 3 = 19809, 4 = 20005]
</pre>
=={{header|Ada}}==
Ada solution using a package to encapsulate the PCG32 algorithm.
<syntaxhighlight lang="ada">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;
</syntaxhighlight>
<syntaxhighlight lang="ada">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;
</syntaxhighlight>
<syntaxhighlight lang="ada">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;
</syntaxhighlight>
{{output}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005
</pre>
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
<
# note that although LONG INT is 64 bits in Algol 68G, LONG BITS is longer than 64 bits #
LONG BITS state := LONG 16r853c49e6748fea9b;
Line 130 ⟶ 286:
print( ( newline ) )
END
END</
{{out}}
<pre>
Line 143 ⟶ 299:
=={{header|C}}==
{{trans|Go}}
<
#include <stdint.h>
#include <stdio.h>
Line 196 ⟶ 352:
return 0;
}</
{{out}}
<pre>2707161783
Line 210 ⟶ 366:
3 : 19809
4 : 20005</pre>
=={{header|C#}}==
{{trans|C++}}
<syntaxhighlight lang="C#">
using System;
class PCG32
{
private const ulong N = 6364136223846793005;
private ulong state = 0x853c49e6748fea9b;
private ulong inc = 0xda3e39cb94b95bdb;
public uint NextInt()
{
ulong old = state;
state = old * N + inc;
uint shifted = (uint)(((old >> 18) ^ old) >> 27);
uint rot = (uint)(old >> 59);
return (shifted >> (int)rot) | (shifted << (int)((~rot + 1) & 31));
}
public double NextFloat()
{
return ((double)NextInt()) / (1UL << 32);
}
public void Seed(ulong seedState, ulong seedSequence)
{
state = 0;
inc = (seedSequence << 1) | 1;
NextInt();
state += seedState;
NextInt();
}
}
class Program
{
static void Main(string[] args)
{
var r = new PCG32();
r.Seed(42, 54);
Console.WriteLine(r.NextInt());
Console.WriteLine(r.NextInt());
Console.WriteLine(r.NextInt());
Console.WriteLine(r.NextInt());
Console.WriteLine(r.NextInt());
Console.WriteLine();
int[] counts = new int[5];
r.Seed(987654321, 1);
for (int i = 0; i < 100000; i++)
{
int j = (int)Math.Floor(r.NextFloat() * 5.0);
counts[j]++;
}
Console.WriteLine("The counts for 100,000 repetitions are:");
for (int i = 0; i < counts.Length; i++)
{
Console.WriteLine($" {i} : {counts[i]}");
}
}
}
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005
</pre>
=={{header|C++}}==
{{trans|C}}
<
#include <iostream>
#include <math.h>
class PCG32 {
Line 267 ⟶ 507:
return 0;
}</
{{out}}
<pre>2707161783
Line 284 ⟶ 524:
=={{header|D}}==
{{trans|C++}}
<
import std.stdio;
Line 337 ⟶ 577:
writeln(" ", i, " : ", v);
}
}</
{{out}}
<pre>2707161783
Line 351 ⟶ 591:
3 : 19809
4 : 20005</pre>
=={{header|Dart}}==
{{trans|Python}}
<syntaxhighlight lang="Dart">
import 'dart:math';
class PCG32 {
BigInt fState = BigInt.zero;
BigInt fInc = BigInt.zero;
final BigInt mask64 = (BigInt.one << 64) - BigInt.one;
final BigInt mask32 = (BigInt.one << 32) - BigInt.one;
final BigInt k = BigInt.parse('6364136223846793005');
PCG32(BigInt seedState, BigInt seedSequence) {
seed(seedState, seedSequence);
}
PCG32.noSeed() {
fState = BigInt.zero;
fInc = BigInt.zero;
}
void seed(BigInt seedState, BigInt seedSequence) {
fState = BigInt.zero;
fInc = ((seedSequence << 1) | BigInt.one) & mask64;
nextInt();
fState += seedState;
nextInt();
}
BigInt nextInt() {
BigInt old = fState;
fState = ((old * k) + fInc) & mask64;
BigInt xorshifted = ( ((old >> 18) ^ old) >> 27) & mask32;
BigInt rot = (old >> 59) & mask32;
BigInt shifted = (xorshifted >> rot.toInt()) | (xorshifted << ((-rot) & BigInt.from(31)).toInt());
return shifted & mask32;
}
double nextFloat() {
return nextInt().toDouble() / (BigInt.one << 32).toDouble();
}
List<BigInt> nextIntRange(int size) {
List<BigInt> result = [];
for (int i = 0; i < size; i++) {
result.add(nextInt());
}
return result;
}
}
void main() {
var pcg32 = PCG32(BigInt.from(42), BigInt.from(54));
for (int i = 0; i < 5; i++) {
print(pcg32.nextInt().toString());
}
pcg32.seed(BigInt.from(987654321), BigInt.one);
var count = <int, int>{};
for (int i = 0; i < 100000; i++) {
int key = (pcg32.nextFloat() * 5).truncate();
count[key] = (count[key] ?? 0) + 1;
}
print('\nThe counts for 100,000 repetitions are:');
count.forEach((key, value) {
print('$key : $value');
});
}
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
2 : 20115
3 : 19809
0 : 20049
4 : 20005
1 : 20022
</pre>
=={{header|Delphi}}==
Line 358 ⟶ 688:
{{libheader| System.Generics.Collections}}
{{Trans|Python}}
<syntaxhighlight lang="delphi">
program PCG32_test;
Line 479 ⟶ 809:
Readln;
end.
</syntaxhighlight>
{{out}}
<pre>
Line 498 ⟶ 828:
=={{header|F_Sharp|F#}}==
===The Functions===
<
// PCG32. Nigel Galloway: August 13th., 2020
let N=6364136223846793005UL
Line 504 ⟶ 834:
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)
</syntaxhighlight>
===The Tasks===
<
pcg32(seed 42UL 54UL)|>Seq.take 5|>Seq.iter(printfn "%d")
</syntaxhighlight>
{{out}}
<pre>
Line 517 ⟶ 847:
3215226955
</pre>
<
pcgFloat(seed 987654321UL 1UL)|>Seq.take 100000|>Seq.countBy(fun n->int(n*5.0))|>Seq.iter(printf "%A");printfn ""
</syntaxhighlight>
<pre>
(2, 20115)(3, 19809)(0, 20049)(4, 20005)(1, 20022)
</pre>
=={{header|Factor}}==
{{trans|Python}}
{{works with|Factor|0.99 2020-08-14}}
<
prettyprint sequences ;
Line 558 ⟶ 889:
987654321 1 [ seed ] keepdd
100,000 [ dup next-float 5 * >integer ] replicate nip
histogram .</
{{out}}
<pre>
Line 571 ⟶ 902:
=={{header|Go}}==
{{trans|Python}}
<
import (
Line 621 ⟶ 952:
fmt.Printf(" %d : %d\n", i, counts[i])
}
}</
{{out}}
Line 638 ⟶ 969:
4 : 20005
</pre>
=={{header|Haskell}}==
Implement given algorithm as an instance of <code>RandomGen</code> class.
<syntaxhighlight lang="haskell">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)</syntaxhighlight>
Direct usage of generator:
<pre>*Main> take 5 $ randoms' (mkPCGen 42 54)
[2707161783,2068313097,3122475824,2211639955,3215226955]
*Main> let hist = map length . group . sort
*Main> hist . take 100000 $ (floor . (*5) . toFloat) <$> (randoms' (mkPCGen 987654321 1))
[20049,20022,20115,19809,20005]</pre>
Using <code>Random</code> class gives different results due to internal shuffling:
<pre>*Main> take 5 $ randoms (mkPCGen 42 54)
[2068313097,2211639955,3421331566,2167406445,4181216144]
*Main>let hist = map length . group . sort
*Main> hist . take 100000 $ (floor . (*5)) <$> (randoms (mkPCGen 987654321 1) :: [Float])
[20009,20065,20023,19876,20027]</pre>
=={{header|J}}==
Implementation:
<syntaxhighlight lang="j">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)</syntaxhighlight>
Task examples:
<syntaxhighlight lang="j"> 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</syntaxhighlight>
=={{header|Java}}==
{{trans|C++}}
<syntaxhighlight lang="java">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]);
}
}
}</syntaxhighlight>
{{out}}
<pre>2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005</pre>
=={{header|Julia}}==
{{trans|Python}}
<
mutable struct PCG32
Line 687 ⟶ 1,176:
testPCG32()
</
<pre>
2707161783
Line 701 ⟶ 1,190:
{{trans|C++}}
Requires the experimental unsigned feature for integer types
<
class PCG32 {
Line 754 ⟶ 1,243:
println(" %d : %d".format(iv.index, iv.value))
}
}</
{{out}}
<pre>2707161783
Line 768 ⟶ 1,257:
3 : 19809
4 : 20005</pre>
=={{header|Lua}}==
{{trans|C}}
<syntaxhighlight lang="lua">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</syntaxhighlight>
{{out}}
<pre>2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0: 20049
1: 20022
2: 20115
3: 19809
4: 20005</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
{{trans|Julia}}
<syntaxhighlight lang="Mathematica">
ClearAll["Global`*"];
(*Constants*)
mask32 = BitAnd[2^32 - 1];
CONST = 6364136223846793005;
(*Convert Hex String to Expression*)
Hex[x_?StringQ] := ToExpression["16^^" <> StringDrop[x, 2]];
(*Definition of PCG32 Structure*)
PCG32[state_: Hex["0x853c49e6748fea9b"],
inc_: Hex["0xda3e39cb94b95bdb"]] := <|"state" -> state,
"inc" -> inc|>;
(*Function to generate next integer*)
nextInt[pcg_Association] :=
Module[{old, xorshifted, rot, newState}, old = pcg["state"];
newState = BitAnd[(old*CONST + pcg["inc"]), 2^64 - 1];
xorshifted =
BitAnd[BitShiftRight[BitXor[BitShiftRight[old, 18], old], 27],
mask32];
rot = BitAnd[BitShiftRight[old, 59], mask32];
<|"state" -> newState, "inc" -> pcg["inc"],
"nextInt" ->
BitAnd[BitOr[BitShiftRight[xorshifted, rot],
BitShiftLeft[xorshifted, BitAnd[-rot, 31]]], mask32]|>];
(*Function to generate next float*)
nextFloat[pcg_Association] := nextInt[pcg]["nextInt"]/2^32;
(*Function to seed the generator*)
seed[pcg_Association, st_, seq_] :=
Module[{newPcg},
newPcg = <|"state" -> 0,
"inc" -> BitOr[BitShiftLeft[seq, 1], 1]|>;
newPcg = nextInt[newPcg];
<|"state" -> newPcg["state"] + st, "inc" -> newPcg["inc"]|>];
(*Test function*)
testPCG32[] :=
Module[{randomGen, hist, n, nextGen}, randomGen = PCG32[];
randomGen = seed[randomGen, 42, 54];
Do[
nextGen = nextInt[randomGen];
randNumber = nextGen["nextInt"];
If[randNumber != 0, Print[randNumber]];
randomGen = nextGen
, {6}];
randomGen = seed[randomGen, 987654321, 1];
hist = ConstantArray[0, 5];
Do[nextGen = nextInt[randomGen];
hist[[Floor[nextFloat[nextGen]*5] + 1]] += 1;
randomGen = nextGen, {100000}];
Print[hist];
Do[Print[n - 1, ": ", hist[[n]], " "], {n, 1, 5}];];
(*Run the test*)
testPCG32[];
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
{20049, 20022, 20115, 19809, 20005}
0: 20049
1: 20022
2: 20115
3: 19809
4: 20005
</pre>
=={{header|Nim}}==
<syntaxhighlight lang="nim">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(", ")</syntaxhighlight>
{{out}}
<pre>2707161783
2068313097
3122475824
2211639955
3215226955
0: 20049, 1: 20022, 2: 20115, 3: 19809, 4: 20005</pre>
=={{header|OCaml}}==
<syntaxhighlight lang="ocaml">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</syntaxhighlight>
;<nowiki>Test:</nowiki>
<syntaxhighlight lang="ocaml">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")</syntaxhighlight>
{{out}}
<pre>
2707161783 2068313097 3122475824 2211639955 3215226955
0: 20049
1: 20022
2: 20115
3: 19809
4: 20005
</pre>
=={{header|Perl}}==
<
use warnings;
use feature 'say';
use Math::AnyNum qw(:overload);
use constant {
};
sub new {
my ($
my $seed = $opt{seed} //
my $
$incr
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 =
$self->{state
($shift >> $rotate) | $shift << (32 - $rotate) & mask32;
}
sub next_float {
my ($self) = @_;
$self->next_int / 2**32;
}
}
Line 800 ⟶ 1,535:
say "Seed: 42, Increment: 54, first 5 values:";
my $rng = PCG32->new(seed => 42, incr => 54);
say
say "\nSeed: 987654321, Increment: 1, values histogram:";
my %h;
$rng = PCG32->new(
$h{int 5 *
say "$_ $h{$_}" for sort keys %h;</
{{out}}
<pre>Seed: 42, Increment: 54, first 5 values:
Line 827 ⟶ 1,562:
Phix atoms are limited to 53/64 bits of precision, however (given the above) this task would need 128 bits.<br>
First, for comparison only, this is the usual recommended native approach for this genre of task (different output)
<!--<syntaxhighlight lang="phix">(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>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 848 ⟶ 1,585:
{20080,19802,19910,20039,20169}
</pre>
To meet the spec, similar to the Delphi and Wren entries, we resort to using mpfr/gmp, but it is a fair bit longer than the above, and almost certainly slower,
<!--<syntaxhighlight lang="phix">(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>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 909 ⟶ 1,652:
=={{header|Python}}==
===Python: As class===
<syntaxhighlight lang="python">mask64 = (1 << 64) - 1
mask32 = (1 << 32) - 1
CONST = 6364136223846793005
Line 955 ⟶ 1,700:
for i in range(100_000):
hist[int(random_gen.next_float() *5)] += 1
print(hist)</
{{out}}
<pre>2707161783
2068313097
3122475824
2211639955
3215226955
{0: 20049, 1: 20022, 2: 20115, 3: 19809, 4: 20005}</pre>
===Python: As generator===
<syntaxhighlight lang="python">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)</syntaxhighlight>
{{out}}
Line 971 ⟶ 1,760:
Raku does not have unsigned Integers at this time (Integers are arbitrary sized) so use explicit bit masks during bitwise operations.
<syntaxhighlight lang="raku"
has $!state;
has $!incr;
Line 1,012 ⟶ 1,801:
say "\nSeed: default, Increment: default; first five Int values:";
$rng = PCG32.new;
.say for $rng.next-int xx 5;</
{{out}}
<pre>Seed: 42, Increment: 54; first five Int values:
Line 1,030 ⟶ 1,819:
3759121132
2984354868</pre>
=={{header|REXX}}==
{{trans|Java}}
It was a challenge to understand how some Java constructs work and to end up with the identical output.
DON'T use Rexx, however, for this type of problem unless you take the time spent
for some Java coffees!
<syntaxhighlight lang="rexx">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 </syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005
</pre>
=={{header|Ruby}}==
{{trans|Python}}
<
MASK64 = (1 << 64) - 1
MASK32 = (1 << 32) - 1
Line 1,066 ⟶ 2,168:
random_gen.seed(987654321, 1)
p 100_000.times.each{(random_gen.next_float * 5).floor}.tally.sort.to_h
</syntaxhighlight>
{{out}}
<pre>2707161783
Line 1,075 ⟶ 2,177:
{0=>20049, 1=>20022, 2=>20115, 3=>19809, 4=>20005}
</pre>
=={{header|Rust}}==
{{trans|C++}}
<syntaxhighlight lang="Rust">
struct PCG32 {
multiplier: u64,
state: u64,
inc: u64,
}
impl PCG32 {
fn new() -> Self {
PCG32 {
multiplier: 6364136223846793005,
state: 0x853c49e6748fea9b,
inc: 0xda3e39cb94b95bdb,
}
}
fn next_int(&mut self) -> u32 {
let old = self.state;
self.state = old.wrapping_mul(self.multiplier).wrapping_add(self.inc);
let xorshifted = (((old >> 18) ^ old) >> 27) as u32;
let rot = (old >> 59) as u32;
(xorshifted >> rot) | (xorshifted << ((!rot).wrapping_add(1) & 31))
}
fn next_float(&mut self) -> f64 {
(self.next_int() as f64) / ((1u64 << 32) as f64)
}
fn seed(&mut self, seed_state: u64, seed_sequence: u64) {
self.state = 0;
self.inc = (seed_sequence << 1) | 1;
self.next_int();
self.state = self.state.wrapping_add(seed_state);
self.next_int();
}
}
fn main() {
let mut rng = PCG32::new();
rng.seed(42, 54);
for _ in 0..5 {
println!("{}", rng.next_int());
}
println!();
let mut counts = [0; 5];
rng.seed(987654321, 1);
for _ in 0..100000 {
let j = (rng.next_float() * 5.0).floor() as usize;
counts[j] += 1;
}
println!("The counts for 100,000 repetitions are:");
for (i, count) in counts.iter().enumerate() {
println!(" {} : {}", i, count);
}
}
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005
</pre>
=={{header|Scala}}==
{{trans|Java}}
<syntaxhighlight lang="Scala">
object PCG32 {
private val N = 6364136223846793005L
private var state = 0x853c49e6748fea9bL
private var inc = 0xda3e39cb94b95bdbL
def seed(seedState: Long, seedSequence: Long): Unit = {
state = 0
inc = (seedSequence << 1) | 1
nextInt()
state += seedState
nextInt()
}
def nextInt(): Int = {
val old = state
state = old * N + inc
val shifted = (((old >>> 18) ^ old) >>> 27).toInt
val rot = (old >>> 59).toInt
(shifted >>> rot) | (shifted << ((~rot + 1) & 31))
}
def nextFloat(): Double = {
val u = nextInt() & 0xffffffffL
u.toDouble / (1L << 32)
}
}
object Main extends App {
val r = PCG32
r.seed(42, 54)
println(Integer.toUnsignedString(r.nextInt()))
println(Integer.toUnsignedString(r.nextInt()))
println(Integer.toUnsignedString(r.nextInt()))
println(Integer.toUnsignedString(r.nextInt()))
println(Integer.toUnsignedString(r.nextInt()))
println()
val counts = Array(0, 0, 0, 0, 0)
r.seed(987654321, 1)
for (_ <- 1 to 100000) {
val j = Math.floor(r.nextFloat() * 5.0).toInt
counts(j) += 1
}
println("The counts for 100,000 repetitions are:")
for (i <- counts.indices) {
println(s" $i : ${counts(i)}")
}
}
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005
</pre>
=={{header|Scheme}}==
{{trans|Ruby}}
<syntaxhighlight lang="scheme">(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))))
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
0 : 20049
1 : 20022
2 : 20115
3 : 19809
4 : 20005
</pre>
=={{header|Sidef}}==
{{trans|Perl}}
<syntaxhighlight lang="ruby">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 }</syntaxhighlight>
{{out}}
<pre>
Seed: 42, Increment: 54, first 5 values:
[2707161783, 2068313097, 3122475824, 2211639955, 3215226955]
Seed: 987654321, Increment: 1, values histogram:
0: 20049
1: 20022
2: 20115
3: 19809
4: 20005
</pre>
=={{header|Standard ML}}==
<syntaxhighlight lang="sml">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</syntaxhighlight>
;Test code<nowiki>:</nowiki>
<syntaxhighlight lang="sml">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")</syntaxhighlight>
{{out}}
<pre>2707161783
2068313097
3122475824
2211639955
3215226955
0: 20049, 1: 20022, 2: 20115, 3: 19809, 4: 20005</pre>
=={{header|Tcl}}==
{{trans|C}}
<syntaxhighlight lang="Tcl">
proc uint32 {n} {
return [expr {$n & 0xffffffff}]
}
proc uint64 {n} {
return [expr {$n & 0xffffffffffffffff}]
}
set N 6364136223846793005
set state 0x853c49e6748fea9b
set inc 0xda3e39cb94b95bdb
proc pcg32_seed {seed_state seed_sequence} {
global state inc
set state 0
set inc [expr {($seed_sequence << 1) | 1}]
pcg32_int
set state [expr {$state + $seed_state}]
pcg32_int
}
proc pcg32_int {} {
global state N inc
set old $state
set state [uint64 [expr {$old * $N + $inc}]]
set shifted [uint32 [expr {(($old >> 18) ^ $old) >> 27}]]
set rot [uint32 [expr {$old >> 59}]]
return [uint32 [expr {($shifted >> $rot) | ($shifted << ((~$rot + 1) & 31))}]]
}
proc pcg32_float {} {
return [expr {1.0 * [pcg32_int] / (1 << 32)}]
}
# -------------------------------------------------------------------
pcg32_seed 42 54
puts [pcg32_int]
puts [pcg32_int]
puts [pcg32_int]
puts [pcg32_int]
puts [pcg32_int]
puts ""
set counts {0 0 0 0 0}
pcg32_seed 987654321 1
for {set i 1} {$i <= 100000} {incr i} {
set j [expr {int([pcg32_float] * 5.0) + 1}]
lset counts [expr {$j - 1}] [expr {[lindex $counts [expr {$j - 1}]] + 1}]
}
puts "The counts for 100,000 repetitions are:"
foreach idx {0 1 2 3 4} {
puts " $idx: [lindex $counts $idx]"
}
</syntaxhighlight>
{{out}}
<pre>
2707161783
2068313097
3122475824
2211639955
3215226955
The counts for 100,000 repetitions are:
0: 20049
1: 20022
2: 20115
3: 19809
4: 20005
</pre>
=={{header|uBasic/4tH}}==
{{trans|C}}
uBasic/4tH only supports signed integers - so floating point is out of the question. It also requires clipping some integers to 32 bits in order to make this work.
<syntaxhighlight lang="text">' ** NOTE: this requires a 64-bit uBasic. **
If Info("wordsize") < 64 Then Print "This program requires a 64-bit uBasic" : End
n = 6364136223846793005
s = 377257722939173531 + 9223372036854775807 + 1
i = 6502698458505894875 + 9223372036854775807 + 1
Proc _PCG32Seed(42, 54);
Print FUNC(_PCG32Int)
Print FUNC(_PCG32Int)
Print FUNC(_PCG32Int)
Print FUNC(_PCG32Int)
Print FUNC(_PCG32Int)
End
_PCG32Int
Local (3)
a@ = s
s = (a@ * n) + i
b@ = And(Shl(Xor(Shl(a@, -18), a@), -27), 4294967295)
c@ = And(Shl(a@, -59), 4294967295)
Return (And(Or(Shl(b@, -c@), Shl(b@, And((Not(c@) + 1), 31))), 4294967295))
_PCG32Seed
Param (2)
s = 0
i = Or(Shl(b@, 1), 1)
Proc _PCG32Int
s = s + a@
Proc _PCG32Int
Return</syntaxhighlight>
{{Out}}
<pre>2707161783
2068313097
3122475824
2211639955
3215226955
0 OK, 0:391</pre>
=={{header|Wren}}==
Line 1,080 ⟶ 2,654:
{{libheader|Wren-big}}
As Wren doesn't have a 64-bit integer type, we use BigInt instead.
<
var Const = BigInt.new("6364136223846793005")
Line 1,122 ⟶ 2,696:
}
System.print("\nThe counts for 100,000 repetitions are:")
for (i in 0..4) System.print(" %(i) : %(counts[i])")</
{{out}}
|