hdcstorage / tests /test_shader.py
AEUPH's picture
HDCSTORAGE: hyperdimensional computer, webOS and agentic MCP layer (stdlib-only Python)
ad474c9 verified
Raw History Blame Contribute Delete
9.32 kB
"""Tests for the HDC shader layer.
The interesting cases are the ones that separate exact from approximate:
``test_adjacent_depths_are_indistinguishable_by_similarity`` shows why the
depth buffer uses the bit-scan comparator rather than a similarity ranking.
"""
import math
import random
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from hdc.hypervec import hv_to_int, int_to_hv, shift, sim
from hdc.shader import (
DepthBuffer,
Image,
NormalCodebook,
ShaderFabric,
demo_report,
step_image,
)
D = 2000
class TestShift(unittest.TestCase):
"""The dimming operator rests entirely on this identity."""
def test_left_and_right_shift_are_exact(self):
rng = random.Random(11)
values = [0, 1, 2, 3, 7, 42, 100, 200, 255, 1000, 65535] + [
rng.randrange(0, 1 << 20) for _ in range(40)
]
for n in values:
for k in (1, 2, 3, 8, 16):
hv = int_to_hv(n, D)
# A shift that overflows the 31-bit magnitude lands in the sign
# bit by design; the identity is claimed for in-range results.
if n << k < (1 << 31):
self.assertEqual(hv_to_int(shift(hv, k, D), D), n << k, (n, k))
self.assertEqual(hv_to_int(shift(hv, -k, D), D), n >> k, (n, k))
def test_shift_is_not_a_decode_roundtrip(self):
"""Two rotations and two XORs; the value is never read out."""
n = 200
hv = int_to_hv(n, D)
folded = shift(hv, -1, D)
self.assertNotEqual(folded, hv)
self.assertEqual(hv_to_int(folded, D), 100)
class TestFabric(unittest.TestCase):
def setUp(self):
self.f = ShaderFabric(d=D)
def test_dim_and_brighten(self):
self.assertEqual(hv_to_int(self.f.dim(self.f.level(200)), D), 100)
self.assertEqual(hv_to_int(self.f.dim(self.f.level(200), 2), D), 50)
self.assertEqual(hv_to_int(self.f.dim(self.f.level(41), 1), D), 20) # truncating
self.assertEqual(
hv_to_int(self.f.brighten(self.f.dim(self.f.level(200), 1), 1), D), 200
)
def test_compare_is_a_comparator(self):
rng = random.Random(12)
for _ in range(30):
a = rng.randrange(0, 1000)
b = rng.randrange(0, 1000)
expected = (a > b) - (a < b)
self.assertEqual(self.f.compare(self.f.level(a), self.f.level(b)), expected, (a, b))
def test_compare_handles_equal_values(self):
self.assertEqual(self.f.compare(self.f.level(77), self.f.level(77)), 0)
def test_max_and_min(self):
a, b = self.f.level(10), self.f.level(250)
self.assertEqual(hv_to_int(self.f.max_of(a, b), D), 250)
self.assertEqual(hv_to_int(self.f.min_of(a, b), D), 10)
def test_abs_and_gradient(self):
self.assertEqual(hv_to_int(self.f.abs_of(self.f.sub(self.f.level(40), self.f.level(200))), D), 160)
self.assertEqual(hv_to_int(self.f.gradient(self.f.level(200), self.f.level(40)), D), 160)
self.assertEqual(hv_to_int(self.f.gradient(self.f.level(40), self.f.level(200)), D), 160)
def test_sign_probe(self):
self.assertTrue(self.f.is_negative(self.f.sub(self.f.level(1), self.f.level(2))))
self.assertFalse(self.f.is_negative(self.f.level(5)))
def test_discontinuity_is_similarity_based(self):
same = self.f.discontinuity(self.f.level(200), self.f.level(200))
different = self.f.discontinuity(self.f.level(200), self.f.level(40))
self.assertEqual(same, 0.0)
self.assertGreater(different, 0.5)
class TestImage(unittest.TestCase):
def setUp(self):
self.f = ShaderFabric(d=D)
def test_roundtrip_levels(self):
rows = [[0, 50, 100], [150, 200, 255]]
img = Image.from_levels(rows, self.f)
self.assertEqual(img.levels(), rows)
self.assertEqual((img.w, img.h), (3, 2))
def test_ragged_rows_rejected(self):
with self.assertRaises(ValueError):
Image.from_levels([[1, 2], [3]], self.f)
def test_dim_scales_every_pixel_exactly(self):
img = Image.from_levels([[200, 40]], self.f)
self.assertEqual(img.dim(1).levels(), [[100, 20]])
self.assertEqual(img.dim(3).levels(), [[25, 5]])
def test_edges_find_the_step(self):
img = step_image(8, 4, edge=4, fabric=self.f, bright_b=200)
mags = img.edges().levels()
self.assertEqual(mags[0], [0, 0, 0, 160, 0, 0, 0, 0])
for row in mags:
self.assertEqual(sum(row), 160)
def test_edges_of_a_flat_image_are_zero(self):
img = Image.from_levels([[7, 7, 7], [7, 7, 7]], self.f)
self.assertEqual(img.edges().levels(), [[0, 0, 0], [0, 0, 0]])
def test_discontinuity_map_marks_the_edge(self):
img = step_image(8, 2, fabric=self.f)
grid = img.discontinuities()
self.assertGreater(grid[0][3], 0.5)
self.assertEqual(grid[0][0], 0.0)
def test_pixel_record_roundtrip(self):
img = Image.from_levels([[11, 22]], self.f)
record = img.pixel_record(1, 0, depth=9)
self.assertEqual(img.read_level(record), 22)
def test_ascii_and_stat(self):
img = Image.from_levels([[0, 100, 200]], self.f)
self.assertEqual(len(img.ascii()), 3)
stat = img.stat()
self.assertEqual((stat["min"], stat["max"], stat["distinct"]), (0, 200, 3))
class TestDepthBuffer(unittest.TestCase):
def setUp(self):
self.f = ShaderFabric(d=D)
def test_keeps_the_nearest_fragment(self):
zb = DepthBuffer(1, 1, self.f)
self.assertTrue(zb.test(0, 0, self.f.level(20)))
self.assertFalse(zb.test(0, 0, self.f.level(50)))
self.assertFalse(zb.test(0, 0, self.f.level(30)))
self.assertTrue(zb.test(0, 0, self.f.level(5)))
self.assertEqual(zb.depths(), [[5]])
self.assertEqual((zb.tests, zb.rejected), (4, 2))
def test_similarity_cannot_rank_depths(self):
"""Why the buffer compares bits instead of calling sim.
The integer codec is symbolic: 20 and 21 score about the same as 20
and 200, so there is no threshold that orders depths by similarity.
"""
adjacent = sim(self.f.level(20), self.f.level(21), D)
distant = sim(self.f.level(20), self.f.level(200), D)
self.assertLess(adjacent, 0.8)
self.assertLess(abs(adjacent - distant), 0.5) # same band: not a ranking
self.assertEqual(self.f.compare(self.f.level(20), self.f.level(21)), -1)
class TestNormalCodebook(unittest.TestCase):
def setUp(self):
self.f = ShaderFabric(d=D)
self.cb = NormalCodebook(entries=64, d=D, fabric=self.f)
def test_nearest_recovers_a_stored_direction(self):
for entry in self.cb.entries[:8]:
found, match = self.cb.nearest(entry.direction)
self.assertEqual(found.index, entry.index)
self.assertGreater(match, 0.9)
@staticmethod
def _cos(u, v):
nu = math.sqrt(sum(c * c for c in u))
nv = math.sqrt(sum(c * c for c in v))
return sum(a * b for a, b in zip(u, v)) / (nu * nv)
def test_lookup_tracks_angle_not_bit_patterns(self):
"""The thermometer code makes cleanup agree with angle, not with bits.
With the symbolic integer codec this fails badly: similarity there
measures shared bit atoms, so cleanup returns a geometrically much
worse entry (measured 0.537 cosine against a 0.712 best). With the
thermometer code most misses are boundary cases, so the assertions are
the measured floor — exact agreement >= 60% and mean cosine deficit
<= 0.06 — rather than a perfect hit rate.
"""
rng = random.Random(21)
trials = 60
exact = 0
deficits = []
for _ in range(trials):
v = [rng.gauss(0, 1) for _ in range(3)]
norm = math.sqrt(sum(c * c for c in v)) or 1.0
query = tuple(c / norm for c in v)
found, _ = self.cb.nearest(query)
best = max(self._cos(query, e.direction) for e in self.cb.entries)
got = self._cos(query, found.direction)
deficits.append(best - got)
exact += 1 if got >= best - 1e-9 else 0
self.assertGreaterEqual(exact / trials, 0.60)
self.assertLessEqual(sum(deficits) / len(deficits), 0.06)
def test_lambert_terms(self):
up = self.cb.nearest((0.0, 0.0, 1.0))[0]
self.assertGreater(self.cb.lambert(up, (0.0, 0.0, 1.0)), 0.9)
self.assertEqual(self.cb.lambert(up, (0.0, 0.0, -1.0)), 0.0)
index, match, lambert, intensity = self.cb.shade((0.0, 0.0, 1.0), (0.0, 0.0, 1.0))
self.assertEqual(index, up.index)
self.assertGreater(intensity, 200.0)
def test_codebook_needs_at_least_four_entries(self):
with self.assertRaises(ValueError):
NormalCodebook(entries=3, d=D)
class TestReport(unittest.TestCase):
def test_demo_report_renders(self):
text = demo_report(d=D)
for needle in ("HDC shader fabric", "after dim(1)", "edge magnitudes", "normal LUT", "depth buffer"):
self.assertIn(needle, text)
if __name__ == "__main__":
unittest.main()