<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Gianni Tedesco</title>
<link href="https://www.scaramanga.co.uk/" rel="alternate"/>
<link href="https://www.scaramanga.co.uk/feed.xml" rel="self"/>
<id>https://www.scaramanga.co.uk/</id>
<updated>2020-02-08T10:14:00+09:00</updated>
<author><name>Gianni Tedesco</name></author>

<entry>
<title>Arbitrary Remote Code Execution is (Still) Arbitrary Remote Code Execution</title>
<link href="https://www.scaramanga.co.uk/journal/arbitrary-remote-code-exec/" rel="alternate"/>
<id>https://www.scaramanga.co.uk/journal/arbitrary-remote-code-exec/</id>
<updated>2020-02-08T10:14:00+09:00</updated>
<published>2020-02-08T10:14:00+09:00</published>
<summary>In which we warn the youth against downloading malware and running it</summary>
<content type="html">&lt;p&gt;Long gone are the days when servers were like little pets. You logged in to
them, you stroked them, you ran little commands on them. Probably some commands
you copied and pasted out of stackoverflow or that you found in some google
search results.&lt;&#x2f;p&gt;
&lt;p&gt;Then when the server died, you had a little funeral, buried it in a little pet
cemetery, and then tried to remember how the hell you had set it up.&lt;&#x2f;p&gt;
&lt;p&gt;But that was fine, you were in grief, you didn&#x27;t want another pet to be
identical to your dead pet anyway.&lt;&#x2f;p&gt;
&lt;p&gt;That is, unless you were trying to deliver consistent, performant, and
uninterrupted service to colleagues, customers, or the like.&lt;&#x2f;p&gt;
&lt;h2&gt;Cattle, not Pets&lt;&#x2f;h2&gt;
&lt;p&gt;In that case you&#x27;d want something a bit more repeatable. A bit more automated.
A bit more like a production-line eviscerating pigs for the manufacture of
sausage.&lt;&#x2f;p&gt;
&lt;p&gt;First there were configuration management systems, like:&lt;&#x2f;p&gt;
&lt;ul&gt;
&lt;li&gt;1993: CFEngine&lt;&#x2f;li&gt;
&lt;li&gt;2000: Spooner (proprietary, developed by yours truly) :)&lt;&#x2f;li&gt;
&lt;li&gt;2005: Puppet&lt;&#x2f;li&gt;
&lt;li&gt;2009: Chef&lt;&#x2f;li&gt;
&lt;li&gt;2012: Ansible&lt;&#x2f;li&gt;
&lt;&#x2f;ul&gt;
&lt;p&gt;These tools allowed you to represent the configuration or desired state of a
server as code or data but, in either case, as a version-controlled repository
subject to the quality-oriented practices which began to be adopted by
programmers in the early decades of the 21st century.&lt;&#x2f;p&gt;
&lt;p&gt;Later, in 2013, Docker came along. The idea behind docker was to use containers
as a way to build or deploy software in an industrialised fashion, like the
afore-mentioned sausage factory. The more inspirational, but frankly less
tasty, metaphor here would be the containerisation of bulk cargo. Before this
idea took hold, containers were thought of as more to do with the containment
or confinement of running software. They were sometimes called jails and still
widely viewed as being fancy chroots.&lt;&#x2f;p&gt;
&lt;p&gt;In combining the underlying technology of namespaces, control-groups, jails,
containers with the philosophy and concepts of infrastructure-as-code, Docker,
and systems like it, revolutionised how software services were delivered. By
now these, and related, techniques are ubiquitous in the data-centre.&lt;&#x2f;p&gt;
&lt;p&gt;Which is great, because now all of the insecure and insane practices get
written down and permanently archived in git repositories instead of being a
secret burden of guilt and shame carried on the shoulders of an entire class of
people: systems administrators.&lt;&#x2f;p&gt;
&lt;p&gt;Now the blame can be diffused among software developers of all hues and stripes
and we can call it a cultural problem :)&lt;&#x2f;p&gt;
&lt;h2&gt;Building and Bootstrapping Infrastructure Now.&lt;&#x2f;h2&gt;
&lt;p&gt;Well, a container really is just a fancy chroot. Whereas chroot changes the
process&#x27;s view of the VFS namespace by setting the root to some directory,
thereby restricting its view of the filesystem to a subtree of that directory,
containers are processes which have their own private, possibly unique, set of
mounts.&lt;&#x2f;p&gt;
&lt;p&gt;However, we still need to populate the mounted directories or filesystems with
the software that&#x27;s going to run!&lt;&#x2f;p&gt;
&lt;p&gt;There are any number of ways of doing this.&lt;&#x2f;p&gt;
&lt;h2&gt;SnapCraft&lt;&#x2f;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2f;&#x2f;snapcraft.io&quot;&gt;Snapcraft&lt;&#x2f;a&gt; uses a YAML file which defines sources to be
downloaded, which will then be compiled and installed on top of a base OS layer
which contains compilers, a package manager, etc.&lt;&#x2f;p&gt;
&lt;p&gt;Snapcraft provides security measures, such as the ability to check source code
downloads against checksums with the &lt;code&gt;source-checksum&lt;&#x2f;code&gt; feature and the ability
to download code over https.&lt;&#x2f;p&gt;
&lt;p&gt;However, if you just download code from the internet over http, then you&#x27;re
just an &lt;a href=&quot;https:&#x2f;&#x2f;github.com&#x2f;Ettercap&#x2f;ettercap&quot;&gt;ettercap&lt;&#x2f;a&gt; or a dns poisoning
away from being fed exploit code which will automatically be run as part of the
snap build process.&lt;&#x2f;p&gt;
&lt;p&gt;The snapcraft tour, part of the getting started guide, suffered from this
problem, which was
&lt;a href=&quot;https:&#x2f;&#x2f;bugs.launchpad.net&#x2f;snapcraft&#x2f;+bug&#x2f;1634415&quot;&gt;reported in Oct 2016&lt;&#x2f;a&gt;
and was &lt;a href=&quot;https:&#x2f;&#x2f;github.com&#x2f;snapcore&#x2f;snapcraft&#x2f;pull&#x2f;1329&quot;&gt;fixed in May 2017&lt;&#x2f;a&gt;.&lt;&#x2f;p&gt;
&lt;p&gt;Which is great. We shouldn&#x27;t be teaching a new generation of programmers to
automatically trust and execute arbitrary remote code.&lt;&#x2f;p&gt;
&lt;h2&gt;LXC Templates : CVE-2017-18641&lt;&#x2f;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2f;&#x2f;linuxcontainers.org&quot;&gt;LXC&lt;&#x2f;a&gt; shipped a series of templates which are
scripts which initialise the container root filesystem.&lt;&#x2f;p&gt;
&lt;p&gt;The centos and fedora templates relied on yum being installed on the host. The
host&#x27;s yum would be used to download RPMs and install them into the rootfs.&lt;&#x2f;p&gt;
&lt;p&gt;The RPMs were being downloaded over http, which could be okay, since RPMs are
signed. However yum was being invoked with &lt;code&gt;--nogpgcheck&lt;&#x2f;code&gt; which disabled this
feature. The upshot being that anyone using the template is also an ettercap or
a hacked mirror or untrustworthy proxy away from having arbitrary code executed
as root.&lt;&#x2f;p&gt;
&lt;p&gt;This was &lt;a href=&quot;https:&#x2f;&#x2f;bugs.launchpad.net&#x2f;ubuntu&#x2f;+source&#x2f;lxc&#x2f;+bug&#x2f;1661447&quot;&gt;reported&lt;&#x2f;a&gt;
on Feb 3 2017. And it turned out after a quick investigation that the problem
applied to around a dozen of the template scripts.&lt;&#x2f;p&gt;
&lt;p&gt;Some were fixed in short order. But there were so many cases of this, all in
different ad-hoc scripts, by different authors, that it became &amp;quot;a bit of a
mess.&amp;quot;&lt;&#x2f;p&gt;
&lt;p&gt;By Feb 2 2018 the LXC team had started work on
&lt;a href=&quot;https:&#x2f;&#x2f;github.com&#x2f;lxc&#x2f;distrobuilder&quot;&gt;distrobuilder&lt;&#x2f;a&gt; which had support for
https and gpg from the outset and would be difficult to get wrong.&lt;&#x2f;p&gt;
&lt;p&gt;By LXC 3 the templates system had been removed to a historical repo and the
&lt;em&gt;status quo&lt;&#x2f;em&gt; is now that images are built securely and signed on trusted
infrastructure and then sent to users over https and with a signature which
is checked by &lt;code&gt;lxc-download&lt;&#x2f;code&gt;.&lt;&#x2f;p&gt;
&lt;p&gt;This is a fine example of the concerns which go into building a software
distribution mechanism in which trust can be established.&lt;&#x2f;p&gt;
&lt;h2&gt;Insecurely Downloaded Remote Code is, by Definition, Arbitrary.&lt;&#x2f;h2&gt;
&lt;h3&gt;And If it&#x27;s Arbitrary then You Have No Reason to Trust it.&lt;&#x2f;h3&gt;
&lt;h4&gt;So Why Would You Want to Execute it?&lt;&#x2f;h4&gt;
&lt;p&gt;It&#x27;s certainly tempting, when writing a Dockerfile, to imagine that everything
is executing in some sort of secure isolation layer and that, because of this,
security is irrelevant.&lt;&#x2f;p&gt;
&lt;p&gt;For now, let&#x27;s ignore the historical record of security vulnerabilities in
container isolation, and the entire available attack surface of the kernel, and
the fact that namespaces and control groups are not purpose-built security
isolation systems. And the fact that even if they were such, then with all their
flexibility and configurability there would be bound to be many possible insecure
configurations. Let&#x27;s ignore all of that for now.&lt;&#x2f;p&gt;
&lt;p&gt;Usually, if you&#x27;re creating a container, you want to be able to trust the code
inside it with whatever else is in that container. So even if an attacker can&#x27;t
break out to the host, you won&#x27;t want them to have full control over the
container because they may be able to deface your website, defraud your
customers, introduce backdoors into your software builds, etc.&lt;&#x2f;p&gt;
&lt;p&gt;And if the attacker has corrupted the image at container build time, then you
don&#x27;t even have the defence that the container instances are cattle that can be
shot in the head with a bolt-gun and replaced with a fresh new lump of meat,
cloned from the same DNA.&lt;&#x2f;p&gt;
&lt;p&gt;So are these practices common?&lt;&#x2f;p&gt;
&lt;p&gt;From a quick search on github I was able to find
&lt;a href=&quot;https:&#x2f;&#x2f;github.com&#x2f;search?l=&amp;amp;q=%22wget+http%3A%2F%2F%22+language%3ADockerfile&amp;amp;type=Code&quot;&gt;23,000 instances&lt;&#x2f;a&gt; of &amp;quot;wget &lt;a href=&quot;http:&#x2f;&#x2f;&quot;&gt;http:&#x2f;&#x2f;&lt;&#x2f;a&gt;...&amp;quot; in Dockerfiles.&lt;&#x2f;p&gt;
&lt;p&gt;By randomly clicking them you can see that most of these (100% of the ones I
looked at anyway) absolutely are downloading arbitrary code and then running
it.&lt;&#x2f;p&gt;
&lt;p&gt;I was also able to find a further &lt;a href=&quot;https:&#x2f;&#x2f;github.com&#x2f;search?utf8=%E2%9C%93&amp;amp;q=%22curl+http%3A%2F%2F%22+language%3ADockerfile&amp;amp;type=Code&amp;amp;ref=advsearch&amp;amp;l=&amp;amp;l=&quot;&gt;4,000 instances&lt;&#x2f;a&gt;
for curl, but some of these looked legitimate.&lt;&#x2f;p&gt;
&lt;p&gt;With a bit of regex trickery one could probably find many more instances.&lt;&#x2f;p&gt;
&lt;p&gt;GitHub really is a repository of endless trivial security vulnerabilities.&lt;&#x2f;p&gt;
&lt;h2&gt;A Brief Message from the Cast&lt;&#x2f;h2&gt;
&lt;p&gt;While software vendors take vulnerabilities seriously when they are discovered,
and act to remediate them in a timely and responsible fashion, we probably need
to be doing a little bit more, as a community, for the typical users of these
things to drill into them the dangers involved.&lt;&#x2f;p&gt;
&lt;p&gt;It&#x27;s never going to be comfortable for purveyors of band-saws to be always
pointing out that band-saws can irreparably alter the relation between a user&#x27;s
fingers and said user&#x27;s hands.&lt;&#x2f;p&gt;
&lt;p&gt;That&#x27;s just not the fun stuff, compared to all the cool things you can make and
do with power-tools.&lt;&#x2f;p&gt;
&lt;p&gt;However, when we see how widespread some of these unsafe practices are, we
might want to think about what sort of technical or social interventions might
work to improve the situation.&lt;&#x2f;p&gt;
</content>
</entry>

<entry>
<title>Abusing the CPU&#x27;s adder circuits</title>
<link href="https://www.scaramanga.co.uk/journal/abusing-add/" rel="alternate"/>
<id>https://www.scaramanga.co.uk/journal/abusing-add/</id>
<updated>2019-06-15T10:14:00+09:00</updated>
<published>2019-06-15T10:14:00+09:00</published>
<summary>In which we explain how and why Kernighan&#x27;s popcnt trick works</summary>
<content type="html">&lt;p&gt;Have you ever been asked the interview question &amp;quot;how do you count the number of
bits set in an integer?&amp;quot;&lt;&#x2f;p&gt;
&lt;p&gt;A smart-ass like myself might answer something like:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; &lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;entity name function c&quot;&gt;count_set_bits&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter c&quot;&gt;x&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;
&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;__builtin_popcount&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;x&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Which, on &lt;code&gt;x86_64&lt;&#x2f;code&gt;, produces:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-nasm&quot;&gt;&lt;span class=&quot;text plain&quot;&gt;	xor	eax, eax
	popcnt	eax, edi
	ret
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;The interviewer, of course, doesn&#x27;t like that. He wants to see you come up with
an algorithm. So you come up with something like this:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; &lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;entity name function c&quot;&gt;count_set_bits&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;support type stdint c&quot;&gt;uint32_t&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter c&quot;&gt;x&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;
&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;
	&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; i&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt; ret&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;for&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;ret &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; i &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; i &lt;span class=&quot;keyword operator comparison c&quot;&gt;&amp;lt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;32&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; i&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
		ret &lt;span class=&quot;keyword operator assignment augmented c&quot;&gt;+=&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;!&lt;&#x2f;span&gt;&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;!&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;x &lt;span class=&quot;keyword operator c&quot;&gt;&amp;amp;&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;constant numeric c&quot;&gt;1U&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;&amp;lt;&amp;lt;&lt;&#x2f;span&gt; i&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;return&lt;&#x2f;span&gt; ret&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Which gives you something like:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-nasm&quot;&gt;&lt;span class=&quot;text plain&quot;&gt;	xor	r8d, r8d
	xor	eax, eax
	mov	ecx, 1
	.p2align 4,,10
	.p2align 3
.L4:
	shlx	edx, ecx, eax
	test	edx, edi
	setne	dl
	movzx	edx, dl
	inc	eax
	add	r8d, edx
	cmp	eax, 32
	jne	.L4
	mov	eax, r8d
	ret
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Which is, of course, dreadful. But the reason the interviewer likes this is
because it sets up the next question: &amp;quot;how can we optimize this?&amp;quot; Or if you
want to be more circumspect: &amp;quot;what if we only expect one or two bits to be
set?&amp;quot; or &amp;quot;what if our data is very sparse?&amp;quot;&lt;&#x2f;p&gt;
&lt;p&gt;Realistically though, you either know about &amp;quot;Kernighan&#x27;s trick&amp;quot;, or, you don&#x27;t.
It goes something like this:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; &lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;entity name function c&quot;&gt;count_set_bits&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter c&quot;&gt;x&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;
&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;
	&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; ret&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;for&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;ret &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; x&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; x &lt;span class=&quot;keyword operator assignment augmented c&quot;&gt;&amp;amp;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;x &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;-&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;1&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
		ret&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;return&lt;&#x2f;span&gt; ret&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Which, at least for an Intel weenie such as myself, was a pointless exercise
because gcc compiles that to:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-nasm&quot;&gt;&lt;span class=&quot;text plain&quot;&gt;	xor	eax, eax
	popcnt	eax, edi
	mov	edx, 0
	test	edi, edi
	cmove	eax, edx
	ret
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Which looks like a terrible code-generation bug in gcc. But hey, at least clang
does the right thing here:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-nasm&quot;&gt;&lt;span class=&quot;text plain&quot;&gt;	popcnt	eax, edi
	ret
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Anyway, I digress. Did you notice the &lt;code&gt;x &amp;amp;= (x - 1)&lt;&#x2f;code&gt; part? That is bitwise
woo-woo magic to unset the rightmost bit in &lt;code&gt;x&lt;&#x2f;code&gt;. It&#x27;s a neat trick, and if you
know it you&#x27;ll ace this part of the job interview.&lt;&#x2f;p&gt;
&lt;p&gt;But later, when you&#x27;re at home, alone, contemplating the empty meaninglessness
of the universe, you might ask yourself &amp;quot;but why does it work?&amp;quot;&lt;&#x2f;p&gt;
&lt;h2&gt;Two&#x27;s complement&lt;&#x2f;h2&gt;
&lt;p&gt;Let&#x27;s forget the &lt;code&gt;&amp;amp;&lt;&#x2f;code&gt; part and just focus on what &lt;code&gt;x - 1&lt;&#x2f;code&gt; is doing for now.&lt;&#x2f;p&gt;
&lt;p&gt;One thing you&#x27;re going to need to know about is
&lt;a href=&quot;https:&#x2f;&#x2f;en.wikipedia.org&#x2f;wiki&#x2f;Two%27s_complement&quot;&gt;two&#x27;s complement&lt;&#x2f;a&gt;
arithmetic.&lt;&#x2f;p&gt;
&lt;p&gt;I won&#x27;t bore you by recapitulating the details but we should do well to
remember the following equations:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code&gt;&lt;span class=&quot;text plain&quot;&gt;x - y = x + -y
-x    = ~x + 1
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Therefore:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code&gt;&lt;span class=&quot;text plain&quot;&gt;x - 1 = x + -1
      = x + 1111...
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;So the magic rune is just adding all ones to our original value.&lt;&#x2f;p&gt;
&lt;h2&gt;Half adder&lt;&#x2f;h2&gt;
&lt;p&gt;So here&#x27;s the part where we get into how addition really works. You probably
have a good handle on this already from your school days, but let&#x27;s refresh.&lt;&#x2f;p&gt;
&lt;p&gt;The simplest case is if we&#x27;re just adding together a couple of 1-bit numbers.&lt;&#x2f;p&gt;
&lt;p&gt;Let&#x27;s write out the truth table for that:&lt;&#x2f;p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;&#x2f;th&gt;
&lt;th&gt;y&lt;&#x2f;th&gt;
&lt;th&gt;result&lt;&#x2f;th&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0... oh yeah, we need to carry...&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;tbody&gt;
&lt;&#x2f;table&gt;
&lt;p&gt;Let&#x27;s try again:&lt;&#x2f;p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;&#x2f;th&gt;
&lt;th&gt;y&lt;&#x2f;th&gt;
&lt;th&gt;result&lt;&#x2f;th&gt;
&lt;th&gt;carry&lt;&#x2f;th&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;tbody&gt;
&lt;&#x2f;table&gt;
&lt;p&gt;Right, if we&#x27;re going to expand this to add numbers with more than one bit,
we&#x27;re going to need to do something about this carry output.&lt;&#x2f;p&gt;
&lt;h2&gt;Full adder&lt;&#x2f;h2&gt;
&lt;p&gt;Let&#x27;s call the last adder with 2 inputs, and 2 outputs, the &amp;quot;half-adder.&amp;quot;&lt;&#x2f;p&gt;
&lt;p&gt;The full adder is going to have 3 inputs: the 2 operands, and then a carry-in
which is going to be connected to the next least significant bit&#x27;s carry-out.&lt;&#x2f;p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;&#x2f;th&gt;
&lt;th&gt;y&lt;&#x2f;th&gt;
&lt;th&gt;carry-in&lt;&#x2f;th&gt;
&lt;th&gt;result&lt;&#x2f;th&gt;
&lt;th&gt;carry-out&lt;&#x2f;th&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;tbody&gt;
&lt;&#x2f;table&gt;
&lt;p&gt;So you can see in this example of a 4-bit adder that there&#x27;s this chain of
carry inputs going from right to left:&lt;&#x2f;p&gt;
&lt;p&gt;&lt;img src=&quot;4-bit_ripple_carry_adder.png&quot; alt=&quot;there&quot; title=&quot;4-bit ripple carry adder&quot; &#x2f;&gt;&lt;&#x2f;p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https:&#x2f;&#x2f;en.wikipedia.org&#x2f;wiki&#x2f;User:Cburnett&quot;&gt;Colin M.L. Burnett&lt;&#x2f;a&gt;
for the excellent diagram.&lt;&#x2f;p&gt;
&lt;h2&gt;Putting it all together&lt;&#x2f;h2&gt;
&lt;p&gt;The basic outline of the algorithm is that we start with an input, &lt;code&gt;x&lt;&#x2f;code&gt;. And as
long as it isn&#x27;t zero, we unset the least significant bit, and increment the
result.&lt;&#x2f;p&gt;
&lt;p&gt;So if the input is &lt;code&gt;1000_1100&lt;&#x2f;code&gt;, the loop will iterate 3 times.&lt;&#x2f;p&gt;
&lt;p&gt;&lt;code&gt;x &amp;amp;= (x - 1)&lt;&#x2f;code&gt; is an operation which clears the least-significant set bit in
the input, &lt;code&gt;x&lt;&#x2f;code&gt;.&lt;&#x2f;p&gt;
&lt;p&gt;Since we&#x27;re going to do &lt;code&gt;x &amp;amp;= mask&lt;&#x2f;code&gt;, that must mean that &lt;code&gt;mask&lt;&#x2f;code&gt; has a zero in
the position we want to zero out. And it can&#x27;t have any zeroes where the input
has a one.&lt;&#x2f;p&gt;
&lt;p&gt;So we abuse the carry-chain to create such a mask. By adding &lt;code&gt;1111_1111&lt;&#x2f;code&gt; to the
input, we&#x27;re essentially ensuring that the carry signal is not asserted until
we hit the first one bit, but after that it will be asserted for all the rest
of the bits (travelling from right to left).&lt;&#x2f;p&gt;
&lt;p&gt;If we extract the relevant parts of the adder truth table we can see how the
addition operation will produce the mask that we need:&lt;&#x2f;p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;&#x2f;th&gt;
&lt;th&gt;y&lt;&#x2f;th&gt;
&lt;th&gt;cin&lt;&#x2f;th&gt;
&lt;th&gt;result&lt;&#x2f;th&gt;
&lt;th&gt;cout&lt;&#x2f;th&gt;
&lt;th&gt;explanation&lt;&#x2f;th&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;Before the first bit, produce ones&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;For the first bit, produce a zero and set the carry going&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;0&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;now the result is zero if x was 0&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;1&lt;&#x2f;td&gt;
&lt;td&gt;or 1 if x was one&lt;&#x2f;td&gt;
&lt;&#x2f;tr&gt;
&lt;&#x2f;tbody&gt;
&lt;&#x2f;table&gt;
&lt;p&gt;What that gives us is a number which is (from right to left):&lt;&#x2f;p&gt;
&lt;ol&gt;
&lt;li&gt;all ones (but that&#x27;s okay because corresponding input bits are zeroes)&lt;&#x2f;li&gt;
&lt;li&gt;zero for the first one bit (which ensures that it will be cleared)&lt;&#x2f;li&gt;
&lt;li&gt;and then equal to the input after that (leaving all higher bits unchanged)&lt;&#x2f;li&gt;
&lt;&#x2f;ol&gt;
</content>
</entry>

<entry>
<title>Item-at-a-time Reduce Functions in Python</title>
<link href="https://www.scaramanga.co.uk/journal/reduce-mypy/" rel="alternate"/>
<id>https://www.scaramanga.co.uk/journal/reduce-mypy/</id>
<updated>2019-03-09T23:28:47+09:00</updated>
<published>2019-03-09T23:28:47+09:00</published>
<summary>A nice way to implement reduce functions avoiding a conditional</summary>
<content type="html">&lt;p&gt;If you need to write a
&lt;a href=&quot;https:&#x2f;&#x2f;en.wikipedia.org&#x2f;wiki&#x2f;Fold_(higher-order_function)&quot;&gt;Reduce&lt;&#x2f;a&gt; function
in python, there&#x27;s a number of ways of doing it. I&#x27;m going to assume you
already know what that is and leap right in. Suffice to say, you can think of
that as something like an aggregate function in an SQL query.&lt;&#x2f;p&gt;
&lt;p&gt;Perhaps the most obvious would be to use
&lt;a href=&quot;https:&#x2f;&#x2f;docs.python.org&#x2f;3&#x2f;library&#x2f;functools.html#functools.reduce&quot;&gt;functools.reduce&lt;&#x2f;a&gt;.&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;source python&quot;&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;functools&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;support function builtin python&quot;&gt;reduce&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;operator&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;add&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;support function builtin python&quot;&gt;reduce&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;add&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator arguments python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;support function builtin python&quot;&gt;range&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;constant numeric integer decimal python&quot;&gt;20&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;But in this case you would need the entire iterable to be ready at the time of
calling &lt;code&gt;reduce&lt;&#x2f;code&gt;. What if you want to call the &lt;code&gt;reduce&lt;&#x2f;code&gt; one step at a time?
This would be particularly important, for example, if you were receiving the
items over a network connection or reading them from a huge file.&lt;&#x2f;p&gt;
&lt;h2&gt;With Generators&lt;&#x2f;h2&gt;
&lt;p&gt;Another way might be to use a generator, but that&#x27;s not without its problems either:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;source python&quot;&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;operator&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;add&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;genreduce&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;func&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;keyword control flow yield python&quot;&gt;yield&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta statement while python&quot;&gt;&lt;span class=&quot;keyword control flow while python&quot;&gt;while&lt;&#x2f;span&gt; &lt;span class=&quot;constant language python&quot;&gt;True&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section block while python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;nxt&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;keyword control flow yield python&quot;&gt;yield&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;func&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator arguments python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;nxt&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;online_reduce&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;func&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;gen&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;state&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;genreduce&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator arguments python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;func&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;support function builtin python&quot;&gt;next&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;state&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta statement for python&quot;&gt;&lt;span class=&quot;keyword control flow for python&quot;&gt;for&lt;&#x2f;span&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;item&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement for python&quot;&gt;&lt;span class=&quot;keyword control flow for in python&quot;&gt;in&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement for python&quot;&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;gen&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section block for python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;state&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation accessor dot python&quot;&gt;.&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;send&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;item&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;So now things have got pretty ponderous. And the two things we want to specify
here are quite cumbersome to carry around - the function defining the reduction
and its initial value.&lt;&#x2f;p&gt;
&lt;h2&gt;With Function Attributes&lt;&#x2f;h2&gt;
&lt;p&gt;What I&#x27;m really after is a concise way to specify the &lt;em&gt;callees&lt;&#x2f;em&gt; - the reduce
functions themselves. And an intuitive pythonic protocol for a &lt;em&gt;caller&lt;&#x2f;em&gt; to use
them.&lt;&#x2f;p&gt;
&lt;p&gt;Luckily, in Python, we can just add attributes to functions.&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;source python&quot;&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;foldsum&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;prev_val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;prev_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic python&quot;&gt;+&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;foldsum&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation accessor dot python&quot;&gt;.&lt;&#x2f;span&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric integer decimal python&quot;&gt;0&lt;&#x2f;span&gt;

&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;online_reduce&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;func&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;gen&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;func&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation accessor dot python&quot;&gt;.&lt;&#x2f;span&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta statement for python&quot;&gt;&lt;span class=&quot;keyword control flow for python&quot;&gt;for&lt;&#x2f;span&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;item&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement for python&quot;&gt;&lt;span class=&quot;keyword control flow for in python&quot;&gt;in&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement for python&quot;&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;gen&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section block for python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;func&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator arguments python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;item&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;This is nice, it lets us combine the function and the initial-value without
resorting to defining some new class, or just using a tuple like &lt;code&gt;(add, 0)&lt;&#x2f;code&gt;
which is essentially untyped and can get confusing.&lt;&#x2f;p&gt;
&lt;p&gt;It does make type checking blow up though.&lt;&#x2f;p&gt;
&lt;h2&gt;With a Decorator&lt;&#x2f;h2&gt;
&lt;p&gt;Let&#x27;s try again but make this a function decorator. We want to be able to
decorate our own functions as well as things like &lt;code&gt;operator.add&lt;&#x2f;code&gt;, so we&#x27;ll need
an extra level of indirection so we don&#x27;t start adding attributes onto members
of the &lt;code&gt;operator&lt;&#x2f;code&gt; module!&lt;&#x2f;p&gt;
&lt;p&gt;When it comes to typing, we want the caller to be able to access
&lt;code&gt;func.init_val&lt;&#x2f;code&gt; without causing a type error. We can define a custom protocol
for that using the
&lt;a href=&quot;https:&#x2f;&#x2f;mypy.readthedocs.io&#x2f;en&#x2f;latest&#x2f;protocols.html#simple-user-defined-protocols&quot;&gt;typing_extensions&lt;&#x2f;a&gt;
module.&lt;&#x2f;p&gt;
&lt;p&gt;But also, our actual decorator needs to not blow up &lt;code&gt;mypy&lt;&#x2f;code&gt; and that gets a
little bit tricky. I couldn&#x27;t figure out how to avoid using a
&lt;a href=&quot;https:&#x2f;&#x2f;docs.python.org&#x2f;3&#x2f;library&#x2f;typing.html#typing.cast&quot;&gt;cast&lt;&#x2f;a&gt;.&lt;&#x2f;p&gt;
&lt;p&gt;With all that said, here&#x27;s all the tedious boilerplate for the decorator:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;source python&quot;&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;typing&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;Callable&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator import-list python&quot;&gt;,&lt;&#x2f;span&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;Any&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator import-list python&quot;&gt;,&lt;&#x2f;span&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;cast&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;typing_extensions&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;Protocol&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;functools&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;wraps&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;span class=&quot;meta class python&quot;&gt;&lt;span class=&quot;storage type class python&quot;&gt;class&lt;&#x2f;span&gt; &lt;span class=&quot;entity name class python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;ReduceFunc&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta class inheritance python&quot;&gt;&lt;span class=&quot;punctuation section inheritance begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta class inheritance python&quot;&gt;&lt;span class=&quot;entity other inherited-class python&quot;&gt;Protocol&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section inheritance end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta class python&quot;&gt;&lt;span class=&quot;punctuation section class begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;punctuation separator annotation variable python&quot;&gt;:&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;Any&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta function python&quot;&gt;    &lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;support function magic python&quot;&gt;__call__&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;prev_val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta statement raise python&quot;&gt;&lt;span class=&quot;keyword control flow raise python&quot;&gt;raise&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;support type exception python&quot;&gt;NotImplementedError&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;reducer&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;parm&lt;&#x2f;span&gt; &lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters annotation python&quot;&gt;&lt;span class=&quot;punctuation separator annotation parameter python&quot;&gt;:&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;Any&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta function python&quot;&gt;    &lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;decorator&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;func&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt; &lt;&#x2f;span&gt;&lt;span class=&quot;meta function annotation return python&quot;&gt;&lt;span class=&quot;punctuation separator annotation return python&quot;&gt;-&amp;gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;ReduceFunc&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta annotation python&quot;&gt;&lt;span class=&quot;punctuation definition annotation python&quot;&gt;@&lt;&#x2f;span&gt;&lt;span class=&quot;meta annotation function python&quot;&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta annotation function python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable annotation function python&quot;&gt;wraps&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta annotation arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;func&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta function python&quot;&gt;        &lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;wrapper&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;a&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;b&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
            &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;func&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;a&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator arguments python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;b&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;rf&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;cast&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;ReduceFunc&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator arguments python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;wrapper&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;rf&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation accessor dot python&quot;&gt;.&lt;&#x2f;span&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;init_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;parm&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
        &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;rf&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;decorator&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;support variable magic python&quot;&gt;__all__&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta group python&quot;&gt;&lt;span class=&quot;punctuation section group begin python&quot;&gt;(&lt;&#x2f;span&gt;
    &lt;span class=&quot;meta string python&quot;&gt;&lt;span class=&quot;string quoted single python&quot;&gt;&lt;span class=&quot;punctuation definition string begin python&quot;&gt;&amp;#39;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta string python&quot;&gt;&lt;span class=&quot;string quoted single python&quot;&gt;reducer&lt;span class=&quot;punctuation definition string end python&quot;&gt;&amp;#39;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;punctuation section group end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;And here&#x27;s two ways of defining a &lt;code&gt;reduce&lt;&#x2f;code&gt; function. First for a user-defined
function, secondly when wrapping a function from somewhere else like the
&lt;code&gt;operator&lt;&#x2f;code&gt; module.&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;source python&quot;&gt;&lt;span class=&quot;meta annotation python&quot;&gt;&lt;span class=&quot;punctuation definition annotation python&quot;&gt;@&lt;&#x2f;span&gt;&lt;span class=&quot;meta annotation function python&quot;&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta annotation function python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable annotation function python&quot;&gt;reducer&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta annotation arguments python&quot;&gt;&lt;span class=&quot;constant numeric integer decimal python&quot;&gt;0&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;storage type function python&quot;&gt;def&lt;&#x2f;span&gt; &lt;span class=&quot;entity name function python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;foldsum&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;punctuation section parameters begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters python&quot;&gt;&lt;span class=&quot;variable parameter python&quot;&gt;prev_val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator parameters python&quot;&gt;,&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter python&quot;&gt;val&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section parameters end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function python&quot;&gt;&lt;span class=&quot;punctuation section function begin python&quot;&gt;:&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
    &lt;span class=&quot;keyword control flow return python&quot;&gt;return&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;prev_val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic python&quot;&gt;+&lt;&#x2f;span&gt; &lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;val&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;source python&quot;&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import from python&quot;&gt;from&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;meta import-source python&quot;&gt; &lt;span class=&quot;meta import-path python&quot;&gt;&lt;span class=&quot;meta import-name python&quot;&gt;operator&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta statement import python&quot;&gt;&lt;span class=&quot;keyword control import python&quot;&gt;import&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta statement import python&quot;&gt; &lt;span class=&quot;meta generic-name python&quot;&gt;add&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;foldsum&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment python&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;variable function python&quot;&gt;reducer&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;constant numeric integer decimal python&quot;&gt;0&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;punctuation section arguments begin python&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call python&quot;&gt;&lt;span class=&quot;meta function-call arguments python&quot;&gt;&lt;span class=&quot;meta qualified-name python&quot;&gt;&lt;span class=&quot;meta generic-name python&quot;&gt;add&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section arguments end python&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
</content>
</entry>

<entry>
<title>Getting Bitmasks from SSE Vector Comparisons</title>
<link href="https://www.scaramanga.co.uk/journal/simd-cmp-bitmasks/" rel="alternate"/>
<id>https://www.scaramanga.co.uk/journal/simd-cmp-bitmasks/</id>
<updated>2019-03-08T18:49:47+09:00</updated>
<published>2019-03-08T18:49:47+09:00</published>
<summary>How to actually use SIMD comparison results</summary>
<content type="html">&lt;p&gt;These days the single-threaded performance of CPUs just isn&#x27;t advancing as
quickly as it did in my salad days of the late 90s and early 2000s. Personally
I think it&#x27;s God&#x27;s revenge for people putting pineapple on pizza. Regardless
of the causes, I find it to be increasingly the case that if you aren&#x27;t using
SIMD in the performance critical areas of your software, then you are leaving a
lot of performance on the floor.&lt;&#x2f;p&gt;
&lt;p&gt;Let&#x27;s say that you have an array of &lt;code&gt;uint16_t&lt;&#x2f;code&gt;&#x27;s and you want to go through
them all looking for all instances of a given number. In plain-old-C you would
do something like:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;storage type c&quot;&gt;void&lt;&#x2f;span&gt; &lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;entity name function c&quot;&gt;my_pipeline_is_as_empty_as_my_soul&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function parameters c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;storage modifier c&quot;&gt;const&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter c&quot;&gt;count&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
					&lt;span class=&quot;storage modifier c&quot;&gt;const&lt;&#x2f;span&gt; &lt;span class=&quot;support type stdint c&quot;&gt;uint16_t&lt;&#x2f;span&gt; &lt;span class=&quot;variable parameter c&quot;&gt;vector&lt;&#x2f;span&gt;&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;&lt;span class=&quot;storage modifier c&quot;&gt;static&lt;&#x2f;span&gt; count&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;
&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;
	&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; i&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;for&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;i &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; i &lt;span class=&quot;keyword operator comparison c&quot;&gt;&amp;lt;&lt;&#x2f;span&gt; count&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; i&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
		&lt;span class=&quot;keyword control c&quot;&gt;if&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt; vector&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;i&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator comparison c&quot;&gt;==&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt; &lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
			&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; do the thing &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
		&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
	&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function c&quot;&gt;&lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;But you&#x27;ve been chilling listening to &amp;quot;smooth&amp;quot; by Carlos Santana, and you&#x27;ve
heard of this hip new technology called SSE2. It allows you to do EIGHT of
these comparisons in a single bound!&lt;&#x2f;p&gt;
&lt;p&gt;So you include the relevant header and you start working on an inner-loop which
handles 8 items at a time. We&#x27;ll worry about any trailing data later. You&#x27;ll
use &lt;code&gt;_mm_load_si128&lt;&#x2f;code&gt; to just slurp an array of 8 elements into one of these
new wide-boy registers:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;meta preprocessor include c&quot;&gt;&lt;span class=&quot;keyword control import include c&quot;&gt;#include&lt;&#x2f;span&gt; &lt;span class=&quot;string quoted other lt-gt include c&quot;&gt;&lt;span class=&quot;punctuation definition string begin c&quot;&gt;&amp;lt;&lt;&#x2f;span&gt;emmintrin.h&lt;span class=&quot;punctuation definition string end c&quot;&gt;&amp;gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_Alignas&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;constant numeric c&quot;&gt;16&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;support type stdint c&quot;&gt;uint16_t&lt;&#x2f;span&gt; in16&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;&lt;span class=&quot;constant numeric c&quot;&gt;8&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 0 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 1 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x4567&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 2 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 3 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 4 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 5 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 6 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x1212&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;
	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; 7 &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0x3434&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt;

&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
__m128i h &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm_load_si128&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;__m128i &lt;span class=&quot;keyword operator c&quot;&gt;*&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;in16&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; 1234 4567 1234 1234 1234 0000 1212 3434
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;And, as before, we are looking for all instances of &lt;code&gt;0x1234&lt;&#x2f;code&gt; so we do a
comparison using the &lt;code&gt;_mm_cmpeq_epi16&lt;&#x2f;code&gt; intrinsic:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;__m128i n &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm_set1_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; 1234 1234 1234 1234 1234 1234 1234 1234
&lt;&#x2f;span&gt;__m128i r &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm_cmpeq_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;n&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt; h&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; ffff 0000 ffff ffff ffff 0000 0000 0000
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Astute readers will notice that these equality tests can be achieved with
&lt;code&gt;and&lt;&#x2f;code&gt;-ing or &lt;code&gt;xor&lt;&#x2f;code&gt;-ing, and that&#x27;s correct. But the topic of this post is the
comparison operators. These become really useful when you want to do range
comparisons using greater-than and&#x2f;or less-than or things like that.&lt;&#x2f;p&gt;
&lt;p&gt;Anyway, this is all wonderful but what am I going to do with this weird
two-byte boolean-like thing?&lt;&#x2f;p&gt;
&lt;p&gt;I now have a vector of &lt;code&gt;uint16_t&lt;&#x2f;code&gt;&#x27;s which are set to all 1s for matching items
and all 0s for non-matching items. We could just break these out in a loop but
that would waste all the effort we&#x27;ve put in to avoid branching and looping by
doing this with SIMD in the first place.&lt;&#x2f;p&gt;
&lt;p&gt;It would be nice if we could get the results in a bitmask, so we can do other
set-wise operations on all 8 elements at once. Or use &lt;code&gt;__builtin_ctz&lt;&#x2f;code&gt;
and &lt;code&gt;__builtin_clz&lt;&#x2f;code&gt; respectively to find the first&#x2f;last set bits.&lt;&#x2f;p&gt;
&lt;h2&gt;The solution&lt;&#x2f;h2&gt;
&lt;p&gt;How we&#x27;re going to do this is by using
&lt;a href=&quot;https:&#x2f;&#x2f;software.intel.com&#x2f;sites&#x2f;landingpage&#x2f;IntrinsicsGuide&#x2f;#text=_mm_packs_epi16&amp;amp;expand=4904,4043&quot;&gt;_mm_packs_epi16&lt;&#x2f;a&gt;
to collapse the 16bit values down to 8bit values and then
&lt;a href=&quot;https:&#x2f;&#x2f;software.intel.com&#x2f;sites&#x2f;landingpage&#x2f;IntrinsicsGuide&#x2f;#expand=4904,4043,3831,3831&amp;amp;text=_mm_movemask_epi8&quot;&gt;_mm_movemask_epi8&lt;&#x2f;a&gt;
to extract the mask.&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;__m128i p &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm_packs_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;r&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt; r&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; ff 00 ff ff ff 00 00 00 (x2)
&lt;&#x2f;span&gt;&lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; mask &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm_movemask_epi8&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;p&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator c&quot;&gt;&amp;amp;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0xff&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; 0x1d (or 00011101)
&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Now, this might require a bit of unpacking - if you will excuse the pun. At
first glance &lt;code&gt;_mm_packs_epi16&lt;&#x2f;code&gt; doesn&#x27;t seem an obvious choice. Intel describes
it as:&lt;&#x2f;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Convert packed 16-bit integers from &lt;code&gt;a&lt;&#x2f;code&gt; and &lt;code&gt;b&lt;&#x2f;code&gt; to packed 8-bit integers
using signed saturation, and store the results in &lt;code&gt;dst&lt;&#x2f;code&gt;.&lt;&#x2f;p&gt;
&lt;&#x2f;blockquote&gt;
&lt;p&gt;To put this in plain english, what happens is that each 16 bit integer in our
input vectors is treated as signed and squeezed down into a signed 8-bit
integer. But, instead of just chopping off the top bits, anything that doesn&#x27;t
fit gets &#x27;stuck&#x27; at the nearest end of the 8-bit range, &lt;code&gt;0x7f&lt;&#x2f;code&gt; (127) or &lt;code&gt;0x80&lt;&#x2f;code&gt;
(-128) (ie. &lt;a href=&quot;https:&#x2f;&#x2f;en.wikipedia.org&#x2f;wiki&#x2f;Saturation_arithmetic&quot;&gt;saturation&lt;&#x2f;a&gt;).
The eight results from &lt;code&gt;a&lt;&#x2f;code&gt; come first, followed by the eight from &lt;code&gt;b&lt;&#x2f;code&gt;. Our
comparison results are either &lt;code&gt;0xffff&lt;&#x2f;code&gt;, which is -1 and fits as &lt;code&gt;0xff&lt;&#x2f;code&gt;, or
&lt;code&gt;0&lt;&#x2f;code&gt;, so nothing ever actually saturates. A C implementation would look
something like this:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;support type stdint c&quot;&gt;int16_t&lt;&#x2f;span&gt; in&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;&lt;span class=&quot;constant numeric c&quot;&gt;16&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; &lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; this is the concatenation of the two 128bit operands, a then b
&lt;&#x2f;span&gt;&lt;span class=&quot;support type stdint c&quot;&gt;int8_t&lt;&#x2f;span&gt; out&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;&lt;span class=&quot;constant numeric c&quot;&gt;16&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; &lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; output operand
&lt;&#x2f;span&gt;
&lt;span class=&quot;keyword control c&quot;&gt;for&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;i &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; i &lt;span class=&quot;keyword operator comparison c&quot;&gt;&amp;lt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;16&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt; i&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;keyword operator arithmetic c&quot;&gt;+&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
	&lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; res&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;

	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; Load the input &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
	res &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; in&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;i&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;

	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; Signed saturation &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
	&lt;span class=&quot;keyword control c&quot;&gt;if&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt; res &lt;span class=&quot;keyword operator comparison c&quot;&gt;&amp;gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;127&lt;&#x2f;span&gt; &lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
		res &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;127&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword control c&quot;&gt;else&lt;&#x2f;span&gt; &lt;span class=&quot;keyword control c&quot;&gt;if&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt; res &lt;span class=&quot;keyword operator comparison c&quot;&gt;&amp;lt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;-&lt;&#x2f;span&gt;&lt;span class=&quot;constant numeric c&quot;&gt;128&lt;&#x2f;span&gt; &lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;meta block c&quot;&gt;&lt;span class=&quot;punctuation section block begin c&quot;&gt;{&lt;&#x2f;span&gt;
		res &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;-&lt;&#x2f;span&gt;&lt;span class=&quot;constant numeric c&quot;&gt;128&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
	&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;

	&lt;span class=&quot;comment block c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;*&lt;&#x2f;span&gt; Store the result &lt;span class=&quot;punctuation definition comment c&quot;&gt;*&#x2f;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
	out&lt;span class=&quot;meta brackets c&quot;&gt;&lt;span class=&quot;punctuation section brackets begin c&quot;&gt;[&lt;&#x2f;span&gt;i&lt;span class=&quot;punctuation section brackets end c&quot;&gt;]&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; res&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;punctuation section block end c&quot;&gt;}&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;To avoid adding a dependency on any other registers we use the same input
register for both operands. This leaves us with two identical copies of the
desired output in the upper and lower 8 lanes of the output register
respectively. That&#x27;s why after converting to a bitmask with
&lt;code&gt;_mm_movemask_epi8&lt;&#x2f;code&gt;, we mask out the upper 8 bits to ensure that they&#x27;re always
zero.&lt;&#x2f;p&gt;
&lt;p&gt;This is, of course, a little wasteful. If we&#x27;re looping through a huge array
we would just do two lots of comparisons so we can fill two registers full of
results and then do a single &lt;code&gt;_mm_packs_epi16&lt;&#x2f;code&gt; to generate a 16 bit mask.&lt;&#x2f;p&gt;
&lt;h2&gt;What about with 256 and 512 bit vectors?&lt;&#x2f;h2&gt;
&lt;p&gt;The 256 bit version looks much the same. It produces a 16-bit bitmask at the
end and uses &lt;code&gt;immintrin.h&lt;&#x2f;code&gt; and the corresponding AVX2 versions of each
operation. The one gotcha is that the AVX2 pack works on each 128-bit half of
the register separately, so the two halves of our result need stitching back
together:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;&lt;span class=&quot;meta preprocessor include c&quot;&gt;&lt;span class=&quot;keyword control import include c&quot;&gt;#include&lt;&#x2f;span&gt; &lt;span class=&quot;string quoted other lt-gt include c&quot;&gt;&lt;span class=&quot;punctuation definition string begin c&quot;&gt;&amp;lt;&lt;&#x2f;span&gt;immintrin.h&lt;span class=&quot;punctuation definition string end c&quot;&gt;&amp;gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;__m256i h &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm256_load_si256&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;__m256i &lt;span class=&quot;keyword operator c&quot;&gt;*&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;ptr&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
__m256i n &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm256_set1_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
__m256i r &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm256_cmpeq_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;n&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt; h&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
__m256i p &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm256_packs_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;r&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt; r&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;comment line double-slash c&quot;&gt;&lt;span class=&quot;punctuation definition comment c&quot;&gt;&#x2f;&#x2f;&lt;&#x2f;span&gt; lanes 0-7 land in bits 0-7 (and 8-15), lanes 8-15 in bits 16-23 (and 24-31)
&lt;&#x2f;span&gt;&lt;span class=&quot;storage type c&quot;&gt;unsigned&lt;&#x2f;span&gt; &lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; m &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm256_movemask_epi8&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;p&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;span class=&quot;storage type c&quot;&gt;int&lt;&#x2f;span&gt; mask &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;m &lt;span class=&quot;keyword operator c&quot;&gt;&amp;amp;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0xff&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;|&lt;&#x2f;span&gt; &lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;m &lt;span class=&quot;keyword operator arithmetic c&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;8&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt; &lt;span class=&quot;keyword operator c&quot;&gt;&amp;amp;&lt;&#x2f;span&gt; &lt;span class=&quot;constant numeric c&quot;&gt;0xff00&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;If you have BMI2, &lt;code&gt;_pext_u32(_mm256_movemask_epi8(r), 0x55555555)&lt;&#x2f;code&gt; gets the
same mask without the pack at all.&lt;&#x2f;p&gt;
&lt;p&gt;For AVX-512 (specifically AVX-512BW, which is the part that handles 16-bit
elements) you needn&#x27;t go through the rigmarole because of the in-built
support for mask registers.&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;source c&quot;&gt;__m512i h &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm512_load_si512&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;span class=&quot;storage modifier c&quot;&gt;const&lt;&#x2f;span&gt; __m512i &lt;span class=&quot;keyword operator c&quot;&gt;*&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;ptr&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
__m512i n &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm512_set1_epi16&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;constant numeric c&quot;&gt;0x1234&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
__mmask32 mask  &lt;span class=&quot;keyword operator assignment c&quot;&gt;=&lt;&#x2f;span&gt; &lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;variable function c&quot;&gt;_mm512_cmpeq_epi16_mask&lt;&#x2f;span&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group begin c&quot;&gt;(&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;n&lt;span class=&quot;punctuation separator c&quot;&gt;,&lt;&#x2f;span&gt; h&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;meta function-call c&quot;&gt;&lt;span class=&quot;meta group c&quot;&gt;&lt;span class=&quot;punctuation section group end c&quot;&gt;)&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;&#x2f;span&gt;&lt;span class=&quot;punctuation terminator c&quot;&gt;;&lt;&#x2f;span&gt;
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;Easy! And it&#x27;s nice and fast. Looks like you can run comparisons on an entire
cache line, 32 &lt;code&gt;uint16_t&lt;&#x2f;code&gt;&#x27;s at a time, with 3 or 4 cycles of latency (4 on
Skylake-X, 3 on Ice Lake and later) and a throughput of one per cycle. Pretty
neat.&lt;&#x2f;p&gt;
&lt;h2&gt;Corrections (October 2026)&lt;&#x2f;h2&gt;
&lt;p&gt;The 2019 version of this post got a few things wrong:&lt;&#x2f;p&gt;
&lt;ul&gt;
&lt;li&gt;It described &lt;code&gt;_mm_packs_epi16&lt;&#x2f;code&gt; as splitting each 16-bit value into two bytes
and adding them with saturation. It actually narrows each signed 16-bit
value to a signed 8-bit one, saturating at -128 and 127. The code worked
anyway, because -1 and 0 come out the same under either reading.&lt;&#x2f;li&gt;
&lt;li&gt;The 128-bit mask was &lt;code&gt;&amp;amp; 0x7f&lt;&#x2f;code&gt;, which throws away the result for lane 7. It
should be &lt;code&gt;&amp;amp; 0xff&lt;&#x2f;code&gt;. The example only worked because lane 7 didn&#x27;t match.&lt;&#x2f;li&gt;
&lt;li&gt;The 256-bit instructions were described as SSE3. They&#x27;re AVX2.&lt;&#x2f;li&gt;
&lt;li&gt;The 256-bit code was broken: &lt;code&gt;_mm256_packs_epi16&lt;&#x2f;code&gt; packs within each 128-bit
half, so &lt;code&gt;&amp;amp; 0xffff&lt;&#x2f;code&gt; returned lanes 0-7 twice and lost lanes 8-15 entirely.&lt;&#x2f;li&gt;
&lt;li&gt;The AVX-512 compare was claimed to have 1 cycle of latency and run two per
cycle. &lt;a href=&quot;https:&#x2f;&#x2f;uops.info&#x2f;html-instr&#x2f;VPCMPEQW_K_ZMM_ZMM.html&quot;&gt;uops.info&lt;&#x2f;a&gt;
measures 4 cycles on Skylake-X and 3 on Ice Lake, at one per cycle (it only
runs on port 5).&lt;&#x2f;li&gt;
&lt;li&gt;Smaller fixes to the code: &lt;code&gt;in16&lt;&#x2f;code&gt; wasn&#x27;t aligned for &lt;code&gt;_mm_load_si128&lt;&#x2f;code&gt;, which
faults on unaligned addresses; a semicolon was missing; the comparison result
was called &lt;code&gt;r&lt;&#x2f;code&gt; in one snippet and &lt;code&gt;cmp_res&lt;&#x2f;code&gt; in the next; and
&lt;code&gt;__builtin_ctzl&lt;&#x2f;code&gt; is now &lt;code&gt;__builtin_ctz&lt;&#x2f;code&gt; to match the &lt;code&gt;int&lt;&#x2f;code&gt; mask.&lt;&#x2f;li&gt;
&lt;&#x2f;ul&gt;
</content>
</entry>

<entry>
<title>From Hash File to JIT: Building an Experimental OLAP Engine</title>
<link href="https://www.scaramanga.co.uk/journal/olap-query-engine/" rel="alternate"/>
<id>https://www.scaramanga.co.uk/journal/olap-query-engine/</id>
<updated>2018-04-09T12:00:00Z</updated>
<published>2018-04-09T12:00:00Z</published>
<summary>From a cdb-inspired hash file to a bytecode evaluator to a JIT — an experimental OLAP database, and the design decisions behind each step.</summary>
<content type="html">&lt;p&gt;Despite sharing the same name as &lt;a href=&quot;&#x2f;skunk&#x2f;&quot;&gt;skunk&lt;&#x2f;a&gt;, a small cdb-inspired hash
file, this article is actually about my journey writing a full database system
intended for workloads where query speed is paramount and data is written to
infrequently in an append-only fashion. The system is currently experimental,
and not available, but here are some ruminations on the design considerations
and some of the salient technical details of how it got there.&lt;&#x2f;p&gt;
&lt;h2&gt;Table format (rec)&lt;&#x2f;h2&gt;
&lt;p&gt;There are many options for how to store records. If records have primary keys
then, often, records are embedded into a b-tree. Other options are to use a
paged-format and then allocate space heap-style from there. Fancy items such as a
schema version, or a null bitmap might also be included.&lt;&#x2f;p&gt;
&lt;p&gt;For our considerations, we don&#x27;t care too much about primary-keyed tables, or
can implement them with a different format later. Also we don&#x27;t support nulled
values or updates at all.&lt;&#x2f;p&gt;
&lt;p&gt;For this reason we chose to round up record size to a power of two. And then
use a power-of-two of records inside each buffer, aiming for a page size of
1MiB. The trailing page is allowed to be shorter. This allows us to locate all
records with shifts and masks and means we write to the storage device in 1MiB
chunks which should be good for both spinning rust and SSD alike.&lt;&#x2f;p&gt;
&lt;p&gt;Not much to say about this, it&#x27;s the simplest imaginable approach. As we look
to support star-schemas and other primary-keyed tables later we will look into
a different table format for that.&lt;&#x2f;p&gt;
&lt;p&gt;Originally we did support updates and deletes. Deletes were based on bitmaps
which were placed at the trailer of each page. But doing this caused locating a
record to include an &lt;code&gt;idiv&lt;&#x2f;code&gt; (integer division) instruction that couldn&#x27;t be
optimised into a multiply at compile-time. This led to a 10x slowdown in
locating records. In retrospect a better approach would have been a separate
roaring bitmap - which allows random access - that would cover the entire
table. Anyway, for my intended use-case, deletes are not important and updates
would be a staggering rarity.&lt;&#x2f;p&gt;
&lt;h2&gt;Insert Performance&lt;&#x2f;h2&gt;
&lt;p&gt;A real-world dataset is used. It&#x27;s 1 month of netflow records from a busy
network.&lt;&#x2f;p&gt;
&lt;p&gt;Import 151,137,635 64-byte records (from binary) into a table. Final table
size is 9226 MiB. Note that space-overhead here is basically zero, this is
partly luck that our record size is a power-of-two already. Overhead could be
close to double in the worst-case.&lt;&#x2f;p&gt;
&lt;p&gt;At the same time as importing we index src&#x2f;dst ip&#x27;s into a single index, and
protocol-id into another index. This results in 609 MiB (656,047 keys) and 77
MiB (39 keys) indices respectively. Note that the biggest index is only a 6.5%
overhead which is much better than with EWAH compressed bitmaps which almost
double the size. A postings-list or b-tree would be more inefficient still.&lt;&#x2f;p&gt;
&lt;p&gt;Overall, the process takes 28.7s, or around 5.27M rows per second insert rate
with indexing. Without indexing, we can do this in 7.31s, which is about 20M
rows per second. There&#x27;s still some room for optimisations here but this is a
nice start. Indexing performance seems pretty bad, but it makes sense because
we&#x27;re not using write-optimised data structures since we care more about query
performance. Still, it might be a nice thing to add in future as a trade-off
that the user can make - much faster inserts in return for slightly slower
queries.&lt;&#x2f;p&gt;
&lt;h2&gt;Index Format (br64)&lt;&#x2f;h2&gt;
&lt;p&gt;A big part of our intended use-case is using indices to speed up searches.
Eventually there will be specialised indices for various data types such as
text or multi-dimensional data. But for now we focus on integers of up to 64
bits in width.&lt;&#x2f;p&gt;
&lt;p&gt;Since our indices are constructed in a single-pass during table construction we
have no reason to avoid b-trees whose worst-case performance is only
encountered when performing random inserts. If a b-tree is &amp;quot;bulk-loaded&amp;quot; then
we can obtain optimal packing and layout.&lt;&#x2f;p&gt;
&lt;p&gt;We chose a fanout of 512. This works out to a page size of 4KiB which should be
good for mmapped access on both SSD and spinning rust - a random read anywhere
within the memory mapped index file should bring in exactly one node. Keys and
values are both 64bit integers. We lay out nodes in breadth-first-search (BFS)
order.&lt;&#x2f;p&gt;
&lt;p&gt;For internal pages, the values are page-numbers pointing to a child page and
keys are splitting keys. The unused splitting key at the start of the page is
used to record the number of values in that page.&lt;&#x2f;p&gt;
&lt;p&gt;For leaf nodes, the values are implementation-defined. The only implementation
right now is to point to a roaring-bitmap of records in the table which match
the associated key. Since there is no space in the pages to record node-type or
number of nodes, we store this information in the file-header. Specifically,
the number of keys, and the page number of the first leaf node is stored. From
this we can determine if a page is a leaf node by its page number (pgno ≥
first leaf) and how many keys are stored in the possibly not-full final leaf
(&lt;code&gt;nr_keys&lt;&#x2f;code&gt; modulo fanout). Note that these header values also permit very
efficient index-scans, since our leaves are packed contiguously and can be
located instantly. A useful optimisation for queries ordered by the search key.&lt;&#x2f;p&gt;
&lt;p&gt;Bitmaps are stored in something similar to roaring-bitmap style. This seems to
provide much better compression ratios than run-length encoded (RLE) bitmaps
while maintaining all the good properties (set operations can be performed
directly on compressed representation). But it also allows for fast random access&lt;&#x2f;p&gt;
&lt;ul&gt;
&lt;li&gt;unlike RLE.&lt;&#x2f;li&gt;
&lt;&#x2f;ul&gt;
&lt;p&gt;These bitmaps work by dividing up the value-space and choosing the smallest
representation for each part of that space, based on its density. First, the
space of record-numbers is divided up into containers which cover 2^16
contiguous records, starting from the zeroth. For each container, we maintain a
count of the number of items which are present. For sparsely populated
containers we use a sorted array of 16-bit unsigned integers, for semi-dense
containers we use a bitmap, and for dense containers we use a sorted array of
16-bit integers mentioning all unset items (ie. an inverted-list
representation). The boundaries between sparse, semi-dense and dense are chosen
at the crossover points where each representation becomes the most
space-efficient.&lt;&#x2f;p&gt;
&lt;p&gt;Unpacking and intersecting of the bitmaps can be performed pretty efficiently
with just a little bit of clever bit twiddling in C. Further, several of the
important cases, such as unpacking the bitmaps or intersecting bitmaps, can be
optimized with AVX-512. List containers aren&#x27;t as easily optimized but the
silver lining there is that the list container is only used in very sparse (or
very dense) regions which are, by definition, the easiest cases.&lt;&#x2f;p&gt;
&lt;p&gt;For 8 and 16 bit keys we can dispense with the b-tree and use a direct
table-lookup, avoiding the need to binary search. For larger composite keys we
will probably use a multi-level version of these schemes where each component
of a composite key is indexed in a separate b-tree. This should assist with
left-anchored queries and index-scans.&lt;&#x2f;p&gt;
&lt;h2&gt;Query Planner&lt;&#x2f;h2&gt;
&lt;p&gt;Right now the query planner is unremarkable and uses heuristics to pick indices
to use and a join order that looks useful for hash joins. In future we will be
implementing a cost-based query planner.&lt;&#x2f;p&gt;
&lt;p&gt;The write-once query-many architecture makes materialisation cheap and
efficient for us, so we may experiment with tweaking the query planner to make
more extensive use of materialisation, which is usually avoided in more
conventional RDBMS&#x27;s. One anticipated problem with this is that without limiting
query plan searches only to left-deep trees then we increase our search space
which will increase the cost of planning. But for prepared-statements or
stored-procedures where the plan is generated only once, it might pay off,
especially if we introduce a parametrised planner.&lt;&#x2f;p&gt;
&lt;p&gt;Another benefit of this architecture is that we can produce catalogs with
accurate selectivity information which will be useful when picking indices and
when planning equi-joins.&lt;&#x2f;p&gt;
&lt;h2&gt;Query Evaluator&lt;&#x2f;h2&gt;
&lt;p&gt;Currently, the query evaluator follows the volcano model. It&#x27;s a tree of nodes
which implement a generator function, iterating over the output of a previous
node. In reality the tree is more of a linked list since the planner is using
left-deep trees.&lt;&#x2f;p&gt;
&lt;p&gt;Evaluation uses the &amp;quot;pull&amp;quot; method. Iteration over the results is driven from
the outside-in. That is to say that the front-end interface contains &lt;code&gt;rewind&lt;&#x2f;code&gt;,
&lt;code&gt;get-next-row&lt;&#x2f;code&gt; and &lt;code&gt;is_eof?&lt;&#x2f;code&gt; methods. This avoids the need for consumers to
provide a callback function to receive the results of the queries.&lt;&#x2f;p&gt;
&lt;p&gt;However, this is a pretty inefficient design since everything works one row at
a time. This means we need to spill our most performance critical loop state
into memory rather than giving it a chance to stay in registers. Consequently,
the overhead of the generators&#x2f;iterators model starts to dominate the cost of
query evaluation.&lt;&#x2f;p&gt;
&lt;p&gt;The inherent slowness of the volcano model has been worked around so far by
making use of batching, especially in tablescan, and indexseek node types. More
importantly the system is being moved towards more of a compiler-oriented
design where multiple stages may be inlined together into a well optimized
piece of machine-code.&lt;&#x2f;p&gt;
&lt;h2&gt;Bytecode Virtual Machine&lt;&#x2f;h2&gt;
&lt;p&gt;Where possible, selection expressions are compiled into a bytecode for
efficient evaluation. Right now, only basic expressions are supported.  That
means column-to-column comparisons and column-to-literal comparisons joined by
conjunctions (AND) or disjunctions (OR). For more complex queries involving
arithmetic or variable assignments we fall back to other, more functional,
methods.&lt;&#x2f;p&gt;
&lt;p&gt;The bytecode is designed to reduce the number of instructions as much as
possible. In my previous experiences with bytecode vm&#x27;s, RISC-like approaches
based on separate loading, storing and control-flow instructions increase
overhead by making it necessary to perform more instruction dispatches. They
also require more state, such as registers and condition flags.&lt;&#x2f;p&gt;
&lt;p&gt;In our system, the machine state is simply the instruction pointer, a halted
flag, and a matched flag. The program is a linear array of instructions,
contiguously following the machine state to reduce pointer chasing and boil the
main-loop down to a bunch of fast &lt;code&gt;lea&lt;&#x2f;code&gt; and &lt;code&gt;call&lt;&#x2f;code&gt; instructions.&lt;&#x2f;p&gt;
&lt;p&gt;There are four instruction types:&lt;&#x2f;p&gt;
&lt;ol&gt;
&lt;li&gt;Halt without match&lt;&#x2f;li&gt;
&lt;li&gt;Halt with match&lt;&#x2f;li&gt;
&lt;li&gt;Compare a column to a column&lt;&#x2f;li&gt;
&lt;li&gt;Compare a column to a literal&lt;&#x2f;li&gt;
&lt;&#x2f;ol&gt;
&lt;p&gt;Each instruction contains a pointer to a function which implements the
instruction. A different function implements each of the instruction types. The
operand space in the instruction contains the information necessary to retrieve
the field (an index to find the relation, and an offset and length to locate
the column within the relation). And that is either doubled up for
field-to-field compares, or a literal is added in place of the second field&#x27;s
information. Finally two addresses are included in each instruction, the first
is followed if the comparison evaluates false, and the second is followed if
the comparison evaluates true.&lt;&#x2f;p&gt;
&lt;p&gt;The instruction at address zero halts without a match. The instruction at
address one halts with a match. This eliminates unnecessary condition checking
and branching in the inner loop. The entry point is always at address two.&lt;&#x2f;p&gt;
&lt;p&gt;The compiler itself is only 317 lines of code, half of which is checking an
abstract-syntax tree representing the selection in order to determine if it
is representable in the bytecode. The main dispatch loop of the interpreter is 7
lines of code.&lt;&#x2f;p&gt;
&lt;p&gt;On the dataset mentioned below, a series of un-indexed equality conditions over
4 columns using full table scan over ~151M records was reduced from 9.7s to
2.9s of run-time. That translates to an improvement in evaluation rate from 15M
rows per second to 50M rows per second.&lt;&#x2f;p&gt;
&lt;p&gt;Contrary to popular belief, the cause of the improved performance is not
reduced branch-misses (which actually increased ten-fold) or cache misses
(which stayed roughly equal). But simply a drastic reduction in instruction
path-length (~99Bn down to ~27Bn), with a slight reduction in instructions
per-clock. About 20% of the removed instructions were branches, however.&lt;&#x2f;p&gt;
&lt;p&gt;The main benefit of the machine is that it&#x27;s pretty efficient - close to the
performance of native code in fact. But the downside is that only simple
operations are supported. Support for a much wider variety of selection
expressions could probably be achieved by adding new instructions and an
accumulator - maybe even a stack. But we would want to be careful not to slow
down the usual, simple, kinds of selections - the common case we&#x27;ve optimized
for - by adding too much complexity.&lt;&#x2f;p&gt;
&lt;h2&gt;JIT Compilation of Query Evaluators&lt;&#x2f;h2&gt;
&lt;p&gt;In order to support more complex queries than the bytecode interpreter,
&lt;code&gt;libgccjit&lt;&#x2f;code&gt; is used to compile selection expressions into native machine code.
This approach produces faster code at the expense of taking a bit more time and
resources during the preparation of the query. Compiling and optimizing is hard
work, after all. Certainly more so than the simple methods used for the bytecode
interpreter.&lt;&#x2f;p&gt;
&lt;p&gt;A well known limitation of JIT compilation in query evaluation is that most of
the benefits to be had come from combining and inlining multiple stages of the
query, which can often be difficult.&lt;&#x2f;p&gt;
&lt;p&gt;The architecture allows us to combine full table scans and selections into a
single JITed program. This is because it&#x27;s easy to iterate over all records
with a simple for-loop without having to bring huge amounts of code to walk
through a complicated b-tree or record structure.&lt;&#x2f;p&gt;
&lt;p&gt;Using this technique, the query used to test the bytecode evaluator above can
be executed in around 1.5s, which gives us an evaluation rate of nearly 105M
rows per second.&lt;&#x2f;p&gt;
&lt;p&gt;One shortcoming right now is that no special-case code is generated to catch
exception conditions like undefined shifts or divides by zero.  Typically the
most difficult part about JITing evaluators is that as more internal functions
are inlined, more and more errors and exception cases need to be handled within
the JITd code which can greatly increase the complexity of this solution. After
all, if writing some code itself is difficult, then writing code which
generates an AST equivalent to that code is always going to be even more
difficult.&lt;&#x2f;p&gt;
&lt;h2&gt;Atomicity and Durability&lt;&#x2f;h2&gt;
&lt;p&gt;Our append-only design makes atomicity and durability relatively easy to
achieve. There is code for WAL operations that we might resurrect in future.
Given our use cases, it&#x27;s more likely that we will have a data-ingestion API
that provides special control over checkpointing and recovery.&lt;&#x2f;p&gt;
&lt;h2&gt;Final Thoughts and Future Directions&lt;&#x2f;h2&gt;
&lt;p&gt;Overall, for a few weeks of part-time work, I&#x27;m quite happy with the results.
Certainly there are some interesting future directions still, especially in
query planning and evaluation.&lt;&#x2f;p&gt;
&lt;p&gt;The most immediate task is rounding out the query language and implementing
joins, aggregates, and other expected features of an RDBMS. After that the
system will need a real cost-based query planner to make the best use of the
query evaluator.&lt;&#x2f;p&gt;
&lt;p&gt;There are plans for a few exotic features to specifically optimize time-series
tables. Those are tables where timestamped rows are appended, either
periodically, or from a real-time event-stream. Also I&#x27;d be quite interested in
experimenting with column-store record organisation if I can ever find the free
time.&lt;&#x2f;p&gt;
</content>
</entry>

<entry>
<title>Qemu, curses and caca</title>
<link href="https://www.scaramanga.co.uk/journal/qemu-curses-and-caca/" rel="alternate"/>
<id>https://www.scaramanga.co.uk/journal/qemu-curses-and-caca/</id>
<updated>2010-06-21T14:00:00Z</updated>
<published>2010-06-21T14:00:00Z</published>
<summary>Fun with text-mode qemu consoles</summary>
<content type="html">&lt;p&gt;I have recently discovered, and been very impressed with, the qemu ncurses
display driver. Basically it lets you run a guest OS inside of a regular
terminal emulator. Currently the curses display works almost perfectly when the
BIOS and guest OS have the VGA card programmed in text mode but when switched to
graphics mode all you get is a message telling you “Graphic mode 800 x 600″ for
example.&lt;&#x2f;p&gt;
&lt;p&gt;Well, realising that there are the excellent aalib and libcaca ASCII-art text
rendering engines out there I began thinking about the possibilities.. Firstly
it is possible to set the (default) SDL display to use the libcaca video
driver. Then I realised libcaca has an ncurses back-end. So the following
command will let you run a full graphics mode OS inside your terminal emulator:&lt;&#x2f;p&gt;
&lt;pre class=&quot;syntax-highlighting&quot;&gt;&lt;code&gt;&lt;span class=&quot;text plain&quot;&gt;$ env CACA_DRIVER=ncurses SDL_VIDEODRIVER=caca kvm ...
&lt;&#x2f;span&gt;&lt;&#x2f;code&gt;&lt;&#x2f;pre&gt;
&lt;p&gt;The results look great but the only problem at the moment is mouse integration
in that button presses don’t get through. I think I have tracked this down to a
bug in the SDL libcaca wrapper so watch this space :)&lt;&#x2f;p&gt;
&lt;p&gt;&lt;img src=&quot;winxp-textmode.png&quot; alt=&quot;Screenshot&quot; &#x2f;&gt;&lt;&#x2f;p&gt;
</content>
</entry>

</feed>