whitepaper: add §9.1 on isqrt integer square root

New subsection under Language Coverage covers the isqrt primitive that
shipped in 6e9d3ea across Python + C + asm. Documents:

- Semantics: (isqrt n) -> floor(sqrt(n)), integer in / integer out,
  negative argument raises; matches Python 3.8+ math.isqrt and R7RS
  exact-integer-sqrt.
- Why integer: no FPU drift, no libm platform variance, portal replays
  stay bit-identical.
- Algorithm: bit-by-bit digit recurrence, O(log n), no multiply/divide,
  no FPU. Asm variant runs in three integer registers.
- Domain limits: Python unbounded, asm 61-bit, C 48-bit (NaN-boxed).
  Portal round-trips bit-identical within the smaller tier's window.
- MOAD-0001 note: O(log n) per call, no hidden linear scan.

21 RST lines. Rebuilt PDF and HTML from source.
This commit is contained in:
russell@unturf.com 2026-04-23 20:18:50 -04:00
parent d2866f486d
commit 5ec3da03a8
3 changed files with 656 additions and 588 deletions

View file

@ -2153,6 +2153,19 @@ ALL EML THEOREMS VERIFIED IN LUMBDA</pre>
<p><strong>Hygienic macros</strong>: <span class="docutils literal"><span class="pre">syntax-rules</span></span> with ellipsis (<span class="docutils literal">...</span>) support. Pattern matching, template instantiation, proper hygiene. Also <span class="docutils literal"><span class="pre">define-macro</span></span> for procedural macros.</p>
<p><strong>Standard library</strong> (<span class="docutils literal">stdlib.lsp</span>, 385 lines): Additional macros (<span class="docutils literal">swap!</span>, <span class="docutils literal"><span class="pre">fluid-let</span></span>, <span class="docutils literal">while</span>, <span class="docutils literal">dotimes</span>), utility functions, simple object system, SRFI-2/8/64 test framework.</p>
<p><strong>Test suite</strong>: 974 verified assertions covering lexing, parsing, special forms, bytecode compilation, macros (hygienic &amp; procedural), continuations, generators, record types, modules, arithmetic, higher-order functions, error handling, portal serialization, cross-implementation portal exchange, file I/O parity, &amp; graceful degradation on mismatched or corrupt input.</p>
<section id="integer-square-root-isqrt">
<h3>9.1 Integer Square Root (<span class="docutils literal">isqrt</span>)</h3>
<p><span class="docutils literal">sqrt</span> returns an inexact real. That is the right answer when the caller wants a distance or a norm, and the wrong answer when the caller wants a count: bucket indices, loop bounds, coordinates on a grid, bignum primality witnesses. Float <span class="docutils literal">sqrt</span> drifts with FPU mode, with the <span class="docutils literal">libm</span> in play, and across platforms — none of which a portal should let into a replay trace.</p>
<p><span class="docutils literal">(isqrt n) → floor(sqrt(n))</span> ships in all three implementations. Contract matches Python 3.8+ <span class="docutils literal">math.isqrt</span> and the integer half of R7RS <span class="docutils literal"><span class="pre">exact-integer-sqrt</span></span>: integer-in, integer-out, negative argument raises. No floats anywhere in the pipeline.</p>
<pre class="literal-block">(isqrt 0) ; =&gt; 0
(isqrt 16) ; =&gt; 4 ; exact
(isqrt 17) ; =&gt; 4 ; floor, not round
(isqrt 1000000) ; =&gt; 1000
(isqrt -1) ; error: negative argument</pre>
<p><strong>Algorithm.</strong> Bit-by-bit digit-recurrence (Wikipedia &quot;Methods of computing square roots&quot;). O(log n) shifts, adds, and compares; no multiplies, no divides, no FPU. The C and asm implementations share the same loop skeleton — the asm version (<span class="docutils literal">bi_isqrt</span>, <span class="docutils literal">asm/lumbda.s</span>) runs it in three integer registers (<span class="docutils literal">%r8</span> radicand, <span class="docutils literal">%r9</span> bit, <span class="docutils literal">%r10</span> result) with no memory traffic per iteration. Python delegates to CPython's <span class="docutils literal">math.isqrt</span>, which uses Karatsuba-square-root for bignums.</p>
<p><strong>Domain limits.</strong> Python: unbounded — works on arbitrary-precision <span class="docutils literal">int</span>. asm: 61-bit (three tag bits consumed at the bottom of the word). C: 48-bit (NaN-boxed doubles carry the integer payload in the mantissa). Portal round-trips remain bit-identical within the smaller of the two tiers on either end; a value that fits in the C tier's 48-bit window survives every Python ↔ C ↔ asm crossing in §7.2's 3×3 matrix.</p>
<p><strong>MOAD-0001 note.</strong> Each call is O(log n) in the value, not in the heap or the symbol table. No hidden linear scan, no per-call allocation in C or asm. Safe to invoke inside a tight loop without inflating the overall complexity class.</p>
</section>
</section>
<section id="relationship-to-companion-papers">
<h2>10. Relationship to Companion Papers</h2>

File diff suppressed because it is too large Load diff

View file

@ -1066,6 +1066,27 @@ Lumbda implements a near-complete R7RS-small Scheme:
**Test suite**: 974 verified assertions covering lexing, parsing, special forms, bytecode compilation, macros (hygienic & procedural), continuations, generators, record types, modules, arithmetic, higher-order functions, error handling, portal serialization, cross-implementation portal exchange, file I/O parity, & graceful degradation on mismatched or corrupt input.
9.1 Integer Square Root (``isqrt``)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``sqrt`` returns an inexact real. That is the right answer when the caller wants a distance or a norm, and the wrong answer when the caller wants a count: bucket indices, loop bounds, coordinates on a grid, bignum primality witnesses. Float ``sqrt`` drifts with FPU mode, with the ``libm`` in play, and across platforms — none of which a portal should let into a replay trace.
``(isqrt n) → floor(sqrt(n))`` ships in all three implementations. Contract matches Python 3.8+ ``math.isqrt`` and the integer half of R7RS ``exact-integer-sqrt``: integer-in, integer-out, negative argument raises. No floats anywhere in the pipeline.
::
(isqrt 0) ; => 0
(isqrt 16) ; => 4 ; exact
(isqrt 17) ; => 4 ; floor, not round
(isqrt 1000000) ; => 1000
(isqrt -1) ; error: negative argument
**Algorithm.** Bit-by-bit digit-recurrence (Wikipedia "Methods of computing square roots"). O(log n) shifts, adds, and compares; no multiplies, no divides, no FPU. The C and asm implementations share the same loop skeleton — the asm version (``bi_isqrt``, ``asm/lumbda.s``) runs it in three integer registers (``%r8`` radicand, ``%r9`` bit, ``%r10`` result) with no memory traffic per iteration. Python delegates to CPython's ``math.isqrt``, which uses Karatsuba-square-root for bignums.
**Domain limits.** Python: unbounded — works on arbitrary-precision ``int``. asm: 61-bit (three tag bits consumed at the bottom of the word). C: 48-bit (NaN-boxed doubles carry the integer payload in the mantissa). Portal round-trips remain bit-identical within the smaller of the two tiers on either end; a value that fits in the C tier's 48-bit window survives every Python ↔ C ↔ asm crossing in §7.2's 3×3 matrix.
**MOAD-0001 note.** Each call is O(log n) in the value, not in the heap or the symbol table. No hidden linear scan, no per-call allocation in C or asm. Safe to invoke inside a tight loop without inflating the overall complexity class.
10. Relationship to Companion Papers
--------------------------------------