Pseudo-random numbers/Splitmix64: Difference between revisions

m
→‎jq: 13 minutes u+s
No edit summary
m (→‎jq: 13 minutes u+s)
(17 intermediate revisions by 11 users not shown)
Line 66:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">T Splitmix64
UInt64 state
 
Line 91:
L 100'000
hist[Int(random_gen.next_float() * 5)]++
print(hist)</langsyntaxhighlight>
 
{{out}}
Line 104:
 
=={{header|Ada}}==
Ada conversion of Next_float * 5.0 to an integer value resulted in some values of 5 which would have caused a buffer overflow in the counting array. The fix was to truncate Next_float * 5.0 as a floating point value and convert that value to an integer. Upon doing this the counts of each array element become 20073, indicating there are an equal number values in each portion of the random number range.
 
The random number functions are written in a stand-alone package. The package is split into a package specification defining the interfaces to the public subprograms and a body containing the implementation of the random number generator.
 
'''package specification:'''
<langsyntaxhighlight Adalang="ada">with Interfaces; use Interfaces;
 
package Random_Splitmix64 is
Line 116 ⟶ 114:
function next_float return Float;
procedure Set_State (Seed : in Unsigned_64);
end Random_Splitmix64;</langsyntaxhighlight>
'''package body:'''
<langsyntaxhighlight Adalang="ada">package body Random_Splitmix64 is
Internal : Unsigned_64 := 1234567;
 
Line 153 ⟶ 151:
end Set_State;
 
end Random_Splitmix64;</langsyntaxhighlight>
'''Main procedure:'''
<langsyntaxhighlight Adalang="ada">with Interfaces; use Interfaces;
with Random_Splitmix64; use Random_Splitmix64;
with Ada.Text_IO; use Ada.Text_IO;
Line 161 ⟶ 159:
procedure Main is
subtype idx is Integer range 0 .. 4;
type answer_arr is array (idx) of Unsigned_64Natural;
Vec : answer_arr := (others => 0);
J : idxInteger;
fj : Float;
begin
Line 176 ⟶ 174:
for I in 1 .. 100_000 loop
fj := Float'Truncation (next_float * 5.0);
J := idxInteger (fj);
Vec (J) := Vec (J) + 1;
end loop;
 
for I in Vec'Range loop
Put_Line (I'Image & ":" & Unsigned_64Integer'Image (Vec (JI)));
end loop;
 
end Main;</lang>
</syntaxhighlight>
{{out}}
<pre>
Line 192 ⟶ 191:
4593380528125082431
16408922859458223821
0: 2007320027
1: 2007319892
2: 20073
3: 2007319978
4: 2007320030
</pre>
 
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any Tested with release 2.8.3.win32}}
<langsyntaxhighlight lang="algol68">BEGIN # generate some pseudo random numbers using Splitmix64 #
# note that although LONG INT is 64 bits in Algol 68G, LONG BITS is longer than 64 bits #
LONG BITS mask 64 = LONG 16rffffffffffffffff;
Line 248 ⟶ 247:
print( ( newline ) )
END
END</langsyntaxhighlight>
{{out}}
<pre>
Line 261 ⟶ 260:
=={{header|C}}==
Code copied from the reference C implementation used by Java, and using GNU GCC v7.1.1.
<langsyntaxhighlight lang="c">/* Written in 2015 by Sebastiano Vigna (vigna@acm.org)
 
To the extent possible under law, the author has dedicated all copyright
Line 307 ⟶ 306:
printf("%d: %d ", i, vec5[i]);
}
</langsyntaxhighlight>{{out}}
<pre>
6457827717110365317
Line 315 ⟶ 314:
16408922859458223821
0: 20027 1: 19892 2: 20073 3: 19978 4: 20030
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
 
#include <iostream>
#include <cmath>
#include <vector>
 
class Splitmix64 {
public:
Splitmix64() { state = 0; }
Splitmix64(const uint64_t seed) : state(seed) {}
 
void seed(const uint64_t seed) {
state = seed;
}
 
uint64_t next_int() {
uint64_t z = ( state += 0x9e3779b97f4a7c15 );
z = ( z ^ ( z >> 30 ) ) * 0xbf58476d1ce4e5b9;
z = ( z ^ ( z >> 27 ) ) * 0x94d049bb133111eb;
return z ^ ( z >> 31 );
}
 
double next_float() {
return next_int() / twoPower64;
}
 
private:
uint64_t state;
const double twoPower64 = pow(2.0, 64);
};
 
int main() {
Splitmix64 random;
random.seed(1234567);
for ( int32_t i = 0; i < 5; ++i ) {
std::cout << random.next_int() << std::endl;
}
std::cout << std::endl;
 
Splitmix64 rand(987654321);
std::vector<uint32_t> counts(5, 0);
for ( int32_t i = 0; i < 100'000; ++i ) {
uint32_t value = floor(rand.next_float() * 5.0);
counts[value] += 1;
}
 
for ( int32_t i = 0; i < 5; ++i ) {
std::cout << i << ": " << counts[i] << " ";
}
std::cout << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
 
0: 20027 1: 19892 2: 20073 3: 19978 4: 20030
</pre>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: io kernel math math.bitwise math.functions
math.statistics namespaces prettyprint sequences ;
 
Line 339 ⟶ 402:
"Seed: 987654321; first 100,000 float values histogram" print
987654321 seed 100,000 [ next-float 5 * >integer ] replicate
histogram .</langsyntaxhighlight>
{{out}}
<pre>
Line 358 ⟶ 421:
{{works with|gforth|0.7.3}}
 
<langsyntaxhighlight lang="forth">variable rnd-state
 
: rnd-base-op ( z factor shift -- u ) 2 pick swap rshift rot xor * ;
Line 397 ⟶ 460:
;
 
counts-fill counts-disp</langsyntaxhighlight>
 
{{out}}
Line 413 ⟶ 476:
ok</pre>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">// Pure F# Implementation of SplitMix64
let a: uint64 = 0x9e3779b97f4a7c15UL
 
Line 443 ⟶ 506:
printfn "%i" fourth
printfn "%i" fifth
0</langsyntaxhighlight>
 
{{out}}
Line 455 ⟶ 518:
 
=={{header|Go}}==
<langsyntaxhighlight Golang="go">package main
 
import (
Line 494 ⟶ 557:
fmt.Printf(" %d : %d\n", i, counts[i])
}
}</langsyntaxhighlight>
 
{{out}}
Line 514 ⟶ 577:
=={{header|Haskell}}==
 
<langsyntaxhighlight lang="haskell">import Data.Bits
 
import Data.Word
import Data.List
Line 528 ⟶ 592:
randoms = unfoldr (pure . next)
 
toFloat n = fromIntegral n / (2^64 - 1)</langsyntaxhighlight>
 
<pre>λ> mapM_ print $ take 5 $ randoms 1234567
Line 540 ⟶ 604:
λ> hist . take 100000 $ (floor . (*5) . toFloat) <$> (randoms 987654321)
[20027,19892,20073,19978,20030]</pre>
 
=={{header|Java}}==
Java integers are signed and so have a maximum value of 2^63 - 1, requiring the use of the BigInteger class for this task.
<syntaxhighlight lang="java">
 
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public final class PseudoRandomSplitmix64 {
 
public static void main(String[] aArgs) {
Splitmix64 random = new Splitmix64();
random.seed(1234567);
for ( int i = 0; i < 5; i++ ) {
System.out.println(random.nextInt());
}
List<Integer> counts = new ArrayList<Integer>(Collections.nCopies(5, 0));
Splitmix64 rand = new Splitmix64(987654321);
for ( int i = 0; i < 100_000; i++ ) {
BigDecimal value = rand.nextFloat();
final int count = value.multiply(BigDecimal.valueOf(5.0)).toBigInteger().intValue();
counts.set(count, counts.get(count) + 1);
}
System.out.println(System.lineSeparator() + "The counts for 100,000 repetitions are: ");
for ( int i = 0; i < 5; i++ ) {
System.out.print(i + ": " + counts.get(i) + " ");
}
System.out.println();
}
}
 
final class Splitmix64 {
public Splitmix64() {
state = BigInteger.ZERO;
}
public Splitmix64(long aSeed) {
state = BigInteger.valueOf(aSeed).and(mask64);
}
public void seed(long aNumber) {
state = BigInteger.valueOf(aNumber);
}
public BigInteger nextInt() {
state = state.add(constant1).and(mask64);
BigInteger z = state;
z = z.xor(z.shiftRight(30)).multiply(constant2).and(mask64);
z = z.xor(z.shiftRight(27)).multiply(constant3).and(mask64);
BigInteger result = z.xor(z.shiftRight(31)).and(mask64);
return result;
}
public BigDecimal nextFloat() {
return new BigDecimal(nextInt()).divide(twoPower64, MathContext.DECIMAL64);
}
private BigInteger state;
private final BigInteger constant1 = new BigInteger("9e3779b97f4a7c15", 16);
private final BigInteger constant2 = new BigInteger("bf58476d1ce4e5b9", 16);
private final BigInteger constant3 = new BigInteger("94d049bb133111eb", 16);
private final BigInteger mask64 = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);
private final BigDecimal twoPower64 = new BigDecimal(BigInteger.ONE.shiftLeft(64));
 
}
</syntaxhighlight>
{{ out }}
<pre>
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
 
The counts for 100,000 repetitions are:
0: 20027 1: 19892 2: 20073 3: 19978 4: 20030
</pre>
 
=={{header|Jasmin}}==
 
<syntaxhighlight lang="text">u64 c1 = 0x9e3779b97f4a7c15;
u64 c2 = 0xbf58476d1ce4e5b9;
u64 c3 = 0x94d049bb133111eb;
 
inline
fn next_int(reg u64 state) -> reg u64 {
reg u64 z a;
z = [state];
z += c1;
[state] = z;
a = z;
a >>= 30;
z ^= a;
z *= c2;
a = z;
a >>= 27;
z ^= a;
z *= c3;
a = z;
a >>= 31;
z ^= a;
return z;
}
 
inline
fn test() -> reg u64[5] {
reg u64 seed;
seed = 0x1000;
[seed] = 1234567;
inline int i;
reg u64[5] result;
for i = 0 to 5 {
result[i] = next_int(seed);
}
return result;
}
exec test(0x1000:8)</syntaxhighlight>
 
=={{header|jq}}==
'''Works with gojq, the Go implementation of jq'''
 
'''Adapted from [[#Wren|Wren]]'''
 
This entry assumes sufficiently precise integer arithmetic, e.g. as provided by gojq,
which supports infinite-precision integer arithmetic.
Unfortunately, though, gojq does not support efficient bitwise operations, and using
the following to generate 100,000 random numbers takes about 13 minutes on a 3GHz machine.
 
The main significance of this entry is thus to increase confidence in the correctness of the
definitions as well as in the Go implementation of jq.
 
In the following, a 'bitarray' is a 0/1 array, and when integers are represented by bitarrays, the first bit is the least-significant one. Unless otherwise indicated, the bitwise operations work on bitarrays.
 
'''Generic utilities'''
<syntaxhighlight lang="jq">
# Input: a string in base $b (2 to 35 inclusive)
# Output: a JSON number, being the decimal value corresponding to the input.
def frombase($b):
def decimalValue:
if 48 <= . and . <= 57 then . - 48
elif 65 <= . and . <= 90 then . - 55 # (10+.-65)
elif 97 <= . and . <= 122 then . - 87 # (10+.-97)
else "decimalValue" | error
end;
reduce (explode|reverse[]|decimalValue) as $x ({p:1};
.value += (.p * $x)
| .p *= $b)
| .value ;
 
# To take advantage of gojq's arbitrary-precision integer arithmetic:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
 
# If the input and $j are integers, then the result will be an integer.
def div($j):
(. - (. % j)) / $j;
 
# Convert an integer to a bitarray, least significant bit first
def bitwise:
recurse( if . >= 2 then div(2) else empty end) | . % 2;
 
# Essentially the inverse of bitwise,
# i.e. interpret an array of 0s and 1s (with least-significant-bit first ) as a decimal
def to_int:
. as $in
# state: [sum, power]
| reduce .[] as $i ([0, 1]; .[1] as $p | [.[0] + $p * $i, ($p * 2)])
| .[0];
 
# $x and $y and output are bitarrays
def xor($x;$y):
def lxor(a;b):
if (a==1 or b==1) and ((a==1 and b==1)|not) then 1
elif a == null then b
elif b == null then a
else 0
end;
if $x == [0] then $y
elif $y == [0] then $x
else
[ range(0; [($x|length), ($y|length)] | max) as $i
| lxor($x[$i]; $y[$i]) ]
end ;
 
# $x and $y and output are bitarrays
def xand($x;$y):
def lxand(a;b):
(a==1 and b==1) | 1 // 0;
if $x == [0] or $y == [0] then [0]
else
[range(0; [($x|length), ($y|length)] | min) as $i
| lxand($x[$i]; $y[$i]) ]
end ;
 
# shift right
def right($n): .[$n:];
 
def mask64: .[:64];
 
# input and output: a bitarray
def mult($int):
($int * to_int) | [bitwise];
 
def plus($int):
($int + to_int) | [bitwise];
 
def tabulate(stream):
reduce stream as $i ([]; .[$i] += 1)
| range(0;length) as $i
| " \($i) : \(.[$i] // 0)" ;
</syntaxhighlight>
'''Splitmix64'''
<syntaxhighlight lang="jq">
# input: a bitarray
def nextInt:
def Const1: "9e3779b97f4a7c15" | frombase(16) ;
def Const2: "bf58476d1ce4e5b9" | frombase(16) ;
def Const3: "94d049bb133111eb" | frombase(16) ;
 
(plus(Const1) | mask64)
| . as $state
| xor(.; right(30)) | mult(Const2) | mask64
| xor(.; right(27)) | mult(Const3) | mask64
| xor(.; right(31)) | mask64
| ., ($state|nextInt) ;
 
def randomInt64: [bitwise] | nextInt | to_int;
 
def randomReal:
pow(2;64) as $d
| [bitwise] | nextInt | to_int / $d;
 
### The tasks
(limit(5; 1234567 | randomInt64)),
 
"\nThe counts for 100,000 repetitions are:",
tabulate( limit(100; 987654321 | randomReal * 5 | floor) )
 
</syntaxhighlight>
{{output}}
<pre>
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
 
The counts for 100,000 repetitions are:
0 : 20027
1 : 19892
2 : 20073
3 : 19978
4 : 20030
</pre>
 
=={{header|Julia}}==
{{trans|Python}}
<langsyntaxhighlight lang="julia">const C1 = 0x9e3779b97f4a7c15
const C2 = 0xbf58476d1ce4e5b9
const C3 = 0x94d049bb133111eb
Line 577 ⟶ 905:
 
testSplitmix64()
</langsyntaxhighlight>{{out}}
<pre>
6457827717110365317
Line 588 ⟶ 916:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[BitShiftLevelUint, MultiplyUint, GenerateRandomNumbers]
BitShiftLevelUint[z_, n_] := BitShiftRight[z, n]
MultiplyUint[z_, n_] := Mod[z n, 2^64]
Line 605 ⟶ 933:
GenerateRandomNumbers[1234567, 5]
nums = GenerateRandomNumbers[987654321, 10^5];
KeySort[Counts[Floor[5 nums/N[2^64]]]]</langsyntaxhighlight>
{{out}}
<pre>{6457827717110365317, 3203168211198807973, 9817491932198370423, 4593380528125082431, 16408922859458223821}
Line 611 ⟶ 939:
 
=={{header|Nim}}==
<langsyntaxhighlight Nimlang="nim">import math, sequtils, strutils
 
const Two64 = 2.0^64
Line 647 ⟶ 975:
for _ in 1..100_000:
inc counts[int(prng.nextFloat * 5)]
echo toSeq(counts.pairs).mapIt(($it[0]) & ": " & ($it[1])).join(", "</langsyntaxhighlight>
 
{{out}}
Line 659 ⟶ 987:
Seed = 987654321:
0: 20027, 1: 19892, 2: 20073, 3: 19978, 4: 20030</pre>
 
=={{header|Perl}}==
<lang perl>use strict;
use warnings;
no warnings 'portable';
use feature 'say';
use Math::AnyNum qw(:overload);
 
package splitmix64 {
 
sub new {
my ($class, %opt) = @_;
bless {state => $opt{seed}}, $class;
}
 
sub next_int {
my ($self) = @_;
my $next = $self->{state} = ($self->{state} + 0x9e3779b97f4a7c15) & (2**64 - 1);
$next = ($next ^ ($next >> 30)) * 0xbf58476d1ce4e5b9 & (2**64 - 1);
$next = ($next ^ ($next >> 27)) * 0x94d049bb133111eb & (2**64 - 1);
($next ^ ($next >> 31)) & (2**64 - 1);
}
 
sub next_float {
my ($self) = @_;
$self->next_int / 2**64;
}
}
 
say 'Seed: 1234567, first 5 values:';
my $rng = splitmix64->new(seed => 1234567);
say $rng->next_int for 1 .. 5;
 
my %h;
say "\nSeed: 987654321, values histogram:";
$rng = splitmix64->new(seed => 987654321);
$h{int 5 * $rng->next_float}++ for 1 .. 100_000;
say "$_ $h{$_}" for sort keys %h;</lang>
{{out}}
<pre>Seed: 1234567, first 5 values:
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
 
Seed: 987654321, values histogram:
0 20027
1 19892
2 20073
3 19978
4 20030</pre>
 
=={{header|Phix}}==
As per [[Pseudo-random_numbers/PCG32#Phix]], resorting to mpfr/gmp
<!--<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;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">shift</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0x9e3779b97f4a7c15"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mult1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0xbf58476d1ce4e5b9"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">mult2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0x94d049bb133111eb"</span><span style="color: #0000FF;">),</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;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">z</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;">num</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">,</span><span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">next_int</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;">shift</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- state += shift</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(z,b64) </span>
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">state</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z := state</span>
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- tmp := trunc(z/2^30)</span>
<span style="color: #7060A8;">mpz_xor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z := xor_bits(z,tmp)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mult1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z *= mult1</span>
<span style="color: #7060A8;">mpz_fdiv_r</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b64</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z := remainder(z,b64) </span>
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- tmp := trunc(z/2^27)</span>
<span style="color: #7060A8;">mpz_xor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z := xor_bits(z,tmp)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mult2</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z *= mult2</span>
<span style="color: #7060A8;">mpz_fdiv_r</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b64</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z := remainder(z,b64) </span>
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">31</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- tmp := trunc(z/2^31)</span>
<span style="color: #7060A8;">mpz_xor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">z</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z := xor_bits(z,tmp)
-- (result left in z)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">next_float</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">next_int</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">mpfr</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_init_set_z</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_div_z</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b64</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mpfr_get_d</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</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;">1234567</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: #000000;">next_int</span><span style="color: #0000FF;">()</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;">"%s\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</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: #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;">rdx</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;">rdx</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>
<!--</lang>-->
{{out}}
<pre>
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
{20027,19892,20073,19978,20030}
</pre>
 
=={{header|Object Pascal}}==
<syntaxhighlight lang="pascal">
<lang Pascal>
program splitmix64;
 
Line 855 ⟶ 1,067:
Write(i, ': ', vec[i], ' ');
end.
</langsyntaxhighlight>{{out}}
<pre>
6457827717110365317
Line 863 ⟶ 1,075:
16408922859458223821
0: 20027 1: 19892 2: 20073 3: 19978 4: 20030
</pre>
 
=={{header|Odin}}==
Based on the C reference implementation.
<syntaxhighlight lang="odin">package main
 
import "core:fmt"
import "core:math"
 
TWO64 :f64: 1 << 64
 
SplitMix64 :: struct {
state: u64,
}
 
next_int :: proc(rng: ^SplitMix64) -> u64 {
rng.state += 0x9e3779b97f4a7c15
z := rng.state
z = (z ~ (z >> 30)) * 0xbf58476d1ce4e5b9
z = (z ~ (z >> 27)) * 0x94d049bb133111eb
return z ~ (z >> 31)
}
 
next_float :: proc(rng: ^SplitMix64) -> f64 {
return f64(next_int(rng)) / TWO64
}
 
main :: proc() {
rng := SplitMix64{1234567}
 
for i in 0..<5 {
fmt.println(next_int(&rng))
}
 
rng.state = 987654321
vec5 := [5]int{0,0,0,0,0}
for i in 0..<100000 {
j := int(math.floor(next_float(&rng) * 5.))
vec5[j] += 1
}
 
for v,i in vec5 {
fmt.printf("%d: %d ", i, v)
}
}
</syntaxhighlight>{{out}}
<pre>
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
0: 20027 1: 19892 2: 20073 3: 19978 4: 20030
</pre>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">use strict;
use warnings;
no warnings 'portable';
use feature 'say';
use Math::AnyNum qw(:overload);
 
package splitmix64 {
 
sub new {
my ($class, %opt) = @_;
bless {state => $opt{seed}}, $class;
}
 
sub next_int {
my ($self) = @_;
my $next = $self->{state} = ($self->{state} + 0x9e3779b97f4a7c15) & (2**64 - 1);
$next = ($next ^ ($next >> 30)) * 0xbf58476d1ce4e5b9 & (2**64 - 1);
$next = ($next ^ ($next >> 27)) * 0x94d049bb133111eb & (2**64 - 1);
($next ^ ($next >> 31)) & (2**64 - 1);
}
 
sub next_float {
my ($self) = @_;
$self->next_int / 2**64;
}
}
 
say 'Seed: 1234567, first 5 values:';
my $rng = splitmix64->new(seed => 1234567);
say $rng->next_int for 1 .. 5;
 
my %h;
say "\nSeed: 987654321, values histogram:";
$rng = splitmix64->new(seed => 987654321);
$h{int 5 * $rng->next_float}++ for 1 .. 100_000;
say "$_ $h{$_}" for sort keys %h;</syntaxhighlight>
{{out}}
<pre>Seed: 1234567, first 5 values:
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
 
Seed: 987654321, values histogram:
0 20027
1 19892
2 20073
3 19978
4 20030</pre>
 
=={{header|Phix}}==
As per [[Pseudo-random_numbers/PCG32#Phix]], resorting to mpfr/gmp
<syntaxhighlight lang="phix">
with javascript_semantics
include mpfr.e
mpz state = mpz_init(),
shift = mpz_init("0x9e3779b97f4a7c15"),
mult1 = mpz_init("0xbf58476d1ce4e5b9"),
mult2 = mpz_init("0x94d049bb133111eb"),
b64 = mpz_init("0x10000000000000000"), -- (truncate to 64 bits)
tmp = mpz_init(),
z = mpz_init()
procedure seed(integer num)
mpz_set_si(state,num)
end procedure
procedure next_int()
mpz_add(state, state, shift) -- state += shift
mpz_fdiv_r(state, state, b64) -- state := remainder(z,b64)
mpz_set(z, state) -- z := state
mpz_tdiv_q_2exp(tmp, z, 30) -- tmp := trunc(z/2^30)
mpz_xor(z, z, tmp) -- z := xor_bits(z,tmp)
mpz_mul(z, z, mult1) -- z *= mult1
mpz_fdiv_r(z, z, b64) -- z := remainder(z,b64)
mpz_tdiv_q_2exp(tmp, z, 27) -- tmp := trunc(z/2^27)
mpz_xor(z, z, tmp) -- z := xor_bits(z,tmp)
mpz_mul(z, z, mult2) -- z *= mult2
mpz_fdiv_r(z, z, b64) -- z := remainder(z,b64)
mpz_tdiv_q_2exp(tmp, z, 31) -- tmp := trunc(z/2^31)
mpz_xor(z, z, tmp) -- z := xor_bits(z,tmp)
-- (result left in z)
end procedure
function next_float()
next_int()
mpfr f = mpfr_init_set_z(z)
mpfr_div_z(f, f, b64)
return mpfr_get_d(f)
end function
seed(1234567)
for i=1 to 5 do
next_int()
printf(1,"%s\n",mpz_get_str(z))
end for
seed(987654321)
sequence r = repeat(0,5)
for i=1 to 100000 do
integer rdx = floor(next_float()*5)+1
r[rdx] += 1
end for
?r
</syntaxhighlight>
{{out}}
<pre>
6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
{20027,19892,20073,19978,20030}
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(zero *Split) # global state
 
(de mod64 (N)
Line 898 ⟶ 1,280:
(roundf (* 5 (*/ (nextSplit) 1.0 18446744073709551616)))
1 ) )
(mapc println (sort R))</langsyntaxhighlight>
{{out}}
<pre>
Line 917 ⟶ 1,299:
=={{header|Python}}==
 
<langsyntaxhighlight lang="python">MASK64 = (1 << 64) - 1
C1 = 0x9e3779b97f4a7c15
C2 = 0xbf58476d1ce4e5b9
Line 956 ⟶ 1,338:
for i in range(100_000):
hist[int(random_gen.next_float() *5)] += 1
print(hist)</langsyntaxhighlight>
 
{{out}}
Line 965 ⟶ 1,347:
16408922859458223821
{0: 20027, 1: 19892, 2: 20073, 3: 19978, 4: 20030}</pre>
 
=={{header|Quackery}}==
 
Note that Quackery does not have floating point, so this code uses rational numbers and approximates them to 16 places after the decimal point (when displayed as decimal fractions), so is at least as good as 64 bit floating point.
 
<syntaxhighlight lang="Quackery"> [ $ "bigrat.qky" loadfile ] now!
 
[ stack hex DEFACEABADFACADE ] is state ( --> s )
 
[ state replace ] is seed ( n ---> )
 
[ state take
hex 9E3779B97F4A7C15 + 64bits
dup state put
dup 30 >> ^
hex BF58476D1CE4E5B9 * 64bits
dup 27 >> ^
hex 94D049BB133111EB * 64bits
dup 31 >> ^ ] is nextint ( --> n )
 
[ nextint
hex 10000000000000000
10000000000000000 round ] is nextfrac ( --> n/d )
 
1234567 seed
5 times [ nextint echo cr ]
cr
987654321 seed
' [ 0 0 0 0 0 ]
100000 times
[ nextfrac 5 1 v* proper 2drop
2dup peek 1+ unrot poke ]
echo</syntaxhighlight>
 
{{out}}
 
<pre>6457827717110365317
3203168211198807973
9817491932198370423
4593380528125082431
16408922859458223821
 
[ 20027 19892 20073 19978 20030 ]</pre>
 
=={{header|Raku}}==
{{works with|Rakudo|2020.07}}
 
<syntaxhighlight lang="raku" perl6line>class splitmix64 {
has $!state;
 
Line 993 ⟶ 1,418:
say "\nSeed: 987654321; first 1e5 Rat values histogram";
$rng = splitmix64.new( :seed(987654321) );
say ( ($rng.next-rat * 5).floor xx 100_000 ).Bag;</langsyntaxhighlight>
{{out}}
<pre>Seed: 1234567; first five Int values
Line 1,006 ⟶ 1,431:
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program generates pseudo─random numbers using the split mix 64 bit method.*/
numeric digits 200 /*ensure enough decimal digs for mult. */
parse arg n reps pick seed1 seed2 . /*obtain optional arguments from the CL*/
Line 1,056 ⟶ 1,481:
xor: parse arg a, b; $= /*perform a bit─wise XOR. */
do !=1 for length(a); $= $ || (substr(a,!,1) && substr(b,!,1) )
end /*!*/; return $</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 1,074 ⟶ 1,499:
3: 19,978
4: 20,030
</pre>
 
=={{header|RPL}}==
RPL offers hundreds of instructions and commands but, strangely, bitwise operations are limited to the set defined for the HP-16C RPN calculator in 1982.
So, to shift an integer n times, we can either stay in low gear, shifting one bit at a time:
≪ 1 SWAP '''START''' SR '''NEXT'''
≫ '<span style="color:blue">SRn</span>' STO
or play with the gearbox:
8 MOD LAST / IP ROT <span style="color:grey">@ q, r = divmod(n,8)</span>
'''IF''' SWAP THEN 1 LAST '''START''' SRB '''NEXT END''' <span style="color:grey">@ q, r = divmod(n,8)</span>
'''IF''' SWAP '''THEN''' 1 LAST '''START''' SR '''NEXT END''' <span style="color:grey">@ shift & bit right, r times</span>
≫ '<span style="color:blue">SRn</span>' STO
The first version is less efficient in terms of response time, but more idiomatic because it takes much less time to type on a calculator keyboard.
{{works with|HP|28}}
≪ # 9E3779B97F4A7C15h 'STATE' STO+
<span style="color:green">STATE</span> DUP 30 SRn XOR # BF58476D1CE4E5B9h *
DUP 27 <span style="color:blue">SRn</span> XOR # 94D049BB133111EBh *
DUP 31 <span style="color:blue">SRn</span> XOR
≫ '<span style="color:blue">NEXTINT</span>' STO
≪ <span style="color:blue">NEXTINT</span> B→R 2 64 ^ /
≫ '<span style="color:blue">NEXTFLOAT</span>' STO
≪ # 1234567d '<span style="color:green">STATE</span>' STO
1 5 '''START''' <span style="color:blue">NEXTINT</span> '''NEXT'''
≫ '<span style="color:blue">TASK1</span>' STO
≪ { 5 } O CON
1 10000 '''START'''
<span style="color:blue">NEXTFLOAT</span> 5 * CEIL DUP2 GET 1 + PUT '''NEXT'''
≫ '<span style="color:blue">TASK2</span>' STO
 
The last task requirement takes too much time to be run on a calculator. On a emulator, we had to split it into 10 runs to not wake up the watchdog timer.
<span style="color:blue">TASK1</span>
# 987654321d '<span style="color:green">STATE</span>' STO
{ 5 } O CON
<span style="color:blue">TASK2</span> <span style="color:blue">TASK2</span> .. <span style="color:blue">TASK2</span> <span style="color:grey">@ 10 times</span>
{{out}}
<pre>
6: # 6457827717110365317d
5: # 3203168211198807973d
4: # 9817491932198370423d
3: # 4593380528125082431d
2: # 16408922859458223821d
1: [ 20027 19892 20073 19978 20030 ]
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class Splitmix64
MASK64 = (1 << 64) - 1
C1, C2, C3 = 0x9e3779b97f4a7c15, 0xbf58476d1ce4e5b9, 0x94d049bb133111eb
Line 1,099 ⟶ 1,570:
rand_gen = Splitmix64.new(987654321)
p 100_000.times.lazy.map{(rand_gen.rand_f * 5).floor}.tally.sort.to_h
</syntaxhighlight>
</lang>
{{out}}
<pre>6457827717110365317
Line 1,108 ⟶ 1,579:
{0=>20027, 1=>19892, 2=>20073, 3=>19978, 4=>20030}
</pre>
 
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">class Splitmix64(state) {
 
define (
Line 1,135 ⟶ 1,607:
var rng = Splitmix64(987654321)
var histogram = Bag(1e5.of { floor(5*rng.next_float) }...)
histogram.pairs.sort.each { .join(": ").say }</langsyntaxhighlight>
{{out}}
<pre>
Line 1,156 ⟶ 1,628:
{{libheader|Wren-big}}
No 64 bit integers so we use BigInt with a mask.
<langsyntaxhighlight ecmascriptlang="wren">import "./big" for BigInt
 
var Const1 = BigInt.fromBaseString("9e3779b97f4a7c15", 16)
Line 1,189 ⟶ 1,661:
}
System.print("\nThe counts for 100,000 repetitions are:")
for (i in 0..4) System.print(" %(i) : %(counts[i])")</langsyntaxhighlight>
 
{{out}}
2,442

edits