codex/finite-field-four-operations.py

finite-field-four-operations.py
"""Compute F4 tables using coefficient bits; write matching PNG to cwd.

Tested with Python 3.14.4 and the repository's matplotlib dependency.
Bit 0 is the constant coefficient; bit 1 is the coefficient of alpha.
"""

from itertools import product
from pathlib import Path

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle


LABELS = ["0", "1", r"$\alpha$", r"$\alpha+1$"]
COLORS = ["#f0f2f4", "#cce8f6", "#f9ddb3", "#ded5ed"]


def multiply(x, y):
    """Reduce the product using alpha**2 = alpha + 1 over F2."""
    a, b = x & 1, (x >> 1) & 1
    c, d = y & 1, (y >> 1) & 1
    constant = (a * c) ^ (b * d)
    alpha = (a * d) ^ (b * c) ^ (b * d)
    return constant | (alpha << 1)


def verify():
    add = [[x ^ y for y in range(4)] for x in range(4)]
    mul = [[multiply(x, y) for y in range(4)] for x in range(4)]
    assert add == [[0, 1, 2, 3], [1, 0, 3, 2],
                   [2, 3, 0, 1], [3, 2, 1, 0]]
    assert mul == [[0, 0, 0, 0], [0, 1, 2, 3],
                   [0, 2, 3, 1], [0, 3, 1, 2]]
    for x in range(4):
        assert x ^ 0 == x and x ^ x == 0
        assert multiply(x, 1) == x and multiply(x, 0) == 0
        assert sorted(add[x]) == list(range(4))
        if x:
            assert sorted(mul[x]) == list(range(4))
            assert sum(multiply(x, y) == 1 for y in range(1, 4)) == 1
    for x, y in product(range(4), repeat=2):
        assert multiply(x, y) == multiply(y, x)
    for x, y, z in product(range(4), repeat=3):
        assert multiply(multiply(x, y), z) == multiply(x, multiply(y, z))
        assert multiply(x, y ^ z) == multiply(x, y) ^ multiply(x, z)
    assert [multiply(x, x) for x in range(4)] == [0, 1, 3, 2]
    assert multiply(2, multiply(2, 2)) == 1
    assert [((x * x) ^ x ^ 1) for x in range(2)] == [1, 1]
    print("F4 addition, labels 0, 1, alpha, alpha+1:", add)
    print("F4 multiplication:", mul)
    print("Checked all 64 associativity and distributivity triples; inverses [1, 3, 2].")
    return add, mul


def draw_table(ax, values, symbol, title):
    ax.set_xlim(-1.15, 4.05)
    ax.set_ylim(-0.15, 5.5)
    ax.set_aspect("equal")
    ax.axis("off")
    ax.text(1.5, 5.15, title, ha="center", fontsize=16, weight="bold")
    ax.text(-0.55, 4.45, symbol, ha="center", va="center", fontsize=20)
    for index, label in enumerate(LABELS):
        ax.text(index + 0.5, 4.45, label, ha="center", va="center", fontsize=17)
        ax.text(-0.55, 3.5 - index, label, ha="center", va="center", fontsize=17)
    for row, col in product(range(4), repeat=2):
        value = values[row][col]
        ax.add_patch(Rectangle((col, 3 - row), 1, 1,
                               facecolor=COLORS[value], edgecolor="white", lw=2))
        ax.text(col + 0.5, 3.5 - row, LABELS[value],
                ha="center", va="center", fontsize=19, color="#263746")


def main():
    add, mul = verify()
    fig, axes = plt.subplots(1, 2, figsize=(10.2, 5.7), dpi=120, facecolor="white")
    draw_table(axes[0], add, "+", "Addition: coefficient XOR")
    draw_table(axes[1], mul, r"$\times$", r"Multiplication: $\alpha^2=\alpha+1$")
    fig.suptitle(r"The four-element field $\mathbb{F}_2[t]/(t^2+t+1)$",
                 fontsize=18, y=0.96)
    fig.text(0.5, 0.055,
             r"Bit labels:  $0\leftrightarrow00$     $1\leftrightarrow01$     "
             r"$\alpha\leftrightarrow10$     $\alpha+1\leftrightarrow11$",
             ha="center", fontsize=13)
    fig.subplots_adjust(left=0.045, right=0.985, top=0.87, bottom=0.14, wspace=0.2)
    fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name,
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()