from __future__ import annotations import torch from orbitquant_packed_matmul import matmul_packed_weight def _pack(values: torch.Tensor, bits: int) -> torch.Tensor: flat = values.detach().to(device="cpu", dtype=torch.uint8).flatten() packed = torch.zeros((flat.numel() * bits + 7) // 8, dtype=torch.uint8) for value_index, value in enumerate(flat.tolist()): bit_start = value_index * bits byte_index = bit_start // 8 shift = bit_start % 8 packed[byte_index] |= (value << shift) & 0xFF if shift + bits > 8: packed[byte_index + 1] |= value >> (8 - shift) return packed device = "cuda" if torch.cuda.is_available() else "mps" bits = 4 rows = 8 in_features = 16 out_features = 6 x = torch.randn(rows, in_features, device=device, dtype=torch.float16) indices = torch.arange(out_features * in_features, dtype=torch.uint8).reshape( out_features, in_features ) % (2**bits) packed = _pack(indices, bits).to(device) row_norms = torch.linspace(0.5, 1.5, out_features, device=device) centroids = torch.linspace(-1.0, 1.0, 2**bits, device=device) out = matmul_packed_weight( x, packed, row_norms, centroids, bits=bits, out_features=out_features, in_features=in_features, ) print(out.shape)