- Notifications
You must be signed in to change notification settings - Fork6
FAST 32/64 bit PRNG (pseudo-random generator), highly optimized, based on xoshiro* / xoroshiro*, xorshift and other Marsaglia algorithms.
License
BrutPitt/fastPRNG
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
fastPRNG is a single header-only FAST 32/64 bit PRNG (pseudo-random generator), highly optimized to obtain faster code from compilers, it's based onxoshiro /xoroshiro (Blackman/Vigna),xorshift and otherMarsaglia algorithms.
- Blackman/Vigna
- xoshiro256+ / xoshiro256++ / xoshiro256**
- xoroshiro128+ / xoroshiro128++ / xoroshiro128**
- Marsaglia
- xorshift
- znew / wnew / MWC / CNG / FIB / XSH / KISS
- Blackman/Vigna
- xoshiro128+ / xoshiro128++ / xoshiro128**
- xoroshiro64+ / xoroshiro64++
- Marsaglia
- xorshift
- znew / wnew / MWC / CNG / FIB / XSH / KISS
- LFIB4 / SWB
All functions are tested, below the distribution test screenshots in a cube with [-1.0, 1.0] side (OpenGL/WebGL)
30M dots/spheres | 30M dots/spheres clipping planes | 3 thin boards from 30M cube dots/spheres |
---|---|---|
![]() | ![]() | ![]() |
==> *view theLive WebGL distribution test section.
All base functions return integers:
- 32bit ==>
uint32_t
in[0, UINT32_MAX]
interval - 64bit ==>
uint64_t
in[0, UINT64_MAX]
interval.
*If you need (e.g.) values between[INT32_MIN, INT32_MAX]
, just cast result toint32_t
, same for 64bit (cast toint64_t
): look at the examples below
Floating point helpers
- There are a single/double precisionfloating point template functions, to generate fast numbers in:
(they have same base name, but with the following suffix)[-1.0, 1.0]
interval ==> suffix_VNI<T> (Vector Normalized Interval)[ 0.0, 1.0]
interval ==> suffix_UNI<T> (Unity Normalized Interval)[ min, max]
interval ==> suffix_Range<T>(min, max)
*look at the examples below
To use it just includefastPRNG.h
in your code:
#include"fastPRNG.h"
It contains following classes and member functions, inside the namespacefastPRNG
:
- fastXS64 ==> contains xor-shift algorithms
- xoshiro256p / xoshiro256pp / xoshiro256xx
- xoroshiro128p / xoroshiro128pp / xoroshiro128xx
- xorShift
- fastXS64s ==> same as before, but class with static members, to use directly w/o declaration
- fastXS64s::xoshiro256p / fastXS64s::xoshiro256pp / fastXS64s::xoshiro256xx
- fastXS64s::xoroshiro128p / fastXS64s::xoroshiro128pp / fastXS64s::xoroshiro128xx
- fastXS64s::xorShift
- fastRand64 ==> other Marsaglia algorithms
- znew / wnew / MWC / CNG / FIB / XSH / KISS
- fastXS32 ==> contains xor-shift algorithms
- xoshiro128p / xoshiro128pp / xoshiro128xx
- xoroshiro64p / xoroshiro64pp
- xorShift
- fastXS32s ==> same as before, but class with static members, to use directly w/o declaration
- fastXS32s::xoshiro128p / fastXS32s::xoshiro128pp / fastXS32s::xoshiro128xx
- fastXS32s::xoroshiro64p / fastXS32s::xoroshiro64pp
- fastXS32s::xorShift
- fastRand32 ==> other Marsaglia algorithms
- znew / wnew / MWC / CNG / FIB / XSH / KISS
- LFIB4 / SWB
- Example: use xoshiro256+ 64bit algorithm:
using fastPRNG; fastXS64 fastR;// default "chrono" seed// fastXS64 fastR(0x123456789ABCDEF0); // personal seed also to (re)generate a specific random numbers sequencefor(int i=0; i<10000; i++) { cout << fastR.xoshiro256p() << endl;// returns number in [0, UINT64_MAX] interval cout <<int64_t(fastR.xoshiro256p()) << endl;// returns number in [INT64_MIN, INT32_MAX] interval cout << fastR.xoshiro256p_VNI<float>()) << endl;// returns number in [-1.0, 1.0] interval in single precision cout << fastR.xoshiro256p_UNI<float>()) << endl;// returns number in [ 0.0, 1.0] interval in single precision cout << fastR.xoshiro256p_Range<double>(-3.0,7.0)) << endl;// returns number in [-3.0, 7.0] interval in double precision }// N.B. all members/functions share same seed and subsequent xor & shift operations on it.// it is usually not a problem, but if need different seeds (or separate PRNG) have to declare// more/different fastXS64 objects// or you can also use static members from fastXS64s class w/o declaration: the seed is always "chrono"for(int i=0; i<10000; i++) { cout <<fastXS64s::xoshiro256p() << endl;// returns number in [0, UINT64_MAX] interval cout <<int64_t(fastXS64s::xoshiro256p()) << endl;// returns number in [INT64_MIN, INT32_MAX] interval cout << fastXS64s::xoshiro256p_VNI<float>()) << endl;// returns number in [-1.0, 1.0] interval in single precision from 64bit PRNG cout << fastXS64s::xoshiro256p_UNI<float>()) << endl;// returns number in [ 0.0, 1.0] interval in single precision from 64bit PRNG cout << fastXS64s::xoshiro256p_Range<double>(-5.0,5.0)) << endl;// returns number in [-5.0, 5.0] interval in double precision from 64bit PRNG }// N.B. all members/functions share same seed, and subsequent xor & shift operations on it.// it is usually not a problem, but if need different seeds (or separate PRNG) have to use// fastXS64 (non static) class, and have to declare different fastXS64 objects.// static declaration of a non static class (e.g. if you need to initialize it to specific seed)for(int i=0; i<10000; i++) {static fastXS64fastR(0x123456789ABCDEF0);// personal seed also to (re)generate a specific random numbers sequence cout << fastR.xoshiro256p() << endl;// returns number in [0, UINT64_MAX] interval cout <<int64_t(fastR.xoshiro256p()) << endl;// returns number in [INT64_MIN, INT32_MAX] interval cout << fastR.xoshiro256p_VNI<float>()) << endl;// returns number in [-1.0, 1.0] interval in single precision cout << fastR.xoshiro256p_UNI<float>()) << endl;// returns number in [ 0.0, 1.0] interval in single precision cout << fastR.xoshiro256p_Range<double>(-3.0,7.0)) << endl;// returns number in [-3.0, 7.0] interval in double precision }
- Example: use KISS 32bit algorithm:
fastPRNG::fastRand32 fastRandom;// for 32bit// fstRnd::fastRand32 fastRandom(0x12345678); or with seed initialization: to (re)generate a specific random numbers sequencefor(int i=0; i<10000; i++) { cout << fastRandom.KISS() << endl;// returns number in [0, UINT32_MAX] interval cout <<int32_t(fastRandom.KISS()) << endl;// returns number in [INT32_MIN, INT32_MAX] interval cout << fastRandom.KISS_VNI<float>()) << endl;// returns number in [-1.0, 1.0] interval in single precision from 32bit PRNG cout << fastRandom.KISS_UNI<float>()) << endl;// returns number in [ 0.0, 1.0] interval in single precision from 32bit PRNG cout << fastRandom.KISS_Range<double>(-3.0,7.0)) << endl;// returns number in [-3.0, 7.0] interval in from 32bit PRNG }
- Any class object can to re-initialized with a new seed calling
seed()
fastPRNG::fastXS32fastR(0x12345678);// seed to specific valuefor(int i=0; i<10000; i++) cout << fastR.xoshiro256p() << endl;// returns number in [0, UINT64_MAX] interval fastR.seed(0x12345678);// same seed to obtain same sequencefor(int i=0; i<10000; i++) cout << fastR.xoshiro256p() << endl;// returns same number sequence in [0, UINT64_MAX] interval fastR.seed();// new seed to 'chrono" to obtain different sequencefor(int i=0; i<10000; i++) cout << fastR.xoshiro256p() << endl;// returns number in [0, UINT64_MAX] interval
*classesfastXS32s andfastXS64s don't haveseed()
function: they have/are only static members.
For more details look at the source file: it's well documented.
Classes and functions are currently used
- glChAoS.P / wglChAoS.P Realtime 3D GPUs Strange Attractors and Hypercomplex Fractals scout
Hypercomplex fractals with stochastic IIM (Inverse Iteration Method) algorithm | DLA 3D (Diffusion Limited Aggregation) algorithm |
---|---|
![]() | ![]() |
- DLAf-optimized fast DLA (Diffusion Limited Aggregation) 2D/3D
All functions are tested, below the distribution test in a cube with [-1.0, 1.0] side.
LiveWebGL 2 /WebAssemly ==>fastPRNG distribution test
*Only FireFox and Chromium based web-browsers (Chrome / Opera / new Edge / etc.) are supported
30M dots/spheres cube | 30M dots/spheres cube with clipping planes | 3 thin boards from 30M dots cube |
---|---|---|
![]() | ![]() | ![]() |
thin board from a 10M dots cube | 2.5M dots/spheres with clipping planes | 3 thin boards from 5M dots cube |
![]() | ![]() | ![]() |
*It's builded on the rendering particles engine ofglChAoS.P / wglChAoS.P
*N.B.it's a distribution test,NOT a speed/benchmark test, since the rendering time/calculus is preeminent
TheJavaScript /WebGL version is slower of Desktop one, so the test starts with 2.5M of particles, and a pre-allocatedmaxbuffer
of 15M (for slow / low memory GPUs)
Particles panel
A) Start / Stop particles emitter
B) Continue / FullStop: continue endless (circular buffer) / stop when buffer is full
C) Endless / Restart: rewrite circular buffer / restart deleting all circular buffer
D) Set circular buffer size (drag with mouse)
from .01M (10'000) tomaxbuffer
(default 15M pre-allocated) particles
*You can resize pre-allocated buffer changing the URL value ofmaxbuffer
(in your browser address box)(e.g.maxbuffer=30
pre allocate a 30M particles memory buffer)
If you want use the desktop version (available for Windows / Linux / MacOS), please downloadglChAoS.P / wglChAoS.P and build it with-DGLCHAOSP_TEST_RANDOM_DISTRIBUTION
or enable the#define GLCHAOSP_TEST_RANDOM_DISTRIBUTION
inattractorsBase.h file