/*
 * Copyright 2015 - 2025 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "bit.hpp"
#include "def.hpp"
#include "stddef.hpp"
#include "types.hpp"

OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)

namespace ox {

using RandomSeed = uint64_t[2];

// An implementation of the Xoroshiro128+ algorithm
class OX_PACKED Random {
	private:
		RandomSeed m_seed = {540932923848, 540932540932};

	public:
		constexpr Random() noexcept = default;

		explicit constexpr Random(const RandomSeed &seed) noexcept;

		constexpr void seed(const RandomSeed &seed) noexcept;

		constexpr uint64_t gen() noexcept;
};

constexpr Random::Random(const RandomSeed &seed) noexcept: m_seed{seed[0], seed[1]} {
}

constexpr void Random::seed(const RandomSeed &seed) noexcept {
	m_seed[0] = seed[0];
	m_seed[1] = seed[1];
}

constexpr uint64_t Random::gen() noexcept {
	auto s0 = m_seed[0];
	auto s1 = m_seed[1];
	const auto retval = s0 + s1;
	// reseed for next number
	s1 ^= s0;
	m_seed[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
	m_seed[1] = rotl(s1, 36);
	return retval;
}

}

OX_CLANG_NOWARN_END
