<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Linus’s Blog</title>
    <link href="http://funloop.org/atom.xml" rel="self" />
    <link href="http://funloop.org" />
    <id>http://funloop.org/atom.xml</id>
    <author>
        <name>Linus Arver</name>
        
    </author>
    <updated>2025-09-29T00:00:00Z</updated>
    <entry>
    <title>Status Update</title>
    <link href="http://funloop.org/post/2025-09-29-general-update.html" />
    <id>http://funloop.org/post/2025-09-29-general-update.html</id>
    <published>2025-09-29T00:00:00Z</published>
    <updated>2025-09-29T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2025-09-29-general-update.org" title="History"><code class="date">2025-09-29</code></a>
	<br>
	<a title="All pages tagged &#39;update&#39;." href="/tag/update.html" rel="tag">update</a>
</div>

<p>It’s been a long time. The most important thing you should know is that I’ve
been working on a new version of <a href="https://funloop.org/lilac-legacy">Lilac</a>; as such I’ve renamed the existing
version as <code>lilac-legacy</code>.</p>
<p>I’ve learned over the past year or so that I prefer literate programming over
any other programming paradigm. Sadly the tooling is just not that great
(<code>lilac-legacy</code> included) if you want to work with Orgmode as the foundation. This
is why I’ve spent a fair amount of time rewriting Lilac from scratch. I hope to
unveil it soon (hopefully within this year).</p>
<p>Another thing: I will probably port this blog over to use the new Lilac version
over the coming months. The reason is, I don’t want to maintain the tech stack
behind Hakyll (and the other programs I’ve written over the years on this blog).
Or, I may decide to just freeze the old posts and move them to a separate page.
Although, that’s probably not very desirable because it will break links for
people who have linked to this blog (there are quite a few hits if you search
for <code>funloop.org</code> on GitHub). I haven’t really done a blog tech stack migration
before (while keeping the same domain name), so it’ll be interesting.</p>
]]></summary>
</entry>
<entry>
    <title>Using Git the Right Way</title>
    <link href="http://funloop.org/post/2024-10-11-using-git-the-right-way.html" />
    <id>http://funloop.org/post/2024-10-11-using-git-the-right-way.html</id>
    <published>2024-10-11T00:00:00Z</published>
    <updated>2024-10-11T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2024-10-11-using-git-the-right-way.org" title="History"><code class="date">2024-10-11</code></a>
	<br>
	<a title="All pages tagged &#39;git&#39;." href="/tag/git.html" rel="tag">git</a>, <a title="All pages tagged &#39;programming&#39;." href="/tag/programming.html" rel="tag">programming</a>
</div>

<p>I’ll first describe 3 different levels of Git proficiency. Then I’ll discuss
ways to actually use Git “The Right Way” to get the most value out of it, and
end with some tips. Hopefully by the end of this post you’ll want to become an
advanced Git user if you’re not one already.</p>
<h1 id="beginner">Beginner</h1>
<p>You use Git as a necessary evil, because it’s mandated by your company to use
it. It’s the only way for you to contribute code, so you put up with it.</p>
<p>You use <code class="verbatim">git commit .</code> to commit everything in the (top-level?) directory, because
you don’t know how to use <code class="verbatim">git rebase -i</code> effectively.</p>
<h1 id="intermediate">Intermediate</h1>
<p>You realize that Git is a useful tool for organizing code changes. You have
multiple branches and know how to keep each one up-to-date. You might also know
how to use <code class="verbatim">git rebase -i</code> to clean up history, for example to separate out
formatting changes from semantic changes.</p>
<p>You use <code class="verbatim">git add -p</code> to help avoid needing to reach for <code class="verbatim">git rebase -i</code>.</p>
<h1 id="advanced">Advanced</h1>
<p>You appreciate Git commit messages as an important tool for archiving historical
context and knowledge about every code change. These commit messages are written
in stone forever, so you take care to craft each one with the utmost care. You
care about giving a good reason (the <em>why</em>) in each commit message. And sometimes
there are multiple “why” reasons: why you are authoring the commit at all in the
first place, as well as why you are choosing the particular approach in the code.</p>
<p>This makes it pleasant for others to review your code, because you’ve taken the
time to explain everything in each commit, perhaps even preemptively answering
questions that code reviewers might have.</p>
<p>You try your best to help others understand the benefit of clean, beautiful Git
history, because you know that future maintainers of the codebase will
appreciate the story behind how it evolved over time.</p>
<h1 id="using-git-the-right-way-as-an-advanced-user">Using Git “The Right Way” as an Advanced User</h1>
<p>But what does it mean to use Git as an advanced user? How do commits
actually get created in an advanced way? This is what that looks like in
practice:</p>
<ul>
<li><p>You have to make each commit do exactly one thing, and also explain why you
did it that way (esp. if there are several alternative paths you rejected).</p></li>
<li><p>You have to order each commit so that it makes sense from the reviewer’s point
of view as they review each commit one at a time (for example, you don’t want
to have a pure formatting (whitespace) commit right in the middle of your
5-commit PR).</p></li>
<li><p>When you get PR comments, you have to go back to each commit and modify each
one accordingly. That is, you mustn’t add a trailing “address PR comments”
commit at the end which does 5 different things in one commit. That’s because
there is little value in preserving the original approach (with all its warts)
if they’re going to be deprecated within the same PR by an “address PR
comments” commit at the end. And such commits are by definition poorly crafted
because they often do 2, 3, or 5 things at once in a single commit.</p></li>
</ul>
<p>The last point may be the dealbreaker for most Git users, because it requires
<code class="verbatim">git rebase -i</code> familiarity. However there are at least two fantastic benefits
that you get from a codebase where Git was used in “The Right Way”:</p>
<ul>
<li><p><strong>Code review becomes much more effective</strong>, because reviewers only have to focus
on one (neatly-explained and crafted) commit at a time. The signal-to-noise
ratio of each commit is high, so reviewers can spend more of their brainpower
actually thinking about the code, instead of fighting an uphill battle against
poorly organized commits that do several things at once (perhaps even wasting
time commenting on commit 1, only to see in commit 2 that a large chunk of
commit 1 has already been deprecated).</p></li>
<li><p><strong>Using <code class="verbatim">git-blame</code> becomes less noisy</strong>, because you’re not led back to messy
commits. This matters even more when the original authors of the codebase are
gone, because the value of a Git repo is that it can tell you a story of how
code changed over time. The value of this story is directly correlated with
the quality of the commit history. Woe to the developer who is led by
<code class="verbatim">git-blame</code> to a mega-commit (perhaps squashed together automatically by
GitHub), which squashes together 20 commits all together into a single
2000-line diff.</p></li>
</ul>
<p>The benefit to code review alone should be reason enough for you to get better
at using Git if you’re not comfortable with it already.</p>
<h1 id="tips-for-getting-better-at-git">Tips for getting better at Git</h1>
<h2 id="most-useful-git-commands">Most useful Git commands</h2>
<p>If I had to recommend 2 commands (which are most often neglected), it would be:</p>
<ul>
<li><p><code class="verbatim">git add -p</code> to add only those pieces that belong logically together, and</p></li>
<li><p><code class="verbatim">git rebase -i</code> to modify history for both preparing a PR for review, as well as
addressing review comments on a commit-by-commit basis (and not overall PR
basis as mentioned above with “address PR comments”)</p></li>
</ul>
<p>These two commands help you craft small, short-and-sweet commits that do one
thing well. It makes code review a breeze because the reviewer only has to look
at each of these small commits, one at a time.</p>
<h2 id="dont-create-meaningless-merges">Don’t create meaningless merges</h2>
<p>Another thing you can do is to avoid merging in the latest <code class="verbatim">main</code> (or <code class="verbatim">master</code>)
branch into your PR branch. GitHub shockingly encourages this horrible behavior,
encouraging newcomers to create many useless merge commits in a PR before it is
merged, making a real mess of the history.</p>
<p>Never merge <code class="verbatim">main</code> into your branch. Instead, every PR should have only 1 merge
commit — when the PR is merged into <code class="verbatim">main</code>. This keeps the history clean.</p>
<h2 id="rich-commit-messages">Rich commit messages</h2>
<p>Lastly, I recommend using the <strong>active voice</strong> in <strong>present tense (imperative mood)</strong> to
keep commit messages as <strong>direct</strong> as possible. Here’s an example of a noisy commit
message not adhering to these rules:</p>
<pre class="example"><code>fixed string buffer to have dynamically allocated memory instead of statically allocated limit of 255 characters sometimes we might need more than this esp on production
</code></pre>
<p>Terrible, right? Here’s why:</p>
<ul>
<li><p>There’s no commit message. It’s just the commit title.</p></li>
<li><p>The commit title is a long string (far over the recommended 50-character
limit) that will get truncated by GitHub on some of its UIs, not to mention
other Git tooling.</p></li>
<li><p>There is no use of punctuation like this sentence which makes it a run-on
sentence that makes it hard to read because punctuation was designed to help
break up long series of words into smaller chunks of logical groupings do you
really like to read long sentences without any punctuation I don’t think so
but if you do then I don’t know what to say about that.</p></li>
<li><p>It’s messy. There are several ideas here (string buffers, memory allocation,
hardcoded limits, and real-world production use-cases), but they aren’t really
given any attention individually. Instead they’re all jumbled up together into
one big mess.</p></li>
</ul>
<p>In summary, there are all of these <em>speed bumps</em> that just get in your way. It has
a very low signal-to-noise ratio. Well, at least it’s better than “fix string
bug” or some other lazy gibberish.</p>
<p>Now consider how the same commit message could have been written:</p>
<pre class="example"><code>module foo: use dynamic strings to avoid truncation

The use of the 255-character limit for strings in module foo was first
introduced in 0a6f593 (use fixed sizes for strings, 2022-03-14). This
worked for a long time because we always knew (at program init time)
what each string looked like.

But then 51b475c (allow changing strings during runtime, 2024-06-29)
introduced the ability for strings to be reassigned during runtime, not
just at program initialization. This means that sometimes users were
assigning strings longer than 255 characters without realizing that this
was the case, because we don&#39;t perform input validation during string
reassignments. This led to these strings getting silently truncated,
leading to a jarring experience later on.

Drop the 255-character limit, and instead use dynamic strings. We could
probably get away with a larger 1024-character limit, but then given how
most strings are far less than 1024 characters, using a larger hardcoded
limit would lead to a large amount of memory being wasted in practice.
If we do need to go back to a larger hardcoded limit in the future, we
could consider moving toward a model of multiple hardcoded limits,
perhaps 255, 512, and 1024. For now, using dynamic allocation everywhere
is simpler, so that&#39;s what we do here.
</code></pre>
<p>And here’s why it’s better:</p>
<ul>
<li><p>It had a clear title. It even has a “module foo” prefix to signal that it’s
about the “foo” module.</p></li>
<li><p>It shares some historical knowledge (which is already present in Git but
perhaps not obvious to those not familiar with “module foo”) to explain the
problem, its origins, and current status quo. It references important
historical events with the associated commit messages, using <code class="verbatim">git show
 --no-patch --pretty=reference</code> output. The historical tour of these important
commits provides a huge amount of value behind the motivation of this commit.</p></li>
<li><p>It uses imperative mood “Drop the 255-character limit, and instead use dynamic
strings” to emphasize (and summarize) what’s actually changing in this commit.
So now when reviewers read this commit, they already know what to look for
(did the committer actually remove all fixed string limits?). This <em>empowers</em>
reviewers, because now they know what to expect.</p></li>
<li><p>It explains how the problem was happening, with “This means that sometimes
users were assigning strings longer than 255 characters without realizing that
this was the case, because we don’t perform input validation during string
reassignments.” A good reviewer may ask “why not just add input validation as
an alternative solution, instead of using dynamic allocation, to fix the
problem?” during code review. A commit message isn’t good because it’s some
bulletproof case for doing something a particular way — it also exposes
(perhaps unintentionally) any possible weaknesses with the chosen approach by
providing sufficient context into the problem space.</p></li>
<li><p>It uses well-formed sentences! With punctuation!</p></li>
<li><p>It has no typos and observes the “~50 char title, 72 char commit message”
rule. The 72 characters for commit messages could be relaxed to 80 or 100, but
you don’t want it too long because shorter columns are simply easier to read
when scanning the text with your eyes.</p></li>
</ul>
<p>Of course, it is longer. And it took more effort to write. I’m arguing that such
effort is worth it for future maintainers (maybe it’ll be the same person who
authored the commit 6 months later who has forgotten everything about “module
foo”).</p>
<h1 id="conclusion">Conclusion</h1>
<p>Hopefully I’ve convinced you that using Git is much more nuanced than simply
knowing the right commands. If you want to get exposure to a project that
follows the above recommendations (full of advanced Git users), I recommend the
<a href="https://git-scm.com/community">Git project itself</a>.</p>
<p>Please use Git to its full potential. Don’t settle!</p>
]]></summary>
</entry>
<entry>
    <title>A New Chapter Begins</title>
    <link href="http://funloop.org/post/2024-06-29-a-new-chapter-begins.html" />
    <id>http://funloop.org/post/2024-06-29-a-new-chapter-begins.html</id>
    <published>2024-06-29T00:00:00Z</published>
    <updated>2024-06-29T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2024-06-29-a-new-chapter-begins.org" title="History"><code class="date">2024-06-29</code></a>
	<br>
	<a title="All pages tagged &#39;life&#39;." href="/tag/life.html" rel="tag">life</a>
</div>

<h1 id="jobs">Jobs</h1>
<p>I recently started work at Qantas, focusing on backend systems written in
Clojure! It’s an interesting change from the Golang work I did at Google for the
Kubernetes community (primarily on <a href="https://github.com/kubernetes-sigs/prow">Prow</a>, the Kubernetes-native CI system). I
expect to learn lots of new things and continue to grow as an engineer.</p>
<p>The opportunity at Qantas presents a unique proposition to me because I’ve
somehow managed to avoid getting familiar with Java and the JVM so far in my
career. I’ve been doing some Clojure exercises on <a href="https://exercism.org/profiles/listx">Exercism</a> for a few weeks now
and am getting the hang of the language. And I’ve been liking it so far — it
feels like Haskell without all of the mind-bending GHC extensions, plus a great
library/ecosystem story (seamless JVM interop). Oh and I actually prefer Lisp
syntax over Haskell syntax (I’ll choose Lisp macros over Template Haskell, every
time).</p>
<h1 id="blog">Blog</h1>
<p>I have some other blog post items in the backlog, so I plan on getting around to
them in due time. I’ve just cleaned out some of the bitrot that’s been plaguing
this site’s codebase for a while, so things are in working order again.</p>
<h1 id="git">Git</h1>
<p>I must mention that a few months back the Git community interviewed me for their
<a href="https://git.github.io/rev_news/2024/03/31/edition-109/#developer-spotlight-linus-arver">Developer Spotlight</a>! Sadly I haven’t been involved much with Git as of late (due
to moving countries, and also battling a nasty cold), but I do hope to upstream
the 50+ patches I still have locally for improving the parser for the
<code class="verbatim">git-interpret-trailers</code> subcommand. You could say that those patches helped me
understand how to work with the Git mailing list (as well as getting used to
writing C again).</p>
<p>I also started using Notmuch again inside Emacs to communicate with the mailing
list. I should write a short post about it.</p>
<h1 id="australia">Australia</h1>
<p>I’m now in Australia! How exciting! I fell in love with the country when I first
visited it in 2019, and now I feel very lucky to call Australia home. I’m slowly
getting used to the accent, and I do wonder if I’ll ever pick it up myself.</p>
<p>The weather has been a bit wild (we had a cold snap with sub-zero temperatures
in the first couple weeks of winter), but I really can’t complain because it’s
still quite nice compared to Seattle’s cold and wet climate.</p>
<p>Cheers!</p>
]]></summary>
</entry>
<entry>
    <title>Lilac and Codex</title>
    <link href="http://funloop.org/post/2023-11-21-lilac-and-codex.html" />
    <id>http://funloop.org/post/2023-11-21-lilac-and-codex.html</id>
    <published>2023-11-21T00:00:00Z</published>
    <updated>2023-11-21T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2023-11-21-lilac-and-codex.org" title="History"><code class="date">2023-11-21</code></a>
	<br>
	<a title="All pages tagged &#39;programming&#39;." href="/tag/programming.html" rel="tag">programming</a>
</div>

<p>TL;DR: Check out my new open source projects, <a href="https://funloop.org/lilac-legacy">Lilac</a> (<a href="https://github.com/listx/lilac-legacy">GitHub</a>) and <a href="https://funloop.org/codex">Codex</a> (<a href="https://github.com/listx/codex">GitHub</a>)!</p>
<h1 id="lilac">Lilac</h1>
<p><a href="https://funloop.org/lilac-legacy">Lilac</a> builds on top of Emacs Orgmode to make Literate Programming (LP) targeting
HTML
much more pleasant than the default experience. It’s unapologetically
opinionated. It encourages heavy use of Noweb-style references.</p>
<p>Most people don’t believe in LP, which means it’ll get little use. But there is
at least one user, officially…</p>
<h1 id="codex">Codex</h1>
<p><a href="https://funloop.org/codex">Codex</a> uses Lilac! Codex is a collection of blogpost-worthy solutions for some
programming
problems. I’m mainly doing this because it’s really fun for me when I dive deep
into technical problems.</p>
<p>Using Lilac and LP is a natural choice for Codex, because many (if not all?) the
topics are small enough to be read and understood in one sitting. Bite-sized
knowledge, my favorite!</p>
<h1 id="lp-is-amazing">LP is amazing</h1>
<p>I’m starting to think that any new programming project of mine should be done
with LP. There’s already been numerous times when I had to dig deep into Lilac
to edit things around after taking a long break, fearing that I may have trouble
regaining context to become productive; and each time I was surprised to see how
easy it was to context-switch.</p>
<p>Thank you, Donald Knuth, for introducing LP to the world!</p>
]]></summary>
</entry>
<entry>
    <title>Git Archaeology</title>
    <link href="http://funloop.org/post/2023-03-21-git-archaeology.html" />
    <id>http://funloop.org/post/2023-03-21-git-archaeology.html</id>
    <published>2023-03-21T00:00:00Z</published>
    <updated>2023-03-21T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2023-03-21-git-archaeology.org" title="History"><code class="date">2023-03-21</code></a>
	<br>
	<a title="All pages tagged &#39;programming&#39;." href="/tag/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;git&#39;." href="/tag/git.html" rel="tag">git</a>
</div>

<p>TL;DR: Check out my <a href="https://github.com/listx/git/blob/study/STUDY_NOTES.md">STUDY_NOTES.md</a> on Git if you want a quick understanding of (ancient) Git internals!</p>
<p>I’ve been using Git since 2009. In all that time I never really bothered with
understanding Git internals, because frankly after learning what a directed
acyclic graph (DAG) was, everything just fell into place.</p>
<p>That’s going to change, because in the coming weeks, I will start contributing
to Git on a somewhat regular basis (at least, that’s the plan). It won’t be the
first time contributing to the project (which I did back in <a href="2014-09-09-my-first-contribution-to-git.html">2014</a>), but I will
need to begin studying how Git works under the hood.</p>
<p>To that end, I spent the better part of last weekend trying to understand Git’s
internals. The current Git codebase is a bit daunting, and there’s no way that
I’m going to read it all any time soon. But the very first commit of Git <em>is</em>
small enough to read in one sitting, and so I tried compiling it (there were
lots of errors), while taking notes in the source code directly. I also actually
used the produced binaries to prove to myself that yes, this system actually
does work even at this primitive stage.</p>
<p>Now, there <strong>are</strong> major differences between this ancient root-commit version of
“Git” and modern Git. However, I’ve taken note of all such differences (at least
as many as I could gather, within reason) by digging into the <a href="https://lore.kernel.org/git/">Git mailing list archive</a> to try to make sense of why things were changed the way they were (e.g.,
How come we have so-called “pack” files? How come the SHA1 hash of an object
(using <code class="verbatim">sha1sum</code>) is not the same as its directory name plus filename?) You can
see my notes in the <a href="https://github.com/listx/git/blob/study/STUDY_NOTES.md">STUDY_NOTES.md</a> file for the answers.</p>
<p>I have to admit that I found Linus Torvalds’ initial design decisions to be
impressively elegant. Reading the first commit made me have multiple “ah-ha!”
moments behind why Git has a distinction between the index and the working tree,
why it doesn’t track empty directories, why Git doesn’t care if you blow away
the working tree as long as the <code class="verbatim">.git</code> folder is intact, etc. And the code is
pretty easy to follow! It’s a great resource for any aspiring C hacker.</p>
<p>Note: I’ve reproduced the study notes below for posterity. Do check out <a href="https://github.com/listx/git/tree/study">the branch directly</a>, or apply <a href="https://github.com/listx/listx_blog/tree/master/file/git-archaeology">the patches</a> yourself on the root commit.</p>
<h1 id="root-commit-git-study-notes">Root-commit Git study notes</h1>
<p>This is a special branch of Git for learning purposes. It is special
because it is based off the absolute minimal “ancient” implementation of
Git (Linus Torvald’s root commit at
<a href="https://github.com/git/git/commit/e83c5163316f89bfbde7d9ab23ca2e25604af290"><code class="verbatim">e83c5163316f89bfbde7d9ab23ca2e25604af290</code></a>),
with some small changes to make it easy to compile with
<a href="https://nixos.org/download.html">Nix</a> (see the Makefile changes) and
also “feel” more like modern Git (namely, the use of <code class="verbatim">.git/</code> instead of
<code class="verbatim">.dircache/</code>). Yes, you can technically grab the
<a href="https://github.com/git/git/commit/6ad6d3d36c5924c8ff502ebbb6a6216df01e7efb">100th or so commit</a> which basically has all of the changes I made, but you’d
be dealing with a lot more code to read. If you just want to quickly
understand Git’s data structures, there’s honestly nothing faster than
reading the root commit (it’s only ~1000 lines of C, including comments)
and with some additional notes to fill in any missing gaps (which this
document tries to do).</p>
<p>The biggest revelation I had while creating these notes is that Git’s
data structures have proven to be incredibly stable — the initial idea
of an object database (<code class="verbatim">.git/objects/...</code>) and the cache (<code class="verbatim">.git/index</code>)
were there from day 1 and are still the main workhorses for Git. Knowing
these two concepts will radically reduce the perceived complexity of
modern Git’s numerous bells and whistles, as every other thing you see
in the <code class="verbatim">.git</code> folder are mere extensions of these two essential data
structures.</p>
<p>This version comes with a basic Usage Guide to help users actually use
the binaries that shipped with the root commit. Run <code class="verbatim">make</code> (you need the
<a href="https://nixos.org/download.html">Nix package manager</a>) and try to use
the commands in the order described in the Usage Guide below. After (or
perhaps before?) you run each command, read its source code. You might
want to have a look at <code class="verbatim">cache.h</code> first — but the main “meat” of it all
is in <code class="verbatim">update-cache.c</code> — which makes sense, because the cache is
always updated first before anything is written to the object database.</p>
<p>Pro tip: use
<a href="https://github.com/git/git/commit/6ad6d3d36c5924c8ff502ebbb6a6216df01e7efb"><code class="verbatim">6ad6d3d36c5924c8ff502ebbb6a6216df01e7efb</code></a>
as a shortcut to view the first 100ish commits in Git’s history. This is
handy to understand some of the early changes that went into Git. As a
bonus, this commit also updates the README to capture the workflow of
actually using GIT in its ancient form. Perhaps it is obvious, but use
<code class="verbatim">git log -p README</code> to see its history.</p>
<h1 id="data-structures">Data structures</h1>
<p>The two big data structures are:</p>
<ol type="1">
<li>The object database (all files under <code class="verbatim">.git/objects/...</code>), and</li>
<li>The index file (aka “cache”, at <code class="verbatim">.git/index</code>).</li>
</ol>
<p>Refer to README for a more thorough discussion of these data structures.
But here are a few more interesting notes about each data structure.</p>
<h2 id="the-object-database">The Object Database</h2>
<h3 id="the-8-bit-fanout">The 8-bit fanout</h3>
<p>The object database has 256 folders, named <code class="verbatim">00</code> through <code class="verbatim">ff</code> in hex
notation (the first 8 bits of the 20-byte SHA1 hashing scheme used to
generate the object IDs for this database). You may wonder why do we
bother with this structure (after all, all files are already named with
their unique SHA1 hash so the chance of an innocent collision is
virtually zero). Torvalds stated in
<a href="https://lore.kernel.org/git/Pine.LNX.4.58.0504220844390.2344@ppc970.osdl.org/">April 2005</a> that he didn’t want hundreds of thousands of files in one
subdirectory:</p>
<pre class="example"><code>The 8-bit initial fan-out is very much a
middle ground: we waste some space (and some time) doing it, but it does
make the really horrible case largely go away.
</code></pre>
<p>The “horrible case” probably refers to the possibility of hundreds of
thousands of files all residing in a single directory, which Torvalds
brought up in the linked email.</p>
<h3 id="object-ids">Object IDs</h3>
<p>You can run <code class="verbatim">sha1sum</code> of any file in the object database and the output
(SHA1 hash) will match the filename path. E.g.,</p>
<div class="sourceCode" id="cb2" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> sha1sum .git/objects/cc/41b0dfbe81a71ca922cda3c9de9db3a25a56b4</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">cc41b0dfbe81a71ca922cda3c9de9db3a25a56b4</span>  .git/objects/cc/41b0dfbe81a71ca922cda3c9de9db3a25a56b4</span></code></pre></div>
<p>and notice that <code class="verbatim">cc41b0dfbe81a71ca922cda3c9de9db3a25a56b4</code> matches the
<code class="verbatim">cc/41b0dfbe81a71ca922cda3c9de9db3a25a56b4</code>. However, this is no longer
the case and you’ll get a different SHA1 hash using any recent Git
version. The reason is because Git originally hashed the compressed
(post-zlibbed) contents, but now it hashes the decompressed
(pre-zlibbed) content. This switch-over was done in
<a href="https://github.com/git/git/commit/d98b46f8d9a3daf965a39f8c0089c1401e0081ee"><code class="verbatim">d98b46f8d9a3daf965a39f8c0089c1401e0081ee</code></a>
and
<a href="https://github.com/git/git/commit/f18ca7316631914776136455c151d70318299459"><code class="verbatim">f18ca7316631914776136455c151d70318299459</code></a>,
just a couple weeks after the root commit, mainly for performance
reasons (because <code class="verbatim">write-tree</code> was taking too long in applying patches).
See
<a href="https://lore.kernel.org/git/Pine.LNX.4.58.0504192337120.6467@ppc970.osdl.org/">the original discussion</a> and the
<a href="https://lore.kernel.org/git/Pine.LNX.4.58.0504200144260.6467@ppc970.osdl.org/">“Object DB conversion” announcement</a>.</p>
<p>Also see
<a href="https://matthew-brett.github.io/curious-git/reading_git_objects.html">this page</a> for a guide on using Python to check the hashes of objects (in
case you want to check the hash output independently of Git tooling).</p>
<h3 id="only-basic-compression">Only basic compression</h3>
<p>Modern Git uses at least two additional schemes not present in this
initial version to help reduce redundant data: pack files (record deltas
of similar objects), and recursive tree objects (that’s right, in the
original implementation, a tree object could only refer to blobs).</p>
<ol>
<li><p>Pack files</p>
<p>Note that in this version, Git treats a file’s content as an atomic unit
of data — it doesn’t perform any form of “chunking” to divide it up
into smaller bits (similar to what bittorrent does). So every file will
get its own blob, and the only way that a blob will be reused (thus
saving disk space) in a subsequent commit is if does not change. It must
match identically!</p>
<p>You may think, “why not just divide a file into chunks, and make blobs
out of each chunk?” — that way, you’d naturally get some level of
deduping, even without any additional work. Torvalds <a href="https://lore.kernel.org/git/Pine.LNX.4.58.0504151117360.7211@ppc970.osdl.org/">considered this but rejected the idea for two reasons: performance and simplicity</a>.</p>
<p>Just a couple months after the above email though, Git
<a href="https://github.com/git/git/commit/c323ac7d9c573c5ee8b45b9b9def92a4d4d8204d">learned about pack files</a>. Basically, pack files compress a range of reachable
objects between two commits and puts them all into two files, a pack
index (<code class="verbatim">.idx</code>) and pack (<code class="verbatim">.pack</code>) file. The basic idea is that you can
put all of these objects together in the <code class="verbatim">.pack</code> file, allowing you to
do some level of compression inside it (assuming you have lots of
objects that have similar content). Here is a description of how it
would work in
<a href="https://lore.kernel.org/git/Pine.LNX.4.58.0506260905200.19755@ppc970.osdl.org/">Torvald’s own words</a>. Here’s a somewhat retrospective
<a href="https://lore.kernel.org/git/Pine.LNX.4.58.0506271755140.19755@ppc970.osdl.org/">announcement</a>,
which explains that the previous “delta object” approach (where Git
stored delta objects in the object database) is deprecated (however, do
note that the algorithms to find the deltas (<code class="verbatim">diff_delta()</code>) was re-used
in the pack files, so not everything was discarded).</p>
<p>If you’re wondering why the pack files have a separate dedicated index
file, it basically comes down to
<a href="https://lore.kernel.org/git/Pine.LNX.4.58.0506261206170.19755@ppc970.osdl.org/">performance and simplicity, again</a>.</p></li>
<li><p>Recursive tree objects</p>
<p>As trees can currently only refer to blobs only, this means that every
commit is somewhat wasteful (although this has the unique property that
a single commit refers to a single tree object that has everything in
it).</p>
<p>Recursive tree objects were added in
<a href="https://github.com/git/git/commit/d6d3f9d0125a7215f3cdc2600b2307ca55b69536"><code class="verbatim">d6d3f9d0125a7215f3cdc2600b2307ca55b69536</code></a>.</p></li>
</ol>
<h2 id="the-cache">The Cache</h2>
<p>The cache, or index file, represents a tree “snapshot”. It is what is
staged, ready to be committed. More precisely, it is just a
<code class="verbatim">cache_header</code> followed by a list of <code class="verbatim">cache_entry</code> values, where each
<code class="verbatim">cache_entry</code> is a <code class="verbatim">blob</code> object’s metadata. Among other things, the
<code class="verbatim">cache_header</code> records how many cache entries there are in the index
file. This is still true in modern Git as of March 2023 — if you run
<code class="verbatim">hexdump -C .git/index | head -n1</code> you can see, for example:</p>
<div class="sourceCode" id="cb3" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> hexdump <span class="at">-C</span> .git/index <span class="kw">|</span> <span class="fu">head</span> <span class="at">-n1</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">00000000</span>  44 49 52 43 00 00 00 01  00 00 00 0d 64 15 77 69  <span class="kw">|</span><span class="ex">DIRC........d.wi</span><span class="kw">|</span></span></code></pre></div>
<p>where the <code class="verbatim">DIRC</code> is a magic number (standing for <code class="verbatim">dircache</code>, the
original name of the <code class="verbatim">.git</code> folder) followed by 4 bytes (unsigned int)
for the index version and another 4 bytes showing the number of cache
entries, or file paths, that are being “tracked” for purposes of tree
object creation. In the example above the index version is <code class="verbatim">1</code> (modern
Git uses version <code class="verbatim">2</code>), and there are <code class="verbatim">0x0d</code> or <code class="verbatim">13</code> cache entries, or
files, that would make up the current tree.</p>
<p>Note that if you run the above on an index file created by the original
<code class="verbatim">update-cache</code>, you would see instead something like:</p>
<div class="sourceCode" id="cb4" data-org-language="sh"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">$</span> hexdump <span class="at">-C</span> .git/index <span class="kw">|</span> <span class="fu">head</span> <span class="at">-n1</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ex">00000000</span>  43 52 49 44 01 00 00 00  01 00 00 00 2b 1a 2d 28  <span class="kw">|</span><span class="ex">CRID........+.-</span><span class="er">(</span><span class="kw">|</span></span></code></pre></div>
<p>because the byte order was using little-endian, “host byte order”. This
is what is meant by “native CPU byte format” comment in <code class="verbatim">cache.h</code>
(because most CPUs are Intel, and Intel uses little-endian). The byte
order was changed in
<a href="https://github.com/git/git/commit/ccc4feb579265266d0a4a73c0c9443ecc0c26ce3"><code class="verbatim">ccc4feb579265266d0a4a73c0c9443ecc0c26ce3</code></a>
to use big-endian, also called “network byte order”, for convenience
over NFS.</p>
<h2 id="other-missing-things-vs-modern-git">Other missing things vs modern Git</h2>
<p>This initial version of Git does not have support for <code class="verbatim">HEAD</code>
(<code class="verbatim">.git/HEAD</code>) or branches (<code class="verbatim">.git/refs/heads/...</code>). In fact there are no
human-friendly references at all! But one can easily understand that
references are just pointers to the object store — all you would need
is a way to keep track of the latest commit by saving its object ID
(SHA1 hash) somewhere. The simplest possible thing you could do is to
have a file with this object ID in it — and this is what modern Git
(still) does. The old
<a href="https://github.com/git/git/commit/6ad6d3d36c5924c8ff502ebbb6a6216df01e7efb">README</a>
notes that in practice, the SHA1 hash was written at <code class="verbatim">.git/HEAD</code>. It was
formally recognized as such just a day later in
<a href="https://github.com/git/git/commit/839a7a06f35bf8cd563a41d6db97f453ab108129"><code class="verbatim">839a7a06f35bf8cd563a41d6db97f453ab108129</code></a>, as part of the <code class="verbatim">git-prune-script</code>
and <code class="verbatim">git-pull-script</code> helpers to help with merging.</p>
<h2 id="usage-guide">Usage Guide</h2>
<p>This guide explains how the earliest version of Git (root commit) works.
You can read these steps and also look up the C source code and read
them to get a better sense of how everything works.</p>
<ol type="1">
<li><p>Initialize the object database with <code class="verbatim">init-db</code>. This is the <code class="verbatim">.git</code>
directory.</p></li>
<li><p>Make changes to files. These files can be any file except the <code class="verbatim">.git</code>
directory. We don’t have the concept of <code class="verbatim">.gitignore</code> yet, and also,
all dotfiles (any file that begins with a <code class="verbatim">.</code>) are ignored and cannot
be tracked by Git.</p></li>
<li><p>Stage modified files with <code class="verbatim">update-cache &lt;FILE&gt; [...FILES]</code>. This
compresses these files’ contents and saves them to the object
database, such that each file gets its own object database file. At
this point the files are tracked by Git. It also results in adding
this file’s metadata (essentially the filename and SHA1 of its
contents) to the <code class="verbatim">.git/index</code> file.</p></li>
<li><p>(Optional) Check the diff of what is in the <code class="verbatim">.git/index</code> (staged)
versus the current working tree with <code class="verbatim">show-diff</code>. We are just diffing
whatever is in the current cache <code class="verbatim">.git/index</code> (essentially the last
known “tree-to-be-written-to-object-database-but-not-yet”) and what
is on disk at those paths that the cache describes. The diffing
comparison is basic and is based on timestamps and inodes (presumably
for performance).</p>
<p>This diff is the ancient equivalent of <code class="verbatim">git diff</code>. If we add those
files that have been modified with <code class="verbatim">update-cache</code>, then <code class="verbatim">show-diff</code>
will show nothing, because the working tree files on disk match what
is in the index file (just like how modern <code class="verbatim">git diff</code> will show
nothing, unless you invoke <code class="verbatim">git diff --cached</code>, in this situation).</p>
<p>Note also that we are not comparing things to a previous commit of
any kind. Instead we are always only diffing the files that were
touched/modified (during the course of normal development) and what
the index file has. It’s even more primitive than the modern
“detached HEAD mode” in Git because we do not automatically diff
against a “current commit” because the concept of a “current commit”
doesn’t exist yet — we literally have blobs, trees, and commits in
the object database, the index file (describing whatever paths make
up another (perhaps new and unique) tree object), and the working
tree (everything except the <code class="verbatim">.git</code> folder).</p>
<p>Lastly, the <code class="verbatim">show-diff</code> command shells out to <code class="verbatim">diff</code> (so the codebase
doesn’t have any fancy diffing algorithms).</p></li>
<li><p>Run <code class="verbatim">write-tree</code> to save the data in <code class="verbatim">.git/index</code> is its own tree
object in the object database. The SHA1 of this tree object is
printed to STDOUT. Take a note of this SHA1 hash, as it will be
referenced to construct a commit (changeset) object.</p></li>
<li><p>(Optional) Check the SHA1 from <code class="verbatim">write-tree</code> with <code class="verbatim">read-tree &lt;SHA1&gt;</code>.
This will display the tree object (by displaying its blobs).</p></li>
<li><p>Create a new commit with
<code class="verbatim">echo "my-commit-message" | commit-tree &lt;SHA1&gt;</code>, using the SHA1 from
step 5 above. This will create a new commit object and write it to
the object database.</p></li>
<li><p>(Optional) Check the commit with <code class="verbatim">cat-file &lt;COMMIT_SHA1&gt;</code>. This will
write the commit message and metadata (including the tree SHA (and
parent commit SHAs for non-root commits)) to a temporary file. You
can just <code class="verbatim">cat</code> out this file to see it (commit date, author name,
email, etc.).</p>
<p>The fact that <code class="verbatim">cat-file</code> writes to disk is a bit annoying, and so it
learned to output to STDOUT in
<a href="https://github.com/git/git/commit/bf0c6e839c692142784caf07b523cd69442e57a5"><code class="verbatim">bf0c6e839c692142784caf07b523cd69442e57a5</code></a>.</p></li>
<li><p>Repeat steps 2-7 above, but for step 5 pass in the <code class="verbatim">-p &lt;SHA1&gt;</code> flag
to mark it as a child of a previous commit SHA. You can pass in
multiple <code class="verbatim">-p</code> flags to denote multiple parents (e.g., a merge). For
the very first merge in Git’s own history, see
<a href="https://github.com/git/git/commit/b51ad4314078298194d23d46e2b4473ffd32a88a"><code class="verbatim">b51ad4314078298194d23d46e2b4473ffd32a88a</code></a>.</p></li>
</ol>
]]></summary>
</entry>
<entry>
    <title>Bresenham's Circle Drawing Algorithm</title>
    <link href="http://funloop.org/post/2021-03-15-bresenham-circle-drawing-algorithm.html" />
    <id>http://funloop.org/post/2021-03-15-bresenham-circle-drawing-algorithm.html</id>
    <published>2021-03-15T00:00:00Z</published>
    <updated>2021-03-15T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2021-03-15-bresenham-circle-drawing-algorithm.org" title="History"><code class="date">2021-03-15</code></a>
	<br>
	<a title="All pages tagged &#39;programming&#39;." href="/tag/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;math&#39;." href="/tag/math.html" rel="tag">math</a>
</div>

<!-- This is from https://rustwasm.github.io/docs/wasm-bindgen/examples/without-a-bundler.html. -->
<!-- The `type=module` is required if we want to use the "import" statement. -->
<script type="module">
  import init from '../rust-js/js/rust_js.js';

  async function run() {
    await init();

    // Here we can use the JS generated by Rust. For example, you might do:
    //
    //    const result = add_from_rust(1, 2);
    //    console.log(`1 + 2 = ${result}`);
    //    if (result !== 3)
    //      throw new Error("wasm addition doesn't work!");
    //
    // However, the entrypoint() function in the Rust library calls the
    // "draw_all_circles()" function which finds all Canvas elements with
    // specially-named ID fields, so there is no need to call the functions from
    // here at all.
  }

  run();
</script>

<p>Once upon a time I was given the following problem for a technical programming interview:</p>
<blockquote>
<p>Write a function <code>draw_circle(r)</code> that draws a circle with radius <code>r</code>. Use the given method <code>draw_pixel(x, y)</code> which takes a 2-dimensional point <code>(x, y)</code> and colors it in on the computer screen.</p>
</blockquote>
<p>For the solution, you can either collect all pixels (tuples) of <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> coordinate pairs, or just call <code>draw_pixel()</code> on them during the “search” for those pixels that must be filled in.</p>
<p>This post goes over several solutions, ultimately arriving at Bresenham’s algorithm.
The content of this post is merely a distillation of Section 3.3 from the book “Computer Graphics: Principles and Practice (1996)”.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
The authors of the book state that their implementation results in code “essentially the same as that specified in patent 4,371,933 [a.k.a. Bresenham’s algorithm].”<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<p>I’ve gone all out and converted the “reference” implementations found in the book and translated them into Rust and Python.
The Python was written first, and I used a text-based drawing system to test the correctness.
However I became dissatisfied with the non-square “aspect ratio” of most monospaced fonts out there, which distorted the circles to look more like ellipses.
To fix this, I decided to port the Python code to Rust, and then target WASM so that I can use it to draw on the HTML5 <code>&lt;canvas&gt;</code> elements (and to eliminate the “aspect ratio” problem).
All of the drawings in this document are powered by the Rust code.</p>
<h1 id="constraints">Constraints</h1>
<h2 id="drawable-canvas">Drawable canvas</h2>
<p>Before we start, let’s define the drawable surface (canvas) of pixels for this problem.
The pixels are arranged in a 2-dimensional grid.
The important thing here is the grid or coordinate system, with the pixel at the center of the grid having the traditional <code>(0, 0)</code> Cartesian coordinate.</p>
<p>Below is a sample grid to give you a sense of what this will look like.
There is a central <code>(0, 0)</code> origin pixel, and 15 pixels to the north, south, east, and west, and everything in-between.
Pixels that lie on interesting points of symmetry are highlighted in green.</p>
<canvas id="blank__14__20"></canvas>

<h2 id="mathematical-definitions">Mathematical definitions</h2>
<p>The exact definition of a circle (given infinite precision, as on the traditional Cartesian plane) centered at the origin is</p>
<p><span class="math display">\[
\begin{equation} \label{eq:circle}
x^2 + y^2 = r^2.
\end{equation}
\]</span></p>
<p>This resembles the Pythagorean Theorem</p>
<p><span class="math display">\[
a^2 + b^2 = c^2,
\]</span></p>
<p>for any right-angled triangle with sides <span class="math inline">\(a\)</span> and <span class="math inline">\(b\)</span> and hypotenuse <span class="math inline">\(c\)</span>.
The resemblance is not a coincidence, because an infinite number of such triangles exists within the top right quadrant of the plane (that is, Quadrant I<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>, or the part of the plane such that <span class="math inline">\(x \geq 0\)</span> and <span class="math inline">\(y \geq 0\)</span>); in Quadrant I, for all points <span class="math inline">\((x,y)\)</span> that make up this portion (or arc) of the circle, their radii is the same as the hypotenuses of these triangles (whose sides are <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span>).
Later in this post, this will become relevant again when we discuss <a href="https://en.wikipedia.org/wiki/Pythagorean_triple">Pythagorean Triples</a>.</p>
<p>Anyway, solving for <span class="math inline">\(y\)</span> in Equation <span class="math inline">\(\ref{eq:circle}\)</span> gives</p>
<p><span class="math display">\[
\begin{equation} \label{eq:circle-y}
y = \pm\sqrt{r^2 - x^2}
\end{equation}
\]</span></p>
<p>to get 2 functions for the top-half and bottom-half of the circle (that’s what the <span class="math inline">\(\pm\)</span> symbol means).
Consider the function <span class="math inline">\(y = x\)</span>.
This function has slope 1 and is a diagonal line where all values of <span class="math inline">\(x = y\)</span>.
Now consider how this line intersects the quarter-arc of the circle in Quadrant I.
This intersection point evenly divides the arc into 2 halves, and is where</p>
<p><span class="math display">\[
x = y = \tfrac{r}{\sqrt{2}},
\]</span></p>
<p>or simply the point</p>
<p><span class="math display">\[
\begin{equation}
(\tfrac{r}{\sqrt{2}}, \tfrac{r}{\sqrt{2}}).
\end{equation}
\]</span></p>
<p>This is because if <span class="math inline">\(x = y\)</span>, then Equation <span class="math inline">\(\ref{eq:circle}\)</span> becomes</p>
<p><span class="math display">\[
\begin{align}
x^2 + y^2 &amp;= r^2
\\
x^2 + x^2 &amp;= r^2
\\
2x^2 &amp;= r^2
\\
\tfrac{2x^2}{2} &amp;= \tfrac{r^2}{2}
\\
x^2 &amp;= \tfrac{r^2}{2}
\\
\sqrt{x^2} &amp;= \tfrac{\sqrt{r^2}}{\sqrt{2}}
\\
x &amp;= \tfrac{r}{\sqrt{2}}. \label{eq:arc-intersection}
\end{align}
\]</span></p>
<p>This is not that interesting for purposes of the algorithms in this post, but is something that is glossed over in the book.</p>
<h2 id="symmetry">Symmetry</h2>
<p>Because of symmetry, we can mirror the solution <span class="math inline">\((x,y)\)</span> pairs we get in Quadrant I into the other quadrants.
This gives us 4-way symmetry because there are 4 quadrants.</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb1" data-startFrom="164"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 163;"><span id="cb1-164"><a href="#cb1-164"></a><span class="kw">def</span> mirror_points_4(x, y):</span>
<span id="cb1-165"><a href="#cb1-165"></a>    <span class="co">&quot;&quot;&quot; Return 4-way symmetry of points. &quot;&quot;&quot;</span></span>
<span id="cb1-166"><a href="#cb1-166"></a>    <span class="cf">return</span> [( x,  y),</span>
<span id="cb1-167"><a href="#cb1-167"></a>            (<span class="op">-</span>x,  y),</span>
<span id="cb1-168"><a href="#cb1-168"></a>            ( x, <span class="op">-</span>y),</span>
<span id="cb1-169"><a href="#cb1-169"></a>            (<span class="op">-</span>x, <span class="op">-</span>y)]</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>lib.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/lib.py#L164-L169"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/lib.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>Note, however, that there is actually 8-way symmetry at hand because (1) we can swap <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span>, and (2) because of the way we can distribute the negative sign:</p>
<table>
<thead>
<tr>
<th>#</th>
<th>Coordinate</th>
<th>Quadrant</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><code>( x, y)</code></td>
<td>I</td>
</tr>
<tr>
<td>2</td>
<td><code>( y, x)</code></td>
<td>I</td>
</tr>
<tr>
<td>3</td>
<td><code>(-x, y)</code></td>
<td>II</td>
</tr>
<tr>
<td>4</td>
<td><code>(-y, x)</code></td>
<td>II</td>
</tr>
<tr>
<td>6</td>
<td><code>(-x,-y)</code></td>
<td>III</td>
</tr>
<tr>
<td>5</td>
<td><code>(-y,-x)</code></td>
<td>III</td>
</tr>
<tr>
<td>7</td>
<td><code>( x,-y)</code></td>
<td>IV</td>
</tr>
<tr>
<td>8</td>
<td><code>( y,-x)</code></td>
<td>IV</td>
</tr>
</tbody>
</table>
<div class="code-and-raw">
<div class="sourceCode" id="cb2" data-startFrom="172"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 171;"><span id="cb2-172"><a href="#cb2-172"></a><span class="kw">def</span> mirror_points_8(x, y):</span>
<span id="cb2-173"><a href="#cb2-173"></a>    <span class="co">&quot;&quot;&quot; Return 8-way symmetry of points. &quot;&quot;&quot;</span></span>
<span id="cb2-174"><a href="#cb2-174"></a>    <span class="cf">return</span> [( x,  y),</span>
<span id="cb2-175"><a href="#cb2-175"></a>            ( y,  x),</span>
<span id="cb2-176"><a href="#cb2-176"></a>            (<span class="op">-</span>x,  y),</span>
<span id="cb2-177"><a href="#cb2-177"></a>            (<span class="op">-</span>y,  x),</span>
<span id="cb2-178"><a href="#cb2-178"></a>            ( x, <span class="op">-</span>y),</span>
<span id="cb2-179"><a href="#cb2-179"></a>            ( y, <span class="op">-</span>x),</span>
<span id="cb2-180"><a href="#cb2-180"></a>            (<span class="op">-</span>x, <span class="op">-</span>y),</span>
<span id="cb2-181"><a href="#cb2-181"></a>            (<span class="op">-</span>y, <span class="op">-</span>x)]</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>lib.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/lib.py#L172-L181"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/lib.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>Fun fact: the exact point at which <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> get “swapped” in Quadrant I is when <span class="math inline">\(x = y = \tfrac{r}{\sqrt{2}}\)</span> (Equation <span class="math inline">\(\ref{eq:arc-intersection}\)</span>).</p>
<h1 id="naive-solutions">Naive solutions</h1>
<p>When in doubt, brute force is always a great answer, because at least it gets you started on something that works given enough time and/or memory.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>
Because we already have clear mathematical definitions, we can just translate them (albeit mechanically) to code.</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb3" data-startFrom="7"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 6;"><span id="cb3-7"><a href="#cb3-7"></a><span class="kw">def</span> get_circle_points_naive_4(r):</span>
<span id="cb3-8"><a href="#cb3-8"></a>    <span class="co">&quot;&quot;&quot; Draw a circle by pairing up each Y value with an X value that lie on a</span></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="co">    circle with radius &#39;r&#39;. This has a bug because some Y values get skipped.</span></span>
<span id="cb3-10"><a href="#cb3-10"></a><span class="co">    Can you see why?</span></span>
<span id="cb3-11"><a href="#cb3-11"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb3-12"><a href="#cb3-12"></a>    points <span class="op">=</span> []</span>
<span id="cb3-13"><a href="#cb3-13"></a>    <span class="cf">for</span> x <span class="kw">in</span> <span class="bu">range</span>(r <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb3-14"><a href="#cb3-14"></a>        <span class="co"># isqrt() gets the integer square root.</span></span>
<span id="cb3-15"><a href="#cb3-15"></a>        y <span class="op">=</span> isqrt((r <span class="op">*</span> r) <span class="op">-</span> (x <span class="op">*</span> x))</span>
<span id="cb3-16"><a href="#cb3-16"></a>        points.extend(mirror_points_4(x, y))</span>
<span id="cb3-17"><a href="#cb3-17"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>naive.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py#L7-L17"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p><code>get_circle_points_naive_4()</code> is the simplest translation, although there is a bug, which is obvious when we visualize it (in this case, for <span class="math inline">\(r = 15\)</span>):</p>
<canvas id="naive_4__15__20"></canvas>

<p>The <code>get_circle_points_naive_4()</code> is based on Equation <span class="math inline">\(\ref{eq:circle-y}\)</span>.
We iterate <span class="math inline">\(x\)</span> from <span class="math inline">\(0\)</span> to <span class="math inline">\(r\)</span> <a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a>, and at each <span class="math inline">\(x\)</span> try to find the best value for <span class="math inline">\(y\)</span>.
The problem is that we’re only solving for 1 <span class="math inline">\(y\)</span> value for every <span class="math inline">\(x\)</span> value we increment by.
As we get near the left and right sides of the circle, we need to calculate more than just 1 <span class="math inline">\(y\)</span> value for every <span class="math inline">\(x\)</span>.<a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a>.</p>
<p>The <code>get_circle_points_naive_8()</code> function gets around this <span class="math inline">\(y\)</span>-skip bug by invoking 8-way symmetry instead:</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb4" data-startFrom="20"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 19;"><span id="cb4-20"><a href="#cb4-20"></a><span class="kw">def</span> get_circle_points_naive_8(r):</span>
<span id="cb4-21"><a href="#cb4-21"></a>    <span class="co">&quot;&quot;&quot; Better than get_circle_points_naive_4, but wastes CPU cycles because</span></span>
<span id="cb4-22"><a href="#cb4-22"></a><span class="co">    the 8-way symmetry overcorrects and we draw some pixels more than once.</span></span>
<span id="cb4-23"><a href="#cb4-23"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb4-24"><a href="#cb4-24"></a>    points <span class="op">=</span> []</span>
<span id="cb4-25"><a href="#cb4-25"></a>    <span class="cf">for</span> x <span class="kw">in</span> <span class="bu">range</span>(r <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb4-26"><a href="#cb4-26"></a>        y <span class="op">=</span> isqrt((r <span class="op">*</span> r) <span class="op">-</span> (x <span class="op">*</span> x))</span>
<span id="cb4-27"><a href="#cb4-27"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb4-28"><a href="#cb4-28"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>naive.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py#L20-L28"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<canvas id="naive_8__15__20"></canvas>

<p>However the downside is that it results in multiple points that will be drawn 2 times, wasting CPU cycles.<a href="#fn7" class="footnote-ref" id="fnref7" role="doc-noteref"><sup>7</sup></a>
To be more precise, all points around the gappy area in Quadrant I are redundant because that part of the arc is already mirrored nicely by the contiguous points from <span class="math inline">\(x = 0\)</span> to <span class="math inline">\(x = y\)</span>.</p>
<p>The <code>get_circle_points_naive_8_faster()</code> function avoids drawing the gappy areas by just breaking the loop when <span class="math inline">\(x &gt; y\)</span>, but is otherwise the same:</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb5" data-startFrom="31"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 30;"><span id="cb5-31"><a href="#cb5-31"></a><span class="kw">def</span> get_circle_points_naive_8_faster(r):</span>
<span id="cb5-32"><a href="#cb5-32"></a>    <span class="co">&quot;&quot;&quot; Slightly faster than get_circle_points_naive_8, because of the break</span></span>
<span id="cb5-33"><a href="#cb5-33"></a><span class="co">    condition at the middle of the arc. However this is still inefficient due</span></span>
<span id="cb5-34"><a href="#cb5-34"></a><span class="co">    to the square root calculation with `isqrt()`.</span></span>
<span id="cb5-35"><a href="#cb5-35"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb5-36"><a href="#cb5-36"></a>    points <span class="op">=</span> []</span>
<span id="cb5-37"><a href="#cb5-37"></a>    <span class="cf">for</span> x <span class="kw">in</span> <span class="bu">range</span>(r <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb5-38"><a href="#cb5-38"></a>        y <span class="op">=</span> isqrt((r <span class="op">*</span> r) <span class="op">-</span> (x <span class="op">*</span> x))</span>
<span id="cb5-39"><a href="#cb5-39"></a>        <span class="co"># When we cross the middle of the arc, stop, because we&#39;re already</span></span>
<span id="cb5-40"><a href="#cb5-40"></a>        <span class="co"># invoking 8-way symmetry.</span></span>
<span id="cb5-41"><a href="#cb5-41"></a>        <span class="cf">if</span> x <span class="op">&gt;</span> y:</span>
<span id="cb5-42"><a href="#cb5-42"></a>            <span class="cf">break</span></span>
<span id="cb5-43"><a href="#cb5-43"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb5-44"><a href="#cb5-44"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>naive.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py#L31-L44"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>This is the best we can do with the simple mathematical translations to code.
Note that in all of these implementations we are still forced to calculate square roots in every iteration, which is certainly suboptimal.</p>
<h1 id="bresenhams-algorithm">Bresenham’s Algorithm</h1>
<p>This as also known as the “Midpoint Circle Algorithm,” where the name “midpoint” comes from the mathematical calculations that are done by considering the midpoint <strong>between</strong> pixels.
The gist of the algorithm is that instead of using Equation <span class="math inline">\(\ref{eq:circle-y}\)</span> to calculate <span class="math inline">\(y\)</span> for every <span class="math inline">\(x\)</span>, instead you try to <em>move</em> along the arc of the circle, pixel-to-pixel, staying as close as possible to the true arc:</p>
<ol type="1">
<li>Start out from the top of the circle (color in pixel <span class="math inline">\((0, r)\)</span>). Note that because of symmetry, we could start out from <span class="math inline">\((0, -r)\)</span>, <span class="math inline">\((r, 0)\)</span>, or even <span class="math inline">\((-r, 0)\)</span> as Bresenham did in his paper.<a href="#fn8" class="footnote-ref" id="fnref8" role="doc-noteref"><sup>8</sup></a></li>
<li>Move right (east (E)) or down-right (southeast (SE)), whichever is closer to the circle.</li>
<li>Stop when <span class="math inline">\(x = y\)</span> (just like in <code>get_circle_points_naive_8_faster()</code>).</li>
</ol>
<p>The hard part is Step 2, where we just need to figure out which direction to move (E or SE) from the current pixel.
The brute force way here is to just calculate the distance away from the center of the circle for the E and SE pixels (using <a href="https://en.wikipedia.org/wiki/Euclidean_distance">Euclidean distance</a>, which is just a variation of Equation <span class="math inline">\(\ref{eq:circle}\)</span> or the Pythagorean Theorem), and just choose the pixel that is closest to the arc of the circle.
This makes sense, but with the power of mathematics, we can do better.</p>
<h2 id="inside-on-or-outside-the-circle">Inside, on, or outside the circle?</h2>
<p>In order to figure out whether some point <span class="math inline">\((x, y)\)</span> is inside, on, or outside of the circle depends on the definition of the circle from Equation <span class="math inline">\(\ref{eq:circle}\)</span>.
We can tweak it in terms of any <span class="math inline">\((x, y)\)</span> pair:</p>
<p><span class="math display">\[
\begin{equation} \label{eq:error-margin}
F(x,y) = x^2 + y^2 - r^2 = \text{distance from true circle line}.
\end{equation}
\]</span></p>
<p>Note that if <span class="math inline">\(F(x,y) = 0\)</span>, then the point <span class="math inline">\((x, y)\)</span> is <em>exactly</em> on the circle.
If <span class="math inline">\(F(x,y) &gt; 0\)</span>, then the point is outside of the circle, and if <span class="math inline">\(F(x,y) &lt; 0\)</span> then the point is inside of it.
In other words, given any point <span class="math inline">\((x, y)\)</span>, <span class="math inline">\(F(x, y)\)</span> is the distance from the true circle line.</p>
<h2 id="choosing-between-e-or-se">Choosing between E or SE</h2>
<p>Let’s remind ourselves that we’ll always be moving E or SE.
One critical (pragmatic) property here is that we’re dealing with a pixel grid with integer increments.
There is a very high chance that neither the E or SE pixels we’re moving to is <strong>exactly</strong> on the circle.
This is because the only time that the point <span class="math inline">\((x,y)\)</span> will exactly be on the line of the circle is if the <span class="math inline">\(x\)</span>, <span class="math inline">\(y\)</span>, and <span class="math inline">\(r\)</span> values (as integers) form a so-called <a href="https://en.wikipedia.org/wiki/Pythagorean_triple">Pythagorean Triple</a>.
For <span class="math inline">\(r &lt; 100\)</span>, there are only 50 such triples:</p>
<pre><code>( 3, 4, 5)  (18,24,30)  (24,45,51)  (16,63,65)  (51,68,85)
( 6, 8,10)  (16,30,34)  (20,48,52)  (32,60,68)  (40,75,85)
( 5,12,13)  (21,28,35)  (28,45,53)  (42,56,70)  (36,77,85)
( 9,12,15)  (12,35,37)  (33,44,55)  (48,55,73)  (13,84,85)
( 8,15,17)  (15,36,39)  (40,42,58)  (24,70,74)  (60,63,87)
(12,16,20)  (24,32,40)  (36,48,60)  (45,60,75)  (39,80,89)
(15,20,25)  ( 9,40,41)  (11,60,61)  (21,72,75)  (54,72,90)
( 7,24,25)  (27,36,45)  (39,52,65)  (30,72,78)  (35,84,91)
(10,24,26)  (30,40,50)  (33,56,65)  (48,64,80)  (57,76,95)
(20,21,29)  (14,48,50)  (25,60,65)  (18,80,82)  (65,72,97)
</code></pre>
<p>In other words, for all practical purposes, <strong>there will always be some error</strong> and we’ll always be outside or inside the circle and never directly on it.
It’s sort of like driving a car and trying to stay within your designated lane: if you think you’re moving too much to the right, you turn your wheel left to stay “within” the lane (or some acceptable amount within the lane), and vice versa.</p>
<p>The idea is the same for moving along the circle: if we think we’re moving too far <em>outside</em> the circle, we try to move into it.
On the other hand, if we think we’re moving <em>into</em> the circle, we move out of it.
And so imagine yourself standing on point <span class="math inline">\((0, r)\)</span>, our starting point.
The line of the circle is our “lane” we want to stay “on” as much as possible.
Choosing to go E is the same as turning “left”.
Choosing to go SE is the same as turning “right”.
Using this metaphor, if we were not to turn at all (go “straight”), we would be heading to the virtual “in-between” pixel between E and SE, the <strong>midpoint</strong> between them.</p>
<p>And so here’s the basic idea behind choosing E or SE:</p>
<ol type="1">
<li>If going “straight” would mean going into the circle (i.e., we’re currently veering too much to the right!), we course-correct by turning left (E).</li>
<li>Conversely, if going “straight” would mean going outside the circle (i.e., we’re currently veering too much to the left), we course-correct by turning right (SE).</li>
<li>Lastly, if going “straight” would mean staying exactly on the circle (we hit a Pythagorean Triple), we turn SE (from an engineering perspective it doesn’t really matter which way we turn in this case, as both E and SE result in some amount of error — although see <a href="#final-tweaks">“Final tweaks”</a> below for a note on aesthetics).</li>
</ol>
<p>Let’s convert this idea into pseudocode:</p>
<pre><code>Let M be the midpoint (going &quot;straight&quot;).

Then, F(M) tells us what direction we&#39;re headed relative to the true circle line.

If F(M) is &lt; 0, we&#39;re moving &quot;into&quot; the circle (veering right), so turn left by moving E.

Otherwise move SE.
</code></pre>
<p>Note that we only have to calculate <span class="math inline">\(F(...)\)</span> for the midpoint <span class="math inline">\(M\)</span>.
Isn’t this cool?
It is much better than calculating <span class="math inline">\(F(E)\)</span> and <span class="math inline">\(F(SE)\)</span> and having to compare them!</p>
<div class="sourceCode" id="cb8" data-startFrom="1"><pre class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1"></a><span class="co"># This F() function is the same as the mathematical F(...) function</span></span>
<span id="cb8-2"><a href="#cb8-2"></a><span class="co"># discussed above (Equation 11).</span></span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="kw">def</span> F(x, y, r):</span>
<span id="cb8-4"><a href="#cb8-4"></a>    <span class="cf">return</span> (x <span class="op">*</span> x) <span class="op">+</span> (y <span class="op">*</span> y) <span class="op">-</span> (r <span class="op">*</span> r)</span>
<span id="cb8-5"><a href="#cb8-5"></a></span>
<span id="cb8-6"><a href="#cb8-6"></a><span class="kw">def</span> get_circle_points_bresenham_WIP1(r):</span>
<span id="cb8-7"><a href="#cb8-7"></a>    points <span class="op">=</span> []</span>
<span id="cb8-8"><a href="#cb8-8"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb8-9"><a href="#cb8-9"></a>    y <span class="op">=</span> r</span>
<span id="cb8-10"><a href="#cb8-10"></a>    <span class="co"># Calculate F(M) for the very first time. That is, if we were to go</span></span>
<span id="cb8-11"><a href="#cb8-11"></a>    <span class="co"># &quot;straight&quot; from (0, r), would we be inside or outside the circle?</span></span>
<span id="cb8-12"><a href="#cb8-12"></a>    xE, yE <span class="op">=</span> (<span class="dv">1</span>, r)</span>
<span id="cb8-13"><a href="#cb8-13"></a>    xSE, ySE <span class="op">=</span> (<span class="dv">1</span>, r <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb8-14"><a href="#cb8-14"></a>    xM, yM <span class="op">=</span> (<span class="dv">1</span>, r <span class="op">-</span> <span class="fl">0.5</span>)</span>
<span id="cb8-15"><a href="#cb8-15"></a>    F_M <span class="op">=</span> F(xM, yM, r)</span>
<span id="cb8-16"><a href="#cb8-16"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb8-17"><a href="#cb8-17"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> y:</span>
<span id="cb8-18"><a href="#cb8-18"></a>        <span class="co"># If going straight would go &quot;into&quot; the circle (too much to the</span></span>
<span id="cb8-19"><a href="#cb8-19"></a>        <span class="co"># right), try to move out of it by turning left by moving E.</span></span>
<span id="cb8-20"><a href="#cb8-20"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb8-21"><a href="#cb8-21"></a>            x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb8-22"><a href="#cb8-22"></a>            F_M <span class="op">=</span> F(x, y, r)</span>
<span id="cb8-23"><a href="#cb8-23"></a>        <span class="co"># Otherwise move SE.</span></span>
<span id="cb8-24"><a href="#cb8-24"></a>        <span class="cf">else</span>:</span>
<span id="cb8-25"><a href="#cb8-25"></a>            x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb8-26"><a href="#cb8-26"></a>            y <span class="op">-=</span> <span class="dv">1</span></span>
<span id="cb8-27"><a href="#cb8-27"></a>            F_M <span class="op">=</span> F(x, y, r)</span>
<span id="cb8-28"><a href="#cb8-28"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb8-29"><a href="#cb8-29"></a>    <span class="cf">return</span> points</span></code></pre></div>
<p>We can refactor the above slightly.
We can simplify the initial calculation of <code>F_M</code> to avoid calling <code>F()</code>, and also move out some of the redundant bits.
The very first midpoint we have to consider is <span class="math inline">\((1, r - \tfrac{1}{2})\)</span>; plugging this into <span class="math inline">\(F()\)</span> gets us</p>
<p><span class="math display">\[
\begin{align}
F(1, r - \tfrac{1}{2}) &amp;= 1^2 + (r - \tfrac{1}{2})^2 - r^2
\\
&amp;= 1 + (r^2 - r + \tfrac{1}{4}) - r^2
\\
&amp;= 1 + r^2 - r^2 - r + \tfrac{1}{4}
\\
&amp;= 1 - r + \tfrac{1}{4}
\\
&amp;= \tfrac{5}{4} - r.
\end{align}
\]</span></p>
<p>With that said, we can get this:</p>
<div class="sourceCode" id="cb9" data-startFrom="1"><pre class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">def</span> get_circle_points_bresenham_WIP2(r):</span>
<span id="cb9-2"><a href="#cb9-2"></a>    points <span class="op">=</span> []</span>
<span id="cb9-3"><a href="#cb9-3"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>    y <span class="op">=</span> r</span>
<span id="cb9-5"><a href="#cb9-5"></a>    F_M <span class="op">=</span> <span class="dv">5</span><span class="op">/</span><span class="dv">4</span> <span class="op">-</span> r</span>
<span id="cb9-6"><a href="#cb9-6"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb9-7"><a href="#cb9-7"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> y:</span>
<span id="cb9-8"><a href="#cb9-8"></a>        <span class="co"># If going straight would go &quot;into&quot; the circle (too much to the</span></span>
<span id="cb9-9"><a href="#cb9-9"></a>        <span class="co"># right), try to move out of it by turning left by moving E.</span></span>
<span id="cb9-10"><a href="#cb9-10"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb9-11"><a href="#cb9-11"></a>            <span class="cf">pass</span></span>
<span id="cb9-12"><a href="#cb9-12"></a>        <span class="co"># Otherwise move SE.</span></span>
<span id="cb9-13"><a href="#cb9-13"></a>        <span class="cf">else</span>:</span>
<span id="cb9-14"><a href="#cb9-14"></a>            y <span class="op">-=</span> <span class="dv">1</span></span>
<span id="cb9-15"><a href="#cb9-15"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb9-16"><a href="#cb9-16"></a>        F_M <span class="op">=</span> F(x, y, r)</span>
<span id="cb9-17"><a href="#cb9-17"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb9-18"><a href="#cb9-18"></a>    <span class="cf">return</span> points</span></code></pre></div>
<p>The annoying bit is the call to <code>F()</code>.
Surprisingly, the call to <code>F()</code> can be elimitated entirely, because we can <em>calculate it once</em>, and then merely adjust it thereafter.</p>
<h2 id="calculate-once-adjust-thereafter">Calculate once, adjust thereafter</h2>
<p>We can just calculate <span class="math inline">\(F(x,y)\)</span> <em>once</em> when we start out at <span class="math inline">\((0, r)\)</span>, and then just <em>adjust it</em> depending on whether we move E or SE.
The key is that this “adjustment” computation is cheaper than calculating the full <span class="math inline">\(F(x,y)\)</span> distance function all over again.</p>
<p>Let <span class="math inline">\(M\)</span> be the midpoint <span class="math inline">\((x + 1, y - \tfrac{1}{2})\)</span> between the E <span class="math inline">\((x + 1, y)\)</span> and SE <span class="math inline">\((x + 1, y - 1)\)</span> pixels.
Then <span class="math inline">\(F(M)\)</span> is the result of going “straight” and tells us the direction we’re veering off from the circle line:</p>
<p><span class="math display">\[
\begin{equation}
F(M) = F(x + 1, y - \tfrac{1}{2}) = (x + 1)^2 + (y - \tfrac{1}{2})^2 - r^2.
\end{equation}
\]</span></p>
<p>The values for <span class="math inline">\(x\)</span> and <span class="math inline">\(y\)</span> are unknown, however they change in only 2 possible ways — by moving E or SE!</p>
<p>If we move E, then <span class="math inline">\(M\)</span> will change from <span class="math inline">\((x + 1, y - \tfrac{1}{2})\)</span> to <span class="math inline">\((x + 2, y - \tfrac{1}{2})\)</span> because we add 1 to <span class="math inline">\(x\)</span> to move 1 pixel east; the new value of <span class="math inline">\(F(M)\)</span> at this pixel, which we can call <span class="math inline">\(F(M_E)\)</span>, will then be:</p>
<p><span class="math display">\[
\begin{equation}
F(M_{E}) = F(x + 2, y - \tfrac{1}{2}) = (x + 2)^2 + (y - \tfrac{1}{2})^2 - r^2.
\end{equation}
\]</span></p>
<p>Now we can take the <strong>difference</strong> between these two full calculations.
That is, if we were to move E, how would <span class="math inline">\(F(M)\)</span> change?
Simple, we just look at the change in <span class="math inline">\(x\)</span> (<span class="math inline">\(\Delta_{x}\)</span>) (we don’t care about the change in <span class="math inline">\(y\)</span> or <span class="math inline">\(r\)</span>, because they stay constant in this case).</p>
<p><span class="math display">\[
\begin{align}
\Delta_{E} &amp;= F(M_{E}) - F(M)
\\ &amp;= [(x + 2)^2 + (y - \tfrac{1}{2})^2 - r^2] - [(x + 1)^2 + (y - \tfrac{1}{2})^2 - r^2]
\\
&amp;= \Delta_{x}
\\
&amp;= (x + 2)^2 - (x + 1)^2 \label{eq:de1}
\\
&amp;= (x^2 + 4x + 4) - (x^2 + 2x + 1)
\\
&amp;= x^2 + 4x + 4 - x^2 - 2x - 1
\\
&amp;= x^2 - x^2 + 4x - 2x + 4 - 1
\\
&amp;= 2x + 3. \label{eq:de2}
\end{align}
\]</span></p>
<p>So <span class="math inline">\(F(M)\)</span> will change by <span class="math inline">\(2x + 3\)</span> if we move E.
So at any given point, if we move E, <span class="math inline">\(F(M)\)</span> will <em>always</em> change by <span class="math inline">\(2x + 3\)</span>.</p>
<p>How about for moving SE?
If we move SE, the new value of <span class="math inline">\(M\)</span> will change from <span class="math inline">\((x + 1, y - \tfrac{1}{2})\)</span> to <span class="math inline">\((x + 2, y - \tfrac{3}{2})\)</span> because we add 1 to <span class="math inline">\(x\)</span> and subtract 1 from <span class="math inline">\(y\)</span> to move 1 pixel southeast; the new value of <span class="math inline">\(F(M)\)</span> for this case, which we call <span class="math inline">\(F(M_{SE})\)</span>, will then be:</p>
<p><span class="math display">\[
\begin{equation}
F(M_{SE}) = F(x + 2, y - \tfrac{3}{2}) = (x + 2)^2 + (y - \tfrac{3}{2})^2 - r^2.
\end{equation}
\]</span></p>
<p>We can do the same difference analysis here, but with the addition that we have to consider the change in <span class="math inline">\(y\)</span> (<span class="math inline">\(\Delta_{y}\)</span>) as well (because of the 1 we subtracted from <span class="math inline">\(y\)</span>):</p>
<p><span class="math display">\[
\begin{align}
\Delta_{SE} &amp;= F(M_{SE}) - F(M)
\\
&amp;= [(x + 2)^2 + (y - \tfrac{3}{2})^2 - r^2] - [(x + 1)^2 + (y - \tfrac{1}{2})^2 - r^2]
\\
&amp;= \Delta_{x} + \Delta_{y}
\\
&amp;= [(x + 2)^2 - (x + 1)^2] + [(y - \tfrac{3}{2})^2 - (y - \tfrac{1}{2})^2]
\\
&amp;= (2x + 3) + [(y^2 - \tfrac{6y}{2} + \tfrac{9}{4}) - (y^2 - y + \tfrac{1}{4})]
\\
&amp;= (2x + 3) + (y^2 - 3y + \tfrac{9}{4} - y^2 + y - \tfrac{1}{4})
\\
&amp;= (2x + 3) + (y^2 - y^2 - 3y + y + \tfrac{9}{4} - \tfrac{1}{4})
\\
&amp;= (2x + 3) + (- 2y + \tfrac{8}{4})
\\
&amp;= (2x + 3) + (-2y + 2)
\\
&amp;= 2x + 3 - 2y + 2
\\
&amp;= 2x - 2y + 5
\\
&amp;= 2(x - y) + 5. \label{eq:se1}
\end{align}
\]</span></p>
<p>And so when moving SE, the new <span class="math inline">\(F(M)\)</span> must change by <span class="math inline">\(2(x - y) + 5\)</span>.</p>
<p>Now we have all the pieces to derive the complete algorithm!</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb10" data-startFrom="6"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 5;"><span id="cb10-6"><a href="#cb10-6"></a><span class="kw">def</span> get_circle_points_bresenham_float_ese(r):</span>
<span id="cb10-7"><a href="#cb10-7"></a>    <span class="co">&quot;&quot;&quot; Draw a circle using a floating point variable, F_M. Draw by moving E or</span></span>
<span id="cb10-8"><a href="#cb10-8"></a><span class="co">    SE.&quot;&quot;&quot;</span></span>
<span id="cb10-9"><a href="#cb10-9"></a>    points <span class="op">=</span> []</span>
<span id="cb10-10"><a href="#cb10-10"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb10-11"><a href="#cb10-11"></a>    y <span class="op">=</span> r</span>
<span id="cb10-12"><a href="#cb10-12"></a>    <span class="co"># F_M is a float.</span></span>
<span id="cb10-13"><a href="#cb10-13"></a>    F_M <span class="op">=</span> <span class="dv">5</span> <span class="op">/</span> <span class="dv">4</span> <span class="op">-</span> r</span>
<span id="cb10-14"><a href="#cb10-14"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb10-15"><a href="#cb10-15"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> y:</span>
<span id="cb10-16"><a href="#cb10-16"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb10-17"><a href="#cb10-17"></a>            F_M <span class="op">+=</span> <span class="fl">2.0</span> <span class="op">*</span> x <span class="op">+</span> <span class="fl">3.0</span></span>
<span id="cb10-18"><a href="#cb10-18"></a>        <span class="cf">else</span>:</span>
<span id="cb10-19"><a href="#cb10-19"></a>            F_M <span class="op">+=</span> <span class="fl">2.0</span> <span class="op">*</span> (x <span class="op">-</span> y) <span class="op">+</span> <span class="fl">5.0</span></span>
<span id="cb10-20"><a href="#cb10-20"></a>            y <span class="op">-=</span> <span class="dv">1</span></span>
<span id="cb10-21"><a href="#cb10-21"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb10-22"><a href="#cb10-22"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb10-23"><a href="#cb10-23"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>bresenham.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py#L6-L23"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<h2 id="integer-only-optimization">Integer-only optimization</h2>
<p>The initial value of <code>F_M</code> (<span class="math inline">\(F(M)\)</span>) is <span class="math inline">\(\tfrac{5}{4} - r\)</span>.
Notice how this is the only place where we have to perform division in the whole algorithm.
We can avoid this initial division (and subsequent floating point arithmetic) by initializing it to <span class="math inline">\(1 - r\)</span> instead, which is a difference of <span class="math inline">\(\tfrac{1}{4}\)</span> vs the original.</p>
<p>Because we tweaked the initialization by <span class="math inline">\(\tfrac{1}{4}\)</span>, we have to do the same for all comparisons of <span class="math inline">\(F(M)\)</span> moving forward.
That is, the comparison <span class="math inline">\(F(M) &lt; 0\)</span> actually becomes <span class="math inline">\(F(M) &lt; -\tfrac{1}{4}\)</span>.
<em>However, this fractional comparison is unnecessary</em> because we only deal with integer increments and decrements in the rest of the code, so we can just keep the same <span class="math inline">\(F(M) &lt; 0\)</span> as before.
In other words, our algorithm only cares about whole numbers, so worrying about this extra <span class="math inline">\(\tfrac{1}{4}\)</span> difference is meaningless.</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb11" data-startFrom="26"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 25;"><span id="cb11-26"><a href="#cb11-26"></a><span class="kw">def</span> get_circle_points_bresenham_integer_ese(r):</span>
<span id="cb11-27"><a href="#cb11-27"></a>    <span class="co">&quot;&quot;&quot; Like draw_circle_bresenham_float_ese, but F_M is an integer variable.</span></span>
<span id="cb11-28"><a href="#cb11-28"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb11-29"><a href="#cb11-29"></a>    points <span class="op">=</span> []</span>
<span id="cb11-30"><a href="#cb11-30"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb11-31"><a href="#cb11-31"></a>    y <span class="op">=</span> r</span>
<span id="cb11-32"><a href="#cb11-32"></a>    <span class="co"># F_M is an integer!</span></span>
<span id="cb11-33"><a href="#cb11-33"></a>    F_M <span class="op">=</span> <span class="dv">1</span> <span class="op">-</span> r</span>
<span id="cb11-34"><a href="#cb11-34"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb11-35"><a href="#cb11-35"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> y:</span>
<span id="cb11-36"><a href="#cb11-36"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb11-37"><a href="#cb11-37"></a>            <span class="co"># We can use a bit-shift safely because 2*n is the same as n &lt;&lt; 1</span></span>
<span id="cb11-38"><a href="#cb11-38"></a>            <span class="co"># in binary, and also because F_M is an integer.</span></span>
<span id="cb11-39"><a href="#cb11-39"></a>            F_M <span class="op">+=</span> (x <span class="op">&lt;&lt;</span> <span class="dv">1</span>) <span class="op">+</span> <span class="dv">3</span></span>
<span id="cb11-40"><a href="#cb11-40"></a>        <span class="cf">else</span>:</span>
<span id="cb11-41"><a href="#cb11-41"></a>            F_M <span class="op">+=</span> ((x <span class="op">-</span> y) <span class="op">&lt;&lt;</span> <span class="dv">1</span>) <span class="op">+</span> <span class="dv">5</span></span>
<span id="cb11-42"><a href="#cb11-42"></a>            y <span class="op">-=</span> <span class="dv">1</span></span>
<span id="cb11-43"><a href="#cb11-43"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb11-44"><a href="#cb11-44"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb11-45"><a href="#cb11-45"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>bresenham.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py#L26-L45"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<h2 id="second-order-differences">Second-order differences</h2>
<p>There is a final optimization we can do.<a href="#fn9" class="footnote-ref" id="fnref9" role="doc-noteref"><sup>9</sup></a>
In the <a href="#calculate-once-adjust-thereafter">“Calculate once, adjust thereafter” section</a> we avoided calculating <span class="math inline">\(F(M)\)</span> from scratch on every iteration.
We can do the same thing for the differences themselves!</p>
<p>That is, we can avoid calculating <span class="math inline">\(\Delta_{E} = (2x + 3)\)</span> and <span class="math inline">\(\Delta_{SE} = 2(x - y) + 5\)</span> on every iteration, and instead just calculate them <em>once</em> and make adjustments to them, just like we did earlier for <span class="math inline">\(F(M)\)</span>.</p>
<p>Let’s first consider how <span class="math inline">\(\Delta_{E} = 2x + 3\)</span> changes.
First, we initialize <span class="math inline">\(\Delta_{E}\)</span> by plugging in <span class="math inline">\((0, r)\)</span> into Equation <span class="math inline">\(\ref{eq:de2}\)</span>, our starting point.
Because there is no <span class="math inline">\(y\)</span> variable in here, we get an initial value of</p>
<p><span class="math display">\[
\begin{equation} \label{eq:de-2ord-initial}
2(0) + 3 = 3.
\end{equation}
\]</span></p>
<p>If we go E, <span class="math inline">\(\Delta_{E}\)</span> changes like this:
<span class="math display">\[
\begin{align}
\Delta_{E_{new}} = \Delta_{E_(x+1,y)} - \Delta_{E_(x,y)} &amp;= [2(x+1) + 3] - (2x + 3) \label{eq:de-2ord-e}
\\
&amp;= 2x + 2 + 3 - 2x - 3
\\
&amp;= 2x - 2x + 3 - 3 + 2
\\
&amp;= 2. \label{eq:e2ord}
\end{align}
\]</span></p>
<p>If we go SE, <span class="math inline">\(\Delta_{E}\)</span> changes in the exact same way, because even though our new point is at <span class="math inline">\((x+1, y-1)\)</span>, there is no <span class="math inline">\(y\)</span> in <span class="math inline">\(\Delta_{E} = 2x + 3\)</span>, so it doesn’t matter and <span class="math inline">\(\Delta_{E_{new}} = 2\)</span> again.</p>
<p>Now let’s consider how <span class="math inline">\(\Delta_{SE}\)</span> changes.
For the initial value, we again plug in <span class="math inline">\((0, r)\)</span> into <span class="math inline">\(2(x-y) + 5\)</span>, to get</p>
<p><span class="math display">\[
\begin{equation} \label{eq:dse-2ord-initial}
2(0-r) + 5 = -2r + 5.
\end{equation}
\]</span></p>
<p>If we go E, <span class="math inline">\(\Delta_{SE}\)</span> changes like this:</p>
<p><span class="math display">\[
\begin{align}
\Delta_{SE_{new}} = \Delta_{SE_(x+1,y)} - \Delta_{SE_(x,y)} &amp;= [2((x + 1)-y) + 5] - [2(x - y) + 5] \label{eq:dse-2ord-e}
\\
&amp;= (2x + 2 - 2y + 5) - (2x - 2y + 5)
\\
&amp;= 2x - 2y + 7 - 2x + 2y - 5
\\
&amp;= 2x - 2x + 2y - 2y + 7 - 5
\\
&amp;= 2. \label{eq:se2ord1}
\end{align}
\]</span></p>
<p>If we go SE, <span class="math inline">\(\Delta_{SE}\)</span> changes like this:</p>
<p><span class="math display">\[
\begin{align}
\Delta_{SE_{new}} = \Delta_{SE_(x+1,y-1)} - \Delta_{SE_(x,y)} &amp;= [2((x + 1)-(y - 1)) + 5] - [2(x - y) + 5] \label{eq:dse-2ord-se}
\\
&amp;= [2(x + 1 - y + 1) + 5] - (2x - 2y + 5)
\\
&amp;= (2x + 2 - 2y + 2 + 5) - 2x + 2y - 5
\\
&amp;= 2x- 2x + 2y - 2y + 5 - 5 + 2 + 2
\\
&amp;= 2 + 2
\\
&amp;= 4. \label{eq:se2ord2}
\end{align}
\]</span></p>
<p>The code should then look like this:</p>
<div class="sourceCode" id="cb12" data-startFrom="1"><pre class="sourceCode numberSource python numberLines"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">def</span> get_circle_points_bresenham_2order(r):</span>
<span id="cb12-2"><a href="#cb12-2"></a>    points <span class="op">=</span> []</span>
<span id="cb12-3"><a href="#cb12-3"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb12-4"><a href="#cb12-4"></a>    y <span class="op">=</span> r</span>
<span id="cb12-5"><a href="#cb12-5"></a>    F_M <span class="op">=</span> <span class="dv">1</span> <span class="op">-</span> r</span>
<span id="cb12-6"><a href="#cb12-6"></a>    d_e <span class="op">=</span> <span class="dv">3</span> <span class="co"># Equation 40</span></span>
<span id="cb12-7"><a href="#cb12-7"></a>    d_se <span class="op">=</span> <span class="op">-</span>(<span class="dv">2</span> <span class="op">*</span> r) <span class="op">+</span> <span class="dv">5</span> <span class="co"># Equation 45</span></span>
<span id="cb12-8"><a href="#cb12-8"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb12-9"><a href="#cb12-9"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> y:</span>
<span id="cb12-10"><a href="#cb12-10"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb12-11"><a href="#cb12-11"></a>            F_M <span class="op">+=</span> d_e</span>
<span id="cb12-12"><a href="#cb12-12"></a>            d_e <span class="op">+=</span> <span class="dv">2</span>  <span class="co"># Equation 44</span></span>
<span id="cb12-13"><a href="#cb12-13"></a>            d_se <span class="op">+=</span> <span class="dv">2</span> <span class="co"># Equation 50</span></span>
<span id="cb12-14"><a href="#cb12-14"></a>        <span class="cf">else</span>:</span>
<span id="cb12-15"><a href="#cb12-15"></a>            F_M <span class="op">+=</span> d_se</span>
<span id="cb12-16"><a href="#cb12-16"></a>            d_e <span class="op">+=</span> <span class="dv">2</span>  <span class="co"># Equation 44</span></span>
<span id="cb12-17"><a href="#cb12-17"></a>            d_se <span class="op">+=</span> <span class="dv">4</span> <span class="co"># Equation 56</span></span>
<span id="cb12-18"><a href="#cb12-18"></a>            y <span class="op">-=</span> <span class="dv">1</span></span>
<span id="cb12-19"><a href="#cb12-19"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb12-20"><a href="#cb12-20"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb12-21"><a href="#cb12-21"></a>    <span class="cf">return</span> points</span></code></pre></div>
<p>With a little refactoring, we can arrive at a slightly simpler version:</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb13" data-startFrom="48"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 47;"><span id="cb13-48"><a href="#cb13-48"></a><span class="kw">def</span> get_circle_points_bresenham_integer_ese_2order(r):</span>
<span id="cb13-49"><a href="#cb13-49"></a>    <span class="co">&quot;&quot;&quot; Like draw_circle_bresenham_integer_ese, but use 2nd-order differences</span></span>
<span id="cb13-50"><a href="#cb13-50"></a><span class="co">    to remove multiplication from the inner loop. &quot;&quot;&quot;</span></span>
<span id="cb13-51"><a href="#cb13-51"></a>    points <span class="op">=</span> []</span>
<span id="cb13-52"><a href="#cb13-52"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb13-53"><a href="#cb13-53"></a>    y <span class="op">=</span> r</span>
<span id="cb13-54"><a href="#cb13-54"></a>    F_M <span class="op">=</span> <span class="dv">1</span> <span class="op">-</span> r</span>
<span id="cb13-55"><a href="#cb13-55"></a>    <span class="co"># Initial value for (0,r) for 2x + 3 = 0x + 3 = 3.</span></span>
<span id="cb13-56"><a href="#cb13-56"></a>    d_e <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb13-57"><a href="#cb13-57"></a>    <span class="co"># Initial value for (0,r) for 2(x - y) + 5 = 0 - 2y + 5 = -2y + 5.</span></span>
<span id="cb13-58"><a href="#cb13-58"></a>    d_se <span class="op">=</span> <span class="op">-</span>(r <span class="op">&lt;&lt;</span> <span class="dv">1</span>) <span class="op">+</span> <span class="dv">5</span></span>
<span id="cb13-59"><a href="#cb13-59"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb13-60"><a href="#cb13-60"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> y:</span>
<span id="cb13-61"><a href="#cb13-61"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb13-62"><a href="#cb13-62"></a>            F_M <span class="op">+=</span> d_e</span>
<span id="cb13-63"><a href="#cb13-63"></a>        <span class="cf">else</span>:</span>
<span id="cb13-64"><a href="#cb13-64"></a>            F_M <span class="op">+=</span> d_se</span>
<span id="cb13-65"><a href="#cb13-65"></a>            <span class="co"># Increment d_se by 2 (total 4) if we go southeast.</span></span>
<span id="cb13-66"><a href="#cb13-66"></a>            d_se <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb13-67"><a href="#cb13-67"></a>            y <span class="op">-=</span> <span class="dv">1</span></span>
<span id="cb13-68"><a href="#cb13-68"></a>        <span class="co"># Always increment d_e and d_se by 2!</span></span>
<span id="cb13-69"><a href="#cb13-69"></a>        d_e <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb13-70"><a href="#cb13-70"></a>        d_se <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb13-71"><a href="#cb13-71"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb13-72"><a href="#cb13-72"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb13-73"><a href="#cb13-73"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>bresenham.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py#L48-L73"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>The “purist” in me felt that the decrementing of <span class="math inline">\(y\)</span> stood out like a sore thumb, and so I created a tweaked version that moves E and NE, starting out from <span class="math inline">\((0, -r)\)</span> instead.
The mathematical techniques are the same, and due to symmetry the behavior of the algorithm does not change.</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb14" data-startFrom="99"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 98;"><span id="cb14-99"><a href="#cb14-99"></a><span class="kw">def</span> get_circle_points_bresenham_integer_ene_2order(r):</span>
<span id="cb14-100"><a href="#cb14-100"></a>    <span class="co">&quot;&quot;&quot; Like draw_circle_bresenham_integer_ene, but start from (0, -r) and move</span></span>
<span id="cb14-101"><a href="#cb14-101"></a><span class="co">    E or NE. Notice how we only need the addition instruction in the while loop</span></span>
<span id="cb14-102"><a href="#cb14-102"></a><span class="co">    (y is incremented, not decremented). &quot;&quot;&quot;</span></span>
<span id="cb14-103"><a href="#cb14-103"></a>    points <span class="op">=</span> []</span>
<span id="cb14-104"><a href="#cb14-104"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb14-105"><a href="#cb14-105"></a>    y <span class="op">=</span> <span class="op">-</span>r</span>
<span id="cb14-106"><a href="#cb14-106"></a>    F_M <span class="op">=</span> <span class="dv">1</span> <span class="op">-</span> r</span>
<span id="cb14-107"><a href="#cb14-107"></a>    <span class="co"># Initial value for (0,-r) for 2x + 3 = 0x + 3 = 3.</span></span>
<span id="cb14-108"><a href="#cb14-108"></a>    d_e <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb14-109"><a href="#cb14-109"></a>    <span class="co"># Initial value for (0,-r) for 2(x + y) + 5 = 0 - 2y + 5 = -2y + 5.</span></span>
<span id="cb14-110"><a href="#cb14-110"></a>    d_ne <span class="op">=</span> <span class="op">-</span>(r <span class="op">&lt;&lt;</span> <span class="dv">1</span>) <span class="op">+</span> <span class="dv">5</span></span>
<span id="cb14-111"><a href="#cb14-111"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb14-112"><a href="#cb14-112"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> <span class="op">-</span>y:</span>
<span id="cb14-113"><a href="#cb14-113"></a>        <span class="cf">if</span> F_M <span class="op">&lt;</span> <span class="dv">0</span>:</span>
<span id="cb14-114"><a href="#cb14-114"></a>            F_M <span class="op">+=</span> d_e</span>
<span id="cb14-115"><a href="#cb14-115"></a>        <span class="cf">else</span>:</span>
<span id="cb14-116"><a href="#cb14-116"></a>            F_M <span class="op">+=</span> d_ne</span>
<span id="cb14-117"><a href="#cb14-117"></a>            d_ne <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb14-118"><a href="#cb14-118"></a>            y <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb14-119"><a href="#cb14-119"></a>        d_e <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb14-120"><a href="#cb14-120"></a>        d_ne <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb14-121"><a href="#cb14-121"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb14-122"><a href="#cb14-122"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb14-123"><a href="#cb14-123"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>bresenham.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py#L99-L123"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>Here are a couple drawings using Bresenham’s algorithm.
This one is for <span class="math inline">\(r = 15\)</span>:</p>
<canvas id="bresenham_integer_ene_2order__15__20"></canvas>

<p>And for <span class="math inline">\(r = 60\)</span>:</p>
<canvas id="bresenham_integer_ene_2order__60__5"></canvas>

<h2 id="comparisons-vs-naive-algorithm">Comparisons vs naive algorithm</h2>
<p>Here are some side-by-side comparisons for <span class="math inline">\(0 \leq r \leq 10\)</span>.</p>
<table>
  <tr>
    <th>Radius</th>
    <th>Naive</th>
    <th>Bresenham</th>
  </tr>
  <tr>
    <td class="centered">0</td>
    <td><canvas id="naive_8__0__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__0__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">1</td>
    <td><canvas id="naive_8__1__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__1__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">2</td>
    <td><canvas id="naive_8__2__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__2__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">3</td>
    <td><canvas id="naive_8__3__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__3__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">4</td>
    <td><canvas id="naive_8__4__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__4__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">5</td>
    <td><canvas id="naive_8__5__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__5__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">6</td>
    <td><canvas id="naive_8__6__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__6__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">7</td>
    <td><canvas id="naive_8__7__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__7__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">8</td>
    <td><canvas id="naive_8__8__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__8__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">9</td>
    <td><canvas id="naive_8__9__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__9__10"></canvas></td>
  </tr>
  <tr>
    <td class="centered">10</td>
    <td><canvas id="naive_8__10__10"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__10__10"></canvas></td>
  </tr>
</table>

<h2 id="final-tweaks">Final tweaks</h2>
<p>It has been kindly <a href="https://www.reddit.com/r/programming/comments/m5g8ck/bresenhams_circle_drawing_algorithm/gr23aie?utm_source=share&amp;utm_medium=web2x&amp;context=3">pointed out</a> that the naive algorithm is aesthetically more pleasing if the calculations involving <span class="math inline">\(r\)</span> is done with <span class="math inline">\(r + \tfrac{1}{2}\)</span> instead of just <span class="math inline">\(r\)</span> itself, like this:</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb15" data-startFrom="47"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 46;"><span id="cb15-47"><a href="#cb15-47"></a><span class="kw">def</span> get_circle_points_naive_8_faster_tweaked_radius(r):</span>
<span id="cb15-48"><a href="#cb15-48"></a>    <span class="co">&quot;&quot;&quot; This is much closer to Bresenham&#39;s algorithm aesthetically, by simply</span></span>
<span id="cb15-49"><a href="#cb15-49"></a><span class="co">    using &#39;r + 0.5&#39; for the square root calculation instead of &#39;r&#39; directly.</span></span>
<span id="cb15-50"><a href="#cb15-50"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb15-51"><a href="#cb15-51"></a>    points <span class="op">=</span> []</span>
<span id="cb15-52"><a href="#cb15-52"></a>    <span class="co"># In the square root calculation, we just use (r + 0.5) instead of just r.</span></span>
<span id="cb15-53"><a href="#cb15-53"></a>    <span class="co"># This is more pleasing to the eye and makes the lines a bit smoother.</span></span>
<span id="cb15-54"><a href="#cb15-54"></a>    r_tweaked <span class="op">=</span> r <span class="op">+</span> <span class="fl">0.5</span></span>
<span id="cb15-55"><a href="#cb15-55"></a>    <span class="cf">for</span> x <span class="kw">in</span> <span class="bu">range</span>(r <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb15-56"><a href="#cb15-56"></a>        y <span class="op">=</span> sqrt((r_tweaked <span class="op">*</span> r_tweaked) <span class="op">-</span> (x <span class="op">*</span> x))</span>
<span id="cb15-57"><a href="#cb15-57"></a>        <span class="cf">if</span> x <span class="op">&gt;</span> y:</span>
<span id="cb15-58"><a href="#cb15-58"></a>            <span class="cf">break</span></span>
<span id="cb15-59"><a href="#cb15-59"></a>        points.extend(mirror_points_8(x, floor(y)))</span>
<span id="cb15-60"><a href="#cb15-60"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>naive.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py#L47-L60"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/naive.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>Indeed, the small tweak seems to do wonders to the output for low values of <span class="math inline">\(r\)</span>.</p>
<p>At the same time, there is a tweak we can do as well for the Bresenham algorithm.
Instead of turning E (“left”, or away from the circle) when <span class="math inline">\(F(M) &lt; 0\)</span>, we can do so when <span class="math inline">\(F(M) \leq 0\)</span>.</p>
<div class="code-and-raw">
<div class="sourceCode" id="cb16" data-startFrom="126"><pre class="sourceCode numberSource numberLines python"><code class="sourceCode python" style="counter-reset: source-line 125;"><span id="cb16-126"><a href="#cb16-126"></a><span class="kw">def</span> get_circle_points_bresenham_integer_ene_2order_leq(r):</span>
<span id="cb16-127"><a href="#cb16-127"></a>    <span class="co">&quot;&quot;&quot; Like draw_circle_bresenham_integer_ene_2order, but use &#39;f_m &lt;= 0&#39;</span></span>
<span id="cb16-128"><a href="#cb16-128"></a><span class="co">    instead of &#39;f_m &lt; 0&#39;.</span></span>
<span id="cb16-129"><a href="#cb16-129"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb16-130"><a href="#cb16-130"></a>    points <span class="op">=</span> []</span>
<span id="cb16-131"><a href="#cb16-131"></a>    x <span class="op">=</span> <span class="dv">0</span></span>
<span id="cb16-132"><a href="#cb16-132"></a>    y <span class="op">=</span> <span class="op">-</span>r</span>
<span id="cb16-133"><a href="#cb16-133"></a>    F_M <span class="op">=</span> <span class="dv">1</span> <span class="op">-</span> r</span>
<span id="cb16-134"><a href="#cb16-134"></a>    d_e <span class="op">=</span> <span class="dv">3</span></span>
<span id="cb16-135"><a href="#cb16-135"></a>    d_ne <span class="op">=</span> <span class="op">-</span>(r <span class="op">&lt;&lt;</span> <span class="dv">1</span>) <span class="op">+</span> <span class="dv">5</span></span>
<span id="cb16-136"><a href="#cb16-136"></a>    points.extend(mirror_points_8(x, y))</span>
<span id="cb16-137"><a href="#cb16-137"></a>    <span class="cf">while</span> x <span class="op">&lt;</span> <span class="op">-</span>y:</span>
<span id="cb16-138"><a href="#cb16-138"></a>        <span class="cf">if</span> F_M <span class="op">&lt;=</span> <span class="dv">0</span>:</span>
<span id="cb16-139"><a href="#cb16-139"></a>            F_M <span class="op">+=</span> d_e</span>
<span id="cb16-140"><a href="#cb16-140"></a>        <span class="cf">else</span>:</span>
<span id="cb16-141"><a href="#cb16-141"></a>            F_M <span class="op">+=</span> d_ne</span>
<span id="cb16-142"><a href="#cb16-142"></a>            d_ne <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb16-143"><a href="#cb16-143"></a>            y <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb16-144"><a href="#cb16-144"></a>        d_e <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb16-145"><a href="#cb16-145"></a>        d_ne <span class="op">+=</span> <span class="dv">2</span></span>
<span id="cb16-146"><a href="#cb16-146"></a>        x <span class="op">+=</span> <span class="dv">1</span></span>
<span id="cb16-147"><a href="#cb16-147"></a>        points.extend(mirror_points_8(x, y))</span>
<span id="cb16-148"><a href="#cb16-148"></a>    <span class="cf">return</span> points</span></code></pre></div>
<div class="raw-link sourceCode">
<p> <code>bresenham.py</code> <a class="raw" href="https://github.com/listx/listx_blog/blob/master/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py#L126-L148"><code>[GitHub]</code></a> <a class="raw" href="/code/2021-03-15-bresenham-circle-drawing-algorithm/bresenham.py"mimetype=text/plain><code>[Download]</code></a> </p>
</div>
</div>
<p>This makes us turn “left” slightly more often, and intuitively, should give us a slightly larger circle.</p>
<p>Anyway, see for yourself how the tweaks play out for <span class="math inline">\(0 \leq r \leq 10\)</span>:</p>
<table>
  <tr>
    <th>Radius</th>
    <th>Naive</th>
    <th>Naive<br>(tweaked radius)</th>
    <th>Bresenham</th>
    <th>Bresenham<br>(tweaked conditional)</th>
  </tr>
  <tr>
    <td class="centered">0</td>
    <td><canvas id="naive_8__0__6"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__0__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__0__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__0__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">1</td>
    <td><canvas id="naive_8__1__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__1__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__1__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__1__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">2</td>
    <td><canvas id="naive_8__2__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__2__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__2__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__2__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">3</td>
    <td><canvas id="naive_8__3__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__3__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__3__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__3__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">4</td>
    <td><canvas id="naive_8__4__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__4__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__4__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__4__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">5</td>
    <td><canvas id="naive_8__5__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__5__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__5__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__5__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">6</td>
    <td><canvas id="naive_8__6__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__6__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__6__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__6__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">7</td>
    <td><canvas id="naive_8__7__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__7__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__7__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__7__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">8</td>
    <td><canvas id="naive_8__8__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__8__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__8__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__8__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">9</td>
    <td><canvas id="naive_8__9__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__9__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__9__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__9__7"></canvas></td>
  </tr>
  <tr>
    <td class="centered">10</td>
    <td><canvas id="naive_8__10__7"></canvas></td>
    <td><canvas id="naive_8_faster_tweaked_radius__10__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order__10__7"></canvas></td>
    <td><canvas id="bresenham_integer_ene_2order_leq__10__7"></canvas></td>
  </tr>
</table>

<p>It appears to me that the most aesthetically pleasing algorithm is the tweaked version of the Bresenham algorithm.<a href="#fn10" class="footnote-ref" id="fnref10" role="doc-noteref"><sup>10</sup></a>
When given equally bad choices (the case where <span class="math inline">\(F(M) = 0\)</span>), this version draws a pixel <em>away</em> from the origin by choosing to go E, thereby drawing a slightly bigger circle.
You can see this play out in the above table for when <span class="math inline">\(r = 6\)</span> and especially <span class="math inline">\(r = 1\)</span>.
It’s a bit unfortunate that the authors of the book did not choose this version, as it seems to do a better job for small values of <span class="math inline">\(r\)</span>.</p>
<p>We can carry over the same intuition over to the tweak to increase <span class="math inline">\(r\)</span> by <span class="math inline">\(\tfrac{1}{2}\)</span> for the naive algorithm — increasing <span class="math inline">\(r\)</span> should result in a larger value of <span class="math inline">\(y\)</span>, thereby resulting in drawing a larger circle (and in the process improving the aesthetics).
Neat!</p>
<h1 id="conclusion">Conclusion</h1>
<p>To me, Bresenham’s algorithm is interesting because it does not try to be “perfect”.
Instead it merely does its best to reduce the amount of error, and in doing so, gets the job done remarkably well.</p>
<p>The technique of avoiding the full polynomial calculation behind <span class="math inline">\(F(M)\)</span> (referred by the book as finding the first and second-order differences) took some time to get used to, but is intuitive enough in the end.
You just need to consider differences in terms of variables.
There’s also a connection to calculus because we’re dealing in terms of <em>differences</em> to “cut down” on the polynomial degrees — we go from the squares in Equation <span class="math inline">\(\ref{eq:circle}\)</span> to just linear functions in Equations <span class="math inline">\(\ref{eq:de2}\)</span> and <span class="math inline">\(\ref{eq:se1}\)</span>, and again go one more step to just constant functions in Equations <span class="math inline">\(\ref{eq:e2ord}\)</span>, <span class="math inline">\(\ref{eq:se2ord1}\)</span>, and <span class="math inline">\(\ref{eq:se2ord2}\)</span>.</p>
<p>I hope you learned something!</p>
<p>Happy hacking!</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>Foley, J. D., van Dam, A., Feiner, S. K., Hughes, J. F. (1996). Basic Raster Graphics Algorithms for Drawing 2D Primitives, Scan Converting Circles. <em>Computer Graphics: Principles and Practice</em> (pp. 81–87). Addison-Wesley. ISBN: 0201848406<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>Bresenham, J.E., D.G. Grice, and S.C. Pi, “Bi-Directional Display of Circular Arcs,” US Patent 4,371,933. February 1, 1983. <em>Note: unfortunately, trying to understand the original text of the patent is perhaps equally as difficult as inventing the algorithm on your own from scratch. Hence this blog post.</em><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p>There are 4 such <a href="https://en.wikipedia.org/wiki/Quadrant_(plane_geometry)">quadrants</a>: I, II, III, and IV.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4"><p>In some sense, all great algorithms are mere optimizations of brute force approaches.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5"><p>In code, we have to write <code>range(r + 1)</code> because the <code>range()</code> function does not include the last integer. Such “fence-post” or “off by one” logic is the bane of computer programmers.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6"><p>Mathematically, this is because the slope of the arc in Equation <span class="math inline">\(\ref{eq:circle-y}\)</span> approach positive and negative infinity around these areas.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn7"><p>In the <a href="https://github.com/listx/listx_blog/blob/master/rust-js/src/lib.rs">Rust WASM implementation</a> that is used for the graphics in this blog post, we actually use a bitmap such that we only draw a particular pixel just once. However, we still end up <em>setting</em> the a pixel as “on” more than once.<a href="#fnref7" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn8"><p>Bresenham, Jack. “A Linear Algorithm for Incremental Digital Display of Circular Arcs.” Communications of the ACM, vol. 20, no. 2, 1977, pp. 100–106., <a href="doi:10.1145/359423.359432">doi:10.1145/359423.359432</a>.<a href="#fnref8" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn9"><p>It is not clear to me if this change runs faster on modern CPUs, because I recall reading that multiplication can sometimes be faster than adding. But it’s still interesting.<a href="#fnref9" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn10"><p>This version looks slightly better than the tweaked naive one for <span class="math inline">\(r = 8\)</span>.<a href="#fnref10" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
]]></summary>
</entry>
<entry>
    <title>Using MPD for ReplayGain</title>
    <link href="http://funloop.org/post/2021-01-05-mpd-and-replaygain.html" />
    <id>http://funloop.org/post/2021-01-05-mpd-and-replaygain.html</id>
    <published>2021-01-05T00:00:00Z</published>
    <updated>2021-01-05T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2021-01-05-mpd-and-replaygain.org" title="History"><code class="date">2021-01-05</code></a>
	<br>
	<a title="All pages tagged &#39;linux&#39;." href="/tag/linux.html" rel="tag">linux</a>, <a title="All pages tagged &#39;audio&#39;." href="/tag/audio.html" rel="tag">audio</a>
</div>

<p>Something like ~10 years ago, there was no easy way to apply <a href="https://en.wikipedia.org/wiki/ReplayGain">ReplayGain</a> to various audio files with different formats (e.g., flac vs mp3).
Over the holiday break I discovered <a href="https://github.com/desbma/r128gain">r128gain</a> which is exactly the tool I wanted for many years.
You just run</p>
<pre><code>r128gain -r &lt;folder&gt;
</code></pre>
<p>and it will recursively tag all music files with ReplayGain information — in parallel, no less!</p>
<p>The only downside is that neither <a href="https://cmus.github.io/">cmus</a> nor <a href="https://mpv.io/">mpv</a> currently support the <code class="verbatim">R128_TRACK_GAIN</code> tag that r128gain generates (at least for <code class="verbatim">*.opus</code> files).<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
However, I discovered that <a href="https://www.musicpd.org/">MPD (Music Player Daemon)</a> supports <code class="verbatim">R128_TRACK_GAIN</code>.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>
MPD is easy to start up and the basic minimal configuration was <a href="https://raw.githubusercontent.com/listx/syscfg/e0f95dd04a4cd7247ca4e0fe3f02eccd78660d24/mpd/mpd.conf">small enough</a>:</p>
<pre><code>music_directory     &quot;~/Music&quot;
# Automatically prune new/deleted files in the music_directory.
auto_update         &quot;yes&quot;

# Allow saving playlists from vimpc.
playlist_directory  &quot;~/Music/playlists&quot;

audio_output {
    type            &quot;pulse&quot;
    name            &quot;My Pulse Output&quot;
}

# Enable replay gain.
replaygain          &quot;track&quot;
</code></pre>
<p>As far as actually controlling MPD, I settled on <a href="https://github.com/boysetsfrog/vimpc">vimpc</a> — because Vi-like keybindings are too good to pass up.</p>
<p>Cheers!</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>To be precise, cmus has a commit in master that <a href="https://github.com/cmus/cmus/commit/174b93ee1c3a290751513ac557b39dea8e31c7f9">adds support</a>, and mpv has an <a href="https://github.com/mpv-player/mpv/issues/5079">open issue</a> for it. And I’m too lazy to compile cmus from source.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>I had actually used MPD back in the day, but switched to cmus because it was simpler. And because cross-format ReplayGain tagging software was not available, MPD’s support for ReplayGain wasn’t very meaningful for me.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
]]></summary>
</entry>
<entry>
    <title>Thoughts on Baduk</title>
    <link href="http://funloop.org/post/2021-01-04-thoughts-on-baduk.html" />
    <id>http://funloop.org/post/2021-01-04-thoughts-on-baduk.html</id>
    <published>2021-01-04T00:00:00Z</published>
    <updated>2021-01-04T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2021-01-04-thoughts-on-baduk.org" title="History"><code class="date">2021-01-04</code></a>
	<br>
	<a title="All pages tagged &#39;baduk&#39;." href="/tag/baduk.html" rel="tag">baduk</a>
</div>

<h1 id="my-history-with-baduk">My history with Baduk</h1>
<p>I’ve started playing Baduk more during the pandemic, and I thought I should write about this fascinating game.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>When I was a child growing up in Korea, I remember seeing newspapers with pictures of Baduk positions with professional commentary.
Unfortunately, no one in my immediate family had any interest in the game, so my initial curiosity of the game came and went.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<p>Later in the United States, I picked up chess during high school.
Chess had the advantage that there were many more people who already know how to play the game.
And also, carrying around a lightweight board with some pieces wasn’t difficult at all.
I recall whipping out my chess board for a quick game during lunch, recess, and any other time I could find an opponent.</p>
<p>I took a step back from chess during college and later years.
I started to lose interest after I kept playing the same openings.</p>
<p>Around 2016 I re-learned how to play Baduk.
One reason I picked it up again was that at this time, Baduk was still played best by humans (a computer AI had not yet defeated a master human player on an even game).
This was just before the great “AlphaGo” match with Lee Sedol, and at the time most people believed that AI supremacy in this game was still another decade away.</p>
<p>I started playing and losing a ton of games against the AI on 9x9 at <a href="https://online-go.com/player/213337/funloop">online-go.com</a>, especially around 2019 when sometimes I played marathon 9x9 games, over and over against the computer.
The most memorable game from this period is <a href="https://online-go.com/game/16295331">this one</a> where I won by 0.5 points against a 7-stone handicap.
That victory was a pleasant surprise, but it also left me with a sense of obligation to study the game with a little more seriousness.</p>
<p>After a brief pause, I returned to the game in the fall of 2020.
During this time I watched some videos from <a href="https://www.youtube.com/channel/UCfA0tTDLNooBB0ymdoI5M7w">this YouTube channel</a>, which I was able to roughly understand thanks to my knowledge of Korean.
I began to realize large gaps in my style of play, and it was only after this realization that I started improving my results.</p>
<h1 id="baduk-vs.-chess">Baduk vs. Chess</h1>
<p>Having a working knowledge of both chess and Baduk, I would have to say that the biggest difference between them for me is that there is far, far more room for strategy in Baduk.
This is because you can ignore threats and play for bigger moves on the more much more often than in chess, especially in the opening and middlegame.
There is more wiggle room for creativity!</p>
<p>Speaking of openings, because the Baduk board has 4 symmetrical corners, there are actually 4 areas of openings in each game.
You can have 4 different “openings” in each game.
In chess there is only 1 “center” of the board where the vast majority of opening theory takes place.</p>
<p>The handicap system is far more elegant in Baduk as well.
In chess, the handicap is usually to remove a pawn (or two), but this drastically alters the nature of the game.
Not so for Baduk!
The weaker player gets up to 9 extra stones on the board before the start of the game.
This way you can play with opponents at different levels without getting completely crushed from the very beginning.</p>
<p>Perhaps the best part of the game is that each game is decided by a score (where the score is the amount of “territory” you control).
A win is technically a win, sure, but the “wins” can be judged against each other by their score.</p>
<p>Finally, the game is more forgiving in terms of errors.
In chess if you lose your queen (without adequate compensation), the game is pretty much over.
In baduk, even if you lose a sizable group, you can still come back.
Actually, the bigger your group of stones, the harder it is to get them captured outright, and so there is a natural, automatic tendency for your strongest “pieces”, if you will, to resist capture.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>
Brilliant!</p>
<h1 id="conclusion">Conclusion</h1>
<p>If you haven’t learned the game yet, I strongly recommend this game!
I used the book <a href="https://www.amazon.com/Go-Complete-Introduction-Beginner-Elementary/dp/4906574505">“Go: A Complete Introduction to the Game”</a> to get a nice overview.<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<p>Have fun!</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>I use the Korean word “Baduk” (바둑) because the usual Japanese loanword “Go” overlaps with the name “Go” of the Go programming language.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>Years later I learned that my uncle is an amateur 5-dan.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p>In Baduk as long as a group gets 2 “eyes”, it becomes uncapturable — and the bigger the group, the easier it is to make such eyes.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4"><p>The author of this book is Cho Chikun, one of the top players of the 20th century.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
]]></summary>
</entry>
<entry>
    <title>The Two Sum Problem Explained</title>
    <link href="http://funloop.org/post/2020-12-05-twosum-problem-explained.html" />
    <id>http://funloop.org/post/2020-12-05-twosum-problem-explained.html</id>
    <published>2020-12-05T00:00:00Z</published>
    <updated>2020-12-05T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2020-12-05-twosum-problem-explained.org" title="History"><code class="date">2020-12-05</code></a>
	<br>
	<a title="All pages tagged &#39;algorithms&#39;." href="/tag/algorithms.html" rel="tag">algorithms</a>, <a title="All pages tagged &#39;math&#39;." href="/tag/math.html" rel="tag">math</a>
</div>

<p>Just over three years ago, I watched <a href="https://youtu.be/XKu_SEDAykw">this video</a> that goes over the so-called “Two Sum” problem for the first time.
The problem statement is as follows:</p>
<blockquote>
<p>Given a sorted list of integers (unimaginitively called <strong>numbers</strong>), determine if any 2 integers in the list sum up to a number <strong>N</strong>.</p>
</blockquote>
<p>To be honest I did not understand why the proposed optimal solution that uses 2 pointers works the way it does, without missing any possible pairs.
The <a href="https://youtu.be/XKu_SEDAykw?t=300">explanation given by the interview candidate in the video</a> always struck me as way too hand-wavy for my tastes.</p>
<p>And to be really honest I never bothered to convince myself that the 2-pointer approach is correct.
Until today.
This post is about the correctness behind the 2-pointer method, because I have yet to see a clear explanation about this topic.</p>
<h1 id="brute-force-approach">Brute force approach</h1>
<p>First let’s look at the brute-force solution.
The brute-force solution looks at every single possible pair of numbers by using a double-for-loop.
This is a very common pattern (nested looping) whenever one wants to consider all possible combinations, where each for-loop corresponds to a single “dimension” we want to exhaustively pore over.
In this case there are 2 dimensions because there are 2 numbers we need to look at, so we must use 2 for-loops.</p>
<p>Here is the basic pseudocode <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>:</p>
<pre><code>for i in numbers:
  for j in numbers:
    if i + j == N:
      return i, j
</code></pre>
<p>I think even beginner programmers can see that the brute force approach works.
We just look at every possible 2-number combination to see if they will add up to <strong>N</strong>, and if so, we stop the search.
Simple! <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<h1 id="pointer-method">2-pointer method</h1>
<p>The 2-pointer method boils down to the following observation:</p>
<blockquote>
<p>Remove numbers from the pairwise search if they cannot be used (with any other number) to sum up to <strong>N</strong>.</p>
</blockquote>
<p>Although the solution posted in countless places online involve pointers, it is more intuitive to think of <em>modifying the list</em> after each pairwise inspection.
Below is the algorithm in plain English:</p>
<ol type="1">
<li>Construct a pair of numbers <code class="verbatim">(a, b)</code> such that <code class="verbatim">a</code> is the smallest number and <code class="verbatim">b</code> is the biggest number in the list. That is, these are the leftmost and rightmost ends of the sorted list, respectively.</li>
<li>If the sum of <code class="verbatim">a + b</code> is equal to <strong>N</strong>, of course we’re done.</li>
<li>If the sum of <code class="verbatim">a + b</code> is bigger than <strong>N</strong>, delete <code class="verbatim">b</code> from the list. Go back to Step 1.</li>
<li>If the sum of <code class="verbatim">a + b</code> is smaller than <strong>N</strong>, delete <code class="verbatim">a</code> from the list. Go back to Step 1.</li>
<li>If the list becomes smaller than 2 elements, stop (obviously, because there are no more pairs to consider). Optionally return an error.</li>
</ol>
<p>The algorithm described above can be equivalently coded with pointers, so there is no material difference to discuss in terms of implementation.</p>
<p>Anyway, we just need to make sense of the critical Steps, namely Steps 3, 4, and 5, and that should be enough to quell any worries about correctness.</p>
<h1 id="step-3">Step 3</h1>
<p>This is the step that removes the largest element <code class="verbatim">b</code> in the list from consideration <em>for all future iterations</em>.
How can this be correct?</p>
<p>Well, let’s consider an example.
If <strong>N</strong> is 50 but <code class="verbatim">a + b</code> is 85, we must look for a smaller sum.
This much is obvious.</p>
<p>We just used <code class="verbatim">a</code> and <code class="verbatim">b</code> to get to 85, but because we <em>must</em> get to a smaller sum, we would like to swap out either <code class="verbatim">a</code> or <code class="verbatim">b</code> (or both, eventually) with another number from the list.
The question is, which one do we swap out?</p>
<p>We can’t replace <code class="verbatim">a</code> with the next bigger number (or any other number between <code class="verbatim">a</code> and <code class="verbatim">b</code>), because doing so will result in a sum that is at least as big as 85 (or bigger).
So <code class="verbatim">a</code> has to stay — we can’t rule out other combinations of <code class="verbatim">a</code> with some number other than <code class="verbatim">b</code> (maybe <code class="verbatim">a</code> and its next-biggest neighbor, etc).</p>
<p>That leaves us with <code class="verbatim">b</code>.
We throw out <code class="verbatim">b</code> and replace it with the next biggest number, which is guaranteed to be less than or equal to the just-thrown-out <code class="verbatim">b</code>, because the list is sorted.</p>
<p>In other words, <em>all pairs</em> of <code class="verbatim">b</code> and every other element in the list already sums up to 85 or some other <em>higher number</em>.
So <code class="verbatim">b</code> is a red herring that’s leading us astray.
We must throw it out.</p>
<h1 id="step-4">Step 4</h1>
<p>This is the “mirror” of Step 3.
Here we throw out the smallest number out of future pairwise searches, because we know that <code class="verbatim">a</code>, no matter which number it is paired with (even with the biggest one, <code class="verbatim">b</code>), is too small to meet the target <strong>N</strong>.
In other words, <code class="verbatim">a</code> fails to give enough of a “boost” to <em>any</em> other number to reach <strong>N</strong>.
It is very much useless to the remaining other candidates, and so we throw it out.</p>
<h1 id="step-5">Step 5</h1>
<p>This Step’s analogy when using pointers is to consider the condition when the pointers “cross”.
The pointers “crossing”, in and of itself, doesn’t seem particularly significant.
However when we view this condition by looking at the dwindling size of the overall list (by chopping off the left and right ends in Steps 4 and 3), the point becomes obvious.
We must stop when the list becomes too small to make Step 1 impossible to fulfill (namely, the construction of the pair <code class="verbatim">(a, b)</code>), due to the fact that there aren’t enough elements in the list (singleton or empty list).</p>
<h1 id="pointer-method-in-pseudocode">2-pointer method, in pseudocode</h1>
<p>For sake of completeness, here is the pseudocode for the same algorithm.
You will see how using pointers (instead of deleting elements outright as described in Steps 3 and 4) doesn’t change the algorithm at all.</p>
<pre><code># Partial implementation of Step 5. Early exit if list is too small to begin with.
if length(numbers) &lt; 2:
  return error

# Step 1.
a_idx = 0
b_idx = length(numbers) - 1
sum = numbers[a_idx] + numbers[b_idx]

# Begin search, but only if we have to search.
while sum != N:
  # Step 3
  if sum &gt; N:
    b_idx -= 1
  # Step 4
  elif sum &lt; N:
    a_idx += 1

  # Step 5
  if a_idx == b_idx:
    return error

  # Step 1 (again, because we didn&#39;t find a match above).
  sum = numbers[a_idx] + numbers[b_idx]

# Step 2
return numbers[a_idx], numbers[b_idx]
</code></pre>
<p>It may be of interest to readers who are fairly new to programming that Step 2 comes in at the very end.
Getting the “feel” for converting plain-English algorithms into actual code is something that requires experience, and can only be acquired with practice over time.</p>
<h2 id="do-the-pointers-ever-skip-over-each-other">Do the pointers ever skip over each other?</h2>
<p>It is worth pointing out that the condition <code>a_idx == b_idx</code> is well-formed.
That is, there will never be a case where <code class="verbatim">a_idx</code> and <code class="verbatim">b_idx</code> will somehow “skip over” each other, rendering the <code class="verbatim">if</code>-condition useless.
This is because we only ever increment <code class="verbatim">a_idx</code> or decrement <code class="verbatim">b_idx</code>, <em>exclusively</em> — that is, we never modify both of them within the same iteration.
So, the variables only ever change by <code class="verbatim">±1</code>, and at some point, if the search goes on long enough, the indices are bound to converge at the same numerical value.</p>
<h1 id="conclusion">Conclusion</h1>
<p>I think the beauty of this problem is that it’s so simple, and yet it is also a very cool way of looking at the problem of <em>search</em>.
Steps 3 and 4 are essentially very aggressive (and correct!) eliminations of bad search paths.
There’s just something refreshing about eliminating entire branches of a search tree to speed things up.</p>
<p>If you compare the 2-pointer method with the brute force approach, it is in essence doing the same logical thing, with fewer steps.
Whereas the brute force approach performs a pairwise comparison across all possible combinations, the 2-pointer method preemptively discards many combinations by removing elements outright from future consideration.
That’s the kind of power you need to go from <span class="math inline">\(O(n^2)\)</span> to <span class="math inline">\(O(n)\)</span>!</p>
<p>Hope this helps!</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>Of course, this pseudocode ignores edge-cases, but I didn’t want to clutter the code listing with non-essential ideas.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>As an added benefit, the brute-force approach works even if the input list is not sorted.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
]]></summary>
</entry>
<entry>
    <title>The Esrille Nisse: Three Years Later</title>
    <link href="http://funloop.org/post/2019-11-13-esrille-nisse-three-years-later.html" />
    <id>http://funloop.org/post/2019-11-13-esrille-nisse-three-years-later.html</id>
    <published>2019-11-13T00:00:00Z</published>
    <updated>2019-11-13T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info center">
	<a class="history" href="https://github.com/listx/listx_blog/commits/master/post/2019-11-13-esrille-nisse-three-years-later.org" title="History"><code class="date">2019-11-13</code></a>
	<br>
	<a title="All pages tagged &#39;hardware&#39;." href="/tag/hardware.html" rel="tag">hardware</a>, <a title="All pages tagged &#39;esrille&#39;." href="/tag/esrille.html" rel="tag">esrille</a>, <a title="All pages tagged &#39;cherry mx&#39;." href="/tag/cherry%20mx.html" rel="tag">cherry mx</a>
</div>

<p>Over three years ago, I wrote <a href="./2016-04-14-esrille-nisse-keyboard.html">a post</a> describing the Esrille Nisse keyboard.
This post is a reflection on the keyboard, more than 3 years later.</p>
<h1 id="layout">Layout</h1>
<p>Ultimately I settled on a different layout than the one described in the old blog post.
This was a result of many hands-on trial-and-error sessions over a period of weeks which turned into many months.
In my old post I described writing a program to help find the optimal layout.
This proved very difficult in practice, because encoding the optimization rules turned out to be non-trivial.
One aspect that was particularly difficult was that the actualy physical shape of my own fingers played a part (some fingers were not as versatile as others, for example the pinky finger, and so the key-distance for certain fingers had to have different “weights”, and this was too much to translate into code).</p>
<p>Anyway, I read <a href="https://norvig.com/mayzner.html">this post by Peter Norvig</a> forwards and backwards, and used the values there to guide the design of my layout.
One big realization after actual usage was that I could not let go of the QWERTY <code>hjkl</code> keys on the home row.
There was just so much muscle memory built into these four keys (the only other key I could not let go of was the spacebar key that I used my left thumb for), that I had to “fix” them on the layout first.
I then focused on getting the commonly-used keys right.</p>
<p>All that being said, here is my current layout.</p>
<pre><code>      LEFT-SIDE     RIGHT-SIDE
    ---------------------------
    □ □ □ □ □ □     □ □ □ □ □ □
    □ □ 0 □ □         □ □ 0 □ 1
□ □ □ y o p z 1     2 f d t r □ □ □
2 / a i e u w ;     &quot; h j k l n 4 : &lt;--- Home row
  3 . x q v &#39;         b m g c s 3
      8 5 6 7 4     5 , 6 7 8 &lt;--------- Thumb row


Left-side legend
0) Escape
1) PgDn
2) Enter
3) Shift
4) Control
5) Super (Windows key)
6) Space
7) Caps Lock (remapped with xmodmap to Hyper key)
8) Right Alt (aka &quot;AltGr&quot; for US International Layout)

Right-side legend
0) Tab
1) Delete
2) PgUp
3) Shift
4) Backspace
5) FN2
6) FN
7) Alt
8) Right Alt (aka &quot;AltGr&quot; for US International Layout)
</code></pre>
<p>The main thing to note is the reduced number of keys that are mapped at all.
I like this aspect a lot (not having to move my fingers around much at all) — I never have to reach for a particular key because everything is just so close.</p>
<p>I also dedicated a key just for the colon symbol (as a “Shift + semicolon” macro), because it comes up often enough in programming.</p>
<p>I should also note that the function keys (F1-F12) are situated on the topmost row, left-to-right.
I just didn’t bother adding them to the legend because of symbol space constraints.</p>
<p>FN layer.</p>
<pre><code>      LEFT-SIDE     RIGHT-SIDE
    ---------------------------
    □ □ □ □ □ □     □ □ □ □ □ □
    □ □ a □ □         □ □ □ □ □
□ □ □ 7 8 9 □ □     □ □ \ _ = □ □ □
□ □ 0 4 5 6 □ b     b - { ( ) } a : &lt;--- Home row
  c . 1 2 3 `         □ [ &lt; &gt; ] c
      □ □ □ □ □     □ □ □ □ □ &lt;--------- Thumb row

Left-side legend
a) ~/ (a macro that inserts the string &quot;~/&quot;)
b) End
c) Shift

Right-side legend
a) Backspace
b) Home
c) Shift
</code></pre>
<p>The FN layer has the majority of the punctuation keys I need.
You might notice that some symbols like <code>!@#$&amp;*^</code> are not in here.
This is because the numeral keys on the left side are actually the same numeral keys on the top row (<strong>not</strong> the Numpad) of a typical QWERTY layout.
This means that I can just press FN+Shift to get these keys.
This is the main trick that allowed me to reduce the number of keys used overall.</p>
<p>The “~/” macro in the left side is particularly useful as well.</p>
<p>FN2 layer.</p>
<pre><code>      LEFT-SIDE     RIGHT-SIDE
    ---------------------------
    □ □ □ □ □ □     □ □ □ □ □ □
    □ □ □ □ □         □ □ □ □ □
□ □ □ □ □ □ □ □     □ □ □ □ □ □ □ □
□ □ □ □ □ □ □ □     □ a b c d □ □ □ &lt;--- Home row
  □ □ □ □ □ □         □ □ □ □ e □
      □ □ □ □ □     □ □ □ □ □ &lt;--------- Thumb row


Right-side legend
a) Left Arrow
b) Down Arrow
c) Up Arrow
d) Right Arrow
e) Shift + Insert macro (for pasting X primary buffer)
</code></pre>
<p>This layer is mostly empty, but it is used surprisingly frequently.
I really like how the arrow keys line up with my <code>hjkl</code> keys in the main layer.</p>
<p>For the latest changes to my layout, check out <a href="https://github.com/listx/new-keyboard">this repo</a>.</p>
<h1 id="typing-speed">Typing Speed</h1>
<p>It took me roughly 3 months of everyday use to get somewhat familiar with the layout, and probably another month or two to reach upwards of 60wpm.</p>
<p>It was painstakingly slow at first (it felt a lot like learning how to type all over again), but still “fun” because I noticed that I was getting better with time.</p>
<p>I think these days (after having used this keyboard every day for both my home and work PCs (yes, I have two of these!)) I can go higher than 60wpm.</p>
<p>Suffice it to say that there is never a time when I think “oh, I wish I could type faster” on this layout.
My speed on this keyboard is about on par as with my old typing speed on QWERTY.</p>
<p>My typing speed on the old QWERTY layout hasn’t really changed.
I still have to use it for when I use the keyboard on laptops.
And surprisingly, my brain knows to “switch” to QWERTY when I’m typing on there — granted, this instinct took some time to kick in.</p>
<h1 id="was-it-worth-it">Was it worth it?</h1>
<p>Totally!</p>
<p>The biggest thing I love about this layout is that I don’t have to move my right hand around when reaching for the typical “hard” keys on QWERTY (such as `[]{}`).
I rarely (if ever) have typos when typing punctuation keys.
The numeral keys being just underneath my left hand in a different layer is nice, too.</p>
<p>There are some “downsides” though in everyday life:</p>
<ul>
<li>it’s hard to play games because the key mappings are usually designed for QWERTY;</li>
<li>when I make typos using this layout, they look rather unusual from a “QWERTY” perspective (as a contrived example, I might type “yen” instead of “yes” because the “n” and “s” keys are next to each other on my layout)</li>
</ul>
<p>I don’t really play games that much though, and when I do I am usually on the separate gaming PC that just use a regular QWERTY layout so it’s not really a negative.</p>
<p>I guess the biggest downside of all is that the keyboard form factor on the Nisse is one-of-a-kind on the planet.
If Esrille goes under, I would be worried about taking very good care of my keyboards in case one of the components breaks for whatever reason.
I imagine that at that point, I would have to just create my own keyboard or make do with a shabby imitation using ErgoDox or some other form factor.
I sincerely hope that that day never comes…!</p>
<p>Happy hacking!</p>
]]></summary>
</entry>

</feed>
