# Roulette Loops - Reads the self crossing count of one trochoid as an exact step function of the pencil's reach `|p|`, past the loop threshold `|p| = 1`, and the crossing count of two trochoids drawn from one wheel. - The object is `mrlynum::spirograph`: a wheel of radius `r` rolls inside or outside a circle with `R/r = a/b` in lowest terms, a pencil sits `|p|` wheel radii from the wheel's centre, and `trace` returns the polyline every count is read back from. - Write `s = -1` inside and `s = +1` outside, `rho = a + s b`, `m = a + 2 s b`. In wheel radii and in the closing parameter `phi` of `[0, 2 pi)` a pencil at the real seat `|p|` draws `z(phi) = rho e^(i b phi) + |p| b e^(i s rho phi)`. - With `sigma = (phi + psi)/2` and `delta = (phi - psi)/2`, `z(phi) = z(psi)` reads `rho sin(b delta) + |p| b sin(s rho delta) e^(i s a sigma) = 0`, so `sigma` is a multiple of `pi / a` and the crossing equation is `rho sin(b delta) = e |p| b sin(rho delta)` with `e = 1` or `e = -1`. - The reflection of the curve in the line of angle `b sigma` fixes the crossing, so every self crossing lies on one of the `a` mirror lines `k pi / a` through the centre, inside and outside alike. A pencil at seat angle `alpha` turns the whole curve by `-s b alpha / a`, so its mirror lines are `-s b alpha / a + k pi / a`; the bare `k pi / a` needs a real seat. - Not every mirror line has to carry a crossing: `4/1` outside puts all four on two of its four lines. - `(a/2)(Z_1 + Z_-1)`, with `Z_e` the roots of the crossing equation in `(0, pi)`, counts unordered parameter pairs, so it is read off a one dimensional root count and never off a picture; it is the number of distinct double points exactly when the curve has no point of multiplicity above two and no self contact. - The one reach with a multiple point is `|p| = rho / b`: there `z = 0` at the `a` parameters `phi = (2j+1) pi / a`, so `C(a, 2)` parameter pairs collapse into the centre and the point count is `C(a, 2) - 1` below the pair count. Elsewhere the two agree, because a multiple point needs every pairwise `delta` to be a multiple of `pi / a`, and such a `delta` solves the crossing equation only there. - A step of the count is a double root: the crossing equation and its `delta` derivative `cos(b delta) = e |p| cos(rho delta)` together force `a sin(m delta) = m sin(a delta)`, equivalently `sinc(m delta) = sinc(a delta)`, with the reach `|p| = |cos(b delta) / cos(rho delta)|`, read as `|rho sin(b delta)| / |b sin(rho delta)|` where both cosines vanish, which is `delta = pi/2` when `a` is even. - A threshold is a tangency angle `delta` in `[0, pi)`, not a reach. Several angles can share one reach, and then the step there is a multiple of `a`; the count `|rho - b|` is a count of angles with multiplicity. - `delta = 0` and `delta = pi` are roots of the crossing equation at every reach, and a root is born at each end as the reach passes `1`, since `f'(0) = rho b (1 - e |p|)` and `f'(pi) = rho b ((-1)^b - e |p| (-1)^rho)`. The single entry at `delta = 0` stands for both births, which is why the jump at reach `1` is `a` and not `a/2`. - On a tangency reach the curve touches itself: the two branches meet with equal tangents, a tacnode, and the meeting count is the transversal count below plus `a/2` for each tangency angle at that reach. The step function is read on the open intervals between tangency reaches, never on one. - Swapping the wheel frequency `b` and the rim frequency `rho` fixes every tangency angle, since `{a, |m|} = {rho + b, |rho - b|}` is symmetric, and inverts every reach, since `|cos(b delta) / cos(rho delta)|` inverts. So the thresholds depend on the ordered pair `(b, rho)`, and the falling `a < 2b` staircase is the reciprocal of the rising `a > 2b` one. - `sin(k delta)` and `cos(k delta)` are expanded exactly in `u = sin^2(delta)` by the integer recursion of Sakhnovich 2023, theorems 2.1 and 2.5, so the tangency equation becomes `u Q(u) = 0`, times `cos(delta)` when `a` is even, for an explicit integer polynomial `Q`, and `|p|^2 = T(u)/B(u)` for explicit integer polynomials `T` and `B`. - The tangency equation integrates: `a sin(m delta) - m sin(a delta)` is `2 a m` times `W(delta) = int_0^delta sin(b t) sin(rho t) dt` up to sign, `W'` vanishes on `(0, pi)` only at `j pi / rho` and `k pi / b`, and there `W` is exactly `(-1)^(j+1) sin(b j pi / rho) rho / (rho^2 - b^2)` and `(-1)^k sin(rho k pi / b) b / (rho^2 - b^2)`, so the threshold count is a sign count over a merged Farey sequence with no numerics in it. - The root scan starts at `0.4 / max(a, |m|)` and hides nothing: `W' > 0` on `(0, pi / max(b, rho))` and `max(a, |m|) = b + rho` exceeds `max(b, rho)`, so no root lies below the cut. The germ at `pi` makes `W` monotone and zero free on the last interval, so the endpoint contributes no sign change and the walk carries only the interior critical values. - Two pencils `p` and `q` on one wheel meet at parameter pairs where `rho^2 sin^2(b delta) = b^2 (P sin^2(rho delta) + E cos^2(rho delta) - s X sin(2 rho delta))` with `P = |p + q|^2/4`, `E = |p - q|^2/4` and `X = Im(q conj(p))/2`, one root count in `[0, 2 pi)` times `a/2`; the equation is `pi` periodic in `delta`, so the root count is even and the halving is exact. - The pair law needs the two curves distinct, which is the coincidence law `mrlynum::spirograph::distinct` already carries. It counts parameter pairs; the point count needs the further condition that no self crossing of one curve lies on the other, and the centre correction `C(a, 2) - 1` per seat that sits at reach `rho / b`. - Everything is checked three ways that do not share a step: the closed step function, the root count of the crossing equation, and the crossing count of the `mrlynum::spirograph::trace` polyline at two sample counts. - A polyline count blurs inside a tangency, so a threshold is decided by the algebra and the trace only brackets it; the sweep's grid is offset off the rational thresholds so no sample lands on one. - The hypotheses on the step function are `|p| > 0`, `|p|` not a tangency reach, `|p|` not `rho / b`, and `m != 0`; `a = 2b` inside, which only `2/1` reaches, has `m = 0`, no tangency and no crossing except at `|p| = 1`, where the curve is a doubled segment. - What is taken from the literature: Wieleitner 1908 has the reach 1 trichotomy and the mirror line fact for the looped epitrochoid, qualitatively; Jaekel has both staircase endpoints `a (b - 1)` and `a (rho - 1)`, the split at `a = 2b`, and the step sizes `a` and `2a`, with the transition reaches solved numerically; Sakhnovich 2023 has the `sin^2` recursion. What is added here: the tangency equation and the reaches in closed form, the sign count, the mirror lines with their seat hypothesis and a bound, the centre correction, the reciprocity, and the pair law. ## RUN - `CARGO_BUILD_JOBS=4 cargo run --release -p roulette-loops` - About three minutes, single threaded; prints only, writes nothing, holds a few megabytes. ## WITNESSES - The mirror lines: at 24001 samples the worst distance from a trace self crossing to the nearest mirror line is `4.33e-7` of the frame, over `a/b` in `5/1, 7/2, 8/3` inside and `5/2, 7/3` outside, reaches `1.4, 2.6, 3.9`, seat angles `0` and `0.3`, 30 cells. The floor is `trace` returning `f32`, not the geometry. - The step function: `a (b - 1)` below the first tangency reach, `a (rho - 1)` above the last, and `a sign(m)` per tangency angle; the number of angles in `[0, pi)`, counting `delta = 0`, is `|rho - b|`, the same integer as `min(|m|, a)`. - The sign count: over all `29450` coprime frequency pairs `b, rho` up to `220` the exact integer sign count of `W` returns `|rho - b|` every time, in integer arithmetic with no root finding. - The census: `179` coprime fractions `a/b` with `a` at most `24`, `357` cases over the two sides with `m` nonzero, the angle count equal to the sign count `|rho - b|`, the limit equal to `a (rho - 1)`, and the closed form equal to the crossing equation's root count at the midpoint of every step, with `0` failures. - The reciprocity: over `210` swaps of `b` and `rho` with `b + rho` at most `26`, the worst deviation of a threshold times its partner from `1` is `1.47e-13`. - The sweep: `25578` reads of `mrlynum::spirograph::trace` over `|p|` from `0.5` to `4` in `203` steps, `b` in `1..6` and `a` in `b+1..11` coprime, inside and outside, at `4001` and `12001` samples, disagree with the closed form `0` times; every jump bracket is `0.0173` wide or less and holds exactly the predicted angles. - The contact: at `|p|^2 = 27/2` the hypotrochoid `5/1` has `2` tangency angles and `2` simple roots, so `10` meetings against `5` below and `15` above, the two branches closing to `8.88e-16` at radius `2.041241`; `7/2` inside gives `21` against `14` and `28`, `11/4` inside `55` against `44` and `66`, `3/1` outside `6` against `3` and `9`, `5/2` outside `15` against `10` and `20` and `25` against `20` and `30`. - The births: `3/1` inside has no root in `(0, pi)` at reach `0.98` and two at reach `1.02`, `0.1984` on `e = 1` and `2.9432` on `e = -1`, count `3`; `7/2` inside goes from `1.4235, 1.7181` and count `7` to those two plus `0.0750` and `3.0666` and count `14`. - The centre: at `|p| = rho / b` the trace's distinct point count is the step function less `C(a, 2) - 1` on every odd `a` read, `1` at `3/1, 5/2, 5/3, 7/4` inside, `6` at `5/1` and `5/4` inside, `8` at `7/2` inside, `7` at `3/1` and `10` at `3/2` and `21` at `5/2` outside, while three percent either side the two counts agree. - The thresholds of `a/b = 5/1` inside: `1` and `3.674234614175` twice, exactly `|p|^2 = 27/2`, at `u = 5/6` on `Q(u) = 40 - 48 u`; the count is `0`, then `5`, then `15`. - The thresholds of `a/b = 7/2` inside: `1` and `2.353415666603` twice, exactly `|p|^2 = (81 + 21 sqrt 21)/32`, at `u` the smaller root of `Q(u) = 192 u^2 - 336 u + 140`; the count is `7`, then `14`, then `28`. - The thresholds of `a/b = 5/1` outside: `1`, `4.180967894379` twice and `5.789603394549` twice, exactly `|p|^2 = (102 - 7 sqrt 21)/4` and `(102 + 7 sqrt 21)/4` on `Q(u) = -320 u^2 + 448 u - 140`; the count is `0`, then `5`, then `15`, then `25`. - When `a` is even, `delta = pi/2` is always a tangency and its reach is the rational `|p| = rho / b`, which is also the centre reach: `3` at `4/1` inside, `5/3` at `8/3` inside, `13/5` at `8/5` outside. There the centre correction and a step fall together and the step function is not read. - The pair law against the trace: `48` reads over `5/1, 7/2, 8/3` inside and `5/2` outside at reaches `0.6, 1.3, 2.4, 3.7` against three seat kinds, equal reach, shorter reach and the wheel's centre, agree on the parameter pair count exactly. - The pair point count parts from it: `3/1` inside with one seat at reach `sqrt 5 - 1` and one at the wheel's centre has `6` parameter pairs and `3` points, since all three self crossings of the first curve sit on the circle of radius `rho` the second draws; two percent either side gives `6` points. - The centre pencil draws the circle of radius `rho`, the law collapses to `|sin(b delta)| = b |p| / (2 rho)`, and the pair count is `2 a b` below `|p| = 2 rho / b` and `0` above: `48` then `0` across `10/3` at `8/3` inside. - The pair count `2 a b` survives the loop threshold `|p| = 1`, which is a tangency of one curve with itself and never of two curves with each other: for two seats at one reach and half angle `nu` apart it first fails at `2.242763, 1.741061, 1.379486, 1.143270, 1.047854, 1.010207, 1.002194` for `5/1` inside at `nu = 1, 0.5, 0.2, 0.05, 0.01, 0.001, 0.0001`, excess falling `4.69` then `4.65` per decade against `10^(2/3) = 4.64`. Seven samples at one fraction; the shape is a reading, not a bound. - The pair threshold is not monotone in `nu`: `8/3` inside gives `1.117596` at `nu = 1` against `1.523254` at `nu = 0.5`. - `mrlynum::spirograph::trace`, `frame` and `track` are the only outside calls; the counters for one polyline and for two are carried here.