/*
 * HPPC
 *
 * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
 * All rights reserved.
 *
 * Refer to the full license file "LICENSE.txt":
 * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
 */
package com.carrotsearch.hppc;

import java.util.Random;

/**
 * A fast pseudo-random number generator. For simplicity, we do not implement
 * all of {@link Random} methods.
 *
 * @see "https://xorshift.di.unimi.it/"
 * @see "https://xorshift.di.unimi.it/xorshift128plus.c"
 */
public class XorShift128P {
	private static long notZero(long value) {
		return value == 0 ? 0xdeadbeefbabeL : value;
	}

	/*
	 * 128 bits of state.
	 */
	private long state0, state1;

	public XorShift128P() {
		this(Containers.randomSeed64());
	}

	public XorShift128P(long seed) {
		state0 = notZero(BitMixer.mix64(seed));
		state1 = notZero(BitMixer.mix64(seed + 1));
	}

	public int nextInt() {
		return (int) nextLong();
	}

	public int nextInt(int bound) {
		if (bound <= 0) {
			throw new IllegalArgumentException();
		}

		int r = (nextInt() >>> 1);
		int m = bound - 1;
		if ((bound & m) == 0) {
			r = (int) ((bound * (long) r) >> 31);
		} else {
			for (int u = r; u - (r = u % bound) + m < 0; u = nextInt() >>> 1) {
			}
		}

		return r;
	}

	public long nextLong() {
		long s1 = state0;
		long s0 = state1;
		state0 = s0;
		s1 ^= s1 << 23;
		return (state1 = (s1 ^ s0 ^ (s1 >>> 17) ^ (s0 >>> 26))) + s0;
	}
}
