"""M5-A: the faithful IGC bit-serial perspective divide + divlogo oracle test. texdivide (EOF.C): restoring long division of the texu/texv field by the texz field, over `sigbits` iterations, quotient written MSB-first into the field. Implemented on a single pixel's 26-byte bit memory using the same read/write primitives as igc_exec. Verified against the divlogo's known mapping. """ import struct # DIVPXMAP.H field bits TEXZ, TEXZBITS = 32, 20 TEXU, TEXUBITS = 57, 20 TEXV, TEXVBITS = 77, 20 PIXBYTES = 26 def rdbits(pix, bit0, bits): v = 0 for k in range(bits): b = bit0 + k v |= ((pix[b >> 3] >> (b & 7)) & 1) << k return v def wrbits(pix, bit0, bits, val): for k in range(bits): b = bit0 + k if (val >> k) & 1: pix[b >> 3] |= 1 << (b & 7) else: pix[b >> 3] &= ~(1 << (b & 7)) def texdivide(pix, num, denom0, sigbits): """num, denom0 = field start bits; num field is divided by denom in place.""" res = num + TEXUBITS - 1 # quotient MSB position divbits = TEXUBITS denom = denom0 for _ in range(sigbits): n = rdbits(pix, num, divbits) d = rdbits(pix, denom, divbits) en = 1 if n >= d else 0 if en: wrbits(pix, num, divbits, (n - d) & ((1 << divbits) - 1)) # ENABintoMEM(res) if en: pix[res >> 3] |= 1 << (res & 7) else: pix[res >> 3] &= ~(1 << (res & 7)) res -= 1 denom += 1 divbits -= 1 def perspective_divide_pixel(texu_val, texv_val, texz_val): """Run the full perspective_divides on one pixel; return (texu_field, texv_field).""" pix = bytearray(PIXBYTES) wrbits(pix, TEXU, TEXUBITS, texu_val & ((1 << TEXUBITS) - 1)) wrbits(pix, TEXV, TEXVBITS, texv_val & ((1 << TEXVBITS) - 1)) wrbits(pix, TEXZ, TEXZBITS, texz_val & ((1 << TEXZBITS) - 1)) # CLEAR(texz+texzbits, 1) -- top guard bit already 0 texdivide(pix, TEXU, TEXZ + 1, 17) texdivide(pix, TEXV, TEXZ + 1, 17) return rdbits(pix, TEXU, TEXUBITS), rdbits(pix, TEXV, TEXVBITS) def texel8_fast(texu_val, texz_val): """Verified fast equivalent of the bit-serial divide's 8-bit texel field: (texu_field>>9)&0xff. Derived + checked against perspective_divide_pixel.""" if texz_val == 0: return 0 return int(texu_val / texz_val * 2048) # 0..2047 (3 int + 8 texel bits) if __name__ == '__main__': # divlogo oracle (EOF.C ~616-654): u sweeps 0.001->0.999 across x[532,660] x0, x1 = 532.0, 660.0 u0, u1 = 0.001, 0.999 du_dx = (u1 - u0) / (x1 - x0) zscale = (1 << (TEXZBITS - 3)) * 0.999 uscale = (1 << (TEXUBITS - 3)) * 0.999 uC = x0 * du_dx - u0 uA, uCk = du_dx * uscale, -uC * uscale zC = 8.0 * zscale prev = -1 monotonic = True exact_vs_fast = [] span = [] for x in range(532, 660, 2): texu_val = int(uA * x + uCk) texz_val = int(zC) tu_field, _ = perspective_divide_pixel(texu_val, 0, texz_val) texel8 = (tu_field >> 9) & 0x7ff # 8 texel + 3 int bits fast = texel8_fast(texu_val, texz_val) & 0x7ff exact_vs_fast.append(abs(texel8 - fast)) span.append(texel8) if texel8 < prev: monotonic = False prev = texel8 print("bit-exact texel8 span: %d..%d over the logo rect (u:0->1)" % (min(span), max(span))) print("monotonic (linear sweep): %s" % monotonic) print("max |exact - fast|: %d (fast formula tracks the bit-serial divide)" % max(exact_vs_fast)) assert monotonic, "texel must increase monotonically with u" assert max(span) - min(span) > 200, "u:0->1 must sweep ~a full 8-bit texel range" assert max(exact_vs_fast) <= 2, "fast formula must match the bit-serial divide" print("M5-A PASS: faithful perspective divide verified against the divlogo oracle")