<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>numericalprogramming &amp;mdash; Nat Knight</title>
    <link>http://natknight.xyz/tag:numericalprogramming</link>
    <description>Reflections, diversions, and opinions from a progressive ex-physicist programmer dad with a sore back.</description>
    <pubDate>Sat, 23 May 2026 16:55:00 -0700</pubDate>
    <item>
      <title>Iterating over the Rational Numbers with Rust</title>
      <link>http://natknight.xyz/iterating-over-the-rational-numbers-with-rust</link>
      <description>&lt;![CDATA[#rust #functionalprogramming #numericalprogramming&#xA;&#xA;[Functional Pearl: Enumerating the Rationals] is a paper that&#39;s been on my &#34;to-read&#34; list for a long time. I finally got around to reading it a while back, and ended up implementing the algorithm it describes and publishing it as a [crate]. This article briefly describes that algorithm and some of the Rust-specific details of implementing it.&#xA;&#xA;!--more--&#xA;&#xA;The Algorithm&#xA;&#xA;The paper describes an algorithm which, starting from a base case, iterates through every possible rational number (up to the limitations of machine precision). The algorithm is interesting because:&#xA;&#xA;each value of the iterator is calculated from only the previous value (no extra state), and&#xA;each value can be calculated in a fixed number of arithmetic operations.&#xA;&#xA;There&#39;s a lengthy proof of why the algorithm works, but the essence is just a few lines of Haskell:&#xA;&#xA;rationals :: [Rational]&#xA;rationals = iterate next 1&#xA;next x = &#xA;  recip (fromInteger n + 1 - y)&#xA;  where (n, y) = properFraction x&#xA;&#xA;Where iterate, recip, fromInteger, and properFraction are functions from the Haskell prelude.&#xA;&#xA;The equivalent Rust code is something like:&#xA;&#xA;implT Iterator for RationalsT&#xA;where&#xA;    T: Integer + Clone + core::ops::Add,&#xA;{&#xA;    type Item = RatioT;&#xA;&#xA;    fn next(&amp;mut self) -  OptionSelf::Item {&#xA;        let r = self.state.clone();&#xA;        let n = r.trunc();&#xA;        let y = r.fract();&#xA;        let next = (n + T::one() - y).recip();&#xA;        self.state = next;&#xA;        Some(r)&#xA;    }&#xA;}&#xA;&#xA;The interesting part of the Rust implementation is how it&#39;s made generic over any numeric type that supports trunc, fract, and recip, and how that integrates with the broader Rust ecosystem.&#xA;&#xA;The Implementation&#xA;&#xA;The iterator is implemented on a struct which takes one generic parameter T, which must be an integer type. It yields ratios of integers of type T. Rather than just picking one integer type or implementing the iterator separately for u8, u32, u64, etc. we use:&#xA;&#xA;Generic Numeric Traits&#xA;&#xA;Specifically, it&#39;s implemented as a RatioInteger, which together provide all the operations we need for our algorithm.&#xA;&#xA;These come from a two different crates:&#xA;&#xA;num-rational provides Ratio&#xA;num-integer provides Integer.&#xA;&#xA;Integer is implemented for  [all the native integer types], so we can iterator over Ratios of u8, u32, u64. There are also other types that implement Integer (e.g: [numbigint::BigInt]) which might be useful in different circumstances (e.g: for arbitrary precision arithmetic which is accurate but slow).&#xA;&#xA;[numbigint::BigInt]: https://docs.rs/num-bigint/0.4.3/numbigint/struct.BigInt.html&#xA;&#xA;Directly implementing Iterator&#xA;&#xA;Rust has functions like [iter::repeatwith] that would let us more or less copy the Haskell code above, but it ended up being just as easy to [implement Iterator directly]. This also made the algorithm:&#xA;&#xA;no-std&#xA;&#xA;Since the implementation is just a bit of math and the types are all straightforward (at least in terms of memory) it ended up not depending on the Rust standard library (i.e. it&#39;s [no-std]), although at the time of writing, num-traits was having some [difficulty] with it&#39;s no-std builds that meant I couldn&#39;t actually test this.&#xA;&#xA;[iter::repeatwith]: https://doc.rust-lang.org/stable/std/iter/fn.repeatwith.html&#xA;[all the native integer types]: https://docs.rs/num-integer/latest/num_integer/trait.Integer.html#foreign-impls&#xA;[crate]: https://crates.io/crates/iter-rationals&#xA;[functional pearl: enumerating the rationals]: https://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/rationals.pdf&#xA;[no-std]: https://doc.rust-lang.org/stable/embedded-book/intro/no-std.html&#xA;[difficulty]: https://github.com/rust-num/num-traits/issues/138]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="http://natknight.xyz/tag:rust" class="hashtag"><span>#</span><span class="p-category">rust</span></a> <a href="http://natknight.xyz/tag:functionalprogramming" class="hashtag"><span>#</span><span class="p-category">functionalprogramming</span></a> <a href="http://natknight.xyz/tag:numericalprogramming" class="hashtag"><span>#</span><span class="p-category">numericalprogramming</span></a></p>

<p><a href="https://www.cs.ox.ac.uk/people/jeremy.gibbons/publications/rationals.pdf">Functional Pearl: Enumerating the Rationals</a> is a paper that&#39;s been on my “to-read” list for a long time. I finally got around to reading it a while back, and ended up implementing the algorithm it describes and publishing it as a <a href="https://crates.io/crates/iter-rationals">crate</a>. This article briefly describes that algorithm and some of the Rust-specific details of implementing it.</p>



<h2 id="the-algorithm" id="the-algorithm">The Algorithm</h2>

<p>The paper describes an algorithm which, starting from a base case, iterates through every possible rational number (up to the limitations of machine precision). The algorithm is interesting because:</p>
<ul><li>each value of the iterator is calculated from only the previous value (no extra state), and</li>
<li>each value can be calculated in a fixed number of arithmetic operations.</li></ul>

<p>There&#39;s a lengthy proof of why the algorithm works, but the essence is just a few lines of <a href="https://play.haskell.org/saved/6IG1LfcC">Haskell</a>:</p>

<pre><code class="language-haskell">rationals :: [Rational]
rationals = iterate next 1
next x = 
  recip (fromInteger n + 1 - y)
  where (n, y) = properFraction x
</code></pre>

<p>Where <a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:iterate">iterate</a>, <a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:recip">recip</a>, <a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:fromInteger">fromInteger</a>, and <a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:properFraction">properFraction</a> are functions from the <a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:properFraction">Haskell prelude</a>.</p>

<p>The equivalent Rust code is something like:</p>

<pre><code class="language-rust">impl&lt;T&gt; Iterator for Rationals&lt;T&gt;
where
    T: Integer + Clone + core::ops::Add,
{
    type Item = Ratio&lt;T&gt;;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        let r = self.state.clone();
        let n = r.trunc();
        let y = r.fract();
        let next = (n + T::one() - y).recip();
        self.state = next;
        Some(r)
    }
}
</code></pre>

<p>The interesting part of the Rust implementation is how it&#39;s made generic over any numeric type that supports <code>trunc</code>, <code>fract</code>, and <code>recip</code>, and how that integrates with the broader Rust ecosystem.</p>

<h2 id="the-implementation" id="the-implementation">The Implementation</h2>

<p>The iterator is implemented on a struct which takes one generic parameter <code>T</code>, which must be an integer type. It yields ratios of integers of type <code>T</code>. Rather than just picking one integer type or implementing the iterator separately for <code>u8</code>, <code>u32</code>, <code>u64</code>, etc. we use:</p>

<h3 id="generic-numeric-traits" id="generic-numeric-traits">Generic Numeric Traits</h3>

<p>Specifically, it&#39;s implemented as a <code>Ratio&lt;Integer&gt;</code>, which together provide all the operations we need for our algorithm.</p>

<p>These come from a two different crates:</p>
<ul><li><a href="https://docs.rs/num-rational/latest/num_rational/"><code>num-rational</code></a> provides <code>Ratio</code></li>
<li><a href="https://docs.rs/num-integer/latest/num_integer/"><code>num-integer</code></a> provides <code>Integer</code>.</li></ul>

<p><code>Integer</code> is implemented for  <a href="https://docs.rs/num-integer/latest/num_integer/trait.Integer.html#foreign-impls">all the native integer types</a>, so we can iterator over <code>Ratio</code>s of <code>u8</code>, <code>u32</code>, <code>u64</code>. There are also other types that implement <code>Integer</code> (e.g: <a href="https://docs.rs/num-bigint/0.4.3/num_bigint/struct.BigInt.html"><code>num_bigint::BigInt</code></a>) which might be useful in different circumstances (e.g: for arbitrary precision arithmetic which is accurate but slow).</p>

<h3 id="directly-implementing-iterator" id="directly-implementing-iterator">Directly implementing <code>Iterator</code></h3>

<p>Rust has functions like <a href="https://doc.rust-lang.org/stable/std/iter/fn.repeat_with.html"><code>iter::repeat_with</code></a> that would let us more or less copy the Haskell code above, but it ended up being just as easy to <a href="https://doc.rust-lang.org/stable/std/iter/index.html#implementing-iterator">implement <code>Iterator</code> directly</a>. This also made the algorithm:</p>

<h3 id="no-std" id="no-std"><code>no-std</code></h3>

<p>Since the implementation is just a bit of math and the types are all straightforward (at least in terms of memory) it ended up not depending on the Rust standard library (i.e. it&#39;s <a href="https://doc.rust-lang.org/stable/embedded-book/intro/no-std.html"><code>no-std</code></a>), although at the time of writing, <code>num-traits</code> was having some <a href="https://github.com/rust-num/num-traits/issues/138">difficulty</a> with it&#39;s <code>no-std</code> builds that meant I couldn&#39;t actually test this.</p>
]]></content:encoded>
      <guid>http://natknight.xyz/iterating-over-the-rational-numbers-with-rust</guid>
      <pubDate>Wed, 08 Mar 2023 08:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>