#ifdef __cplusplus
extern "C" {
#endif

#include "uulib/xoshiro.h"
#include "uulib/splitmix.h"

#ifdef __cplusplus
}
#endif

/* based on xoshiro256++
 * https://prng.di.unimi.it/xoshiro256plusplus.c
*/

#define xo_rotl(x,k) (((x) << (k)) | ((x) >> (64 - (k))))

static U64 xo_s[4];

void xo_srand(void) {
  sm_srand();
  xo_s[0] = sm_rand();
  xo_s[1] = sm_rand();
  xo_s[2] = sm_rand();
  xo_s[3] = sm_rand();
}

U64 xo_rand(void) {
  const U64 result = xo_rotl(xo_s[0] + xo_s[3], 23) + xo_s[0];

  const U64 t = xo_s[1] << 17;

  xo_s[2] ^= xo_s[0];
  xo_s[3] ^= xo_s[1];
  xo_s[1] ^= xo_s[2];
  xo_s[0] ^= xo_s[3];

  xo_s[2] ^= t;

  xo_s[3] = xo_rotl(xo_s[3], 45);

  return result;
}

/* ex:set ts=2 sw=2 itab=spaces: */
