mlx-ternary / tests /test_pack.py
Jakevin's picture
Initial release: mlx-ternary 0.3.0
6154ddb verified
Raw History Blame Contribute Delete
1.84 kB
# Copyright 2026 Jakevin
# SPDX-License-Identifier: Apache-2.0
import math
import numpy as np
import pytest
from mlx_ternary import dequantize, info_bits_per_weight, pack_trits, stored_bits_per_weight, unpack_trits
def test_bits_about_1_85():
bits = info_bits_per_weight()
assert bits == pytest.approx(math.log2(3) + 16 / 64)
assert 1.83 < bits < 1.85
assert stored_bits_per_weight() == pytest.approx(2.25)
def test_roundtrip():
rng = np.random.default_rng(0)
for k in (4, 8, 64, 640, 2048):
codes = rng.integers(-1, 2, size=(5, k), dtype=np.int8)
packed, row = pack_trits(codes)
assert row == k // 4
assert packed.dtype == np.uint8
assert packed.shape == (5, row)
assert np.array_equal(unpack_trits(packed, k), codes)
# Low bits of the first byte are the first trit + 1.
assert int(packed.reshape(-1)[0] & 3) == int(codes.reshape(-1)[0] + 1)
def test_rejects_bad_codes():
with pytest.raises(ValueError):
pack_trits(np.array([[0, 1, 2]], dtype=np.int8))
with pytest.raises(ValueError):
pack_trits(np.array([[-2, 0, 1, 1]], dtype=np.int8))
with pytest.raises(ValueError):
pack_trits(np.array([[0.5, 0, 0, 0]], dtype=np.float32))
def test_rejects_code_3():
packed = np.array([[0x03]], dtype=np.uint8)
with pytest.raises(ValueError):
unpack_trits(packed, 4)
def test_dequantize_groups():
trits = np.array([[1, 0, -1, 1] * 32], dtype=np.int8)
scales = np.array([[0.5, -2.0]], dtype=np.float32)
out = dequantize(trits, scales)
assert out.shape == trits.shape
assert out[0, 0] == pytest.approx(0.5)
assert out[0, 1] == pytest.approx(0.0)
assert out[0, 63] == pytest.approx(0.5)
assert out[0, 64] == pytest.approx(-2.0)
assert out[0, 66] == pytest.approx(2.0)