""" COMP-3 Packed Decimal Verification for COBOL Migration Platform. Validates that binary COMP-3 fields in RATE.dat are correctly encoded. Usage: python verify_comp3.py COMP-3 format: each byte holds 2 nibbles (4-bit digits), last nibble = sign (0xC/0xF = positive, 0xD = negative). PIC 9(1)V9(4) = 5 digits + sign = 3 bytes. """ import struct import sys def unpack_comp3(data: bytes) -> tuple[int, int, str]: """Unpack COMP-3 bytes -> (integer_value, decimal_places, sign).""" nibbles = [] for byte in data: nibbles.append((byte >> 4) & 0x0F) nibbles.append(byte & 0x0F) sign_nibble = nibbles[-1] digit_nibbles = nibbles[:-1] value = 0 for n in digit_nibbles: value = value * 10 + n if sign_nibble in (0xC, 0xF): sign = "positive" elif sign_nibble == 0xD: sign = "negative" else: sign = f"unknown(0x{sign_nibble:X})" return value, sign, data.hex() def main(): rate_path = "D:/jcl-cobol/data/input/rate.dat" with open(rate_path, "rb") as f: data = f.read() rec_size = 12 # PIC X(1) + PIC 9(1)V9(4) COMP-3(3) + PIC 9(8) num_records = len(data) // rec_size print(f"File: {rate_path}") print(f"Size: {len(data)} bytes") print(f"Records: {num_records}") print() expected = { "C": ("Cash rate", 0.0005), "O": ("Overdue rate", 0.0500), } all_ok = True for i in range(num_records): offset = i * rec_size rec = data[offset : offset + rec_size] rate_type = chr(rec[0]) pct_bytes = rec[1:4] eff_date = rec[4:12].decode("ascii") value, sign, pct_hex = unpack_comp3(pct_bytes) int_part = value // 10000 dec_part = value % 10000 pct_float = int_part + dec_part / 10000 name, expected_val = expected.get(rate_type, ("Unknown", None)) match = abs(pct_float - expected_val) < 0.0001 if expected_val else False status = "PASS" if match else "FAIL" if not match: all_ok = False print(f"[{status}] Record {i+1}: type={rate_type} ({name})") print(f" COMP-3 hex: {pct_hex}") print(f" packed int: {value}") print(f" float val: {pct_float:.4f}") print(f" expected: {expected_val}") print(f" eff date: {eff_date}") print() if all_ok: print("=== ALL COMP-3 VALUES VERIFIED ===") else: print("=== COMP-3 MISMATCH DETECTED ===") sys.exit(1) if __name__ == "__main__": main()