Has anyone ported the PCG PRNG to FreeBASIC
Has anyone ported the PCG PRNG to FreeBASIC
Has anyone ported the PCG PRNG from C99 to a version for FreeBASIC that they would like to share?
PCG, A Family of Better Random Number Generators
http://www.pcg-random.org/
Not really a C guy ... so wanted to know before I give it a try.
Thanks,
CBruce
PCG, A Family of Better Random Number Generators
http://www.pcg-random.org/
Not really a C guy ... so wanted to know before I give it a try.
Thanks,
CBruce
Re: Has anyone ported the PCG PRNG to FreeBASIC
Hi,
don't know exactly, what you are looking for, but FB has built in random generators.
There is also a thread in Windows: Fast CPRNG
don't know exactly, what you are looking for, but FB has built in random generators.
There is also a thread in Windows: Fast CPRNG
Re: Has anyone ported the PCG PRNG to FreeBASIC
Hi MrSwiss,
Melissa O'Neill has created an amazing family of PRNG's and CPRNG's, written in pure C99 and/or C++ (no ASM), that are faster and have longer periods of non-repeating sequences than any other RNG out there. These include PRNGs that can provide multiple non-collision streams from a single instance.
She has not created an academic exercise or just published a couple of pseudo-code algorithms. These are multiple RNG algorithms that are coded for the real world, have multiple examples, and work as advertised - and it's all very well documented. [grin]
She has a long whitepaper (47 pages) on her site that is a must read ... a lot of incredible information concerning her family of RNGs - as well as analysis, tests and statistics comparing her RNGs against all other ones that are known.
She has a simple version that is incredible in itself, but her others versions are beyond compare. I've compiled them and her demo/test applications to see them in operation - but I've never ported C code to BASIC code - (but I'm getting ready to try unless someone else has already done so).
Thanks,
CBruce
Melissa O'Neill has created an amazing family of PRNG's and CPRNG's, written in pure C99 and/or C++ (no ASM), that are faster and have longer periods of non-repeating sequences than any other RNG out there. These include PRNGs that can provide multiple non-collision streams from a single instance.
She has not created an academic exercise or just published a couple of pseudo-code algorithms. These are multiple RNG algorithms that are coded for the real world, have multiple examples, and work as advertised - and it's all very well documented. [grin]
She has a long whitepaper (47 pages) on her site that is a must read ... a lot of incredible information concerning her family of RNGs - as well as analysis, tests and statistics comparing her RNGs against all other ones that are known.
She has a simple version that is incredible in itself, but her others versions are beyond compare. I've compiled them and her demo/test applications to see them in operation - but I've never ported C code to BASIC code - (but I'm getting ready to try unless someone else has already done so).
Thanks,
CBruce
Re: Has anyone ported the PCG PRNG to FreeBASIC
hello cbruce
you can use fbfrog to help with the translation there's also a C++ to VB Converter the demo is free though limited.
you can use fbfrog to help with the translation there's also a C++ to VB Converter the demo is free though limited.
-
- Site Admin
- Posts: 6323
- Joined: Jul 05, 2005 17:32
- Location: Manchester, Lancs
Re: Has anyone ported the PCG PRNG to FreeBASIC
I've ported the code at http://www.pcg-random.org/download.html:
And here's a complete C program to test against:
Both should output:
Evidently if you start with a zeroed out pcg32_random_t instance, it takes a couple of iterations to produce anything random-looking. So the minimal implementation at least needs some seeding first.
Code: Select all
'' *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
'' Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
'' FreeBASIC translation by Matthew Fearnley 2017-06-04
type pcg32_random_t
as ulongint state, inc
end type
function pcg32_random_r(byval rng as pcg32_random_t ptr) as ulong
dim as ulongint oldstate = rng->state
'' Advance internal state
rng->state = oldstate * 6364136223846793005ULL + (rng->inc or 1)
'' Calculate output function (XSH RR), uses old state for max ILP
dim as ulong xorshifted = ((oldstate shr 18u) xor oldstate) shr 27u
dim as ulong rot = oldstate shr 59u
return (xorshifted shr rot) or (xorshifted shl ((-rot) and 31))
end function
'' test
dim rng as pcg32_random_t
for i as integer = 1 to 10
print pcg32_random_r(@rng)
next i
Code: Select all
#include <stdint.h>
#include <stdio.h>
// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
typedef struct { uint64_t state; uint64_t inc; } pcg32_random_t;
uint32_t pcg32_random_r(pcg32_random_t* rng)
{
uint64_t oldstate = rng->state;
// Advance internal state
rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1);
// Calculate output function (XSH RR), uses old state for max ILP
uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
uint32_t rot = oldstate >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
int main()
{
pcg32_random_t rng = {0,0};
int i;
for (i = 0; i < 10; i++)
{
printf("%u\n", pcg32_random_r(&rng));
}
return 0;
}
Code: Select all
0
0
3837872008
932996374
1548399547
1612522464
473443212
3522865942
1734871597
2449558126
-
- Site Admin
- Posts: 6323
- Joined: Jul 05, 2005 17:32
- Location: Manchester, Lancs
Re: Has anyone ported the PCG PRNG to FreeBASIC
From just looking at the minimal code and reading a couple of pages, I'm amazed.
The principle is ridiculously simple. I would describe it like this:
1. use a simple, well-understood pseudo-random generator (e.g. linear congruential generator as used in the minimal code)
2. return a secure hash of the output
3. there is no step 3!
The periodicity of the random numbers is the same as that of the simple PRNG, but the secure hashing means that without a massive lookup table you can't find out the internal state based on its output.
(In the example code's case, it returns 32 bits of output for a 64-bit state anyway, so it's definitely a one-way hash.)
I don't really understand the hashing method, although it's clearly pretty simple. But from the Party Tricks page it evidently has the property of being able to calculate the input needed to contrive any output. This itself isn't particularly useful when generating random numbers, but it means that all outputs are possible, which is a good property for a random number generator.
The principle is ridiculously simple. I would describe it like this:
1. use a simple, well-understood pseudo-random generator (e.g. linear congruential generator as used in the minimal code)
2. return a secure hash of the output
3. there is no step 3!
The periodicity of the random numbers is the same as that of the simple PRNG, but the secure hashing means that without a massive lookup table you can't find out the internal state based on its output.
(In the example code's case, it returns 32 bits of output for a 64-bit state anyway, so it's definitely a one-way hash.)
I don't really understand the hashing method, although it's clearly pretty simple. But from the Party Tricks page it evidently has the property of being able to calculate the input needed to contrive any output. This itself isn't particularly useful when generating random numbers, but it means that all outputs are possible, which is a good property for a random number generator.
Re: Has anyone ported the PCG PRNG to FreeBASIC
THANKS for converting the basic version counting_pine!!!
I should be able to convert the full version by referencing this one.
Now I get to go play!!!
CBruce
FYI counting_pine .... From her whitepaper, the simple description of the Ms. O'Neill's algorithm:
I should be able to convert the full version by referencing this one.
Now I get to go play!!!
CBruce
FYI counting_pine .... From her whitepaper, the simple description of the Ms. O'Neill's algorithm:
The key idea is to pass the output of a fast well-understood “medium quality” random number generator to an efficient permutation function (a.k.a. hash function), built from composable primitives, that enhances the quality of the output. The algorithm can be applied at variety of bit sizes, including 64 and 128 bits (which provide 32- and 64-bit outputs, with periods of 2 64 and 2 128). Optionally, we can provide each b -bit generator with a b - 1 bit stream-selection constant, thereby providing 2 b - 1 random streams, which are full period and entirely distinct. An extension adds up to 2 b -dimensional equidistribution for a total period of 2 b 2 b . The construction of the permutation function and the period-extension technique are both founded on the idea of permutation functions on tuples.
In its standard variants, b -bit generators use a 2 b /2 -to-1 function to produce b /2 bits of output. These functions can be designed to make it difficult for an adversary to discover the generator’s internal state by examining its output, and thus make it challenging to predict. This property, coupled with the ability to easily switch between random streams, provides many of the benefits provided by cryptographically secure generators without the overheads usually associated with those generators.
Last edited by cbruce on Jun 04, 2017 16:56, edited 1 time in total.
-
- Site Admin
- Posts: 6323
- Joined: Jul 05, 2005 17:32
- Location: Manchester, Lancs
Re: Has anyone ported the PCG PRNG to FreeBASIC
I'll add the caveat that after further reading (particularly http://www.pcg-random.org/predictability.html), it is obvious that she doesn't guarantee the numbers generated by the algorithm are unpredictable.
It is only clear that with a linear congruential generator, hashing the output or even just discarding some of the state when outputting it, makes it much more "challenging" to predict.
But obviously we can hope that it is secure, and particularly hope that it can be proven to be secure, and she is keen to invite the mathematical community to put it to the test.
It is only clear that with a linear congruential generator, hashing the output or even just discarding some of the state when outputting it, makes it much more "challenging" to predict.
But obviously we can hope that it is secure, and particularly hope that it can be proven to be secure, and she is keen to invite the mathematical community to put it to the test.
-
- Posts: 4292
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: Has anyone ported the PCG PRNG to FreeBASIC
I don't impress easily.
I am impressed.<smile>
I have added a few lines to counting_pine's code to determine the average single in [0,1) and an estimate of the speed of single generation.
I get:
That 0.500004 does not prove randomness. Had we got 0.3, say, then that would prove non-randomness. The speed is very good and about 80% faster than FB's option 2 (MWC) and over twice as fast as FB's option 3 (Mersenne Twister). What is more impressive is the small amount of state space used, admittedly this is the minimal version, and the code size.
Ms O'Neill would do well to include PractRand in the tests. The author of PractRand considered 120 PRNGs and his suite found bias in 78. TestU01(Big Crush) found bias in 50. Dieharder found bias in 25. Dieharder has had its day.
So, I presented the above to PractRand. There was only a couple of anomalies in a one terabyte test, on par with my CryptoRndII which uses cryptographic random nhumbers. I would have posted before now but PractRand cannot be hurried. It should be noted that PractRand does not prove randomness either. What it tells us is whether there is any evidence of non-randomness or not.
I would go futher than counting_pine and say that under no circumstance should this code be used in cryptograhic applications until the paper has been reviewed but, more importantly, examined by the world's crypanalysts who may have some suggestions - they will have some suggestions.<smile>
I shall involve myself no further - this is CBruce's baby.
Call here to see Ms O'Neill in action. Pull up your easy chair - it is 74 minutes long. She is a Professor of Computer Science at Harvey Mudd.
I am impressed.<smile>
I have added a few lines to counting_pine's code to determine the average single in [0,1) and an estimate of the speed of single generation.
I get:
Code: Select all
Average [0,1) : 0.500004
Million singles per second: 188.582
Ms O'Neill would do well to include PractRand in the tests. The author of PractRand considered 120 PRNGs and his suite found bias in 78. TestU01(Big Crush) found bias in 50. Dieharder found bias in 25. Dieharder has had its day.
So, I presented the above to PractRand. There was only a couple of anomalies in a one terabyte test, on par with my CryptoRndII which uses cryptographic random nhumbers. I would have posted before now but PractRand cannot be hurried. It should be noted that PractRand does not prove randomness either. What it tells us is whether there is any evidence of non-randomness or not.
I would go futher than counting_pine and say that under no circumstance should this code be used in cryptograhic applications until the paper has been reviewed but, more importantly, examined by the world's crypanalysts who may have some suggestions - they will have some suggestions.<smile>
I shall involve myself no further - this is CBruce's baby.
I look forward to the full version as others will, I am sure.I should be able to convert the full version by referencing this one.
Now I get to go play!!!
Call here to see Ms O'Neill in action. Pull up your easy chair - it is 74 minutes long. She is a Professor of Computer Science at Harvey Mudd.
Code: Select all
'' *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
'' Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
'' FreeBASIC translation by Matthew Fearnley 2017-06-04
Type pcg32_random_t
As Ulongint state, inc
End Type
Function pcg32_random_r(Byval rng As pcg32_random_t Ptr) As Ulong
Dim As Ulongint oldstate = rng->state
'' Advance internal state
rng->state = oldstate * 6364136223846793005ULL + (rng->inc Or 1)
'' Calculate output function (XSH RR), uses old state for max ILP
Dim As Ulong xorshifted = ((oldstate Shr 18u) xor oldstate) Shr 27u
Dim As Ulong rot = oldstate Shr 59u
Return (xorshifted Shr rot) Or (xorshifted Shl ((-rot) And 31))
End Function
'' test
Dim rng As pcg32_random_t
' Warm up - probably don't need 100 - about 0.5 micro-seconds
' but worth it - trust me <smile>
Randomize , 5
rng.state = Rnd*(2^64-1) ' using a cryptographically random Ulongint seed
For i As Integer = 1 To 100
pcg32_random_r(@rng)
Next i
Dim As Ulong I, N
Dim T As Double
Dim As Ulong TempVar
Dim Result As Single
Dim Tot As Double
N = 10^8 ' 100 x million
T = Timer
For I = 1 To N
TempVar = pcg32_random_r(@rng)
' Single precision
Asm
mov eax, dword Ptr [TempVar]
movd xmm0, eax
psrlq xmm0, 9
mov eax, 1
cvtsi2ss xmm1, eax
por xmm0, xmm1
subss xmm0, xmm1
movd [Result], xmm0
End Asm
Tot += Result
Next
T = Timer - T
Print "Average [0,1) : ";Using "#.######";tot/n
Print "Million singles per second: ";Using "###.###";n/(t*1000000)
Sleep
Re: Has anyone ported the PCG PRNG to FreeBASIC
Thanks, David. The fact that you are impressed, tells me I might be headed down the right road.
I'll be working on this next week in my evenings. and I'll keep you updated.
By the way, if you have time, take a look at her whitepaper ... It is actually the best read I have ever seen on RNGs.
BEH
I'll be working on this next week in my evenings. and I'll keep you updated.
By the way, if you have time, take a look at her whitepaper ... It is actually the best read I have ever seen on RNGs.
BEH
-
- Posts: 4292
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: Has anyone ported the PCG PRNG to FreeBASIC
Thank you. The cheque is in the post.The fact that you are impressed, tells me I might be headed down the right road.
I will.take a look at her whitepaper
Re: Has anyone ported the PCG PRNG to FreeBASIC
hello cbruce
using fbfrog and a bit of editing here's the pcg_prng
pcg_variants.bi
pcg_advance.bas
using fbfrog and a bit of editing here's the pcg_prng
pcg_variants.bi
Code: Select all
/'
* PCG Random Number Generation for C.
*
* Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For additional information about the PCG random number generation scheme,
* including its license and other licensing options, visit
*
* http://www.pcg-random.org
'/
/'
* This code is derived from the canonical C++ PCG implementation, which
* has many additional features and is preferable if you can use C++ in
* your project.
*
* Much of the derivation was performed mechanically. In particular, the
* output functions were generated by compiling the C++ output functions
* into LLVM bitcode and then transforming that using the LLVM C backend
* (from https://github.com/draperlaboratory/llvm-cbe), and then
* postprocessing and hand editing the output.
*
* Much of the remaining code was generated by C-preprocessor metaprogramming.
'/
'translated using fbfrog https://github.com/dkl/fbfrog
#pragma once
'' #include once "inttypes.bi"
extern "C"
const PCG_VARIANTS_H_INCLUDED = 1
function pcg_rotr_8(byval value as ubyte, byval rot as ulong) as ubyte
return (value shr rot) or (value shl ((-rot) and 7))
end function
function pcg_rotr_16(byval value as ushort, byval rot as ulong) as ushort
return (value shr rot) or (value shl ((-rot) and 15))
end function
function pcg_rotr_32(byval value as ulong, byval rot as ulong) as ulong
return (value shr rot) or (value shl ((-rot) and 31))
end function
function pcg_rotr_64(byval value as ulongint, byval rot as ulong) as ulongint
return (value shr rot) or (value shl ((-rot) and 63))
end function
function pcg_output_xsh_rs_16_8(byval state as ushort) as ubyte
return cubyte(((state shr 7u) xor state) shr ((state shr 14u) + 3u))
end function
function pcg_output_xsh_rs_32_16(byval state as ulong) as ushort
return cushort(((state shr 11u) xor state) shr ((state shr 30u) + 11u))
end function
function pcg_output_xsh_rs_64_32(byval state as ulongint) as ulong
return culng(((state shr 22u) xor state) shr ((state shr 61u) + 22u))
end function
function pcg_output_xsh_rr_16_8(byval state as ushort) as ubyte
return pcg_rotr_8(((state shr 5u) xor state) shr 5u, state shr 13u)
end function
function pcg_output_xsh_rr_32_16(byval state as ulong) as ushort
return pcg_rotr_16(((state shr 10u) xor state) shr 12u, state shr 28u)
end function
function pcg_output_xsh_rr_64_32(byval state as ulongint) as ulong
return pcg_rotr_32(((state shr 18u) xor state) shr 27u, state shr 59u)
end function
function pcg_output_rxs_m_xs_8_8(byval state as ubyte) as ubyte
dim word as ubyte = ((state shr ((state shr 6u) + 2u)) xor state) * 217u
return (word shr 6u) xor word
end function
function pcg_output_rxs_m_xs_16_16(byval state as ushort) as ushort
dim word as ushort = ((state shr ((state shr 13u) + 3u)) xor state) * 62169u
return (word shr 11u) xor word
end function
function pcg_output_rxs_m_xs_32_32(byval state as ulong) as ulong
dim word as ulong = ((state shr ((state shr 28u) + 4u)) xor state) * 277803737u
return (word shr 22u) xor word
end function
function pcg_output_rxs_m_xs_64_64(byval state as ulongint) as ulongint
dim word as ulongint = ((state shr ((state shr 59u) + 5u)) xor state) * 12605985483714917081ull
return (word shr 43u) xor word
end function
function pcg_output_xsl_rr_64_32(byval state as ulongint) as ulong
return pcg_rotr_32(culng(culng(state shr 32u) xor culng(state)), state shr 59u)
end function
function pcg_output_xsl_rr_rr_64_64(byval state as ulongint) as ulongint
dim rot1 as ulong = culng(state shr 59u)
dim high as ulong = culng(state shr 32u)
dim low as ulong = culng(state)
dim xored as ulong = high xor low
dim newlow as ulong = pcg_rotr_32(xored, rot1)
dim newhigh as ulong = pcg_rotr_32(high, newlow and 31u)
return (culngint(newhigh) shl 32u) or newlow
end function
const PCG_DEFAULT_MULTIPLIER_8 = 141u
const PCG_DEFAULT_MULTIPLIER_16 = 12829u
const PCG_DEFAULT_MULTIPLIER_32 = 747796405u
const PCG_DEFAULT_MULTIPLIER_64 = 6364136223846793005ull
const PCG_DEFAULT_INCREMENT_8 = 77u
const PCG_DEFAULT_INCREMENT_16 = 47989u
const PCG_DEFAULT_INCREMENT_32 = 2891336453u
const PCG_DEFAULT_INCREMENT_64 = 1442695040888963407ull
type pcg_state_8
state as ubyte
end type
type pcg_state_16
state as ushort
end type
type pcg_state_32
state as ulong
end type
type pcg_state_64
state as ulongint
end type
type pcg_state_setseq_8
state as ubyte
inc as ubyte
end type
type pcg_state_setseq_16
state as ushort
inc as ushort
end type
type pcg_state_setseq_32
state as ulong
inc as ulong
end type
type pcg_state_setseq_64
state as ulongint
inc as ulongint
end type
declare function pcg_advance_lcg_8(byval state as ubyte, byval delta as ubyte, byval cur_mult as ubyte, byval cur_plus as ubyte) as ubyte
declare function pcg_advance_lcg_16(byval state as ushort, byval delta as ushort, byval cur_mult as ushort, byval cur_plus as ushort) as ushort
declare function pcg_advance_lcg_32(byval state as ulong, byval delta as ulong, byval cur_mult as ulong, byval cur_plus as ulong) as ulong
declare function pcg_advance_lcg_64(byval state as ulongint, byval delta as ulongint, byval cur_mult as ulongint, byval cur_plus as ulongint) as ulongint
sub pcg_oneseq_8_step_r(byval rng as pcg_state_8 ptr)
rng->state = (rng->state * 141u) + 77u
end sub
sub pcg_oneseq_8_advance_r(byval rng as pcg_state_8 ptr, byval delta as ubyte)
rng->state = pcg_advance_lcg_8(rng->state, delta, 141u, 77u)
end sub
sub pcg_mcg_8_step_r(byval rng as pcg_state_8 ptr)
rng->state = rng->state * 141u
end sub
sub pcg_mcg_8_advance_r(byval rng as pcg_state_8 ptr, byval delta as ubyte)
rng->state = pcg_advance_lcg_8(rng->state, delta, 141u, 0u)
end sub
sub pcg_unique_8_step_r(byval rng as pcg_state_8 ptr)
rng->state = (rng->state * 141u) + cubyte(cint(rng) or 1u)
end sub
sub pcg_unique_8_advance_r(byval rng as pcg_state_8 ptr, byval delta as ubyte)
rng->state = pcg_advance_lcg_8(rng->state, delta, 141u, cubyte(cint(rng) or 1u))
end sub
sub pcg_setseq_8_step_r(byval rng as pcg_state_setseq_8 ptr)
rng->state = (rng->state * 141u) + rng->inc
end sub
sub pcg_setseq_8_advance_r(byval rng as pcg_state_setseq_8 ptr, byval delta as ubyte)
rng->state = pcg_advance_lcg_8(rng->state, delta, 141u, rng->inc)
end sub
sub pcg_oneseq_16_step_r(byval rng as pcg_state_16 ptr)
rng->state = (rng->state * 12829u) + 47989u
end sub
sub pcg_oneseq_16_advance_r(byval rng as pcg_state_16 ptr, byval delta as ushort)
rng->state = pcg_advance_lcg_16(rng->state, delta, 12829u, 47989u)
end sub
sub pcg_mcg_16_step_r(byval rng as pcg_state_16 ptr)
rng->state = rng->state * 12829u
end sub
sub pcg_mcg_16_advance_r(byval rng as pcg_state_16 ptr, byval delta as ushort)
rng->state = pcg_advance_lcg_16(rng->state, delta, 12829u, 0u)
end sub
sub pcg_unique_16_step_r(byval rng as pcg_state_16 ptr)
rng->state = (rng->state * 12829u) + cushort(cint(rng) or 1u)
end sub
sub pcg_unique_16_advance_r(byval rng as pcg_state_16 ptr, byval delta as ushort)
rng->state = pcg_advance_lcg_16(rng->state, delta, 12829u, cushort(cint(rng) or 1u))
end sub
sub pcg_setseq_16_step_r(byval rng as pcg_state_setseq_16 ptr)
rng->state = (rng->state * 12829u) + rng->inc
end sub
sub pcg_setseq_16_advance_r(byval rng as pcg_state_setseq_16 ptr, byval delta as ushort)
rng->state = pcg_advance_lcg_16(rng->state, delta, 12829u, rng->inc)
end sub
sub pcg_oneseq_32_step_r(byval rng as pcg_state_32 ptr)
rng->state = (rng->state * 747796405u) + 2891336453u
end sub
sub pcg_oneseq_32_advance_r(byval rng as pcg_state_32 ptr, byval delta as ulong)
rng->state = pcg_advance_lcg_32(rng->state, delta, 747796405u, 2891336453u)
end sub
sub pcg_mcg_32_step_r(byval rng as pcg_state_32 ptr)
rng->state = rng->state * 747796405u
end sub
sub pcg_mcg_32_advance_r(byval rng as pcg_state_32 ptr, byval delta as ulong)
rng->state = pcg_advance_lcg_32(rng->state, delta, 747796405u, 0u)
end sub
sub pcg_unique_32_step_r(byval rng as pcg_state_32 ptr)
rng->state = (rng->state * 747796405u) + culng(cint(rng) or 1u)
end sub
sub pcg_unique_32_advance_r(byval rng as pcg_state_32 ptr, byval delta as ulong)
rng->state = pcg_advance_lcg_32(rng->state, delta, 747796405u, culng(cint(rng) or 1u))
end sub
sub pcg_setseq_32_step_r(byval rng as pcg_state_setseq_32 ptr)
rng->state = (rng->state * 747796405u) + rng->inc
end sub
sub pcg_setseq_32_advance_r(byval rng as pcg_state_setseq_32 ptr, byval delta as ulong)
rng->state = pcg_advance_lcg_32(rng->state, delta, 747796405u, rng->inc)
end sub
sub pcg_oneseq_64_step_r(byval rng as pcg_state_64 ptr)
rng->state = (rng->state * 6364136223846793005ull) + 1442695040888963407ull
end sub
sub pcg_oneseq_64_advance_r(byval rng as pcg_state_64 ptr, byval delta as ulongint)
rng->state = pcg_advance_lcg_64(rng->state, delta, 6364136223846793005ull, 1442695040888963407ull)
end sub
sub pcg_mcg_64_step_r(byval rng as pcg_state_64 ptr)
rng->state = rng->state * 6364136223846793005ull
end sub
sub pcg_mcg_64_advance_r(byval rng as pcg_state_64 ptr, byval delta as ulongint)
rng->state = pcg_advance_lcg_64(rng->state, delta, 6364136223846793005ull, 0u)
end sub
sub pcg_unique_64_step_r(byval rng as pcg_state_64 ptr)
rng->state = (rng->state * 6364136223846793005ull) + culngint(cint(rng) or 1u)
end sub
sub pcg_unique_64_advance_r(byval rng as pcg_state_64 ptr, byval delta as ulongint)
rng->state = pcg_advance_lcg_64(rng->state, delta, 6364136223846793005ull, culngint(cint(rng) or 1u))
end sub
sub pcg_setseq_64_step_r(byval rng as pcg_state_setseq_64 ptr)
rng->state = (rng->state * 6364136223846793005ull) + rng->inc
end sub
sub pcg_setseq_64_advance_r(byval rng as pcg_state_setseq_64 ptr, byval delta as ulongint)
rng->state = pcg_advance_lcg_64(rng->state, delta, 6364136223846793005ull, rng->inc)
end sub
sub pcg_oneseq_8_srandom_r(byval rng as pcg_state_8 ptr, byval initstate as ubyte)
rng->state = 0u
pcg_oneseq_8_step_r(rng)
rng->state += initstate
pcg_oneseq_8_step_r(rng)
end sub
sub pcg_mcg_8_srandom_r(byval rng as pcg_state_8 ptr, byval initstate as ubyte)
rng->state = initstate or 1u
end sub
sub pcg_unique_8_srandom_r(byval rng as pcg_state_8 ptr, byval initstate as ubyte)
rng->state = 0u
pcg_unique_8_step_r(rng)
rng->state += initstate
pcg_unique_8_step_r(rng)
end sub
sub pcg_setseq_8_srandom_r(byval rng as pcg_state_setseq_8 ptr, byval initstate as ubyte, byval initseq as ubyte)
rng->state = 0u
rng->inc = (initseq shl 1u) or 1u
pcg_setseq_8_step_r(rng)
rng->state += initstate
pcg_setseq_8_step_r(rng)
end sub
sub pcg_oneseq_16_srandom_r(byval rng as pcg_state_16 ptr, byval initstate as ushort)
rng->state = 0u
pcg_oneseq_16_step_r(rng)
rng->state += initstate
pcg_oneseq_16_step_r(rng)
end sub
sub pcg_mcg_16_srandom_r(byval rng as pcg_state_16 ptr, byval initstate as ushort)
rng->state = initstate or 1u
end sub
sub pcg_unique_16_srandom_r(byval rng as pcg_state_16 ptr, byval initstate as ushort)
rng->state = 0u
pcg_unique_16_step_r(rng)
rng->state += initstate
pcg_unique_16_step_r(rng)
end sub
sub pcg_setseq_16_srandom_r(byval rng as pcg_state_setseq_16 ptr, byval initstate as ushort, byval initseq as ushort)
rng->state = 0u
rng->inc = (initseq shl 1u) or 1u
pcg_setseq_16_step_r(rng)
rng->state += initstate
pcg_setseq_16_step_r(rng)
end sub
sub pcg_oneseq_32_srandom_r(byval rng as pcg_state_32 ptr, byval initstate as ulong)
rng->state = 0u
pcg_oneseq_32_step_r(rng)
rng->state += initstate
pcg_oneseq_32_step_r(rng)
end sub
sub pcg_mcg_32_srandom_r(byval rng as pcg_state_32 ptr, byval initstate as ulong)
rng->state = initstate or 1u
end sub
sub pcg_unique_32_srandom_r(byval rng as pcg_state_32 ptr, byval initstate as ulong)
rng->state = 0u
pcg_unique_32_step_r(rng)
rng->state += initstate
pcg_unique_32_step_r(rng)
end sub
sub pcg_setseq_32_srandom_r(byval rng as pcg_state_setseq_32 ptr, byval initstate as ulong, byval initseq as ulong)
rng->state = 0u
rng->inc = (initseq shl 1u) or 1u
pcg_setseq_32_step_r(rng)
rng->state += initstate
pcg_setseq_32_step_r(rng)
end sub
sub pcg_oneseq_64_srandom_r(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
rng->state = 0u
pcg_oneseq_64_step_r(rng)
rng->state += initstate
pcg_oneseq_64_step_r(rng)
end sub
sub pcg_mcg_64_srandom_r(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
rng->state = initstate or 1u
end sub
sub pcg_unique_64_srandom_r(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
rng->state = 0u
pcg_unique_64_step_r(rng)
rng->state += initstate
pcg_unique_64_step_r(rng)
end sub
sub pcg_setseq_64_srandom_r(byval rng as pcg_state_setseq_64 ptr, byval initstate as ulongint, byval initseq as ulongint)
rng->state = 0u
rng->inc = (initseq shl 1u) or 1u
pcg_setseq_64_step_r(rng)
rng->state += initstate
pcg_setseq_64_step_r(rng)
end sub
function pcg_oneseq_16_xsh_rs_8_random_r(byval rng as pcg_state_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_oneseq_16_step_r(rng)
return pcg_output_xsh_rs_16_8(oldstate)
end function
function pcg_oneseq_16_xsh_rs_8_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_oneseq_16_xsh_rs_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_32_xsh_rs_16_random_r(byval rng as pcg_state_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_oneseq_32_step_r(rng)
return pcg_output_xsh_rs_32_16(oldstate)
end function
function pcg_oneseq_32_xsh_rs_16_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_oneseq_32_xsh_rs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_64_xsh_rs_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_oneseq_64_step_r(rng)
return pcg_output_xsh_rs_64_32(oldstate)
end function
function pcg_oneseq_64_xsh_rs_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_oneseq_64_xsh_rs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_16_xsh_rs_8_random_r(byval rng as pcg_state_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_unique_16_step_r(rng)
return pcg_output_xsh_rs_16_8(oldstate)
end function
function pcg_unique_16_xsh_rs_8_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_unique_16_xsh_rs_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_32_xsh_rs_16_random_r(byval rng as pcg_state_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_unique_32_step_r(rng)
return pcg_output_xsh_rs_32_16(oldstate)
end function
function pcg_unique_32_xsh_rs_16_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_unique_32_xsh_rs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_64_xsh_rs_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_unique_64_step_r(rng)
return pcg_output_xsh_rs_64_32(oldstate)
end function
function pcg_unique_64_xsh_rs_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_unique_64_xsh_rs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_16_xsh_rs_8_random_r(byval rng as pcg_state_setseq_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_setseq_16_step_r(rng)
return pcg_output_xsh_rs_16_8(oldstate)
end function
function pcg_setseq_16_xsh_rs_8_boundedrand_r(byval rng as pcg_state_setseq_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_setseq_16_xsh_rs_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_32_xsh_rs_16_random_r(byval rng as pcg_state_setseq_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_setseq_32_step_r(rng)
return pcg_output_xsh_rs_32_16(oldstate)
end function
function pcg_setseq_32_xsh_rs_16_boundedrand_r(byval rng as pcg_state_setseq_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_setseq_32_xsh_rs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_64_xsh_rs_32_random_r(byval rng as pcg_state_setseq_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_setseq_64_step_r(rng)
return pcg_output_xsh_rs_64_32(oldstate)
end function
function pcg_setseq_64_xsh_rs_32_boundedrand_r(byval rng as pcg_state_setseq_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_setseq_64_xsh_rs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_16_xsh_rs_8_random_r(byval rng as pcg_state_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_mcg_16_step_r(rng)
return pcg_output_xsh_rs_16_8(oldstate)
end function
function pcg_mcg_16_xsh_rs_8_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_mcg_16_xsh_rs_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_32_xsh_rs_16_random_r(byval rng as pcg_state_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_mcg_32_step_r(rng)
return pcg_output_xsh_rs_32_16(oldstate)
end function
function pcg_mcg_32_xsh_rs_16_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_mcg_32_xsh_rs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_64_xsh_rs_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_mcg_64_step_r(rng)
return pcg_output_xsh_rs_64_32(oldstate)
end function
function pcg_mcg_64_xsh_rs_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_mcg_64_xsh_rs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_16_xsh_rr_8_random_r(byval rng as pcg_state_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_oneseq_16_step_r(rng)
return pcg_output_xsh_rr_16_8(oldstate)
end function
function pcg_oneseq_16_xsh_rr_8_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_oneseq_16_xsh_rr_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_32_xsh_rr_16_random_r(byval rng as pcg_state_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_oneseq_32_step_r(rng)
return pcg_output_xsh_rr_32_16(oldstate)
end function
function pcg_oneseq_32_xsh_rr_16_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_oneseq_32_xsh_rr_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_64_xsh_rr_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_oneseq_64_step_r(rng)
return pcg_output_xsh_rr_64_32(oldstate)
end function
function pcg_oneseq_64_xsh_rr_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_oneseq_64_xsh_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_16_xsh_rr_8_random_r(byval rng as pcg_state_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_unique_16_step_r(rng)
return pcg_output_xsh_rr_16_8(oldstate)
end function
function pcg_unique_16_xsh_rr_8_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_unique_16_xsh_rr_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_32_xsh_rr_16_random_r(byval rng as pcg_state_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_unique_32_step_r(rng)
return pcg_output_xsh_rr_32_16(oldstate)
end function
function pcg_unique_32_xsh_rr_16_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_unique_32_xsh_rr_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_64_xsh_rr_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_unique_64_step_r(rng)
return pcg_output_xsh_rr_64_32(oldstate)
end function
function pcg_unique_64_xsh_rr_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_unique_64_xsh_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_16_xsh_rr_8_random_r(byval rng as pcg_state_setseq_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_setseq_16_step_r(rng)
return pcg_output_xsh_rr_16_8(oldstate)
end function
function pcg_setseq_16_xsh_rr_8_boundedrand_r(byval rng as pcg_state_setseq_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_setseq_16_xsh_rr_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_32_xsh_rr_16_random_r(byval rng as pcg_state_setseq_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_setseq_32_step_r(rng)
return pcg_output_xsh_rr_32_16(oldstate)
end function
function pcg_setseq_32_xsh_rr_16_boundedrand_r(byval rng as pcg_state_setseq_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_setseq_32_xsh_rr_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_64_xsh_rr_32_random_r(byval rng as pcg_state_setseq_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_setseq_64_step_r(rng)
return pcg_output_xsh_rr_64_32(oldstate)
end function
function pcg_setseq_64_xsh_rr_32_boundedrand_r(byval rng as pcg_state_setseq_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_setseq_64_xsh_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_16_xsh_rr_8_random_r(byval rng as pcg_state_16 ptr) as ubyte
dim oldstate as ushort = rng->state
pcg_mcg_16_step_r(rng)
return pcg_output_xsh_rr_16_8(oldstate)
end function
function pcg_mcg_16_xsh_rr_8_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_mcg_16_xsh_rr_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_32_xsh_rr_16_random_r(byval rng as pcg_state_32 ptr) as ushort
dim oldstate as ulong = rng->state
pcg_mcg_32_step_r(rng)
return pcg_output_xsh_rr_32_16(oldstate)
end function
function pcg_mcg_32_xsh_rr_16_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_mcg_32_xsh_rr_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_64_xsh_rr_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_mcg_64_step_r(rng)
return pcg_output_xsh_rr_64_32(oldstate)
end function
function pcg_mcg_64_xsh_rr_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_mcg_64_xsh_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_8_rxs_m_xs_8_random_r(byval rng as pcg_state_8 ptr) as ubyte
dim oldstate as ubyte = rng->state
pcg_oneseq_8_step_r(rng)
return pcg_output_rxs_m_xs_8_8(oldstate)
end function
function pcg_oneseq_8_rxs_m_xs_8_boundedrand_r(byval rng as pcg_state_8 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_oneseq_8_rxs_m_xs_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_16_rxs_m_xs_16_random_r(byval rng as pcg_state_16 ptr) as ushort
dim oldstate as ushort = rng->state
pcg_oneseq_16_step_r(rng)
return pcg_output_rxs_m_xs_16_16(oldstate)
end function
function pcg_oneseq_16_rxs_m_xs_16_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_oneseq_16_rxs_m_xs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_32_rxs_m_xs_32_random_r(byval rng as pcg_state_32 ptr) as ulong
dim oldstate as ulong = rng->state
pcg_oneseq_32_step_r(rng)
return pcg_output_rxs_m_xs_32_32(oldstate)
end function
function pcg_oneseq_32_rxs_m_xs_32_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_oneseq_32_rxs_m_xs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_64_rxs_m_xs_64_random_r(byval rng as pcg_state_64 ptr) as ulongint
dim oldstate as ulongint = rng->state
pcg_oneseq_64_step_r(rng)
return pcg_output_rxs_m_xs_64_64(oldstate)
end function
function pcg_oneseq_64_rxs_m_xs_64_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulongint) as ulongint
dim threshold as ulongint = (-bound) mod bound
do
dim as ulongint r = pcg_oneseq_64_rxs_m_xs_64_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_16_rxs_m_xs_16_random_r(byval rng as pcg_state_16 ptr) as ushort
dim oldstate as ushort = rng->state
pcg_unique_16_step_r(rng)
return pcg_output_rxs_m_xs_16_16(oldstate)
end function
function pcg_unique_16_rxs_m_xs_16_boundedrand_r(byval rng as pcg_state_16 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_unique_16_rxs_m_xs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_32_rxs_m_xs_32_random_r(byval rng as pcg_state_32 ptr) as ulong
dim oldstate as ulong = rng->state
pcg_unique_32_step_r(rng)
return pcg_output_rxs_m_xs_32_32(oldstate)
end function
function pcg_unique_32_rxs_m_xs_32_boundedrand_r(byval rng as pcg_state_32 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_unique_32_rxs_m_xs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_64_rxs_m_xs_64_random_r(byval rng as pcg_state_64 ptr) as ulongint
dim oldstate as ulongint = rng->state
pcg_unique_64_step_r(rng)
return pcg_output_rxs_m_xs_64_64(oldstate)
end function
function pcg_unique_64_rxs_m_xs_64_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulongint) as ulongint
dim threshold as ulongint = (-bound) mod bound
do
dim as ulongint r = pcg_unique_64_rxs_m_xs_64_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_8_rxs_m_xs_8_random_r(byval rng as pcg_state_setseq_8 ptr) as ubyte
dim oldstate as ubyte = rng->state
pcg_setseq_8_step_r(rng)
return pcg_output_rxs_m_xs_8_8(oldstate)
end function
function pcg_setseq_8_rxs_m_xs_8_boundedrand_r(byval rng as pcg_state_setseq_8 ptr, byval bound as ubyte) as ubyte
dim threshold as ubyte = cubyte(-bound) mod bound
do
dim as ubyte r = pcg_setseq_8_rxs_m_xs_8_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_16_rxs_m_xs_16_random_r(byval rng as pcg_state_setseq_16 ptr) as ushort
dim oldstate as ushort = rng->state
pcg_setseq_16_step_r(rng)
return pcg_output_rxs_m_xs_16_16(oldstate)
end function
function pcg_setseq_16_rxs_m_xs_16_boundedrand_r(byval rng as pcg_state_setseq_16 ptr, byval bound as ushort) as ushort
dim threshold as ushort = cushort(-bound) mod bound
do
dim as ushort r = pcg_setseq_16_rxs_m_xs_16_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_32_rxs_m_xs_32_random_r(byval rng as pcg_state_setseq_32 ptr) as ulong
dim oldstate as ulong = rng->state
pcg_setseq_32_step_r(rng)
return pcg_output_rxs_m_xs_32_32(oldstate)
end function
function pcg_setseq_32_rxs_m_xs_32_boundedrand_r(byval rng as pcg_state_setseq_32 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_setseq_32_rxs_m_xs_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_64_rxs_m_xs_64_random_r(byval rng as pcg_state_setseq_64 ptr) as ulongint
dim oldstate as ulongint = rng->state
pcg_setseq_64_step_r(rng)
return pcg_output_rxs_m_xs_64_64(oldstate)
end function
function pcg_setseq_64_rxs_m_xs_64_boundedrand_r(byval rng as pcg_state_setseq_64 ptr, byval bound as ulongint) as ulongint
dim threshold as ulongint = (-bound) mod bound
do
dim as ulongint r = pcg_setseq_64_rxs_m_xs_64_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_64_xsl_rr_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_oneseq_64_step_r(rng)
return pcg_output_xsl_rr_64_32(oldstate)
end function
function pcg_oneseq_64_xsl_rr_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_oneseq_64_xsl_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_64_xsl_rr_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_unique_64_step_r(rng)
return pcg_output_xsl_rr_64_32(oldstate)
end function
function pcg_unique_64_xsl_rr_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_unique_64_xsl_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_64_xsl_rr_32_random_r(byval rng as pcg_state_setseq_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_setseq_64_step_r(rng)
return pcg_output_xsl_rr_64_32(oldstate)
end function
function pcg_setseq_64_xsl_rr_32_boundedrand_r(byval rng as pcg_state_setseq_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_setseq_64_xsl_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_mcg_64_xsl_rr_32_random_r(byval rng as pcg_state_64 ptr) as ulong
dim oldstate as ulongint = rng->state
pcg_mcg_64_step_r(rng)
return pcg_output_xsl_rr_64_32(oldstate)
end function
function pcg_mcg_64_xsl_rr_32_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
dim threshold as ulong = (-bound) mod bound
do
dim as ulong r = pcg_mcg_64_xsl_rr_32_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_oneseq_64_xsl_rr_rr_64_random_r(byval rng as pcg_state_64 ptr) as ulongint
dim oldstate as ulongint = rng->state
pcg_oneseq_64_step_r(rng)
return pcg_output_xsl_rr_rr_64_64(oldstate)
end function
function pcg_oneseq_64_xsl_rr_rr_64_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulongint) as ulongint
dim threshold as ulongint = (-bound) mod bound
do
dim as ulongint r = pcg_oneseq_64_xsl_rr_rr_64_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_unique_64_xsl_rr_rr_64_random_r(byval rng as pcg_state_64 ptr) as ulongint
dim oldstate as ulongint = rng->state
pcg_unique_64_step_r(rng)
return pcg_output_xsl_rr_rr_64_64(oldstate)
end function
function pcg_unique_64_xsl_rr_rr_64_boundedrand_r(byval rng as pcg_state_64 ptr, byval bound as ulongint) as ulongint
dim threshold as ulongint = (-bound) mod bound
do
dim as ulongint r = pcg_unique_64_xsl_rr_rr_64_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
function pcg_setseq_64_xsl_rr_rr_64_random_r(byval rng as pcg_state_setseq_64 ptr) as ulongint
dim oldstate as ulongint = rng->state
pcg_setseq_64_step_r(rng)
return pcg_output_xsl_rr_rr_64_64(oldstate)
end function
function pcg_setseq_64_xsl_rr_rr_64_boundedrand_r(byval rng as pcg_state_setseq_64 ptr, byval bound as ulongint) as ulongint
dim threshold as ulongint = (-bound) mod bound
do
dim as ulongint r = pcg_setseq_64_xsl_rr_rr_64_random_r(rng)
if (r >= threshold) then return r mod bound
loop
end function
type pcg32_random_t as pcg_state_setseq_64
type pcg32s_random_t as pcg_state_64
type pcg32u_random_t as pcg_state_64
type pcg32f_random_t as pcg_state_64
declare function pcg32_random_r alias "pcg_setseq_64_xsh_rr_32_random_r"(byval rng as pcg_state_setseq_64 ptr) as ulong
declare function pcg32s_random_r alias "pcg_oneseq_64_xsh_rr_32_random_r"(byval rng as pcg_state_64 ptr) as ulong
declare function pcg32u_random_r alias "pcg_unique_64_xsh_rr_32_random_r"(byval rng as pcg_state_64 ptr) as ulong
declare function pcg32f_random_r alias "pcg_mcg_64_xsh_rs_32_random_r"(byval rng as pcg_state_64 ptr) as ulong
declare function pcg32_boundedrand_r alias "pcg_setseq_64_xsh_rr_32_boundedrand_r"(byval rng as pcg_state_setseq_64 ptr, byval bound as ulong) as ulong
declare function pcg32s_boundedrand_r alias "pcg_oneseq_64_xsh_rr_32_boundedrand_r"(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
declare function pcg32u_boundedrand_r alias "pcg_unique_64_xsh_rr_32_boundedrand_r"(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
declare function pcg32f_boundedrand_r alias "pcg_mcg_64_xsh_rs_32_boundedrand_r"(byval rng as pcg_state_64 ptr, byval bound as ulong) as ulong
declare sub pcg32_srandom_r alias "pcg_setseq_64_srandom_r"(byval rng as pcg_state_setseq_64 ptr, byval initstate as ulongint, byval initseq as ulongint)
declare sub pcg32s_srandom_r alias "pcg_oneseq_64_srandom_r"(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
declare sub pcg32u_srandom_r alias "pcg_unique_64_srandom_r"(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
declare sub pcg32f_srandom_r alias "pcg_mcg_64_srandom_r"(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
declare sub pcg32_advance_r alias "pcg_setseq_64_advance_r"(byval rng as pcg_state_setseq_64 ptr, byval delta as ulongint)
declare sub pcg32s_advance_r alias "pcg_oneseq_64_advance_r"(byval rng as pcg_state_64 ptr, byval delta as ulongint)
declare sub pcg32u_advance_r alias "pcg_unique_64_advance_r"(byval rng as pcg_state_64 ptr, byval delta as ulongint)
declare sub pcg32f_advance_r alias "pcg_mcg_64_advance_r"(byval rng as pcg_state_64 ptr, byval delta as ulongint)
type pcg8si_random_t as pcg_state_8
type pcg16si_random_t as pcg_state_16
type pcg32si_random_t as pcg_state_32
type pcg64si_random_t as pcg_state_64
declare function pcg8si_random_r alias "pcg_oneseq_8_rxs_m_xs_8_random_r"(byval rng as pcg_state_8 ptr) as ubyte
declare function pcg16si_random_r alias "pcg_oneseq_16_rxs_m_xs_16_random_r"(byval rng as pcg_state_16 ptr) as ushort
declare function pcg32si_random_r alias "pcg_oneseq_32_rxs_m_xs_32_random_r"(byval rng as pcg_state_32 ptr) as ulong
declare function pcg64si_random_r alias "pcg_oneseq_64_rxs_m_xs_64_random_r"(byval rng as pcg_state_64 ptr) as ulongint
declare function pcg8si_boundedrand_r alias "pcg_oneseq_8_rxs_m_xs_8_boundedrand_r"(byval rng as pcg_state_8 ptr, byval bound as ubyte) as ubyte
declare function pcg16si_boundedrand_r alias "pcg_oneseq_16_rxs_m_xs_16_boundedrand_r"(byval rng as pcg_state_16 ptr, byval bound as ushort) as ushort
declare function pcg32si_boundedrand_r alias "pcg_oneseq_32_rxs_m_xs_32_boundedrand_r"(byval rng as pcg_state_32 ptr, byval bound as ulong) as ulong
declare function pcg64si_boundedrand_r alias "pcg_oneseq_64_rxs_m_xs_64_boundedrand_r"(byval rng as pcg_state_64 ptr, byval bound as ulongint) as ulongint
declare sub pcg8si_srandom_r alias "pcg_oneseq_8_srandom_r"(byval rng as pcg_state_8 ptr, byval initstate as ubyte)
declare sub pcg16si_srandom_r alias "pcg_oneseq_16_srandom_r"(byval rng as pcg_state_16 ptr, byval initstate as ushort)
declare sub pcg32si_srandom_r alias "pcg_oneseq_32_srandom_r"(byval rng as pcg_state_32 ptr, byval initstate as ulong)
declare sub pcg64si_srandom_r alias "pcg_oneseq_64_srandom_r"(byval rng as pcg_state_64 ptr, byval initstate as ulongint)
declare sub pcg8si_advance_r alias "pcg_oneseq_8_advance_r"(byval rng as pcg_state_8 ptr, byval delta as ubyte)
declare sub pcg16si_advance_r alias "pcg_oneseq_16_advance_r"(byval rng as pcg_state_16 ptr, byval delta as ushort)
declare sub pcg32si_advance_r alias "pcg_oneseq_32_advance_r"(byval rng as pcg_state_32 ptr, byval delta as ulong)
declare sub pcg64si_advance_r alias "pcg_oneseq_64_advance_r"(byval rng as pcg_state_64 ptr, byval delta as ulongint)
type pcg8i_random_t as pcg_state_setseq_8
type pcg16i_random_t as pcg_state_setseq_16
type pcg32i_random_t as pcg_state_setseq_32
type pcg64i_random_t as pcg_state_setseq_64
declare function pcg8i_random_r alias "pcg_setseq_8_rxs_m_xs_8_random_r"(byval rng as pcg_state_setseq_8 ptr) as ubyte
declare function pcg16i_random_r alias "pcg_setseq_16_rxs_m_xs_16_random_r"(byval rng as pcg_state_setseq_16 ptr) as ushort
declare function pcg32i_random_r alias "pcg_setseq_32_rxs_m_xs_32_random_r"(byval rng as pcg_state_setseq_32 ptr) as ulong
declare function pcg64i_random_r alias "pcg_setseq_64_rxs_m_xs_64_random_r"(byval rng as pcg_state_setseq_64 ptr) as ulongint
declare function pcg8i_boundedrand_r alias "pcg_setseq_8_rxs_m_xs_8_boundedrand_r"(byval rng as pcg_state_setseq_8 ptr, byval bound as ubyte) as ubyte
declare function pcg16i_boundedrand_r alias "pcg_setseq_16_rxs_m_xs_16_boundedrand_r"(byval rng as pcg_state_setseq_16 ptr, byval bound as ushort) as ushort
declare function pcg32i_boundedrand_r alias "pcg_setseq_32_rxs_m_xs_32_boundedrand_r"(byval rng as pcg_state_setseq_32 ptr, byval bound as ulong) as ulong
declare function pcg64i_boundedrand_r alias "pcg_setseq_64_rxs_m_xs_64_boundedrand_r"(byval rng as pcg_state_setseq_64 ptr, byval bound as ulongint) as ulongint
declare sub pcg8i_srandom_r alias "pcg_setseq_8_srandom_r"(byval rng as pcg_state_setseq_8 ptr, byval initstate as ubyte, byval initseq as ubyte)
declare sub pcg16i_srandom_r alias "pcg_setseq_16_srandom_r"(byval rng as pcg_state_setseq_16 ptr, byval initstate as ushort, byval initseq as ushort)
declare sub pcg32i_srandom_r alias "pcg_setseq_32_srandom_r"(byval rng as pcg_state_setseq_32 ptr, byval initstate as ulong, byval initseq as ulong)
declare sub pcg64i_srandom_r alias "pcg_setseq_64_srandom_r"(byval rng as pcg_state_setseq_64 ptr, byval initstate as ulongint, byval initseq as ulongint)
declare sub pcg8i_advance_r alias "pcg_setseq_8_advance_r"(byval rng as pcg_state_setseq_8 ptr, byval delta as ubyte)
declare sub pcg16i_advance_r alias "pcg_setseq_16_advance_r"(byval rng as pcg_state_setseq_16 ptr, byval delta as ushort)
declare sub pcg32i_advance_r alias "pcg_setseq_32_advance_r"(byval rng as pcg_state_setseq_32 ptr, byval delta as ulong)
declare sub pcg64i_advance_r alias "pcg_setseq_64_advance_r"(byval rng as pcg_state_setseq_64 ptr, byval delta as ulongint)
declare function pcg32_random() as ulong
declare function pcg32_boundedrand(byval bound as ulong) as ulong
declare sub pcg32_srandom(byval seed as ulongint, byval seq as ulongint)
declare sub pcg32_advance(byval delta as ulongint)
#define PCG_STATE_SETSEQ_8_INITIALIZER (&h9bu, &hdbu)
#define PCG_STATE_SETSEQ_16_INITIALIZER (&he39bu, &h5bdbu)
#define PCG_STATE_SETSEQ_32_INITIALIZER (&hec02d89bu, &h94b95bdbu)
#define PCG_STATE_SETSEQ_64_INITIALIZER (&h853c49e6748fea9bull, &hda3e39cb94b95bdbull)
#define PCG32_INITIALIZER PCG_STATE_SETSEQ_64_INITIALIZER
#define PCG32U_INITIALIZER PCG_STATE_UNIQUE_64_INITIALIZER
#define PCG32S_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER
#define PCG32F_INITIALIZER PCG_STATE_MCG_64_INITIALIZER
end extern
Code: Select all
/'
* PCG Random Number Generation for C.
*
* Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* For additional information about the PCG random number generation scheme,
* including its license and other licensing options, visit
*
* http://www.pcg-random.org
'/
/'
* This code is derived from the canonical C++ PCG implementation, which
* has many additional features and is preferable if you can use C++ in
* your project.
*
* Repetative C code is derived using C preprocessor metaprogramming
* techniques.
'/
'translated to FreeBASIC using fbfrog https://github.com/dkl/fbfrog
#pragma once
#include once "pcg_variants.bi"
/' Multi-step advance functions (jump-ahead, jump-back)
*
* The method used here is based on Brown, "Random Number Generation
* with Arbitrary Stride,", Transactions of the American Nuclear
* Society (Nov. 1994). The algorithm is very similar to fast
* exponentiation.
*
* Even though delta is an unsigned integer, we can pass a
* signed integer to go backwards, it just goes "the long way round".
'/
extern "C"
function pcg_advance_lcg_8(byval state as ubyte, byval delta as ubyte, byval cur_mult as ubyte, byval cur_plus as ubyte) as ubyte
dim acc_mult as ubyte = 1u
dim acc_plus as ubyte = 0u
while delta > 0
if delta and 1 then
acc_mult *= cur_mult
acc_plus = (acc_plus * cur_mult) + cur_plus
end if
cur_plus = (cur_mult + 1) * cur_plus
cur_mult *= cur_mult
delta /= 2
wend
return (acc_mult * state) + acc_plus
end function
function pcg_advance_lcg_16(byval state as ushort, byval delta as ushort, byval cur_mult as ushort, byval cur_plus as ushort) as ushort
dim acc_mult as ushort = 1u
dim acc_plus as ushort = 0u
while delta > 0
if delta and 1 then
acc_mult *= cur_mult
acc_plus = (acc_plus * cur_mult) + cur_plus
end if
cur_plus = (cur_mult + 1) * cur_plus
cur_mult *= cur_mult
delta /= 2
wend
return (acc_mult * state) + acc_plus
end function
function pcg_advance_lcg_32(byval state as ulong, byval delta as ulong, byval cur_mult as ulong, byval cur_plus as ulong) as ulong
dim acc_mult as ulong = 1u
dim acc_plus as ulong = 0u
while delta > 0
if delta and 1 then
acc_mult *= cur_mult
acc_plus = (acc_plus * cur_mult) + cur_plus
end if
cur_plus = (cur_mult + 1) * cur_plus
cur_mult *= cur_mult
delta /= 2
wend
return (acc_mult * state) + acc_plus
end function
function pcg_advance_lcg_64(byval state as ulongint, byval delta as ulongint, byval cur_mult as ulongint, byval cur_plus as ulongint) as ulongint
dim acc_mult as ulongint = 1u
dim acc_plus as ulongint = 0u
while delta > 0
if delta and 1 then
acc_mult *= cur_mult
acc_plus = (acc_plus * cur_mult) + cur_plus
end if
cur_plus = (cur_mult + 1) * cur_plus
cur_mult *= cur_mult
delta /= 2
wend
return (acc_mult * state) + acc_plus
end function
end extern
Re: Has anyone ported the PCG PRNG to FreeBASIC
small test
note that the function pcg32_advance_r does not work as in the C version, the function is declared as
but in the example a negative value is passed to delta which works in C but not in FB
<edit> in case you did't know, the "print Again:" code is supposed to print the same numbers as the previous output just above"
note that the function pcg32_advance_r does not work as in the C version, the function is declared as
Code: Select all
declare sub pcg32_advance_r alias "pcg_setseq_64_advance_r"(byval rng as pcg_state_setseq_64 ptr, byval delta as ulongint)
<edit> in case you did't know, the "print Again:" code is supposed to print the same numbers as the previous output just above"
Code: Select all
#include once "pcg-advance.bas"
dim rounds as long = 5
dim as pcg32_random_t rng
pcg_setseq_64_srandom_r(@rng, 42u, 54u)
print "pcg32_random_r:"
print " - result: 32-bit unsigned int (uint32_t)"
print " - period: 2^64 (* 2^63 streams)"
print " - state type: pcg32_random_t (";sizeof(pcg32_random_t);" bytes)"
print " - output func: XSH-RR"
print
For round As Integer = 1 To rounds
print "Round "; round
print " 32bit: ";
For i As Integer = 0 To 5
print "0x";hex(pcg32_random_r(@rng),8);" ";
next
print
'pcg32_advance_r(@rng, -6) does not work, replace #if 0 with #if 1 to test
#if 0
print " Again: ";
pcg32_advance_r(@rng, -6)
For i As Integer = 0 To 5
print "0x";hex(pcg32_random_r(@rng),8);" ";
next
print
#endif
print " Coins: ";
For i As Integer = 0 To 64
print iif(pcg32_boundedrand_r(@rng, 2) ,"H" , "T");
next
print
print" Rolls:";
For i As Integer = 0 To 32
print cast(long,pcg32_boundedrand_r(@rng, 6) + 1);
next
print
next
Last edited by srvaldez on Jun 06, 2017 14:41, edited 2 times in total.
Re: Has anyone ported the PCG PRNG to FreeBASIC
Wow! Thanks, srvaldez!
I'll look at it tonight.
CBruce
I'll look at it tonight.
CBruce
-
- Posts: 4292
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: Has anyone ported the PCG PRNG to FreeBASIC
@srvaldez
Hi, when you created pcg_variants.bi did you edit out all the 128 bits stuff? I couldn't find any 128 bit functions and also noticed that pcg_variants.h has about twice as many lines as pcg_variants.bi.
Cheers
Hi, when you created pcg_variants.bi did you edit out all the 128 bits stuff? I couldn't find any 128 bit functions and also noticed that pcg_variants.h has about twice as many lines as pcg_variants.bi.
Cheers