#include <amsculib3/amsculib3.hpp>

namespace amscuda
{
namespace random
{
namespace xoroshiro
{

//ref: https://github.com/joelkp/ranoise/blob/main/splitmix32.c
// __device__ __host__ uint32_t splitmix32_next(uint32_t *splitmix32_state)
// {
//     uint32_t ret;
//     *splitmix32_state += 2654435769U;
//     ret = *splitmix32_state;
//     ret ^= ret >> 16;
//     ret *= 0x85ebca6bU;
//     ret ^= ret >> 13;
//     ret *= 0xc2b2ae35U;
//     ret ^= ret >> 16;
//     return ret;
// }

//Better constants: see discussion below.
__device__ __host__ uint32_t splitmix32_next(uint32_t *splitmix32_state)
{
    uint32_t ret;
    *splitmix32_state += 0x9e3779b9U;
    ret = *splitmix32_state;
    ret ^= ret >> 16;
    ret *= 0x21f0aaadU;
    ret ^= ret >> 15;
    ret *= 0x735a2d97U;
    ret ^= ret >> 15;
    return ret;
}


__host__ __device__ void splitmix64_next(uint64_t *state)
{
    //*state += 0x9E3779B97F4A7C15uL;
    *state += 0x9E3779B97F4A7C15ULL;
}

__host__ __device__ uint64_t splitmix64_nextint(uint64_t *state)
{
    //ref: https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64

    uint64_t ret;
    *state += 0x9E3779B97F4A7C15ULL;
    ret = *state;
    ret = (ret ^ (ret >> 30)) * 0xbf58476d1ce4e5b9ULL;
    ret = (ret ^ (ret >> 27)) * 0x94d049bb133111ebULL;
    ret = ret^(ret>>31);
    return ret;
}



////////////////////
// Unsorted Notes //
////////////////////

    //ref: https://github.com/joelkp/ranoise/blob/main/splitmix32.c
    //2654435769U
    //#define ROR32(x, r) \
	//((uint32_t)(x) >> ((r) & 31) | (uint32_t)(x) << ((32-(r)) & 31))

    //#define MUVAROR32(x, r, ro) \
	//(((uint32_t)(x) | ((1<<((ro) & 31))|1)) * ROR32((x), (r)+(ro)))

    // static inline uint32_t splitmix32(uint32_t *restrict pos) {
    //     uint32_t s = *pos += 2654435769U;
    //     s ^= s >> 16;
    //     s *= 0x85ebca6b;
    //     s ^= s >> 13;
    //     s *= 0xc2b2ae35;
    //     s ^= s >> 16;
    //     return s;
    // }
    
    // int main(int argc, char *argv[]) {
    //     uint32_t pos = 0;
    //     for (;;) {
    //         /* SplitMix32 test */
    //         add_output(splitmix32(&pos));
    //     }
    //     return 0;
    // }


    /*
    //ref: https://stackoverflow.com/questions/17035441/looking-for-decent-quality-prng-with-only-32-bits-of-state

    uint32_t splitmix32(void) {
        uint32_t z = state += 0x9e3779b9;
        z ^= z >> 15; // 16 for murmur3
        z *= 0x85ebca6b;
        z ^= z >> 13;
        z *= 0xc2b2ae35;
        return z ^= z >> 16;
    }

    Update: Better constants have been found that potentially make this a very good PRNG:
    uint32_t splitmix32(void) {
    uint32_t z = (state += 0x9e3779b9);
    z ^= z >> 16; z *= 0x21f0aaad;
    z ^= z >> 15; z *= 0x735a2d97;
    z ^= z >> 15;
    return z;
}


Mark Dickinson
Over a year ago
Any thoughts on the PCG family? (E.g., the generator called "PCG RXS M XS 32 (LCG)" in the PCG paper.)
bryc
Over a year ago
@MarkDickinson From what I've seen PCG relies on 64-bit math, and there are no fully 32-bit variants that I can find. I can't find any code specific to the generator you mentioned either. I'm sure PCG is a good generator, but I feel like its a poor choice for JavaScript or embedded systems. xoshiro128** for example is ideal in that regard, since it uses 32-bit integers only.

    */

};//end namespace splitmix 
}; //end namespaces
};