import math
PHI = 1.6180339887498948482
LN_PHI = math.log(PHI)
LN2 = math.log(2)

kp = [2,3,5,7,13,17,19,31,61,89,107,127,521,607,1279,2203,2281,3217,4253,4423,
      9689,9941,11213,19937,21701,23209,44497,86243,110503,132049,216091,756839,
      859433,1257787,1398269,2976221,3021377,6972593,13466917,20996011,24036583,
      25964951,30402457,32582657,37156667,42643801,43112609,57885161,74207281,
      77232917,82589933,136279841]

def omega(p):
    inner = math.log(p * LN2) / LN_PHI
    return math.log(inner) / LN_PHI

print("  {:>12}  {:>8}  {:>11}  {:>13}  {:>10}  {}".format(
      "p", "omega", "theta_frac", "rate_dw/dlnp", "gap_omega", "turns"))
print("  " + "-"*80)

prev_om = None
cumulative_turns = 0.0
for p in kp:
    om = omega(p)
    theta_frac = om - math.floor(om)          # angle / 2pi: 0..1
    rate = 1.0 / (LN_PHI * math.log(p * LN2)) # domega/dlnp
    if prev_om is not None:
        gap = om - prev_om
        cumulative_turns += gap               # total omega traveled
        gap_str = "{:+.4f}".format(gap)
    else:
        gap_str = "      --"
    print("  {:>12}  {:8.4f}  {:11.6f}  {:13.6f}  {}  {:.3f}".format(
          p, om, theta_frac, rate, gap_str, om - omega(kp[0])))
    prev_om = om

print()
print("  --- Angular rate analysis ---")
print("  rate_dw/dlnp = 1 / (ln(phi) * ln(p*ln2))")
print()
small = [p for p in kp if p <= 127]
large = [p for p in kp if p >= 1000000]
r_small = sum(1.0/(LN_PHI*math.log(p*LN2)) for p in small) / len(small)
r_large = sum(1.0/(LN_PHI*math.log(p*LN2)) for p in large) / len(large)
print("  Mean rate (p<=127):    {:.6f}  rad/unit-lnp".format(r_small))
print("  Mean rate (p>=1M):     {:.6f}  rad/unit-lnp".format(r_large))
print("  Rate ratio small/large: {:.1f}x faster at primitive scale".format(r_small/r_large))
print()
print("  Theta (frac) spread:")
thetas_small = [omega(p) - math.floor(omega(p)) for p in small]
thetas_large = [omega(p) - math.floor(omega(p)) for p in large]
print("  Small primes (p<=127): angles = " + ", ".join("{:.3f}".format(t) for t in thetas_small))
print("  Large primes (p>=1M):  angles = " + ", ".join("{:.3f}".format(t) for t in thetas_large))
print()
print("  Conclusion: spiral angle (frac(omega)) is NOT fixed.")
print("  It varies freely — no harmonic lock at either scale.")
gap_small = omega(kp[len(small)-1]) - omega(kp[0])
gap_large = omega(kp[-1]) - omega(kp[len(kp)-len(large)])
print("  Total omega span, small primes (p=2..127):    {:.3f}".format(gap_small))
print("  Total omega span, large primes (p>=1M..136M): {:.3f}".format(gap_large))
print("  Small primes cover {:.1f}x MORE omega per prime than large primes.".format(
      gap_small/len(small) / (gap_large/len(large))))
