| 10 | |
| 11 | |
| 12 | class KeyLUT: |
| 13 | def __init__(self): |
| 14 | r256 = torch.arange(256, dtype=torch.int64) |
| 15 | r512 = torch.arange(512, dtype=torch.int64) |
| 16 | zero = torch.zeros(256, dtype=torch.int64) |
| 17 | device = torch.device("cpu") |
| 18 | |
| 19 | self._encode = { |
| 20 | device: ( |
| 21 | self.xyz2key(r256, zero, zero, 8), |
| 22 | self.xyz2key(zero, r256, zero, 8), |
| 23 | self.xyz2key(zero, zero, r256, 8), |
| 24 | ) |
| 25 | } |
| 26 | self._decode = {device: self.key2xyz(r512, 9)} |
| 27 | |
| 28 | def encode_lut(self, device=torch.device("cpu")): |
| 29 | if device not in self._encode: |
| 30 | cpu = torch.device("cpu") |
| 31 | self._encode[device] = tuple(e.to(device) for e in self._encode[cpu]) |
| 32 | return self._encode[device] |
| 33 | |
| 34 | def decode_lut(self, device=torch.device("cpu")): |
| 35 | if device not in self._decode: |
| 36 | cpu = torch.device("cpu") |
| 37 | self._decode[device] = tuple(e.to(device) for e in self._decode[cpu]) |
| 38 | return self._decode[device] |
| 39 | |
| 40 | def xyz2key(self, x, y, z, depth): |
| 41 | key = torch.zeros_like(x) |
| 42 | for i in range(depth): |
| 43 | mask = 1 << i |
| 44 | key = ( |
| 45 | key |
| 46 | | ((x & mask) << (2 * i + 2)) |
| 47 | | ((y & mask) << (2 * i + 1)) |
| 48 | | ((z & mask) << (2 * i + 0)) |
| 49 | ) |
| 50 | return key |
| 51 | |
| 52 | def key2xyz(self, key, depth): |
| 53 | x = torch.zeros_like(key) |
| 54 | y = torch.zeros_like(key) |
| 55 | z = torch.zeros_like(key) |
| 56 | for i in range(depth): |
| 57 | x = x | ((key & (1 << (3 * i + 2))) >> (2 * i + 2)) |
| 58 | y = y | ((key & (1 << (3 * i + 1))) >> (2 * i + 1)) |
| 59 | z = z | ((key & (1 << (3 * i + 0))) >> (2 * i + 0)) |
| 60 | return x, y, z |
| 61 | |
| 62 | |
| 63 | _key_lut = KeyLUT() |