# A still lattice made to move by adding the golden ratio each frame, fract(d(x, y) + phi t): a lattice whose
# time step is irrational. Its error has the same form with all harmonics k = 1, 2, 3 ... (no level error: the
# moving phase removes it):  J = sum_k |H(k (A, B) / N)|^2 |G(k phi)|^2 / (pi^2 k^2)  (truncated at K; the tail is
# under 1 / (pi^2 K)). Against brute force (practical.py), and against the best rational lattices (search.py).
# Prints out/golden.txt.
import numpy as np
import filters as F, st, practical as P

PHI = P.PHI
def J(A, B, N, taps, G, gamma=PHI, K=20000):
    k = np.arange(1, K + 1)
    H2 = np.abs(F.response(taps, (k * A % N) / N, (k * B % N) / N)) ** 2
    return float((H2 * G(k * gamma % 1) ** 2 / (np.pi ** 2 * k * k)).sum())

taps = F.kuwahara(5)
EYES = [st.box(2), st.box(4), st.decay(40), st.decay(80)]
print('(54,11)/56 + golden ratio each frame, through Starlock\'s pass')
fr = P.make('lattice + golden t', 120, 112, tile=(54, 11, 0, 56))
_, kept, _, _ = P.score(fr, taps, EYES, [], levels=32)
for G, b in zip(EYES, kept):
    print(f'  {G.name:12s} formula {np.sqrt(J(54, 11, 56, taps, G)):.4f}  brute force {b:.4f}')
print('and with sqrt(2) - 1 in place of the golden ratio: ' + ', '.join(f'{G.name} {np.sqrt(J(54, 11, 56, taps, G, np.sqrt(2) - 1)):.4f}' for G in EYES))
