Home

Awesome

fastPRNG

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 on xoshiro / xoroshiro (Blackman/Vigna), xorshift and other Marsaglia algorithms.

64bit algorithms

32bit algorithms

<p>&nbsp;<br></p>

fastPRNG distribution tests - live WebGL

All functions are tested, below the distribution test screenshots in a cube with [-1.0, 1.0] side (OpenGL/WebGL)

30M dots/spheres<br>30M dots/spheres<br> clipping planes3 thin boards<br>from 30M cube dots/spheres
sShot_20191118_173632sShot_20191113_43629sShot_20191112_04710

==>  *view the Live WebGL distribution test section.

<p>&nbsp;<br></p>

Return values and floating point

All base functions return integers:

*If you need (e.g.) values between [INT32_MIN, INT32_MAX], just cast result to int32_t, same for 64bit (cast to int64_t): look at the examples below

Floating point helpers

*look at the examples below

<p>&nbsp;<br></p>

How to use - Examples

To use it just include fastPRNG.h in your code:

#include "fastPRNG.h"

It contains following classes and member functions, inside the namespace fastPRNG:

64bit classes and members

32bit classes and members

Examples

    using fastPRNG;

    fastXS64 fastR; // default "chrono" seed
//  fastXS64 fastR(0x123456789ABCDEF0); // personal seed also to (re)generate a specific random numbers sequence

    for(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 fastXS64 fastR(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
    }


    fastPRNG::fastRand32 fastRandom; // for 32bit
//  fstRnd::fastRand32 fastRandom(0x12345678); or with seed initialization: to (re)generate a specific random numbers sequence 
    for(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
    }
    fastPRNG::fastXS32 fastR(0x12345678); // seed to specific value

    for(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 sequence
    for(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 sequence
    for(int i=0; i<10000; i++) 
        cout << fastR.xoshiro256p()  << endl;   // returns number in [0, UINT64_MAX] interval

*classes fastXS32s and fastXS64s don't have seed() function: they have/are only static members.

For more details look at the source file: it's well documented.

<p>&nbsp;<br></p>

Where it is used

Classes and functions are currently used

Hypercomplex fractals with stochastic IIM <br>(Inverse Iteration Method) algorithmDLA 3D (Diffusion Limited Aggregation) algorithm
<p>&nbsp;<br></p>

Distribution Test

All functions are tested, below the distribution test in a cube with [-1.0, 1.0] side.

Live WebGL 2 / WebAssemly ==> fastPRNG distribution test
*Only FireFox and Chromium based web-browsers (Chrome / Opera / new Edge / etc.) are supported

30M dots/spheres cube30M dots/spheres cube <br> with clipping planes3 thin boards<br>from 30M dots cube
sShot_20191118_173632sShot_20191113_43629sShot_20191112_04710
thin board<br>from a 10M dots cube2.5M dots/spheres<br> with clipping planes3 thin boards<br>from 5M dots cube
sShot_20191118_173632sShot_20191113_43629sShot_20191112_04710

*It's builded on the rendering particles engine of glChAoS.P / wglChAoS.P

*N.B. it's a distribution test, NOT a speed/benchmark test, since the rendering time/calculus is preeminent

Using distribution live WebGL test

The JavaScript / WebGL version is slower of Desktop one, so the test starts with 2.5M of particles, and a pre-allocated maxbuffer of 15M (for slow / low memory GPUs)

<img align="right" src="https://raw.githubusercontent.com/BrutPitt/myRepos/master/fastPRNG/screenShots/sShot_2020626_203217.jpg"/>

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) to maxbuffer (default 15M pre-allocated) particles

*You can resize pre-allocated buffer changing the URL value of maxbuffer (in your browser address box) (e.g. maxbuffer=30 pre allocate a 30M particles memory buffer)

Desktop

If you want use the desktop version (available for Windows / Linux / MacOS), please download glChAoS.P / wglChAoS.P and build it with -DGLCHAOSP_TEST_RANDOM_DISTRIBUTION or enable the #define GLCHAOSP_TEST_RANDOM_DISTRIBUTION in attractorsBase.h file