
class RGE256:
    def __init__(self, seed: int = 1, rounds: int = 3, domain: str = ""):
        seed = seed & 0xFFFFFFFFFFFFFFFF
        self.rounds = rounds
        self.s = [0] * 8
        self._init_state(seed, domain)

    @staticmethod
    def _rotl(x, r):
        return ((x << r) | (x >> (32 - r))) & 0xFFFFFFFF

    def _init_state(self, seed: int, domain: str):
        for i in range(8):
            seed = (seed ^ (seed >> 12) ^ (seed << 25)) & 0xFFFFFFFFFFFFFFFF
            self.s[i] = (seed >> (i * 4)) & 0xFFFFFFFF

        h = 0x9E3779B1
        for ch in domain.encode("utf-8"):
            h = (h ^ (ch + 0x7F4A7C15 + (h << 6) + (h >> 2))) & 0xFFFFFFFF
        self.s[0] ^= h

        for _ in range(8):
            self._step()

    def _round(self):
        s = self.s
        for i in range(0, 8, 2):
            s[i] = (s[i] + s[i+1]) & 0xFFFFFFFF
            s[i+1] ^= self._rotl(s[i], (3 + i) % 32)

        s[0] ^= self._rotl(s[5], 7)
        s[1] = (s[1] + self._rotl(s[6], 11)) & 0xFFFFFFFF
        s[2] ^= self._rotl(s[7], 13)
        s[3] = (s[3] + self._rotl(s[4], 17)) & 0xFFFFFFFF

    def _step(self):
        for _ in range(self.rounds):
            self._round()
        return (self.s[0] ^ self.s[3] ^ self._rotl(self.s[5], 16)) & 0xFFFFFFFF

    def next_u32(self):
        return self._step()

    def next_float(self):
        return self._step() / 2**32

    def randint(self, low, high):
        return low + (self._step() % (high - low))

    def random_bytes(self, n):
        out = bytearray()
        while len(out) < n:
            v = self._step()
            out.extend(v.to_bytes(4, "little"))
        return bytes(out[:n])

    def rand_uint32(self):
        return self.next_u32()

    def random(self):
        return self.next_float()

    def random_array(self, n):
        return [self.next_float() for _ in range(n)]
