from typing import Callable def pack_lut_4(f: Callable[..., int], order: tuple[int, int, int, int] = (0, 1, 2, 3)) -> int: lut = 0 for idx in range(16): bits = [(idx >> i) & 1 for i in range(4)] # b0, b1, b2, b3 args = [0, 0, 0, 0] for bit_pos, arg_pos in enumerate(order): args[arg_pos] = bits[bit_pos] lut |= (f(*args) & 1) << idx return lut # F31 coordinates def F31_0(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ (y0 & y1) ^ y0 ^ y1 def F31_1(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1) ^ (x0 & y0 & y1) ^ (x0 & y1) ^ x0 ^ (x1 & y0) ^ (x1 & y1) ^ (y0 & y1) ^ y0 ^ y1 ^ 1 def F31_2(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ x0 ^ (x1 & y1) ^ y0 def F31_3(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1 & y1) ^ (x0 & x1) ^ (x0 & y0 & y1) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ x1 ^ y1 def F31_4(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & x1) ^ (x0 & y0) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ (x1 & y0) ^ x1 ^ (y0 & y1) ^ y0 ^ y1 ^ 1 def F31_5(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & y0) ^ x0 ^ (x1 & y0 & y1) ^ (x1 & y1) ^ x1 ^ y0 ^ y1 ^ 1 def F31_6(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & y0) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ (x1 & y1) ^ x1 ^ (y0 & y1) ^ 1 def F31_7(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ x1 ^ y1 ^ 1 # F32 coordinates def F32_0(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ y0 ^ y1 ^ 1 def F32_1(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1) ^ (x0 & y0 & y1) ^ (x0 & y1) ^ x0 ^ (x1 & y1) ^ x1 ^ y0 ^ 1 def F32_2(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1 & y1) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ x0 ^ (x1 & y0 & y1) ^ y0 def F32_3(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1 & y1) ^ (x0 & y0 & y1) ^ (x1 & y0 & y1) ^ (x1 & y0) ^ x1 ^ (y0 & y1) ^ y1 def F32_4(x0, x1, y0, y1): return (x0 & x1 & y0) ^ (x0 & x1 & y1) ^ (x0 & x1) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ x0 ^ (x1 & y0 & y1) ^ x1 ^ (y0 & y1) ^ y1 def F32_5(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & y0) ^ (x1 & y0 & y1) ^ (x1 & y1) ^ x1 ^ y1 def F32_6(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & x1) ^ (x0 & y0) ^ (x0 & y1) ^ (x1 & y0 & y1) ^ (x1 & y0) ^ x1 ^ (y0 & y1) ^ y0 ^ y1 def F32_7(x0, x1, y0, y1): return (x0 & x1 & y1) ^ (x0 & y0 & y1) ^ (x0 & y0) ^ (x1 & y0 & y1) ^ x1 ^ y0 ^ y1 ^ 1 def main(): F31_orders = [ (0, 1, 2, 3), (0, 1, 2, 3), (3, 0, 1, 2), (0, 1, 2, 3), (0, 1, 2, 3), (0, 1, 2, 3), (0, 1, 2, 3), (0, 1, 2, 3), ] F32_orders = [ (0, 1, 2, 3), (0, 1, 2, 3), (3, 0, 1, 2), (0, 1, 2, 3), (0, 1, 2, 3), (0, 1, 2, 3), (0, 1, 2, 3), (0, 1, 2, 3), ] F31_coords = [F31_0, F31_1, F31_2, F31_3, F31_4, F31_5, F31_6, F31_7] F32_coords = [F32_0, F32_1, F32_2, F32_3, F32_4, F32_5, F32_6, F32_7] lut_B = [pack_lut_4(f, o) for f, o in zip(F31_coords, F31_orders)] lut_A = [pack_lut_4(f, o) for f, o in zip(F32_coords, F32_orders)] print("TEA3_LUT_A = [", end="") for x in lut_A: print(f"0x{x:04X}, ", end="") print("]") print("TEA3_LUT_B = [", end="") for x in lut_B: print(f"0x{x:04X}, ", end="") print("]")