#ifndef DS1_RANDOM_H
#define DS1_RANDOM_H

#include <cstdint>

/*
 * This is the xoroshiro128+ random generator, designed in 2016 by David Blackman
 * and Sebastiano Vigna, distributed under the CC-0 license. For more details,
 * see http://vigna.di.unimi.it/xorshift/.
 *
 * Rewritten to C++ by Martin Mares, also placed under CC-0.
 */

class RandomGen {
    uint64_t state[2];

    uint64_t rotl(uint64_t x, int k)
    {
        return (x << k) | (x >> (64 - k));
    }

  public:
    // Initialize the generator, set its seed and warm it up.
    RandomGen(unsigned int seed)
    {
        state[0] = seed * 0xdeadbeef;
        state[1] = seed ^ 0xc0de1234;
        for (int i=0; i<100; i++)
            next_u64();
    }

    // Generate a random 64-bit number.
    uint64_t next_u64(void)
    {
        uint64_t s0 = state[0], s1 = state[1];
        uint64_t result = s0 + s1;
        s1 ^= s0;
        state[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
        state[1] = rotl(s1, 36);
        return result;
    }

    // Generate a random 32-bit number.
    uint32_t next_u32(void)
    {
      return next_u64() >> 11;
    }

    // Generate a number between 0 and range-1.
    unsigned int next_range(unsigned int range)
    {
        /*
         * This is not perfectly uniform, unless the range is a power of two.
         * However, for 64-bit random values and 32-bit ranges, the bias is
         * insignificant.
         */
        return next_u64() % range;
    }
};

#endif