Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Involute

A precise gear-train calculator for watchmaking. Give it a target ratio or a real-world period, and it computes the tooth counts that hit it, the exact residual error, and a schematic of the train. Every figure is computed in your browser from exact rational arithmetic. No server, no network, no guesswork.

Validation

Involute reproduces known trains from the horological and astronomical record. These come straight from the engine's golden fixtures and reference database: the same numbers the test suite checks on every commit. Each row cites where its target value comes from.

TrainWhat it should beInvolute reproducesResidual errorSource
Moon phase (frontier)Double-moon disc, 2 lunations per turn, from synodic 29.530589 d6:45 · 8:63 (driver:driven) = 945/16, so 29.531250 d per lunation — the simplest frontier row under the default constraints2.238 × 10⁻⁵ relative; runs slow by ≈ 1 day every 122 yearsSynodic month: Meeus, Astronomical Algorithms.
Metonic cycle235 lunations = 19 tropical years6:30 · 19:47 (driver:driven) = 235/19 exactly, via the exact solver235/19 itself sits 1.5 × 10⁻⁴ absolute (1.2 × 10⁻⁵ relative) from the astronomical target 12.368266Meton of Athens (432 BC). Target derived from tropical ÷ synodic month (Meeus).
Motion worksHour hand : minute hand = 1 : 1212 / 1, solved exactly0 (exact)Standard horological gearing.
ETA 6497 going trainCentre wheel → escape wheel gear ratioTooth counts pending a confirmed primary sourceETA 6497-1 service sheet (tooth counts not yet sourced — see below).

The moon frontier row above is checked end to end (target through frontier, achieved period, and correction) in packages/web/src/solve.test.ts; the Metonic figures and the reference database's source-gating rule are checked in the engine (golden.test.ts, reference.ts).

Asked to approximate the lunations-per-year target rather than reproduce 235/19, the engine does better than Meton: its two-stage frontier row 6:43 · 62:107 = 4601/372 ≈ 12.368280 lands about twelve times closer to the astronomical value than the Metonic fraction. The classical 235/19 never appears on the approximation frontier for exactly that reason; it is reproduced through the exact solver instead, as the table shows.

The historical 59/2 = 29.5 d "classic double-moon" is a stepped mechanism: a 1-tooth pinion driving a 59-tooth wheel, advanced by a jumper. The continuous-gear engine does not reproduce it, because a 1:59 stage exceeds the default single-stage ratio limit. Stepped displays are listed under "what it does not do" below.

A benchmark with no confirmed source is never used to label a result. The reference database keeps unsourced candidates (for example, precision-moon trains attributed to specific calibers) visible in the list but excludes them from matching at runtime, so Involute never prints an accuracy figure it cannot back with a citation. The ETA 6497 row above is deliberately left blank for the same reason: its tooth counts are marked "from the service sheet" until a copy is confirmed.

What it does, and what it does not

Does:

  • Finds the tooth counts for a target ratio, either exactly (Diophantine solve) or as the closest achievable train (a Pareto frontier of the best constrained rational approximations), under tooth-count and wheel-count constraints.
  • Reports the residual error as a human interval ("about 1 day every 2.6 years") and a drift direction (fast / slow).
  • Draws the resulting train as an SVG schematic and exports it, plus the results table, as JSON, CSV, or a print-ready spec sheet.
  • Labels a computed train against known movements when, and only when, a confirmed source exists.

Does not (deferred):

  • Perpetual-calendar leap cam
  • Equation-of-time cam
  • Escapement geometry (Involute models gear ratios, not the escapement)
  • Correctors, stepping, return, and clutch mechanisms for stepped displays

These are gearing-adjacent mechanisms, not gear ratios, and are out of scope for this version. Where a preset touches one (a date ring, a leap wheel), the engine solves the gear side only and marks the mechanism as deferred.

Try it

notadev99.github.io/Involute. Runs entirely in your browser. Nothing is sent anywhere.

The math, in brief

A gear ratio is a rational number, so hitting a target ratio exactly is a Diophantine problem: find integer tooth counts whose product ratio equals the target, within the physical tooth-count limits. When the target is irrational or has no train inside the constraints (a real astronomical period, say), Involute falls back to approximation: for each wheel count it enumerates every admissible driver-gear combination and, for each, the nearest achievable driven combination — an exhaustive search for the best train the constraints allow, not just the classical convergents (a convergent's denominator need not factor into real gears). The result is a Pareto frontier trading train complexity against residual error — you pick the point that fits the movement.

Continued fractions still set the theoretical yardstick (Khinchin): the moon train's 945/16 is in fact the second convergent of the double-lunation target. The search just refuses to stop there when the constraints hold something better.

What is exact, precisely: tooth counts, achieved ratios, and every comparison inside the solver are integer and rational arithmetic on BigInt. The residual errors and correction intervals are reported to double precision, which is more than any gear train can use.

This is the same idea behind the Antikythera mechanism's lunar and Metonic trains, and the lineage runs through Ludwig Oechslin's modern astronomical calendars, which reduce complications to small, exact gear trains. Involute is a calculator for that kind of work, not a designer of movements.

References: continued fractions and best rational approximation (Khinchin, Continued Fractions); the Antikythera gearing (Freeth et al., Nature, 2006); Oechslin's reduction-to-gearing approach to astronomical complications.

Contributing

New presets and reference-database benchmarks are welcome — with one firm rule: a benchmark PR must include a confirmed primary source (a patent, a manufacturer service sheet, or graded horological literature). PRs without a source are declined. See CONTRIBUTING.md for how to add a preset or benchmark and how to run the tests and build.

License

MIT © Thomas Brenas. See LICENSE.

About

Gear-train designer for watchmakers: optimal trains for astronomical complications and exact timekeeping

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages